diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java index 03860a1ae..de66dd8b0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java @@ -6,6 +6,8 @@ import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream; import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.IndexingDataStream; +import com.jpexs.decompiler.flash.iggy.streams.IndexingDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import com.jpexs.helpers.Helper; import java.io.File; @@ -48,7 +50,9 @@ public class IggyFile implements StructureInterface { IggySwf iggySwf = iggySwfs.get(targetSwfIndex); iggySwf.replaceFontTag(fontIndex, newFont); + IndexingDataStreamInterface indexStream = new IndexingDataStream(); DataStreamInterface flashStream = new TemporaryDataStream(); + flashStream.setIndexing(indexStream); iggySwf.writeToDataStream(flashStream); byte flashData[] = flashStream.getAllBytes(); int swfIndex = 0; @@ -56,17 +60,29 @@ public class IggyFile implements StructureInterface { for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); entry.offset += offsetChange; + if (entry.type == IggySubFileEntry.TYPE_INDEX) { + if (swfIndex == targetSwfIndex) { + byte indexData[] = indexStream.getIndexBytes(); + long newLen = indexData.length; + long oldLen = entry.size; + entry.size = newLen; + entry.size2 = newLen; + offsetChange += (newLen - oldLen); + subFileEntriesData.set(i, indexData); + } + swfIndex++; + } if (entry.type == IggySubFileEntry.TYPE_FLASH) { if (swfIndex == targetSwfIndex) { long newLen = flashData.length; long oldLen = entry.size; + entry.size = newLen; + entry.size2 = newLen; offsetChange += (newLen - oldLen); + subFileEntriesData.set(i, flashData); } - swfIndex++; } } - subFileEntriesData.set(targetSwfIndex, flashData); - //TODO: Update index } private boolean setSwfItemLength(int swfIndex, int itemindex, long newLength) { @@ -187,19 +203,31 @@ public class IggyFile implements StructureInterface { } public static void main(String[] args) throws IOException { - /*String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy"; + String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy"; String outFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font2.iggy"; + File extractDirOrig = new File("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig"); + File extractDirNew = new File("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new"); + + if (!extractDirOrig.exists()) { + extractDirOrig.mkdir(); + } + if (!extractDirNew.exists()) { + extractDirNew.mkdir(); + } + File inFile = new File(inFileName); File outFile = new File(outFileName); IggyFile iggyFile = new IggyFile(inFile); + extractIggyFile(inFile, extractDirOrig); IggySwf iswf = iggyFile.getSwf(0); IggyFont ifont = iswf.fonts.get(0); iggyFile.replaceFontTag(0, 0, ifont); outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); - }*/ + } + extractIggyFile(outFile, extractDirNew); } private static void copyStream(InputStream is, OutputStream os) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java index dc0125746..d1b39c06d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java @@ -255,22 +255,14 @@ public class IggyFont extends IggyTag { zeroes48b = s.readBytes(48); if (abs_start_of_name != 0) { + //here is offset [5] - 1096 s.seek(abs_start_of_name, SeekMode.SET); - StringBuilder nameBuilder = new StringBuilder(); - int nameCharCnt = 0; - do { - char c = (char) s.readUI16(); - nameCharCnt++; - if (c == '\0') { - break; - } - nameBuilder.append(c); - } while (true); - s.seek(32 - nameCharCnt * 2, SeekMode.CUR); - name = nameBuilder.toString(); + name = s.readWChar(); + //here is offset [6] - 1130 + s.pad8bytes(); } - s.readUI64(); //pad zero if (abs_start_of_char_struct != 0) { + //here is offset [7] - 1136 s.seek(abs_start_of_char_struct, SeekMode.SET); charOffsets = new ArrayList<>(); for (int i = 0; i < char_count; i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexBuilder.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexBuilder.java new file mode 100644 index 000000000..dace78461 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexBuilder.java @@ -0,0 +1,12 @@ +package com.jpexs.decompiler.flash.iggy; + +/** + * + * @author JPEXS + */ +public class IggyIndexBuilder { + + public void writeTable(int cnt, DataType type, boolean pad) { + + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java index 7757d0772..b8277a0a1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java @@ -3,8 +3,13 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.SeekMode; import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import java.io.IOException; import java.util.List; +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; import java.util.logging.Logger; /** @@ -15,14 +20,24 @@ public class IggyIndexParser { private static Logger LOGGER = Logger.getLogger(IggyIndexParser.class.getName()); - /* - Offsets: - 1) name - 2) UI16 - zero - 3) tag list - 4) ... tag data offsets - - */ + static { + LOGGER.setLevel(Level.ALL); + LOGGER.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + System.out.println("" + record.getMessage()); + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + } + /** * Parser for index data. It creates table of indices and table of offsets * @@ -36,7 +51,7 @@ public class IggyIndexParser { int[] indexTable = new int[indexTableSize]; for (int i = 0; i < indexTableSize; i++) { int offset = indexStream.readUI8(); - LOGGER.fine(String.format("index_table_entry: %02x\n", offset)); + LOGGER.fine(String.format("index_table_entry: %02x", offset)); indexTable[i] = offset; indexTableEntry.add(offset); int num = indexStream.readUI8(); @@ -47,28 +62,32 @@ public class IggyIndexParser { int code; while ((code = indexStream.readUI8()) > -1) { - LOGGER.finer(String.format("Code = %x\n", code)); + LOGGER.finer(String.format("Code = %x", code)); if (code < 0x80) // 0-0x7F { + LOGGER.finest("0-0x7F: code is directly an index to the index_table"); // code is directly an index to the index_table if (code >= indexTableSize) { - LOGGER.severe(String.format("< 0x80: index is greater than index_table_size. %x > %x\n", code, indexTableSize)); + LOGGER.severe(String.format("< 0x80: index is greater than index_table_size. %x > %x", code, indexTableSize)); return; } offset += indexTable[code]; + LOGGER.finest(String.format("ofset += %d", indexTable[code])); + } else if (code < 0xC0) // 0x80-BF { + LOGGER.finest("0x80-BF: table[0..255]*(code-0x7F)"); int index; if ((index = indexStream.readUI8()) < 0) { - LOGGER.severe(String.format("< 0xC0: Cannot read index.\n")); + LOGGER.severe(String.format("< 0xC0: Cannot read index.")); return; } if (index >= indexTableSize) { - LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x\n", index, indexTableSize)); + LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, indexTableSize)); return; } @@ -76,92 +95,116 @@ public class IggyIndexParser { offset += indexTable[index] * n; } else if (code < 0xD0) // 0xC0-0xCF { + LOGGER.finest("0xC0-CF: code*2-0x17E"); offset += ((code * 2) - 0x17E); } else if (code < 0xE0) // 0xD0-0xDF { + LOGGER.finest("0xD0-0xDF: platform based"); + // Code here depends on plattform[0], we are assuming it is 1, as we checked in load function int i = code & 0xF; int n8; int n; if ((n8 = indexStream.readUI8()) < 0) { - LOGGER.severe(String.format("< 0xE0: Cannot read n.\n")); + LOGGER.severe(String.format("< 0xE0: Cannot read n.")); return; } n = n8 + 1; + LOGGER.finest(String.format("i=%X", i)); + LOGGER.finest(String.format("n=%d", n)); + if (is64) { if (i <= 2) { offset += 8 * n; // Ptr type + LOGGER.finest(String.format("offset += %d", 8 * n)); } else if (i <= 4) { offset += 2 * n; + LOGGER.finest(String.format("offset += %d", 2 * n)); } else if (i == 5) { offset += 4 * n; + LOGGER.finest(String.format("offset += %d", 4 * n)); } else if (i == 6) { offset += 8 * n; // 64 bits type + LOGGER.finest(String.format("offset += %d", 8 * n)); } else { - LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)\n", i, code)); + LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)", i, code)); } } else { switch (i) { case 2: offset += 4 * n; // Ptr type + LOGGER.finest(String.format("offset += %d", 4 * n)); break; case 4: offset += 2 * n; + LOGGER.finest(String.format("offset += %d", 2 * n)); break; case 5: offset += 4 * n; // 32 bits type + LOGGER.finest(String.format("offset += %d", 4 * n)); break; case 6: offset += 8 * n; + LOGGER.finest(String.format("offset += %d", 8 * n)); break; default: - LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)\n", i, code)); + LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)", i, code)); } } } else if (code == 0xFC) { + LOGGER.finest(String.format("0xFC: skip 1 ")); indexStream.seek(1, SeekMode.CUR); } else if (code == 0xFD) { + LOGGER.finest(String.format("0xFD: 0..255, skip 2 * 0..255 ")); int n, m; if ((n = indexStream.readUI8()) < 0) { - LOGGER.severe(String.format("0xFD: Cannot read n.\n")); + LOGGER.severe(String.format("0xFD: Cannot read n.")); return; } if ((m = indexStream.readUI8()) < 0) { - LOGGER.severe(String.format("0xFD: Cannot read m.\n")); + LOGGER.severe(String.format("0xFD: Cannot read m.")); return; } offset += n; + LOGGER.finest(String.format("offset += %d", n)); indexStream.seek(m * 2, SeekMode.CUR); + LOGGER.finest(String.format("skip %d", m * 2)); } else if (code == 0xFE) { + LOGGER.finest(String.format("0xFD: 0..255 + 1 ")); int n8; int n; if ((n8 = indexStream.readUI8()) < 0) { - LOGGER.severe(String.format("0xFE: Cannot read n.\n")); + LOGGER.severe(String.format("0xFE: Cannot read n.")); return; } n = n8 + 1; offset += n; + LOGGER.finest(String.format("offset += %d", n)); } else if (code == 0xFF) { + LOGGER.finest(String.format("0xFF: 32bit ")); long n; if ((n = indexStream.readUI32()) < 0) { - LOGGER.severe(String.format("0xFF: Cannot read n.\n")); + LOGGER.severe(String.format("0xFF: Cannot read n.")); return; } offset += n; + LOGGER.finest(String.format("offset += %d", n)); } else { - LOGGER.warning(String.format("Unrecognized code: %x\n", code)); + LOGGER.warning(String.format("Unrecognized code: %x", code)); } + LOGGER.finer(String.format("OFFSET: %d", offset)); + offsets.add(offset); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java index c943bf098..279145d34 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java @@ -88,21 +88,14 @@ public class IggySwf implements StructureInterface { long maxPos = hdr.getFontEndAddress(); allFontBytes = s.readBytes((int) (maxPos - curPos)); s.seek(curPos, SeekMode.SET); - - //here is offset[0] - StringBuilder nameBuilder = new StringBuilder(); - do { - char c = (char) s.readUI16(); - if (c == '\0') { - break; - } - nameBuilder.append(c); - } while (true); - name = nameBuilder.toString(); - //here is offset[1] + //here is offset[0] - 184 + name = s.readWChar(); + //here is offset[1] - 230 int pad8 = 8 - (int) (s.position() % 8); - s.seek(pad8, SeekMode.CUR); - //here is offset [2] + if (pad8 > 8) { + s.seek(pad8, SeekMode.CUR); + } + //here is offset [2] - 232 s.seek(hdr.getBaseAddress(), SeekMode.SET); s.readUI64(); //pad 1 @@ -157,6 +150,7 @@ public class IggySwf implements StructureInterface { } } } + //here is offset [3] - 744 fonts = new HashMap<>(); for (int i = 0; i < hdr.font_count; i++) { s.seek(font_data_addresses[i], SeekMode.SET); @@ -176,10 +170,12 @@ public class IggySwf implements StructureInterface { font_add_data = s.readBytes((int) (long) font_add_size.get(0)); } s.seek(hdr.getFontEndAddress(), SeekMode.SET); + //here is offset [4] - 856 ? font_bin_info = new FontBinInfo[(int) hdr.font_count]; for (int i = 0; i < hdr.font_count; i++) { font_bin_info[i] = new FontBinInfo(s); } + s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET); sequence = new IggySequence(s); s.seek(hdr.getTypeFontsAddress(), SeekMode.SET); @@ -194,7 +190,6 @@ public class IggySwf implements StructureInterface { s.seek(hdr.getDeclStringsAddress(), SeekMode.SET); decl_strings = new IggyDeclStrings(s); - //TODO: binarydata /*WriteDataStreamInterface outs = new TemporaryDataStream(); writeToDataStream(outs); Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());*/ @@ -207,17 +202,9 @@ public class IggySwf implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { hdr.writeToDataStream(s); - for (int i = 0; i < name.length(); i++) { - s.writeUI16(name.charAt(i)); - } - s.writeUI16(0); - - int pad8 = 8 - (int) (s.position() % 8); - if (pad8 < 8) { - for (int i = 0; i < pad8; i++) { - s.write(0); - } - } + s.getIndexing().writeIndexUI8SkipTwice8(184, 25); + s.writeWChar(name); + s.pad8bytes(); s.writeUI64(1); for (int i = 0; i < font_data_addresses.length; i++) { long offset = font_data_addresses[i] - s.position(); @@ -227,8 +214,6 @@ public class IggySwf implements StructureInterface { long offset = text_addresses.get(i) - s.position(); s.writeUI64(offset); } - s.writeUI64(1); - if (hdr.font_count > 0) { while (s.position() < font_data_addresses[0]) { s.writeUI64(1); @@ -264,8 +249,6 @@ public class IggySwf implements StructureInterface { } s.seek(hdr.getDeclStringsAddress(), SeekMode.SET); decl_strings.writeToDataStream(s); - - //TODO: binarydata } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/AbstractDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/AbstractDataStream.java index 88f057208..f99fc86a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/AbstractDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/AbstractDataStream.java @@ -1,7 +1,11 @@ package com.jpexs.decompiler.flash.iggy.streams; +import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; /** * @@ -171,4 +175,36 @@ public abstract class AbstractDataStream implements DataStreamInterface { return val; } + @Override + public boolean writeWChar(String name) throws IOException { + for (int i = 0; i < name.length(); i++) { + writeUI16(name.charAt(i)); + } + writeUI16(0); + return true; + } + + @Override + public String readWChar() throws IOException { + StringBuilder strBuilder = new StringBuilder(); + do { + char c = (char) readUI16(); + if (c == '\0') { + break; + } + strBuilder.append(c); + } while (true); + return strBuilder.toString(); + } + + @Override + public void pad8bytes() throws IOException { + int pad8 = 8 - (int) (position() % 8); + if (pad8 < 8) { + for (int i = 0; i < pad8; i++) { + write(0); + } + } + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/EmptyIndexing.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/EmptyIndexing.java new file mode 100644 index 000000000..6e868625e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/EmptyIndexing.java @@ -0,0 +1,84 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +/** + * + * @author JPEXS + */ +public class EmptyIndexing implements IndexingDataStreamInterface { + + @Override + public void writeIndexToTable(int val0to255) { + + } + + @Override + public long writeIndexFromTable(int tableIndex0to127) { + return 0; + } + + @Override + public long writeIndex40(int num1to40, int countUI8) { + return 0; + } + + @Override + public long writeIndexMultiply2(int num0to15) { + return 0; + } + + @Override + public long writeIndexPtr(boolean is64, long cnt) { + return 0; + } + + @Override + public long writeIndex16bit(long cnt) { + return 0; + } + + @Override + public long writeIndex32bit(long cnt) { + return 0; + } + + @Override + public long writeIndex64bit(long cnt) { + return 0; + } + + @Override + public long writeIndexSkip1() { + return 0; + } + + @Override + public long writeIndexUI8SkipTwice8(int ofs, int skipTwice) { + return 0; + } + + @Override + public long writeIndexUI8Positive(int val) { + return 0; + } + + @Override + public long writeIndexUI32(long offset) { + return 0; + } + + @Override + public long writeIndex(int code, boolean is64, long val, long val2) { + return 0; + } + + @Override + public byte[] getIndexTableBytes() { + return new byte[0]; + } + + @Override + public byte[] getIndexBytes() { + return new byte[0]; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStream.java new file mode 100644 index 000000000..610ab8344 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStream.java @@ -0,0 +1,272 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class IndexingDataStream implements IndexingDataStreamInterface { + + public static final int CODE_FC_SKIP1 = 0xFC; + public static final int CODE_FD_OFS8_SKIP_TWICE8 = 0xFD; + public static final int CODE_FE_OFS8_POSITIVE = 0xFE; + public static final int CODE_FF_OFS32 = 0xFF; + + private static Logger LOGGER = Logger.getLogger(IndexingDataStream.class.getName()); + + private List indexTable; + private WriteDataStreamInterface indexStream; + + public IndexingDataStream() throws IOException { + indexStream = new TemporaryDataStream(); + indexTable = new ArrayList<>(); + } + + @Override + public byte[] getIndexTableBytes() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write(indexTable.size()); + for (int i = 0; i < indexTable.size(); i++) { + baos.write(indexTable.get(i)); + if (i == indexTable.size() - 1) { + int pad8 = (indexTable.size() * 2) % 8; + baos.write(pad8 / 2); //pad to 8 bytes(?) + } else { + baos.write(0); //how many bytes to skip + } + } + return baos.toByteArray(); + } + + public byte[] getIndexBytes() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + baos.write(getIndexTableBytes()); + baos.write(indexStream.getAllBytes()); + } catch (IOException ex) { + //should not happen + } + return baos.toByteArray(); + } + + @Override + public void writeIndexToTable(int val0to255) { + indexTable.add(val0to255); + } + + @Override + public long writeIndexFromTable(int tableIndex0to127) { + return writeIndex(tableIndex0to127, false, 0, 0); + } + + @Override + public long writeIndex40(int num1to40, int countUI8) { + return writeIndex(0x80 + num1to40, false, countUI8, 0); + } + + @Override + public long writeIndexMultiply2(int num0to15) { + return writeIndex(0xC0 + num0to15, false, 0, 0); + } + + @Override + public long writeIndexPtr(boolean is64, long cnt) { + return writeIndex(0xD0 + 0x2, false, cnt - 1, 0); + } + + @Override + public long writeIndex16bit(long cnt) { + return writeIndex(0xD0 + 0x4, false, cnt - 1, 0); + } + + @Override + public long writeIndex32bit(long cnt) { + return writeIndex(0xD0 + 0x5, false, cnt - 1, 0); + } + + @Override + public long writeIndex64bit(long cnt) { + return writeIndex(0xD0 + 0x6, false, cnt - 1, 0); + } + + @Override + public long writeIndexSkip1() { + return writeIndex(CODE_FC_SKIP1, false, 0, 0); + } + + @Override + public long writeIndexUI8SkipTwice8(int ofs, int skipTwice) { + return writeIndex(CODE_FD_OFS8_SKIP_TWICE8, false, ofs, skipTwice); + } + + @Override + public long writeIndexUI8Positive(int val) { + return writeIndex(CODE_FE_OFS8_POSITIVE, false, val, 0); + } + + @Override + public long writeIndexUI32(long offset) { + return writeIndex(CODE_FF_OFS32, false, offset, 0); + } + + @Override + public long writeIndex(int code, boolean is64, long val, long skipNum) { + try { + indexStream.writeUI8(code); + if (code < 0x80) // 0-0x7F + { + LOGGER.finest("0-0x7F: code is directly an index to the index_table"); + // code is directly an index to the index_table + if (code >= indexTable.size()) { + LOGGER.severe(String.format("< 0x80: index is greater than index_table_size. %x > %x", code, indexTable.size())); + return 0; + } + + LOGGER.finest(String.format("ofset += %d", indexTable.get(code))); + return indexTable.get(code); + } else if (code < 0xC0) // 0x80-BF + { + LOGGER.finest("0x80-BF: table[0..255]*(code-0x7F)"); + int index; + + indexStream.writeUI8((int) val); + if ((index = (int) val) < 0) { + LOGGER.severe(String.format("< 0xC0: Cannot read index.")); + return 0; + } + + if (index >= indexTable.size()) { + LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, indexTable.size())); + return 0; + } + + int n = code - 0x7F; + return indexTable.get(index) * n; + } else if (code < 0xD0) // 0xC0-0xCF + { + LOGGER.finest("0xC0-CF: code*2-0x17E"); + return ((code * 2) - 0x17E); + } else if (code < 0xE0) // 0xD0-0xDF + { + LOGGER.finest("0xD0-0xDF: platform based"); + + // Code here depends on plattform[0], we are assuming it is 1, as we checked in load function + int i = code & 0xF; + int n8; + int n; + + indexStream.writeUI8((int) val); + if ((n8 = (int) val) < 0) { + LOGGER.severe(String.format("< 0xE0: Cannot read n.")); + return 0; + } + + n = n8 + 1; + + LOGGER.finest(String.format("i=%X", i)); + LOGGER.finest(String.format("n=%d", n)); + + if (is64) { + if (i <= 2) { + LOGGER.finest(String.format("offset += %d", 8 * n)); + return 8 * n; // Ptr type + + } else if (i <= 4) { + LOGGER.finest(String.format("offset += %d", 2 * n)); + return 2 * n; + } else if (i == 5) { + LOGGER.finest(String.format("offset += %d", 4 * n)); + return 4 * n; + } else if (i == 6) { + LOGGER.finest(String.format("offset += %d", 8 * n)); + return 8 * n; // 64 bits type + } else { + LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)", i, code)); + return 0; + } + } else { + switch (i) { + case 2: + LOGGER.finest(String.format("offset += %d", 4 * n)); + return 4 * n; // Ptr type; + case 4: + LOGGER.finest(String.format("offset += %d", 2 * n)); + return 2 * n; + case 5: + LOGGER.finest(String.format("offset += %d", 4 * n)); + return 4 * n; // 32 bits type + case 6: + LOGGER.finest(String.format("offset += %d", 8 * n)); + return 8 * n; + default: + LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)", i, code)); + return 0; + } + } + } else if (code == CODE_FC_SKIP1) { + LOGGER.finest(String.format("0xFC: skip 1 ")); + //indexStream.seek(1, SeekMode.CUR); + return 1; //seek 1 + } else if (code == CODE_FD_OFS8_SKIP_TWICE8) { + LOGGER.finest(String.format("0xFD: 0..255, skip 2 * 0..255 ")); + int n, m; + + indexStream.writeUI8((int) val); + + if ((n = (int) val) < 0) { + LOGGER.severe(String.format("0xFD: Cannot read n.")); + return 0; + } + + indexStream.writeUI8((int) skipNum); + + if ((m = (int) skipNum) < 0) { + LOGGER.severe(String.format("0xFD: Cannot read m.")); + return 0; + } + + long offset = n; + LOGGER.finest(String.format("offset += %d", n)); + long skip = m * 2; + LOGGER.finest(String.format("skip %d", m * 2)); + return offset + skip; + } else if (code == CODE_FE_OFS8_POSITIVE) { + LOGGER.finest(String.format("0xFD: 0..255 + 1 ")); + int n8; + int n; + + indexStream.writeUI8((int) val); + if ((n8 = (int) val) < 0) { + LOGGER.severe(String.format("0xFE: Cannot read n.")); + return 0; + } + + n = n8 + 1; + LOGGER.finest(String.format("offset += %d", n)); + return n; + } else if (code == CODE_FF_OFS32) { + LOGGER.finest(String.format("0xFF: 32bit ")); + long n; + + indexStream.writeUI32(val); + if ((n = val) < 0) { + LOGGER.severe(String.format("0xFF: Cannot read n.")); + return 0; + } + + LOGGER.finest(String.format("offset += %d", n)); + return n; + } else { + LOGGER.warning(String.format("Unrecognized code: %x", code)); + return 0; + } + } catch (IOException ex) { + return 0; + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStreamInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStreamInterface.java new file mode 100644 index 000000000..0e6d250f3 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStreamInterface.java @@ -0,0 +1,38 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +/** + * + * @author JPEXS + */ +public interface IndexingDataStreamInterface { + + public void writeIndexToTable(int val0to255); + + public long writeIndexFromTable(int tableIndex0to127); + + public long writeIndex40(int num1to40, int countUI8); + + public long writeIndexMultiply2(int num0to15); + + public long writeIndexPtr(boolean is64, long cnt); + + public long writeIndex16bit(long cnt); + + public long writeIndex32bit(long cnt); + + public long writeIndex64bit(long cnt); + + public long writeIndexSkip1(); + + public long writeIndexUI8SkipTwice8(int ofs, int skipTwice); + + public long writeIndexUI8Positive(int val); + + public long writeIndexUI32(long offset); + + public long writeIndex(int code, boolean is64, long val, long val2); + + public byte[] getIndexTableBytes(); + + public byte[] getIndexBytes(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java index 199dc8c93..eb6a15a4c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java @@ -16,13 +16,24 @@ public class RandomAccessFileDataStream extends AbstractDataStream { private File file; private RandomAccessFile raf; + private IndexingDataStreamInterface indexing; protected File getFile() { return file; } + @Override + public void setIndexing(IndexingDataStreamInterface indexing) { + this.indexing = indexing; + } + public RandomAccessFileDataStream(File file) throws FileNotFoundException { + this(file, new EmptyIndexing()); + } + + public RandomAccessFileDataStream(File file, IndexingDataStreamInterface indexing) throws FileNotFoundException { this.file = file; + this.indexing = indexing; raf = new RandomAccessFile(file, "rw"); } @@ -104,4 +115,24 @@ public class RandomAccessFileDataStream extends AbstractDataStream { raf.write(val); } + @Override + public IndexingDataStreamInterface getIndexing() { + return indexing; + } + + @Override + public boolean writeWChar(String name) throws IOException { + indexing.writeIndex16bit(name.length() + 1); + return super.writeWChar(name); + } + + @Override + public void pad8bytes() throws IOException { + int pad8 = 8 - (int) (position() % 8); + if (pad8 < 8) { + indexing.writeIndexMultiply2(pad8 / 2); + } + super.pad8bytes(); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java index 1364ce5da..7536e6aef 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java @@ -41,6 +41,10 @@ public interface ReadDataStreamInterface extends AutoCloseable { public byte[] getAllBytes() throws IOException; + public String readWChar() throws IOException; + + public void pad8bytes() throws IOException; + @Override public void close(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java index 01d48d282..f22ace170 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java @@ -27,6 +27,10 @@ public interface WriteDataStreamInterface extends AutoCloseable { public boolean writeUI16(int val) throws IOException; + public boolean writeWChar(String val) throws IOException; + + public void pad8bytes() throws IOException; + public boolean writeUI8(int val) throws IOException; public void write(int val) throws IOException; @@ -41,4 +45,8 @@ public interface WriteDataStreamInterface extends AutoCloseable { @Override public void close(); + + public void setIndexing(IndexingDataStreamInterface indexing); + + public IndexingDataStreamInterface getIndexing(); }