mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-30 22:34:48 +00:00
Normalize line endings
This commit is contained in:
@@ -1,79 +1,79 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyDeclStrings implements StructureInterface {
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long one;
|
||||
//@IggyFieldType(DataType.uint32_t)
|
||||
//long size;
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, count = 3)
|
||||
byte xxx[];
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, countField = "size")
|
||||
byte data[];
|
||||
byte padd[];
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long one2;
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long zero;
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public IggyDeclStrings(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
one = s.readUI64();
|
||||
long size = s.readUI32();
|
||||
xxx = s.readBytes(3);
|
||||
data = s.readBytes((int) size);
|
||||
if ((15 + size) % 8 != 0) {
|
||||
padd = s.readBytes((int) (((15 + size) / 8 + 1) * 8 - 15 - size));
|
||||
} else {
|
||||
padd = new byte[0];
|
||||
}
|
||||
one = s.readUI64();
|
||||
if (one != 1) {
|
||||
throw new IOException("Wrong iggy font format (declend)!");
|
||||
}
|
||||
zero = s.readUI64();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
IggyIndexBuilder ib = s.getIndexing();
|
||||
s.writeUI64(one);
|
||||
s.writeUI32(data.length);
|
||||
ib.writeLengthCustom(15, new int[]{0x00, 0x08}, new int[]{2, 5});
|
||||
s.writeBytes(xxx);
|
||||
s.writeBytes(data);
|
||||
ib.writeLengthUI32(data.length);
|
||||
if ((15 + data.length) % 8 != 0) {
|
||||
byte[] padd = new byte[((int) (((15 + data.length) / 8 + 1) * 8 - 15 - data.length))];
|
||||
s.writeBytes(padd);
|
||||
}
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
s.writeUI64(one);
|
||||
s.writeUI64(zero);
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyDeclStrings implements StructureInterface {
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long one;
|
||||
//@IggyFieldType(DataType.uint32_t)
|
||||
//long size;
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, count = 3)
|
||||
byte xxx[];
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, countField = "size")
|
||||
byte data[];
|
||||
byte padd[];
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long one2;
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long zero;
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public IggyDeclStrings(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
one = s.readUI64();
|
||||
long size = s.readUI32();
|
||||
xxx = s.readBytes(3);
|
||||
data = s.readBytes((int) size);
|
||||
if ((15 + size) % 8 != 0) {
|
||||
padd = s.readBytes((int) (((15 + size) / 8 + 1) * 8 - 15 - size));
|
||||
} else {
|
||||
padd = new byte[0];
|
||||
}
|
||||
one = s.readUI64();
|
||||
if (one != 1) {
|
||||
throw new IOException("Wrong iggy font format (declend)!");
|
||||
}
|
||||
zero = s.readUI64();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
IggyIndexBuilder ib = s.getIndexing();
|
||||
s.writeUI64(one);
|
||||
s.writeUI32(data.length);
|
||||
ib.writeLengthCustom(15, new int[]{0x00, 0x08}, new int[]{2, 5});
|
||||
s.writeBytes(xxx);
|
||||
s.writeBytes(data);
|
||||
ib.writeLengthUI32(data.length);
|
||||
if ((15 + data.length) % 8 != 0) {
|
||||
byte[] padd = new byte[((int) (((15 + data.length) / 8 + 1) * 8 - 15 - data.length))];
|
||||
s.writeBytes(padd);
|
||||
}
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
s.writeUI64(one);
|
||||
s.writeUI64(zero);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,244 +1,244 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*
|
||||
* Based of works of somebody called eternity.
|
||||
*
|
||||
*/
|
||||
public class IggyFile implements StructureInterface {
|
||||
|
||||
final static Logger LOGGER = Logger.getLogger(IggyFile.class.getName());
|
||||
|
||||
private File originalFile;
|
||||
private IggyHeader header;
|
||||
private List<IggySubFileEntry> subFileEntries = new ArrayList<>();
|
||||
private List<byte[]> subFileEntriesData = new ArrayList<>();
|
||||
|
||||
private IggySwf iggySwf;
|
||||
|
||||
public static final int FIRST_TAG_POSITION = 3;
|
||||
|
||||
public IggySwf getSwf() {
|
||||
return iggySwf;
|
||||
}
|
||||
|
||||
public IggyFile(String filePath) throws IOException {
|
||||
this(new File(filePath));
|
||||
}
|
||||
|
||||
public IggyFile(File file) throws IOException {
|
||||
this.originalFile = file;
|
||||
try (ReadDataStreamInterface stream = new RandomAccessFileDataStream(file)) {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public File getOriginalFile() {
|
||||
return originalFile;
|
||||
}
|
||||
|
||||
public IggyHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public IggySubFileEntry getSubFileEntry(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntries.get(entryIndex);
|
||||
}
|
||||
|
||||
public int getNumEntries() {
|
||||
return subFileEntries.size();
|
||||
}
|
||||
|
||||
public byte[] getEntryData(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntriesData.get(entryIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[IggyFile:").append("\r\n");
|
||||
sb.append(header).append("\r\n");
|
||||
sb.append("Entries:").append("\r\n");
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
sb.append(entry).append("\r\n");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void extractIggyFile(File iggyFile, File extractDir) throws IOException {
|
||||
final String FILENAME_FORMAT = "index%d_type%d.bin";
|
||||
IggyFile ir = new IggyFile(iggyFile);
|
||||
for (int i = 0; i < ir.getNumEntries(); i++) {
|
||||
IggySubFileEntry entry = ir.getSubFileEntry(i);
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(extractDir, String.format(FILENAME_FORMAT, i, entry.type)))) {
|
||||
fos.write(ir.getEntryData(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getSwfName() {
|
||||
return iggySwf.getName();
|
||||
}
|
||||
|
||||
public long getSwfXMin() {
|
||||
return iggySwf.getHdr().getXMin();
|
||||
}
|
||||
|
||||
public long getSwfYMin() {
|
||||
return iggySwf.getHdr().getYMin();
|
||||
}
|
||||
|
||||
public long getSwfXMax() {
|
||||
return iggySwf.getHdr().getXMax();
|
||||
}
|
||||
|
||||
public long getSwfYMax() {
|
||||
return iggySwf.getHdr().getYMax();
|
||||
}
|
||||
|
||||
public float getSwfFrameRate() {
|
||||
return iggySwf.getHdr().getFrameRate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes entries of type INDEX.There can be more than one INDEX,
|
||||
* continuous. This removes all ot them.
|
||||
*/
|
||||
public void removeIndexEntries() {
|
||||
long offsetsChange = 0;
|
||||
final int ENTRY_SIZE = 16;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
offsetsChange = offsetsChange - entry.size - ENTRY_SIZE;
|
||||
subFileEntriesData.remove(i);
|
||||
subFileEntries.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateFlashEntry() throws IOException {
|
||||
|
||||
byte replacementData[];
|
||||
byte replacementIndexData[];
|
||||
IggyIndexBuilder ib = new IggyIndexBuilder();
|
||||
try (DataStreamInterface stream = new TemporaryDataStream()) {
|
||||
stream.setIndexing(ib);
|
||||
iggySwf.writeToDataStream(stream);
|
||||
replacementData = stream.getAllBytes();
|
||||
replacementIndexData = ib.getIndexBytes();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(IggyFile.class.getName()).log(Level.SEVERE, "Error during updating SWF", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
long offsetsChange = 0;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
long oldSize = entry.size;
|
||||
long newSize = replacementData.length;
|
||||
entry.size = newSize;
|
||||
entry.size2 = newSize;
|
||||
offsetsChange = offsetsChange + (newSize - oldSize); //entries after this one will have modified offsets
|
||||
subFileEntriesData.set(i, replacementData);
|
||||
}
|
||||
}
|
||||
|
||||
removeIndexEntries();
|
||||
IggySubFileEntry indexEntry = new IggySubFileEntry(IggySubFileEntry.TYPE_INDEX, replacementIndexData.length, replacementIndexData.length, 0 /*offset will be set automatically*/);
|
||||
subFileEntries.add(indexEntry);
|
||||
subFileEntriesData.add(replacementIndexData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseEntries() throws IOException {
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
iggySwf = new IggySwf(new TemporaryDataStream(getEntryData(i)));
|
||||
break;
|
||||
}
|
||||
/*if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
IggyIndexParser.parseIndex(true, new TemporaryDataStream(getEntryData(i)), new ArrayList<>(), new ArrayList<>());
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface stream) throws IOException {
|
||||
header = new IggyHeader(stream);
|
||||
if (!header.is64()) {
|
||||
throw new IOException("32 bit iggy files are not (yet) supported, sorry");
|
||||
}
|
||||
for (int i = 0; i < header.getNumSubfiles(); i++) {
|
||||
subFileEntries.add(new IggySubFileEntry(stream));
|
||||
}
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
stream.seek(entry.offset, SeekMode.SET);
|
||||
byte[] entryData = stream.readBytes((int) entry.size);
|
||||
subFileEntriesData.add(entryData);
|
||||
}
|
||||
parseEntries();
|
||||
}
|
||||
|
||||
public void saveChanges() throws IOException {
|
||||
updateFlashEntry();
|
||||
try (RandomAccessFileDataStream raf = new RandomAccessFileDataStream(originalFile)) {
|
||||
writeToDataStream(raf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
|
||||
header.writeToDataStream(stream);
|
||||
|
||||
long startOffset = IggyHeader.STRUCT_SIZE + IggySubFileEntry.STRUCTURE_SIZE * subFileEntries.size();
|
||||
long currentOffset = startOffset;
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset = currentOffset;
|
||||
currentOffset += entry.size;
|
||||
entry.writeToDataStream(stream);
|
||||
}
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
byte[] entryData = subFileEntriesData.get(i);
|
||||
stream.writeBytes(entryData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*
|
||||
* Based of works of somebody called eternity.
|
||||
*
|
||||
*/
|
||||
public class IggyFile implements StructureInterface {
|
||||
|
||||
final static Logger LOGGER = Logger.getLogger(IggyFile.class.getName());
|
||||
|
||||
private File originalFile;
|
||||
private IggyHeader header;
|
||||
private List<IggySubFileEntry> subFileEntries = new ArrayList<>();
|
||||
private List<byte[]> subFileEntriesData = new ArrayList<>();
|
||||
|
||||
private IggySwf iggySwf;
|
||||
|
||||
public static final int FIRST_TAG_POSITION = 3;
|
||||
|
||||
public IggySwf getSwf() {
|
||||
return iggySwf;
|
||||
}
|
||||
|
||||
public IggyFile(String filePath) throws IOException {
|
||||
this(new File(filePath));
|
||||
}
|
||||
|
||||
public IggyFile(File file) throws IOException {
|
||||
this.originalFile = file;
|
||||
try (ReadDataStreamInterface stream = new RandomAccessFileDataStream(file)) {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public File getOriginalFile() {
|
||||
return originalFile;
|
||||
}
|
||||
|
||||
public IggyHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public IggySubFileEntry getSubFileEntry(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntries.get(entryIndex);
|
||||
}
|
||||
|
||||
public int getNumEntries() {
|
||||
return subFileEntries.size();
|
||||
}
|
||||
|
||||
public byte[] getEntryData(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntriesData.get(entryIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[IggyFile:").append("\r\n");
|
||||
sb.append(header).append("\r\n");
|
||||
sb.append("Entries:").append("\r\n");
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
sb.append(entry).append("\r\n");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void extractIggyFile(File iggyFile, File extractDir) throws IOException {
|
||||
final String FILENAME_FORMAT = "index%d_type%d.bin";
|
||||
IggyFile ir = new IggyFile(iggyFile);
|
||||
for (int i = 0; i < ir.getNumEntries(); i++) {
|
||||
IggySubFileEntry entry = ir.getSubFileEntry(i);
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(extractDir, String.format(FILENAME_FORMAT, i, entry.type)))) {
|
||||
fos.write(ir.getEntryData(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getSwfName() {
|
||||
return iggySwf.getName();
|
||||
}
|
||||
|
||||
public long getSwfXMin() {
|
||||
return iggySwf.getHdr().getXMin();
|
||||
}
|
||||
|
||||
public long getSwfYMin() {
|
||||
return iggySwf.getHdr().getYMin();
|
||||
}
|
||||
|
||||
public long getSwfXMax() {
|
||||
return iggySwf.getHdr().getXMax();
|
||||
}
|
||||
|
||||
public long getSwfYMax() {
|
||||
return iggySwf.getHdr().getYMax();
|
||||
}
|
||||
|
||||
public float getSwfFrameRate() {
|
||||
return iggySwf.getHdr().getFrameRate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes entries of type INDEX.There can be more than one INDEX,
|
||||
* continuous. This removes all ot them.
|
||||
*/
|
||||
public void removeIndexEntries() {
|
||||
long offsetsChange = 0;
|
||||
final int ENTRY_SIZE = 16;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
offsetsChange = offsetsChange - entry.size - ENTRY_SIZE;
|
||||
subFileEntriesData.remove(i);
|
||||
subFileEntries.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateFlashEntry() throws IOException {
|
||||
|
||||
byte replacementData[];
|
||||
byte replacementIndexData[];
|
||||
IggyIndexBuilder ib = new IggyIndexBuilder();
|
||||
try (DataStreamInterface stream = new TemporaryDataStream()) {
|
||||
stream.setIndexing(ib);
|
||||
iggySwf.writeToDataStream(stream);
|
||||
replacementData = stream.getAllBytes();
|
||||
replacementIndexData = ib.getIndexBytes();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(IggyFile.class.getName()).log(Level.SEVERE, "Error during updating SWF", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
long offsetsChange = 0;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
long oldSize = entry.size;
|
||||
long newSize = replacementData.length;
|
||||
entry.size = newSize;
|
||||
entry.size2 = newSize;
|
||||
offsetsChange = offsetsChange + (newSize - oldSize); //entries after this one will have modified offsets
|
||||
subFileEntriesData.set(i, replacementData);
|
||||
}
|
||||
}
|
||||
|
||||
removeIndexEntries();
|
||||
IggySubFileEntry indexEntry = new IggySubFileEntry(IggySubFileEntry.TYPE_INDEX, replacementIndexData.length, replacementIndexData.length, 0 /*offset will be set automatically*/);
|
||||
subFileEntries.add(indexEntry);
|
||||
subFileEntriesData.add(replacementIndexData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseEntries() throws IOException {
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
iggySwf = new IggySwf(new TemporaryDataStream(getEntryData(i)));
|
||||
break;
|
||||
}
|
||||
/*if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
IggyIndexParser.parseIndex(true, new TemporaryDataStream(getEntryData(i)), new ArrayList<>(), new ArrayList<>());
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface stream) throws IOException {
|
||||
header = new IggyHeader(stream);
|
||||
if (!header.is64()) {
|
||||
throw new IOException("32 bit iggy files are not (yet) supported, sorry");
|
||||
}
|
||||
for (int i = 0; i < header.getNumSubfiles(); i++) {
|
||||
subFileEntries.add(new IggySubFileEntry(stream));
|
||||
}
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
stream.seek(entry.offset, SeekMode.SET);
|
||||
byte[] entryData = stream.readBytes((int) entry.size);
|
||||
subFileEntriesData.add(entryData);
|
||||
}
|
||||
parseEntries();
|
||||
}
|
||||
|
||||
public void saveChanges() throws IOException {
|
||||
updateFlashEntry();
|
||||
try (RandomAccessFileDataStream raf = new RandomAccessFileDataStream(originalFile)) {
|
||||
writeToDataStream(raf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
|
||||
header.writeToDataStream(stream);
|
||||
|
||||
long startOffset = IggyHeader.STRUCT_SIZE + IggySubFileEntry.STRUCTURE_SIZE * subFileEntries.size();
|
||||
long currentOffset = startOffset;
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset = currentOffset;
|
||||
currentOffset += entry.size;
|
||||
entry.writeToDataStream(stream);
|
||||
}
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
byte[] entryData = subFileEntriesData.get(i);
|
||||
stream.writeBytes(entryData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,339 +1,339 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwf implements StructureInterface {
|
||||
|
||||
final static int NO_OFFSET = 1;
|
||||
|
||||
@IggyFieldType(value = DataType.wchar_t, count = 48)
|
||||
String name;
|
||||
|
||||
private List<IggyFont> fonts = new ArrayList<>();
|
||||
// private List<Long> font_data_addresses = new ArrayList<>();
|
||||
private List<IggyFont> add_fonts = new ArrayList<>();
|
||||
// private List<Long> add_font_data_addresses = new ArrayList<>();
|
||||
|
||||
private IggyFlashHeader64 hdr;
|
||||
|
||||
public IggySwf(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
private List<IggyText> texts = new ArrayList<>();
|
||||
//private List<Long> text_data_addresses = new ArrayList<>();
|
||||
private List<IggyText> add_texts = new ArrayList<>();
|
||||
//private List<Long> add_text_data_addresses = new ArrayList<>();
|
||||
|
||||
//private byte font_add_data[];
|
||||
//private List<Long> font_additional_size = new ArrayList<>();
|
||||
private IggyFontBinInfo font_bin_info[];
|
||||
private List<String> sequenceNames = new ArrayList<>();
|
||||
//private List<Long> sequenceValues = new ArrayList<>();
|
||||
|
||||
private IggyFontTypeInfo type_info[];
|
||||
private String type_info_name[];
|
||||
private IggyDeclStrings decl_strings;
|
||||
private long ofs_additional;
|
||||
private long additional_address;
|
||||
|
||||
public IggyFlashHeader64 getHdr() {
|
||||
return hdr;
|
||||
}
|
||||
|
||||
public List<IggyFont> getFonts() {
|
||||
return fonts;
|
||||
}
|
||||
|
||||
public List<IggyFont> getAddFonts() {
|
||||
return add_fonts;
|
||||
}
|
||||
|
||||
public List<IggyText> getTexts() {
|
||||
return texts;
|
||||
}
|
||||
|
||||
public List<IggyText> getAddTexts() {
|
||||
return add_texts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
this.hdr = new IggyFlashHeader64(s);
|
||||
//Save all font bytes to buffer for later easy modification
|
||||
//here is offset[0] - 184
|
||||
name = s.readWChar();
|
||||
//here is offset[1] - 230
|
||||
int pad8 = 8 - (int) (s.position() % 8);
|
||||
if (pad8 > 8) {
|
||||
s.seek(pad8, SeekMode.CUR);
|
||||
}
|
||||
//here is offset [2] - 232
|
||||
s.seek(hdr.getBaseAddress(), SeekMode.SET);
|
||||
s.readUI64(); //pad 1
|
||||
|
||||
List<Long> itemsAddresses = new ArrayList<>();
|
||||
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
itemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
if (hdr.getImported_guid() != 0) {
|
||||
ofs_additional = s.readUI64();
|
||||
additional_address = ofs_additional == 1 ? 0 : ofs_additional + s.position() - 8;
|
||||
}
|
||||
for (Long addr : itemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//font_data_addresses.add(addr);
|
||||
fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//text_data_addresses.add(addr);
|
||||
texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown item kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
if (additional_address != 0) {
|
||||
s.seek(additional_address, SeekMode.SET);
|
||||
List<Long> additionalItemsAddresses = new ArrayList<>();
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
additionalItemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
for (Long addr : additionalItemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//add_font_data_addresses.add(addr);
|
||||
add_fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//add_text_data_addresses.add(addr);
|
||||
add_texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown imported item kind: " + kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
|
||||
//here is offset [4] - 856 ?
|
||||
font_bin_info = new IggyFontBinInfo[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i] = new IggyFontBinInfo(s);
|
||||
}
|
||||
|
||||
sequenceNames = new ArrayList<>();
|
||||
|
||||
long seq_addresses[] = new long[]{hdr.getSequenceStartAddress1(), hdr.getSequenceStartAddress2(), hdr.getSequenceStartAddress3()};
|
||||
long seq_name_addresses[] = new long[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_addresses[i] == 0) {
|
||||
seq_name_addresses[i] = 0;
|
||||
//0
|
||||
} else {
|
||||
s.seek(seq_addresses[i], SeekMode.SET);
|
||||
long ofs_seq_name = s.readUI64();
|
||||
seq_name_addresses[i] = ofs_seq_name == 1 ? 0 : ofs_seq_name + s.position() - 8;
|
||||
s.readUI64(); //is this crucial?
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_name_addresses[i] > 0) {
|
||||
s.seek(seq_name_addresses[i], SeekMode.SET);
|
||||
sequenceNames.add(s.readWChar());
|
||||
} else {
|
||||
sequenceNames.add(null);
|
||||
}
|
||||
}
|
||||
s.pad8bytes();
|
||||
|
||||
//sequence = new IggySequence(s);
|
||||
s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
type_info = new IggyFontTypeInfo[(int) hdr.font_count];
|
||||
type_info_name = new String[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i] = new IggyFontTypeInfo(s);
|
||||
}
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
s.seek(type_info[i].getLocal_name_ofs_pos() + type_info[i].ofs_local_name, SeekMode.SET);
|
||||
type_info_name[i] = s.readWChar();
|
||||
}
|
||||
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings = new IggyDeclStrings(s);
|
||||
/*WriteDataStreamInterface outs = new TemporaryDataStream();
|
||||
writeToDataStream(outs);
|
||||
Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());*/
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
IggyIndexBuilder ib = s.getIndexing();
|
||||
hdr.writeToDataStream(s);
|
||||
s.writeWChar(name);
|
||||
s.pad8bytes();
|
||||
s.writeUI64(1);
|
||||
ib.write16bitArray(name.length() + 1);
|
||||
ib.writeTwoPaddingBytes();
|
||||
ib.write64bitPointerArray(64);
|
||||
long posBeforeOffsets = s.position();
|
||||
|
||||
final int FILL_LATER = 1;
|
||||
|
||||
List<Long> fontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
fontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> textPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
textPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(1);
|
||||
|
||||
long addPosFillLater = s.position();
|
||||
s.writeUI64(FILL_LATER);
|
||||
long posAfter = posBeforeOffsets + 64 * 8;
|
||||
long curPos = s.position();
|
||||
long numLeft = posAfter - curPos;
|
||||
long ofsLeft = numLeft / 8;
|
||||
for (int i = 0; i < ofsLeft - 1; i++) {
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(fontPosFillLater.get(i));
|
||||
fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(textPosFillLater.get(i));
|
||||
texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
|
||||
if (!add_fonts.isEmpty() || !add_texts.isEmpty()) {
|
||||
s.setOlderOffsetToThisPos(addPosFillLater);
|
||||
|
||||
List<Long> addFontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
addFontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> addTextPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
addTextPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(FILL_LATER);
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addFontPosFillLater.get(i));
|
||||
add_fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addTextPosFillLater.get(i));
|
||||
add_texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getFont_end_ofs_pos());
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_BIN_INFO_SIZE, hdr.font_count);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
long seq_ofs_pos[] = new long[]{hdr.getSequence_start1_ofs_pos(), hdr.getSequence_start2_ofs_pos(), hdr.getSequence_start3_ofs_pos()};
|
||||
long off_seq_expected[] = new long[]{hdr.off_sequence_start1, hdr.off_sequence_start2, hdr.off_sequence_start3};
|
||||
|
||||
long seq_name_fill_later[] = new long[3];
|
||||
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[0]);
|
||||
s.writeUI64(1);
|
||||
s.writeUI64(1);
|
||||
ib.writeLengthCustom(16, new int[]{0}, new int[]{2});
|
||||
|
||||
seq_name_fill_later[2] = s.position();
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[2]);
|
||||
s.writeUI64(FILL_LATER);
|
||||
s.writeUI64(0);
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (sequenceNames.get(i) != null) {
|
||||
s.setOlderOffsetToThisPos(seq_name_fill_later[i]);
|
||||
ib.write16bitArray(sequenceNames.get(i).length() + 1);
|
||||
s.writeWChar(sequenceNames.get(i));
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getSequence_end_ofs_pos());
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_TYPE_INFO_SIZE, hdr.font_count);
|
||||
s.setOlderOffsetToThisPos(hdr.getType_fonts_ofs_pos());
|
||||
//s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
ib.write16bitArray(type_info_name[i].length() + 1);
|
||||
s.setOlderOffsetToThisPos(type_info[i].getLocal_name_ofs_pos());
|
||||
s.writeWChar(type_info_name[i]);
|
||||
}
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
s.setOlderOffsetToThisPos(hdr.getDecl_strings_ofs_pos());
|
||||
//s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings.writeToDataStream(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[\r\n");
|
||||
sb.append("name ").append(name).append("\r\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public IggyDeclStrings getDeclStrings() {
|
||||
return decl_strings;
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwf implements StructureInterface {
|
||||
|
||||
final static int NO_OFFSET = 1;
|
||||
|
||||
@IggyFieldType(value = DataType.wchar_t, count = 48)
|
||||
String name;
|
||||
|
||||
private List<IggyFont> fonts = new ArrayList<>();
|
||||
// private List<Long> font_data_addresses = new ArrayList<>();
|
||||
private List<IggyFont> add_fonts = new ArrayList<>();
|
||||
// private List<Long> add_font_data_addresses = new ArrayList<>();
|
||||
|
||||
private IggyFlashHeader64 hdr;
|
||||
|
||||
public IggySwf(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
private List<IggyText> texts = new ArrayList<>();
|
||||
//private List<Long> text_data_addresses = new ArrayList<>();
|
||||
private List<IggyText> add_texts = new ArrayList<>();
|
||||
//private List<Long> add_text_data_addresses = new ArrayList<>();
|
||||
|
||||
//private byte font_add_data[];
|
||||
//private List<Long> font_additional_size = new ArrayList<>();
|
||||
private IggyFontBinInfo font_bin_info[];
|
||||
private List<String> sequenceNames = new ArrayList<>();
|
||||
//private List<Long> sequenceValues = new ArrayList<>();
|
||||
|
||||
private IggyFontTypeInfo type_info[];
|
||||
private String type_info_name[];
|
||||
private IggyDeclStrings decl_strings;
|
||||
private long ofs_additional;
|
||||
private long additional_address;
|
||||
|
||||
public IggyFlashHeader64 getHdr() {
|
||||
return hdr;
|
||||
}
|
||||
|
||||
public List<IggyFont> getFonts() {
|
||||
return fonts;
|
||||
}
|
||||
|
||||
public List<IggyFont> getAddFonts() {
|
||||
return add_fonts;
|
||||
}
|
||||
|
||||
public List<IggyText> getTexts() {
|
||||
return texts;
|
||||
}
|
||||
|
||||
public List<IggyText> getAddTexts() {
|
||||
return add_texts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
this.hdr = new IggyFlashHeader64(s);
|
||||
//Save all font bytes to buffer for later easy modification
|
||||
//here is offset[0] - 184
|
||||
name = s.readWChar();
|
||||
//here is offset[1] - 230
|
||||
int pad8 = 8 - (int) (s.position() % 8);
|
||||
if (pad8 > 8) {
|
||||
s.seek(pad8, SeekMode.CUR);
|
||||
}
|
||||
//here is offset [2] - 232
|
||||
s.seek(hdr.getBaseAddress(), SeekMode.SET);
|
||||
s.readUI64(); //pad 1
|
||||
|
||||
List<Long> itemsAddresses = new ArrayList<>();
|
||||
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
itemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
if (hdr.getImported_guid() != 0) {
|
||||
ofs_additional = s.readUI64();
|
||||
additional_address = ofs_additional == 1 ? 0 : ofs_additional + s.position() - 8;
|
||||
}
|
||||
for (Long addr : itemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//font_data_addresses.add(addr);
|
||||
fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//text_data_addresses.add(addr);
|
||||
texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown item kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
if (additional_address != 0) {
|
||||
s.seek(additional_address, SeekMode.SET);
|
||||
List<Long> additionalItemsAddresses = new ArrayList<>();
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
additionalItemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
for (Long addr : additionalItemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//add_font_data_addresses.add(addr);
|
||||
add_fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//add_text_data_addresses.add(addr);
|
||||
add_texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown imported item kind: " + kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
|
||||
//here is offset [4] - 856 ?
|
||||
font_bin_info = new IggyFontBinInfo[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i] = new IggyFontBinInfo(s);
|
||||
}
|
||||
|
||||
sequenceNames = new ArrayList<>();
|
||||
|
||||
long seq_addresses[] = new long[]{hdr.getSequenceStartAddress1(), hdr.getSequenceStartAddress2(), hdr.getSequenceStartAddress3()};
|
||||
long seq_name_addresses[] = new long[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_addresses[i] == 0) {
|
||||
seq_name_addresses[i] = 0;
|
||||
//0
|
||||
} else {
|
||||
s.seek(seq_addresses[i], SeekMode.SET);
|
||||
long ofs_seq_name = s.readUI64();
|
||||
seq_name_addresses[i] = ofs_seq_name == 1 ? 0 : ofs_seq_name + s.position() - 8;
|
||||
s.readUI64(); //is this crucial?
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_name_addresses[i] > 0) {
|
||||
s.seek(seq_name_addresses[i], SeekMode.SET);
|
||||
sequenceNames.add(s.readWChar());
|
||||
} else {
|
||||
sequenceNames.add(null);
|
||||
}
|
||||
}
|
||||
s.pad8bytes();
|
||||
|
||||
//sequence = new IggySequence(s);
|
||||
s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
type_info = new IggyFontTypeInfo[(int) hdr.font_count];
|
||||
type_info_name = new String[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i] = new IggyFontTypeInfo(s);
|
||||
}
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
s.seek(type_info[i].getLocal_name_ofs_pos() + type_info[i].ofs_local_name, SeekMode.SET);
|
||||
type_info_name[i] = s.readWChar();
|
||||
}
|
||||
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings = new IggyDeclStrings(s);
|
||||
/*WriteDataStreamInterface outs = new TemporaryDataStream();
|
||||
writeToDataStream(outs);
|
||||
Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());*/
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
IggyIndexBuilder ib = s.getIndexing();
|
||||
hdr.writeToDataStream(s);
|
||||
s.writeWChar(name);
|
||||
s.pad8bytes();
|
||||
s.writeUI64(1);
|
||||
ib.write16bitArray(name.length() + 1);
|
||||
ib.writeTwoPaddingBytes();
|
||||
ib.write64bitPointerArray(64);
|
||||
long posBeforeOffsets = s.position();
|
||||
|
||||
final int FILL_LATER = 1;
|
||||
|
||||
List<Long> fontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
fontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> textPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
textPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(1);
|
||||
|
||||
long addPosFillLater = s.position();
|
||||
s.writeUI64(FILL_LATER);
|
||||
long posAfter = posBeforeOffsets + 64 * 8;
|
||||
long curPos = s.position();
|
||||
long numLeft = posAfter - curPos;
|
||||
long ofsLeft = numLeft / 8;
|
||||
for (int i = 0; i < ofsLeft - 1; i++) {
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(fontPosFillLater.get(i));
|
||||
fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(textPosFillLater.get(i));
|
||||
texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
|
||||
if (!add_fonts.isEmpty() || !add_texts.isEmpty()) {
|
||||
s.setOlderOffsetToThisPos(addPosFillLater);
|
||||
|
||||
List<Long> addFontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
addFontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> addTextPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
addTextPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(FILL_LATER);
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addFontPosFillLater.get(i));
|
||||
add_fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addTextPosFillLater.get(i));
|
||||
add_texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getFont_end_ofs_pos());
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_BIN_INFO_SIZE, hdr.font_count);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
long seq_ofs_pos[] = new long[]{hdr.getSequence_start1_ofs_pos(), hdr.getSequence_start2_ofs_pos(), hdr.getSequence_start3_ofs_pos()};
|
||||
long off_seq_expected[] = new long[]{hdr.off_sequence_start1, hdr.off_sequence_start2, hdr.off_sequence_start3};
|
||||
|
||||
long seq_name_fill_later[] = new long[3];
|
||||
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[0]);
|
||||
s.writeUI64(1);
|
||||
s.writeUI64(1);
|
||||
ib.writeLengthCustom(16, new int[]{0}, new int[]{2});
|
||||
|
||||
seq_name_fill_later[2] = s.position();
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[2]);
|
||||
s.writeUI64(FILL_LATER);
|
||||
s.writeUI64(0);
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (sequenceNames.get(i) != null) {
|
||||
s.setOlderOffsetToThisPos(seq_name_fill_later[i]);
|
||||
ib.write16bitArray(sequenceNames.get(i).length() + 1);
|
||||
s.writeWChar(sequenceNames.get(i));
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getSequence_end_ofs_pos());
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_TYPE_INFO_SIZE, hdr.font_count);
|
||||
s.setOlderOffsetToThisPos(hdr.getType_fonts_ofs_pos());
|
||||
//s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
ib.write16bitArray(type_info_name[i].length() + 1);
|
||||
s.setOlderOffsetToThisPos(type_info[i].getLocal_name_ofs_pos());
|
||||
s.writeWChar(type_info_name[i]);
|
||||
}
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
s.setOlderOffsetToThisPos(hdr.getDecl_strings_ofs_pos());
|
||||
//s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings.writeToDataStream(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[\r\n");
|
||||
sb.append("name ").append(name).append("\r\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public IggyDeclStrings getDeclStrings() {
|
||||
return decl_strings;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,198 +1,198 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyText implements StructureInterface {
|
||||
|
||||
public static final int STRUCT_SIZE = 104;
|
||||
|
||||
public static final int ID = 0xFF06;
|
||||
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int type; // Tag type
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int textIndex;
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, count = 28)
|
||||
byte zeroone[];
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par1;
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par2;
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par3;
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par4;
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int enum_hex;
|
||||
|
||||
//Guessed
|
||||
boolean hasText;
|
||||
boolean wordWrap;
|
||||
boolean multiline;
|
||||
boolean password;
|
||||
boolean readOnly;
|
||||
boolean hasTextColor;
|
||||
boolean hasMaxLength;
|
||||
boolean hasFont;
|
||||
boolean hasFontClass;
|
||||
boolean autosize;
|
||||
boolean hasLayout;
|
||||
boolean noSelect;
|
||||
boolean border;
|
||||
boolean wasStatic;
|
||||
boolean html;
|
||||
boolean useOutlines;
|
||||
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int fontIndex;
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long zero;
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long one;
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, count = 32)
|
||||
byte[] some; // same for different fonts
|
||||
long ofs_name;
|
||||
|
||||
@IggyArrayFieldType(value = DataType.wchar_t)
|
||||
String initialText; //till end of info file?
|
||||
|
||||
public IggyText(int type, int order_in_iggy_file, byte[] zeroone, float par1, float par2, float par3, float par4, int enum_hex, int for_which_font_order_in_iggyfile, long zero, long one, byte[] some, long offset_of_name, String name) {
|
||||
this.type = type;
|
||||
this.textIndex = order_in_iggy_file;
|
||||
this.zeroone = zeroone;
|
||||
this.par1 = par1;
|
||||
this.par2 = par2;
|
||||
this.par3 = par3;
|
||||
this.par4 = par4;
|
||||
this.enum_hex = enum_hex;
|
||||
this.fontIndex = for_which_font_order_in_iggyfile;
|
||||
this.zero = zero;
|
||||
this.one = one;
|
||||
this.some = some;
|
||||
this.initialText = name;
|
||||
}
|
||||
|
||||
public IggyText(ReadDataStreamInterface stream) throws IOException {
|
||||
this.readFromDataStream(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
|
||||
type = s.readUI16();
|
||||
//characterId - iggy Id
|
||||
textIndex = s.readUI16();
|
||||
zeroone = s.readBytes(28);
|
||||
|
||||
//bounds?:
|
||||
par1 = s.readFloat();
|
||||
par2 = s.readFloat();
|
||||
par3 = s.readFloat();
|
||||
par4 = s.readFloat();
|
||||
|
||||
enum_hex = s.readUI16();
|
||||
fontIndex = s.readUI16(); //fontId
|
||||
zero = s.readUI32();
|
||||
one = s.readUI64(); //01CB FF33 3333
|
||||
some = s.readBytes(32); // [6] => 40, [24] => 8
|
||||
ofs_name = s.readUI64();
|
||||
long name_address = ofs_name + s.position() - 8;
|
||||
s.seek(name_address, SeekMode.SET);
|
||||
initialText = s.readWChar();
|
||||
s.pad8bytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_TEXT_DATA_SIZE);
|
||||
s.writeUI16(type);
|
||||
s.writeUI16(textIndex);
|
||||
s.writeBytes(zeroone);
|
||||
s.writeFloat(par1);
|
||||
s.writeFloat(par2);
|
||||
s.writeFloat(par3);
|
||||
s.writeFloat(par4);
|
||||
s.writeUI16(enum_hex);
|
||||
s.writeUI16(fontIndex);
|
||||
s.writeUI32(zero);
|
||||
s.writeUI64(one);
|
||||
s.writeBytes(some);
|
||||
s.writeUI64(ofs_name);
|
||||
long name_address = ofs_name + s.position() - 8;
|
||||
s.seek(name_address, SeekMode.SET);
|
||||
s.writeWChar(initialText);
|
||||
s.pad8bytes();
|
||||
|
||||
s.getIndexing().write16bitArray(initialText.length() + 1);
|
||||
s.getIndexing().pad8bytes();
|
||||
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getTextIndex() {
|
||||
return textIndex;
|
||||
}
|
||||
|
||||
public byte[] getZeroone() {
|
||||
return zeroone;
|
||||
}
|
||||
|
||||
public float getPar1() {
|
||||
return par1;
|
||||
}
|
||||
|
||||
public float getPar2() {
|
||||
return par2;
|
||||
}
|
||||
|
||||
public float getPar3() {
|
||||
return par3;
|
||||
}
|
||||
|
||||
public float getPar4() {
|
||||
return par4;
|
||||
}
|
||||
|
||||
public int getEnum_hex() {
|
||||
return enum_hex;
|
||||
}
|
||||
|
||||
public int getFontIndex() {
|
||||
return fontIndex;
|
||||
}
|
||||
|
||||
public long getZero() {
|
||||
return zero;
|
||||
}
|
||||
|
||||
public long getOne() {
|
||||
return one;
|
||||
}
|
||||
|
||||
public byte[] getSome() {
|
||||
return some;
|
||||
}
|
||||
|
||||
public String getInitialText() {
|
||||
return initialText;
|
||||
}
|
||||
|
||||
public void setInitialText(String initialText) {
|
||||
this.initialText = initialText;
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyText implements StructureInterface {
|
||||
|
||||
public static final int STRUCT_SIZE = 104;
|
||||
|
||||
public static final int ID = 0xFF06;
|
||||
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int type; // Tag type
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int textIndex;
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, count = 28)
|
||||
byte zeroone[];
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par1;
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par2;
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par3;
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float par4;
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int enum_hex;
|
||||
|
||||
//Guessed
|
||||
boolean hasText;
|
||||
boolean wordWrap;
|
||||
boolean multiline;
|
||||
boolean password;
|
||||
boolean readOnly;
|
||||
boolean hasTextColor;
|
||||
boolean hasMaxLength;
|
||||
boolean hasFont;
|
||||
boolean hasFontClass;
|
||||
boolean autosize;
|
||||
boolean hasLayout;
|
||||
boolean noSelect;
|
||||
boolean border;
|
||||
boolean wasStatic;
|
||||
boolean html;
|
||||
boolean useOutlines;
|
||||
|
||||
@IggyFieldType(DataType.uint16_t)
|
||||
int fontIndex;
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long zero;
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long one;
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, count = 32)
|
||||
byte[] some; // same for different fonts
|
||||
long ofs_name;
|
||||
|
||||
@IggyArrayFieldType(value = DataType.wchar_t)
|
||||
String initialText; //till end of info file?
|
||||
|
||||
public IggyText(int type, int order_in_iggy_file, byte[] zeroone, float par1, float par2, float par3, float par4, int enum_hex, int for_which_font_order_in_iggyfile, long zero, long one, byte[] some, long offset_of_name, String name) {
|
||||
this.type = type;
|
||||
this.textIndex = order_in_iggy_file;
|
||||
this.zeroone = zeroone;
|
||||
this.par1 = par1;
|
||||
this.par2 = par2;
|
||||
this.par3 = par3;
|
||||
this.par4 = par4;
|
||||
this.enum_hex = enum_hex;
|
||||
this.fontIndex = for_which_font_order_in_iggyfile;
|
||||
this.zero = zero;
|
||||
this.one = one;
|
||||
this.some = some;
|
||||
this.initialText = name;
|
||||
}
|
||||
|
||||
public IggyText(ReadDataStreamInterface stream) throws IOException {
|
||||
this.readFromDataStream(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
|
||||
type = s.readUI16();
|
||||
//characterId - iggy Id
|
||||
textIndex = s.readUI16();
|
||||
zeroone = s.readBytes(28);
|
||||
|
||||
//bounds?:
|
||||
par1 = s.readFloat();
|
||||
par2 = s.readFloat();
|
||||
par3 = s.readFloat();
|
||||
par4 = s.readFloat();
|
||||
|
||||
enum_hex = s.readUI16();
|
||||
fontIndex = s.readUI16(); //fontId
|
||||
zero = s.readUI32();
|
||||
one = s.readUI64(); //01CB FF33 3333
|
||||
some = s.readBytes(32); // [6] => 40, [24] => 8
|
||||
ofs_name = s.readUI64();
|
||||
long name_address = ofs_name + s.position() - 8;
|
||||
s.seek(name_address, SeekMode.SET);
|
||||
initialText = s.readWChar();
|
||||
s.pad8bytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_TEXT_DATA_SIZE);
|
||||
s.writeUI16(type);
|
||||
s.writeUI16(textIndex);
|
||||
s.writeBytes(zeroone);
|
||||
s.writeFloat(par1);
|
||||
s.writeFloat(par2);
|
||||
s.writeFloat(par3);
|
||||
s.writeFloat(par4);
|
||||
s.writeUI16(enum_hex);
|
||||
s.writeUI16(fontIndex);
|
||||
s.writeUI32(zero);
|
||||
s.writeUI64(one);
|
||||
s.writeBytes(some);
|
||||
s.writeUI64(ofs_name);
|
||||
long name_address = ofs_name + s.position() - 8;
|
||||
s.seek(name_address, SeekMode.SET);
|
||||
s.writeWChar(initialText);
|
||||
s.pad8bytes();
|
||||
|
||||
s.getIndexing().write16bitArray(initialText.length() + 1);
|
||||
s.getIndexing().pad8bytes();
|
||||
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getTextIndex() {
|
||||
return textIndex;
|
||||
}
|
||||
|
||||
public byte[] getZeroone() {
|
||||
return zeroone;
|
||||
}
|
||||
|
||||
public float getPar1() {
|
||||
return par1;
|
||||
}
|
||||
|
||||
public float getPar2() {
|
||||
return par2;
|
||||
}
|
||||
|
||||
public float getPar3() {
|
||||
return par3;
|
||||
}
|
||||
|
||||
public float getPar4() {
|
||||
return par4;
|
||||
}
|
||||
|
||||
public int getEnum_hex() {
|
||||
return enum_hex;
|
||||
}
|
||||
|
||||
public int getFontIndex() {
|
||||
return fontIndex;
|
||||
}
|
||||
|
||||
public long getZero() {
|
||||
return zero;
|
||||
}
|
||||
|
||||
public long getOne() {
|
||||
return one;
|
||||
}
|
||||
|
||||
public byte[] getSome() {
|
||||
return some;
|
||||
}
|
||||
|
||||
public String getInitialText() {
|
||||
return initialText;
|
||||
}
|
||||
|
||||
public void setInitialText(String initialText) {
|
||||
this.initialText = initialText;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.MemoryInputStream;
|
||||
import com.jpexs.helpers.ReReadableInputStream;
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwfBundle implements SWFBundle {
|
||||
|
||||
private IggyFile iggyFile;
|
||||
|
||||
public IggySwfBundle(InputStream is) throws IOException {
|
||||
this(is, null);
|
||||
}
|
||||
|
||||
public IggySwfBundle(File filename) throws IOException {
|
||||
this(null, filename);
|
||||
}
|
||||
|
||||
protected IggySwfBundle(InputStream is, File filename) throws IOException {
|
||||
initBundle(is, filename);
|
||||
}
|
||||
|
||||
protected void initBundle(InputStream is, File filename) throws IOException {
|
||||
if (filename == null) {
|
||||
filename = File.createTempFile("bundle", ".iggy");
|
||||
Helper.saveStream(is, filename);
|
||||
}
|
||||
iggyFile = new IggyFile(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> ret = new TreeSet<>();
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ret.add(iggyFile.getSwfName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int keyToSwfIndex(String key) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (key.equals(iggyFile.getSwfName())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Key " + key + " does not exist!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableInputStream getSWF(String key) throws IOException {
|
||||
SWF swf = IggyToSwfConvertor.getSwf(iggyFile);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
swf.saveTo(baos);
|
||||
MemoryInputStream mis = new MemoryInputStream(baos.toByteArray());
|
||||
return mis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, SeekableInputStream> getAll() throws IOException {
|
||||
Map<String, SeekableInputStream> ret = new HashMap<>();
|
||||
for (String key : getKeys()) {
|
||||
ret.put(key, getSWF(key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "iggy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putSWF(String key, InputStream is) throws IOException {
|
||||
try {
|
||||
SWF swf = new SWF(is, false, false);
|
||||
SwfToIggyConvertor.updateIggy(iggyFile.getSwf(), swf);
|
||||
iggyFile.saveChanges();
|
||||
return true;
|
||||
} catch (InterruptedException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.MemoryInputStream;
|
||||
import com.jpexs.helpers.ReReadableInputStream;
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwfBundle implements SWFBundle {
|
||||
|
||||
private IggyFile iggyFile;
|
||||
|
||||
public IggySwfBundle(InputStream is) throws IOException {
|
||||
this(is, null);
|
||||
}
|
||||
|
||||
public IggySwfBundle(File filename) throws IOException {
|
||||
this(null, filename);
|
||||
}
|
||||
|
||||
protected IggySwfBundle(InputStream is, File filename) throws IOException {
|
||||
initBundle(is, filename);
|
||||
}
|
||||
|
||||
protected void initBundle(InputStream is, File filename) throws IOException {
|
||||
if (filename == null) {
|
||||
filename = File.createTempFile("bundle", ".iggy");
|
||||
Helper.saveStream(is, filename);
|
||||
}
|
||||
iggyFile = new IggyFile(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> ret = new TreeSet<>();
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ret.add(iggyFile.getSwfName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int keyToSwfIndex(String key) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (key.equals(iggyFile.getSwfName())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Key " + key + " does not exist!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableInputStream getSWF(String key) throws IOException {
|
||||
SWF swf = IggyToSwfConvertor.getSwf(iggyFile);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
swf.saveTo(baos);
|
||||
MemoryInputStream mis = new MemoryInputStream(baos.toByteArray());
|
||||
return mis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, SeekableInputStream> getAll() throws IOException {
|
||||
Map<String, SeekableInputStream> ret = new HashMap<>();
|
||||
for (String key : getKeys()) {
|
||||
ret.put(key, getSWF(key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "iggy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putSWF(String key, InputStream is) throws IOException {
|
||||
try {
|
||||
SWF swf = new SWF(is, false, false);
|
||||
SwfToIggyConvertor.updateIggy(iggyFile.getSwf(), swf);
|
||||
iggyFile.saveChanges();
|
||||
return true;
|
||||
} catch (InterruptedException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,271 +1,271 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFCompression;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharKerning;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShapeNode;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharOffset;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharAdvances;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyDeclStrings;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.iggy.IggySwf;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyText;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.EndTag;
|
||||
import com.jpexs.decompiler.flash.tags.FileAttributesTag;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.awt.Color;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* WIP
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyToSwfConvertor {
|
||||
|
||||
public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException {
|
||||
exportSwfToDir(file, outputDir);
|
||||
}
|
||||
|
||||
public static void exportSwfToDir(IggyFile file, File outputDir) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(outputDir, file.getSwfName()))) {
|
||||
exportSwf(file, fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportSwfToFile(IggyFile file, File outputFile) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
|
||||
exportSwf(file, fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportSwf(IggyFile file, OutputStream output) throws IOException {
|
||||
SWF swf = getSwf(file);
|
||||
swf.saveTo(output);
|
||||
}
|
||||
|
||||
private static int makeLengthsEm(double val) {
|
||||
return (int) (val * 1024.0);
|
||||
}
|
||||
|
||||
private static int makeLengthsTwip(double val) {
|
||||
return (int) (val * SWF.unitDivisor);
|
||||
}
|
||||
|
||||
public static SWF getSwf(IggyFile file) {
|
||||
SWF swf = new SWF();
|
||||
swf.compression = SWFCompression.NONE;
|
||||
swf.frameCount = 1; //FIXME!!
|
||||
swf.frameRate = file.getSwfFrameRate();
|
||||
swf.gfx = false;
|
||||
swf.displayRect = new RECT(
|
||||
makeLengthsTwip(file.getSwfXMin()),
|
||||
makeLengthsTwip(file.getSwfXMax()),
|
||||
makeLengthsTwip(file.getSwfYMin()),
|
||||
makeLengthsTwip(file.getSwfYMax()));
|
||||
swf.version = 10; //FIXME
|
||||
|
||||
FileAttributesTag fat = new FileAttributesTag(swf);
|
||||
fat.actionScript3 = true;
|
||||
fat.hasMetadata = false;
|
||||
fat.useNetwork = false;
|
||||
swf.addTag(fat);
|
||||
IggySwf iggySwf = file.getSwf();
|
||||
|
||||
int currentCharId = 0;
|
||||
Map<Integer, Integer> fontIndex2CharId = new HashMap<>();
|
||||
|
||||
for (int fontIndex = 0; fontIndex < iggySwf.getFonts().size(); fontIndex++) {
|
||||
IggyFont iggyFont = iggySwf.getFonts().get(fontIndex);
|
||||
DefineFont2Tag fontTag = new DefineFont2Tag(swf);
|
||||
currentCharId++;
|
||||
fontIndex2CharId.put(fontIndex, currentCharId);
|
||||
fontTag.fontID = currentCharId;
|
||||
/*System.out.println("===================");
|
||||
System.out.println("xscale: " + iggyFont.getXscale()); //80
|
||||
System.out.println("yscale: " + iggyFont.getYscale()); //19
|
||||
|
||||
System.out.println("unk_float1: " + iggyFont.getUnk_float()[0]);
|
||||
System.out.println("unk_float2: " + iggyFont.getUnk_float()[1]);
|
||||
System.out.println("unk_float3: " + iggyFont.getUnk_float()[2]);
|
||||
System.out.println("unk_float4: " + iggyFont.getUnk_float()[3]);
|
||||
System.out.println("unk_float5: " + iggyFont.getUnk_float()[4]);
|
||||
System.out.println("what_2: " + iggyFont.getWhat_2());
|
||||
System.out.println("what_3: " + iggyFont.getWhat_3());*/
|
||||
|
||||
fontTag.fontKerningTable = new ArrayList<>();
|
||||
IggyCharKerning ker = iggyFont.getCharKernings();
|
||||
if (ker != null) {
|
||||
for (int i = 0; i < ker.getKernCount(); i++) {
|
||||
int kerningCode1 = ker.getCharsA().get(i);
|
||||
int kerningCode2 = ker.getCharsA().get(i);
|
||||
int kerningOffset = ker.getKerningOffsets().get(i);
|
||||
fontTag.fontKerningTable.add(new KERNINGRECORD(kerningCode1, kerningCode2, kerningOffset));
|
||||
}
|
||||
}
|
||||
|
||||
fontTag.fontFlagsWideCodes = true;
|
||||
fontTag.fontFlagsWideOffsets = true;
|
||||
fontTag.fontAscent = iggyFont.getAscent();
|
||||
fontTag.fontDescent = iggyFont.getDescent();
|
||||
fontTag.fontLeading = iggyFont.getLeading();
|
||||
fontTag.codeTable = new ArrayList<>();
|
||||
fontTag.fontName = iggyFont.getName();
|
||||
fontTag.glyphShapeTable = new ArrayList<>();
|
||||
fontTag.fontBoundsTable = new ArrayList<>();
|
||||
fontTag.fontAdvanceTable = new ArrayList<>();
|
||||
fontTag.fontFlagsHasLayout = true;
|
||||
IggyCharAdvances advanceValues = iggyFont.getCharAdvances();
|
||||
for (int i = 0; i < iggyFont.getCharacterCount(); i++) {
|
||||
int code = iggyFont.getCharIndices().getChars().get(i);
|
||||
fontTag.codeTable.add(code);
|
||||
IggyShape glyph = iggyFont.getChars().get(i);
|
||||
SHAPE shp;
|
||||
if (glyph != null) {
|
||||
shp = IggyShapeToSwfConvertor.convertCharToShape(glyph);
|
||||
fontTag.fontBoundsTable.add(shp.getBounds());
|
||||
} else {
|
||||
shp = new SHAPE();
|
||||
shp.shapeRecords = new ArrayList<>();
|
||||
shp.shapeRecords.add(new EndShapeRecord());
|
||||
fontTag.fontBoundsTable.add(new RECT()); //??
|
||||
}
|
||||
fontTag.glyphShapeTable.add(shp);
|
||||
|
||||
fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i)));
|
||||
|
||||
}
|
||||
fontTag.setModified(true);
|
||||
swf.addTag(fontTag);
|
||||
}
|
||||
|
||||
Map<Integer, Integer> textIndex2CharId = new HashMap<>();
|
||||
|
||||
for (int textIndex = 0; textIndex < iggySwf.getTexts().size(); textIndex++) {
|
||||
IggyText iggyText = iggySwf.getTexts().get(textIndex);
|
||||
DefineEditTextTag textTag = new DefineEditTextTag(swf);
|
||||
currentCharId++;
|
||||
textIndex2CharId.put(textIndex, currentCharId);
|
||||
textTag.characterID = currentCharId;
|
||||
textTag.hasText = true;
|
||||
textTag.initialText = iggyText.getInitialText();
|
||||
textTag.html = true;
|
||||
textTag.noSelect = true;
|
||||
textTag.wasStatic = true;
|
||||
textTag.hasFont = false;
|
||||
textTag.hasFontClass = false;
|
||||
textTag.hasMaxLength = false;
|
||||
//textTag.multiline = true;
|
||||
//textTag.wordWrap = true;
|
||||
//textTag.hasTextColor = true;
|
||||
//textTag.textColor = new RGBA(Color.black);
|
||||
//textTag.fontHeight = 40; //??
|
||||
textTag.readOnly = true;
|
||||
textTag.bounds = new RECT(
|
||||
makeLengthsTwip(iggyText.getPar1()),
|
||||
makeLengthsTwip(iggyText.getPar3()),
|
||||
makeLengthsTwip(iggyText.getPar2()),
|
||||
makeLengthsTwip(iggyText.getPar4())
|
||||
);
|
||||
|
||||
//textTag.hasFont = true;
|
||||
//textTag.fontId = fontIndex2CharId.get(iggyText.getFontIndex());
|
||||
textTag.setModified(true);
|
||||
swf.addTag(textTag);
|
||||
}
|
||||
|
||||
IggyDeclStrings declStrings = iggySwf.getDeclStrings();
|
||||
if (declStrings != null) {
|
||||
byte[] abcData = declStrings.getData();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
baos.write(new byte[]{1, 0, 0, 0, 0, 0x10, 0, 0x2E});
|
||||
baos.write(abcData);
|
||||
} catch (IOException ex) {
|
||||
//should not happen
|
||||
}
|
||||
byte[] fullAbcTagData = baos.toByteArray();
|
||||
try {
|
||||
DoABC2Tag nabc = new DoABC2Tag(new SWFInputStream(swf, fullAbcTagData), new ByteArrayRange(fullAbcTagData));
|
||||
nabc.setModified(true);
|
||||
swf.addTag(nabc);
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
swf.addTag(
|
||||
new EndTag(swf));
|
||||
swf.setModified(
|
||||
true);
|
||||
|
||||
return swf;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
if (args.length < 2 || (args[0].isEmpty() || args[1].isEmpty())) {
|
||||
System.err.println("Invalid arguments");
|
||||
System.err.println("Usage: iggy-extract.bat file.iggy d:/outdir/");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
File file = new File(args[0]);
|
||||
if (!file.exists()) {
|
||||
System.err.println("FAIL: Input file: " + file.getAbsolutePath() + " does not exist.");
|
||||
System.exit(1);
|
||||
}
|
||||
File outDir = new File(args[1]);
|
||||
if (!outDir.exists()) {
|
||||
if (!outDir.mkdirs()) {
|
||||
System.err.println("FAIL: Cannot create output directory");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
System.out.print("(1/2) Loading file " + args[0] + "...");
|
||||
IggyFile iggyFile = new IggyFile(new File(args[0]));
|
||||
System.out.println("OK");
|
||||
System.out.print("(2/2) Exporting SWF files to " + args[1] + "...");
|
||||
exportAllSwfsToDir(iggyFile, new File(args[1]));
|
||||
System.out.println("OK");
|
||||
System.out.println("All finished sucessfully.");
|
||||
System.exit(0);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("FAIL");
|
||||
System.err.println("Error while converting: " + ex.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFCompression;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharKerning;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShapeNode;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharOffset;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharAdvances;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyDeclStrings;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.iggy.IggySwf;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyText;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.EndTag;
|
||||
import com.jpexs.decompiler.flash.tags.FileAttributesTag;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.awt.Color;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* WIP
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyToSwfConvertor {
|
||||
|
||||
public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException {
|
||||
exportSwfToDir(file, outputDir);
|
||||
}
|
||||
|
||||
public static void exportSwfToDir(IggyFile file, File outputDir) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(outputDir, file.getSwfName()))) {
|
||||
exportSwf(file, fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportSwfToFile(IggyFile file, File outputFile) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
|
||||
exportSwf(file, fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportSwf(IggyFile file, OutputStream output) throws IOException {
|
||||
SWF swf = getSwf(file);
|
||||
swf.saveTo(output);
|
||||
}
|
||||
|
||||
private static int makeLengthsEm(double val) {
|
||||
return (int) (val * 1024.0);
|
||||
}
|
||||
|
||||
private static int makeLengthsTwip(double val) {
|
||||
return (int) (val * SWF.unitDivisor);
|
||||
}
|
||||
|
||||
public static SWF getSwf(IggyFile file) {
|
||||
SWF swf = new SWF();
|
||||
swf.compression = SWFCompression.NONE;
|
||||
swf.frameCount = 1; //FIXME!!
|
||||
swf.frameRate = file.getSwfFrameRate();
|
||||
swf.gfx = false;
|
||||
swf.displayRect = new RECT(
|
||||
makeLengthsTwip(file.getSwfXMin()),
|
||||
makeLengthsTwip(file.getSwfXMax()),
|
||||
makeLengthsTwip(file.getSwfYMin()),
|
||||
makeLengthsTwip(file.getSwfYMax()));
|
||||
swf.version = 10; //FIXME
|
||||
|
||||
FileAttributesTag fat = new FileAttributesTag(swf);
|
||||
fat.actionScript3 = true;
|
||||
fat.hasMetadata = false;
|
||||
fat.useNetwork = false;
|
||||
swf.addTag(fat);
|
||||
IggySwf iggySwf = file.getSwf();
|
||||
|
||||
int currentCharId = 0;
|
||||
Map<Integer, Integer> fontIndex2CharId = new HashMap<>();
|
||||
|
||||
for (int fontIndex = 0; fontIndex < iggySwf.getFonts().size(); fontIndex++) {
|
||||
IggyFont iggyFont = iggySwf.getFonts().get(fontIndex);
|
||||
DefineFont2Tag fontTag = new DefineFont2Tag(swf);
|
||||
currentCharId++;
|
||||
fontIndex2CharId.put(fontIndex, currentCharId);
|
||||
fontTag.fontID = currentCharId;
|
||||
/*System.out.println("===================");
|
||||
System.out.println("xscale: " + iggyFont.getXscale()); //80
|
||||
System.out.println("yscale: " + iggyFont.getYscale()); //19
|
||||
|
||||
System.out.println("unk_float1: " + iggyFont.getUnk_float()[0]);
|
||||
System.out.println("unk_float2: " + iggyFont.getUnk_float()[1]);
|
||||
System.out.println("unk_float3: " + iggyFont.getUnk_float()[2]);
|
||||
System.out.println("unk_float4: " + iggyFont.getUnk_float()[3]);
|
||||
System.out.println("unk_float5: " + iggyFont.getUnk_float()[4]);
|
||||
System.out.println("what_2: " + iggyFont.getWhat_2());
|
||||
System.out.println("what_3: " + iggyFont.getWhat_3());*/
|
||||
|
||||
fontTag.fontKerningTable = new ArrayList<>();
|
||||
IggyCharKerning ker = iggyFont.getCharKernings();
|
||||
if (ker != null) {
|
||||
for (int i = 0; i < ker.getKernCount(); i++) {
|
||||
int kerningCode1 = ker.getCharsA().get(i);
|
||||
int kerningCode2 = ker.getCharsA().get(i);
|
||||
int kerningOffset = ker.getKerningOffsets().get(i);
|
||||
fontTag.fontKerningTable.add(new KERNINGRECORD(kerningCode1, kerningCode2, kerningOffset));
|
||||
}
|
||||
}
|
||||
|
||||
fontTag.fontFlagsWideCodes = true;
|
||||
fontTag.fontFlagsWideOffsets = true;
|
||||
fontTag.fontAscent = iggyFont.getAscent();
|
||||
fontTag.fontDescent = iggyFont.getDescent();
|
||||
fontTag.fontLeading = iggyFont.getLeading();
|
||||
fontTag.codeTable = new ArrayList<>();
|
||||
fontTag.fontName = iggyFont.getName();
|
||||
fontTag.glyphShapeTable = new ArrayList<>();
|
||||
fontTag.fontBoundsTable = new ArrayList<>();
|
||||
fontTag.fontAdvanceTable = new ArrayList<>();
|
||||
fontTag.fontFlagsHasLayout = true;
|
||||
IggyCharAdvances advanceValues = iggyFont.getCharAdvances();
|
||||
for (int i = 0; i < iggyFont.getCharacterCount(); i++) {
|
||||
int code = iggyFont.getCharIndices().getChars().get(i);
|
||||
fontTag.codeTable.add(code);
|
||||
IggyShape glyph = iggyFont.getChars().get(i);
|
||||
SHAPE shp;
|
||||
if (glyph != null) {
|
||||
shp = IggyShapeToSwfConvertor.convertCharToShape(glyph);
|
||||
fontTag.fontBoundsTable.add(shp.getBounds());
|
||||
} else {
|
||||
shp = new SHAPE();
|
||||
shp.shapeRecords = new ArrayList<>();
|
||||
shp.shapeRecords.add(new EndShapeRecord());
|
||||
fontTag.fontBoundsTable.add(new RECT()); //??
|
||||
}
|
||||
fontTag.glyphShapeTable.add(shp);
|
||||
|
||||
fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i)));
|
||||
|
||||
}
|
||||
fontTag.setModified(true);
|
||||
swf.addTag(fontTag);
|
||||
}
|
||||
|
||||
Map<Integer, Integer> textIndex2CharId = new HashMap<>();
|
||||
|
||||
for (int textIndex = 0; textIndex < iggySwf.getTexts().size(); textIndex++) {
|
||||
IggyText iggyText = iggySwf.getTexts().get(textIndex);
|
||||
DefineEditTextTag textTag = new DefineEditTextTag(swf);
|
||||
currentCharId++;
|
||||
textIndex2CharId.put(textIndex, currentCharId);
|
||||
textTag.characterID = currentCharId;
|
||||
textTag.hasText = true;
|
||||
textTag.initialText = iggyText.getInitialText();
|
||||
textTag.html = true;
|
||||
textTag.noSelect = true;
|
||||
textTag.wasStatic = true;
|
||||
textTag.hasFont = false;
|
||||
textTag.hasFontClass = false;
|
||||
textTag.hasMaxLength = false;
|
||||
//textTag.multiline = true;
|
||||
//textTag.wordWrap = true;
|
||||
//textTag.hasTextColor = true;
|
||||
//textTag.textColor = new RGBA(Color.black);
|
||||
//textTag.fontHeight = 40; //??
|
||||
textTag.readOnly = true;
|
||||
textTag.bounds = new RECT(
|
||||
makeLengthsTwip(iggyText.getPar1()),
|
||||
makeLengthsTwip(iggyText.getPar3()),
|
||||
makeLengthsTwip(iggyText.getPar2()),
|
||||
makeLengthsTwip(iggyText.getPar4())
|
||||
);
|
||||
|
||||
//textTag.hasFont = true;
|
||||
//textTag.fontId = fontIndex2CharId.get(iggyText.getFontIndex());
|
||||
textTag.setModified(true);
|
||||
swf.addTag(textTag);
|
||||
}
|
||||
|
||||
IggyDeclStrings declStrings = iggySwf.getDeclStrings();
|
||||
if (declStrings != null) {
|
||||
byte[] abcData = declStrings.getData();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
baos.write(new byte[]{1, 0, 0, 0, 0, 0x10, 0, 0x2E});
|
||||
baos.write(abcData);
|
||||
} catch (IOException ex) {
|
||||
//should not happen
|
||||
}
|
||||
byte[] fullAbcTagData = baos.toByteArray();
|
||||
try {
|
||||
DoABC2Tag nabc = new DoABC2Tag(new SWFInputStream(swf, fullAbcTagData), new ByteArrayRange(fullAbcTagData));
|
||||
nabc.setModified(true);
|
||||
swf.addTag(nabc);
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
swf.addTag(
|
||||
new EndTag(swf));
|
||||
swf.setModified(
|
||||
true);
|
||||
|
||||
return swf;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
if (args.length < 2 || (args[0].isEmpty() || args[1].isEmpty())) {
|
||||
System.err.println("Invalid arguments");
|
||||
System.err.println("Usage: iggy-extract.bat file.iggy d:/outdir/");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
File file = new File(args[0]);
|
||||
if (!file.exists()) {
|
||||
System.err.println("FAIL: Input file: " + file.getAbsolutePath() + " does not exist.");
|
||||
System.exit(1);
|
||||
}
|
||||
File outDir = new File(args[1]);
|
||||
if (!outDir.exists()) {
|
||||
if (!outDir.mkdirs()) {
|
||||
System.err.println("FAIL: Cannot create output directory");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
System.out.print("(1/2) Loading file " + args[0] + "...");
|
||||
IggyFile iggyFile = new IggyFile(new File(args[0]));
|
||||
System.out.println("OK");
|
||||
System.out.print("(2/2) Exporting SWF files to " + args[1] + "...");
|
||||
exportAllSwfsToDir(iggyFile, new File(args[1]));
|
||||
System.out.println("OK");
|
||||
System.out.println("All finished sucessfully.");
|
||||
System.exit(0);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("FAIL");
|
||||
System.err.println("Error while converting: " + ex.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,210 +1,210 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharAdvances;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharIndices;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharKerning;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharOffset;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggySwf;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyText;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SwfToIggyConvertor {
|
||||
|
||||
private static float normalizeLengths(int val) {
|
||||
return (val / 1024f);
|
||||
}
|
||||
|
||||
public static void updateIggy(IggySwf iggySwf, SWF swf) throws IOException {
|
||||
List<DefineFont2Tag> fontTags = new ArrayList<>();
|
||||
List<DefineEditTextTag> textTags = new ArrayList<>();
|
||||
List<DoABC2Tag> abcTags = new ArrayList<>();
|
||||
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineFont2Tag) {
|
||||
fontTags.add((DefineFont2Tag) t);
|
||||
}
|
||||
if (t instanceof DefineEditTextTag) {
|
||||
textTags.add((DefineEditTextTag) t);
|
||||
}
|
||||
if (t instanceof DoABC2Tag) {
|
||||
abcTags.add((DoABC2Tag) t);
|
||||
}
|
||||
}
|
||||
if (abcTags.size() > 1) {
|
||||
throw new IOException("Cannot save more than one ABC tag");
|
||||
}
|
||||
int fontCount = iggySwf.getFonts().size();
|
||||
if (fontCount != fontTags.size()) {
|
||||
throw new IOException("Font count is different from original iggy file");
|
||||
}
|
||||
for (int i = 0; i < fontCount; i++) {
|
||||
IggyFont iggyFont = iggySwf.getFonts().get(i);
|
||||
DefineFont2Tag fontTag = fontTags.get(i);
|
||||
SwfToIggyConvertor.updateIggyFont(iggyFont, fontTag);
|
||||
}
|
||||
|
||||
int textCount = iggySwf.getTexts().size();
|
||||
if (textCount != textTags.size()) {
|
||||
throw new IOException("Text count is different from original iggy file");
|
||||
}
|
||||
for (int i = 0; i < textCount; i++) {
|
||||
IggyText iggyText = iggySwf.getTexts().get(i);
|
||||
DefineEditTextTag textTag = textTags.get(i);
|
||||
SwfToIggyConvertor.updateIggyText(iggyText, textTag);
|
||||
}
|
||||
if (!abcTags.isEmpty()) {
|
||||
DoABC2Tag abcTag = abcTags.get(0);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte abcTagData[] = abcTag.getData();
|
||||
byte declData[] = Arrays.copyOfRange(abcTagData, 4/*UI32 flags*/ + 1 /*empty string as name*/ + 3 /*versions, leaving one zero intact*/, abcTagData.length);
|
||||
iggySwf.getDeclStrings().setData(declData);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateIggyText(IggyText iggyText, DefineEditTextTag textTag) {
|
||||
iggyText.setInitialText(textTag.initialText);
|
||||
}
|
||||
|
||||
public static void updateIggyFont(IggyFont iggyFont, DefineFont2Tag fontTag) {
|
||||
/*byte zeroone[] = new byte[28];
|
||||
zeroone[12] = 1;
|
||||
long flags = 65795;
|
||||
float unk_float[] = new float[]{
|
||||
-0.6484375f,
|
||||
-1.116211f,
|
||||
1.116211f,
|
||||
0.6679688f,
|
||||
0f
|
||||
};
|
||||
int xscale = 80;
|
||||
int yscale = 28;
|
||||
float ssr1 = 0.9f;
|
||||
float ssr2 = 0.3f;
|
||||
long what_2 = 33188160;
|
||||
long what_3 = 33600216;
|
||||
byte zeroes48a[] = new byte[48];
|
||||
byte zeroes48b[] = new byte[48];
|
||||
float sss1 = 1.1728859f;
|
||||
float sss2 = 1.1728706f;
|
||||
float sss3 = 1.1728821f;
|
||||
float sss4 = 1.1729145f;*/
|
||||
List<IggyCharOffset> charOffsets = new ArrayList<>();
|
||||
|
||||
List<IggyShape> glyphs = new ArrayList<>();
|
||||
|
||||
for (SHAPE s : fontTag.glyphShapeTable) {
|
||||
glyphs.add(SwfShapeToIggyConvertor.convertShape(s));
|
||||
}
|
||||
|
||||
List<Character> chars = new ArrayList<>();
|
||||
for (int code : fontTag.codeTable) {
|
||||
chars.add((char) code);
|
||||
}
|
||||
IggyCharIndices codePoints = new IggyCharIndices(chars);
|
||||
List<Float> scales = new ArrayList<>();
|
||||
for (int adv : fontTag.fontAdvanceTable) {
|
||||
scales.add(normalizeLengths(adv));
|
||||
}
|
||||
IggyCharAdvances charScales = new IggyCharAdvances(scales);
|
||||
List<Character> charA = new ArrayList<>();
|
||||
List<Character> charB = new ArrayList<>();
|
||||
List<Short> kernOffs = new ArrayList<>();
|
||||
|
||||
//IggyCharOffset
|
||||
for (KERNINGRECORD rec : fontTag.fontKerningTable) {
|
||||
charA.add((char) rec.fontKerningCode1);
|
||||
charB.add((char) rec.fontKerningCode2);
|
||||
kernOffs.add((short) rec.fontKerningAdjustment);
|
||||
}
|
||||
IggyCharKerning charKernings = new IggyCharKerning(charA, charB, kernOffs);
|
||||
|
||||
for (int i = 0; i < fontTag.getCharacterCount(); i++) {
|
||||
charOffsets.add(new IggyCharOffset(1, 0, 80, 19)); //XSCALE, YSCALE???
|
||||
}
|
||||
|
||||
iggyFont.setCharCount(fontTag.getCharacterCount());
|
||||
iggyFont.setCharCount2(fontTag.getCharacterCount());
|
||||
iggyFont.setAscent(fontTag.getAscent());
|
||||
iggyFont.setDescent(fontTag.getDescent());
|
||||
iggyFont.setLeading(fontTag.getLeading());
|
||||
iggyFont.setName(fontTag.getFontName());
|
||||
iggyFont.setCharOffsets(charOffsets);
|
||||
iggyFont.setGlyphs(glyphs);
|
||||
iggyFont.setCodePoints(codePoints);
|
||||
iggyFont.setCharScales(charScales);
|
||||
iggyFont.setCharKernings(charKernings);
|
||||
}
|
||||
|
||||
public static IggyFont createIggyFont(DefineFont2Tag fontTag) {
|
||||
byte zeroone[] = new byte[28];
|
||||
zeroone[12] = 1;
|
||||
long flags = 65795;
|
||||
float unk_float[] = new float[]{
|
||||
-0.6484375f,
|
||||
-1.116211f,
|
||||
1.116211f,
|
||||
0.6679688f,
|
||||
0f
|
||||
};
|
||||
int xscale = 80;
|
||||
int yscale = 28;
|
||||
float ssr1 = 0.9f;
|
||||
float ssr2 = 0.3f;
|
||||
long what_2 = 33188160;
|
||||
long what_3 = 33600216;
|
||||
byte zeroes48a[] = new byte[48];
|
||||
byte zeroes48b[] = new byte[48];
|
||||
float sss1 = 1.1728859f;
|
||||
float sss2 = 1.1728706f;
|
||||
float sss3 = 1.1728821f;
|
||||
float sss4 = 1.1729145f;
|
||||
List<IggyCharOffset> charOffsets = new ArrayList<>();
|
||||
List<IggyShape> glyphs = new ArrayList<>();
|
||||
List<Character> chars = new ArrayList<>();
|
||||
for (int code : fontTag.codeTable) {
|
||||
chars.add((char) code);
|
||||
}
|
||||
IggyCharIndices codePoints = new IggyCharIndices(chars);
|
||||
List<Float> scales = new ArrayList<>();
|
||||
for (int adv : fontTag.fontAdvanceTable) {
|
||||
scales.add((float) adv);
|
||||
}
|
||||
IggyCharAdvances charScales = new IggyCharAdvances(scales);
|
||||
List<Character> charA = new ArrayList<>();
|
||||
List<Character> charB = new ArrayList<>();
|
||||
List<Short> kernOffs = new ArrayList<>();
|
||||
|
||||
for (KERNINGRECORD rec : fontTag.fontKerningTable) {
|
||||
charA.add((char) rec.fontKerningCode1);
|
||||
charB.add((char) rec.fontKerningCode2);
|
||||
kernOffs.add((short) rec.fontKerningAdjustment);
|
||||
}
|
||||
IggyCharKerning charKernings = new IggyCharKerning(charA, charB, kernOffs);
|
||||
|
||||
IggyFont iggyFont = new IggyFont(IggyFont.ID, 0, zeroone, fontTag.getCharacterCount(),
|
||||
fontTag.getAscent(), fontTag.getDescent(), fontTag.getLeading(), flags,
|
||||
fontTag.fontKerningTable.size(), unk_float, 0, what_2, 0, 1,
|
||||
xscale, yscale, 0, ssr1, ssr2, fontTag.getCharacterCount(), 0, what_3, zeroes48a, zeroes48b,
|
||||
sss1, 1, sss2, 1, sss3, 1, sss4, 1, fontTag.getFontName(),
|
||||
charOffsets, glyphs, codePoints, charScales, charKernings);
|
||||
return iggyFont;
|
||||
}
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharAdvances;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharIndices;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharKerning;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharOffset;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggySwf;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyText;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SwfToIggyConvertor {
|
||||
|
||||
private static float normalizeLengths(int val) {
|
||||
return (val / 1024f);
|
||||
}
|
||||
|
||||
public static void updateIggy(IggySwf iggySwf, SWF swf) throws IOException {
|
||||
List<DefineFont2Tag> fontTags = new ArrayList<>();
|
||||
List<DefineEditTextTag> textTags = new ArrayList<>();
|
||||
List<DoABC2Tag> abcTags = new ArrayList<>();
|
||||
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineFont2Tag) {
|
||||
fontTags.add((DefineFont2Tag) t);
|
||||
}
|
||||
if (t instanceof DefineEditTextTag) {
|
||||
textTags.add((DefineEditTextTag) t);
|
||||
}
|
||||
if (t instanceof DoABC2Tag) {
|
||||
abcTags.add((DoABC2Tag) t);
|
||||
}
|
||||
}
|
||||
if (abcTags.size() > 1) {
|
||||
throw new IOException("Cannot save more than one ABC tag");
|
||||
}
|
||||
int fontCount = iggySwf.getFonts().size();
|
||||
if (fontCount != fontTags.size()) {
|
||||
throw new IOException("Font count is different from original iggy file");
|
||||
}
|
||||
for (int i = 0; i < fontCount; i++) {
|
||||
IggyFont iggyFont = iggySwf.getFonts().get(i);
|
||||
DefineFont2Tag fontTag = fontTags.get(i);
|
||||
SwfToIggyConvertor.updateIggyFont(iggyFont, fontTag);
|
||||
}
|
||||
|
||||
int textCount = iggySwf.getTexts().size();
|
||||
if (textCount != textTags.size()) {
|
||||
throw new IOException("Text count is different from original iggy file");
|
||||
}
|
||||
for (int i = 0; i < textCount; i++) {
|
||||
IggyText iggyText = iggySwf.getTexts().get(i);
|
||||
DefineEditTextTag textTag = textTags.get(i);
|
||||
SwfToIggyConvertor.updateIggyText(iggyText, textTag);
|
||||
}
|
||||
if (!abcTags.isEmpty()) {
|
||||
DoABC2Tag abcTag = abcTags.get(0);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte abcTagData[] = abcTag.getData();
|
||||
byte declData[] = Arrays.copyOfRange(abcTagData, 4/*UI32 flags*/ + 1 /*empty string as name*/ + 3 /*versions, leaving one zero intact*/, abcTagData.length);
|
||||
iggySwf.getDeclStrings().setData(declData);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateIggyText(IggyText iggyText, DefineEditTextTag textTag) {
|
||||
iggyText.setInitialText(textTag.initialText);
|
||||
}
|
||||
|
||||
public static void updateIggyFont(IggyFont iggyFont, DefineFont2Tag fontTag) {
|
||||
/*byte zeroone[] = new byte[28];
|
||||
zeroone[12] = 1;
|
||||
long flags = 65795;
|
||||
float unk_float[] = new float[]{
|
||||
-0.6484375f,
|
||||
-1.116211f,
|
||||
1.116211f,
|
||||
0.6679688f,
|
||||
0f
|
||||
};
|
||||
int xscale = 80;
|
||||
int yscale = 28;
|
||||
float ssr1 = 0.9f;
|
||||
float ssr2 = 0.3f;
|
||||
long what_2 = 33188160;
|
||||
long what_3 = 33600216;
|
||||
byte zeroes48a[] = new byte[48];
|
||||
byte zeroes48b[] = new byte[48];
|
||||
float sss1 = 1.1728859f;
|
||||
float sss2 = 1.1728706f;
|
||||
float sss3 = 1.1728821f;
|
||||
float sss4 = 1.1729145f;*/
|
||||
List<IggyCharOffset> charOffsets = new ArrayList<>();
|
||||
|
||||
List<IggyShape> glyphs = new ArrayList<>();
|
||||
|
||||
for (SHAPE s : fontTag.glyphShapeTable) {
|
||||
glyphs.add(SwfShapeToIggyConvertor.convertShape(s));
|
||||
}
|
||||
|
||||
List<Character> chars = new ArrayList<>();
|
||||
for (int code : fontTag.codeTable) {
|
||||
chars.add((char) code);
|
||||
}
|
||||
IggyCharIndices codePoints = new IggyCharIndices(chars);
|
||||
List<Float> scales = new ArrayList<>();
|
||||
for (int adv : fontTag.fontAdvanceTable) {
|
||||
scales.add(normalizeLengths(adv));
|
||||
}
|
||||
IggyCharAdvances charScales = new IggyCharAdvances(scales);
|
||||
List<Character> charA = new ArrayList<>();
|
||||
List<Character> charB = new ArrayList<>();
|
||||
List<Short> kernOffs = new ArrayList<>();
|
||||
|
||||
//IggyCharOffset
|
||||
for (KERNINGRECORD rec : fontTag.fontKerningTable) {
|
||||
charA.add((char) rec.fontKerningCode1);
|
||||
charB.add((char) rec.fontKerningCode2);
|
||||
kernOffs.add((short) rec.fontKerningAdjustment);
|
||||
}
|
||||
IggyCharKerning charKernings = new IggyCharKerning(charA, charB, kernOffs);
|
||||
|
||||
for (int i = 0; i < fontTag.getCharacterCount(); i++) {
|
||||
charOffsets.add(new IggyCharOffset(1, 0, 80, 19)); //XSCALE, YSCALE???
|
||||
}
|
||||
|
||||
iggyFont.setCharCount(fontTag.getCharacterCount());
|
||||
iggyFont.setCharCount2(fontTag.getCharacterCount());
|
||||
iggyFont.setAscent(fontTag.getAscent());
|
||||
iggyFont.setDescent(fontTag.getDescent());
|
||||
iggyFont.setLeading(fontTag.getLeading());
|
||||
iggyFont.setName(fontTag.getFontName());
|
||||
iggyFont.setCharOffsets(charOffsets);
|
||||
iggyFont.setGlyphs(glyphs);
|
||||
iggyFont.setCodePoints(codePoints);
|
||||
iggyFont.setCharScales(charScales);
|
||||
iggyFont.setCharKernings(charKernings);
|
||||
}
|
||||
|
||||
public static IggyFont createIggyFont(DefineFont2Tag fontTag) {
|
||||
byte zeroone[] = new byte[28];
|
||||
zeroone[12] = 1;
|
||||
long flags = 65795;
|
||||
float unk_float[] = new float[]{
|
||||
-0.6484375f,
|
||||
-1.116211f,
|
||||
1.116211f,
|
||||
0.6679688f,
|
||||
0f
|
||||
};
|
||||
int xscale = 80;
|
||||
int yscale = 28;
|
||||
float ssr1 = 0.9f;
|
||||
float ssr2 = 0.3f;
|
||||
long what_2 = 33188160;
|
||||
long what_3 = 33600216;
|
||||
byte zeroes48a[] = new byte[48];
|
||||
byte zeroes48b[] = new byte[48];
|
||||
float sss1 = 1.1728859f;
|
||||
float sss2 = 1.1728706f;
|
||||
float sss3 = 1.1728821f;
|
||||
float sss4 = 1.1729145f;
|
||||
List<IggyCharOffset> charOffsets = new ArrayList<>();
|
||||
List<IggyShape> glyphs = new ArrayList<>();
|
||||
List<Character> chars = new ArrayList<>();
|
||||
for (int code : fontTag.codeTable) {
|
||||
chars.add((char) code);
|
||||
}
|
||||
IggyCharIndices codePoints = new IggyCharIndices(chars);
|
||||
List<Float> scales = new ArrayList<>();
|
||||
for (int adv : fontTag.fontAdvanceTable) {
|
||||
scales.add((float) adv);
|
||||
}
|
||||
IggyCharAdvances charScales = new IggyCharAdvances(scales);
|
||||
List<Character> charA = new ArrayList<>();
|
||||
List<Character> charB = new ArrayList<>();
|
||||
List<Short> kernOffs = new ArrayList<>();
|
||||
|
||||
for (KERNINGRECORD rec : fontTag.fontKerningTable) {
|
||||
charA.add((char) rec.fontKerningCode1);
|
||||
charB.add((char) rec.fontKerningCode2);
|
||||
kernOffs.add((short) rec.fontKerningAdjustment);
|
||||
}
|
||||
IggyCharKerning charKernings = new IggyCharKerning(charA, charB, kernOffs);
|
||||
|
||||
IggyFont iggyFont = new IggyFont(IggyFont.ID, 0, zeroone, fontTag.getCharacterCount(),
|
||||
fontTag.getAscent(), fontTag.getDescent(), fontTag.getLeading(), flags,
|
||||
fontTag.fontKerningTable.size(), unk_float, 0, what_2, 0, 1,
|
||||
xscale, yscale, 0, ssr1, ssr2, fontTag.getCharacterCount(), 0, what_3, zeroes48a, zeroes48b,
|
||||
sss1, 1, sss2, 1, sss3, 1, sss4, 1, fontTag.getFontName(),
|
||||
charOffsets, glyphs, codePoints, charScales, charKernings);
|
||||
return iggyFont;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,188 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.SWFContainerItem;
|
||||
import com.jpexs.decompiler.flash.SWFSourceInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SWFList implements List<SWF>, SWFContainerItem {
|
||||
|
||||
public String name;
|
||||
|
||||
public SWFBundle bundle;
|
||||
|
||||
public SWFSourceInfo sourceInfo;
|
||||
|
||||
public List<SWF> swfs = new ArrayList<>();
|
||||
|
||||
public boolean isBundle() {
|
||||
return bundle != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isBundle()) {
|
||||
return name;
|
||||
} else {
|
||||
return swfs.get(0).getFileTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<SWF> iterator() {
|
||||
return swfs.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return swfs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return swfs.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return swfs.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return swfs.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] ts) {
|
||||
return swfs.toArray(ts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(SWF e) {
|
||||
return swfs.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return swfs.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> clctn) {
|
||||
return swfs.containsAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends SWF> clctn) {
|
||||
return swfs.addAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> clctn) {
|
||||
return swfs.removeAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> clctn) {
|
||||
return swfs.retainAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
swfs.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int i, Collection<? extends SWF> clctn) {
|
||||
return swfs.addAll(i, clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF get(int i) {
|
||||
if (i < 0 || i >= swfs.size()) {
|
||||
return null;
|
||||
}
|
||||
return swfs.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF set(int i, SWF e) {
|
||||
return swfs.set(i, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int i, SWF e) {
|
||||
swfs.add(i, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF remove(int i) {
|
||||
return swfs.remove(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return swfs.indexOf(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return swfs.lastIndexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<SWF> listIterator() {
|
||||
return swfs.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<SWF> listIterator(int i) {
|
||||
return swfs.listIterator(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SWF> subList(int i, int i1) {
|
||||
return swfs.subList(i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
for (SWF s : swfs) {
|
||||
if (s.isModified()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.SWFContainerItem;
|
||||
import com.jpexs.decompiler.flash.SWFSourceInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SWFList implements List<SWF>, SWFContainerItem {
|
||||
|
||||
public String name;
|
||||
|
||||
public SWFBundle bundle;
|
||||
|
||||
public SWFSourceInfo sourceInfo;
|
||||
|
||||
public List<SWF> swfs = new ArrayList<>();
|
||||
|
||||
public boolean isBundle() {
|
||||
return bundle != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isBundle()) {
|
||||
return name;
|
||||
} else {
|
||||
return swfs.get(0).getFileTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<SWF> iterator() {
|
||||
return swfs.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return swfs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return swfs.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return swfs.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return swfs.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] ts) {
|
||||
return swfs.toArray(ts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(SWF e) {
|
||||
return swfs.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return swfs.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> clctn) {
|
||||
return swfs.containsAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends SWF> clctn) {
|
||||
return swfs.addAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> clctn) {
|
||||
return swfs.removeAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> clctn) {
|
||||
return swfs.retainAll(clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
swfs.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int i, Collection<? extends SWF> clctn) {
|
||||
return swfs.addAll(i, clctn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF get(int i) {
|
||||
if (i < 0 || i >= swfs.size()) {
|
||||
return null;
|
||||
}
|
||||
return swfs.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF set(int i, SWF e) {
|
||||
return swfs.set(i, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int i, SWF e) {
|
||||
swfs.add(i, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF remove(int i) {
|
||||
return swfs.remove(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return swfs.indexOf(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return swfs.lastIndexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<SWF> listIterator() {
|
||||
return swfs.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<SWF> listIterator(int i) {
|
||||
return swfs.listIterator(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SWF> subList(int i, int i1) {
|
||||
return swfs.subList(i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
for (SWF s : swfs) {
|
||||
if (s.isModified()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user