From a39f41214c64b2d5f28e89ea04ff495599a690bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 23 Nov 2016 10:55:32 +0100 Subject: [PATCH] Reading index, refactorings --- .../flash/iggy/AbstractDataStream.java | 2 + .../flash/iggy/ByteArrayDataStream.java | 13 +- .../jpexs/decompiler/flash/iggy/DataType.java | 3 +- .../decompiler/flash/iggy/IggyExtractor.java | 202 +++--------------- .../flash/iggy/IggyFlashHeader32.java | 2 +- .../flash/iggy/IggyFlashHeader64.java | 79 +++---- .../flash/iggy/IggyFlashHeaderInterface.java | 9 + .../decompiler/flash/iggy/IggyHeader.java | 82 +++++-- .../flash/iggy/IggyIndexParser.java | 165 ++++++++++++++ .../flash/iggy/IggyNameAndTagList.java | 77 +++++++ .../flash/iggy/IggySubFileEntry.java | 2 + .../flash/iggy/StructureInterface.java | 1 + 12 files changed, 389 insertions(+), 248 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeaderInterface.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyNameAndTagList.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/AbstractDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/AbstractDataStream.java index b5a7fa818..5587457b2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/AbstractDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/AbstractDataStream.java @@ -16,6 +16,8 @@ public abstract class AbstractDataStream { */ public abstract Long available(); + public abstract boolean is64(); + protected long readUI64() throws IOException { try { return (readUI32() + (readUI32() << 32)) & 0xffffffffffffffffL; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/ByteArrayDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/ByteArrayDataStream.java index 7045e7e0f..a9fb716d5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/ByteArrayDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/ByteArrayDataStream.java @@ -12,14 +12,21 @@ public class ByteArrayDataStream extends AbstractDataStream { private byte[] data; private int pos; + private boolean use64bit; - public ByteArrayDataStream(int initialSize) { - this(new byte[initialSize]); + public ByteArrayDataStream(int initialSize, boolean use64bit) { + this(new byte[initialSize], use64bit); } - public ByteArrayDataStream(byte data[]) { + public ByteArrayDataStream(byte data[], boolean use64bit) { this.data = data; pos = 0; + this.use64bit = use64bit; + } + + @Override + public boolean is64() { + return use64bit; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/DataType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/DataType.java index a0c145075..5b4ba5d19 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/DataType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/DataType.java @@ -4,5 +4,6 @@ package com.jpexs.decompiler.flash.iggy; * @author JPEXS */ public enum DataType { - uint8_t, uint16_t, uint32_t, uint64_t, unknown + ubits, uint8_t, uint16_t, uint32_t, uint64_t, unknown, + widechar_t //or maybe just "string"? It has two bytes per character and is null terminated } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyExtractor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyExtractor.java index b4f417aee..2f4892c89 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyExtractor.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyExtractor.java @@ -33,47 +33,47 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable { List> indexTables = new ArrayList<>(); List> offsetTables = new ArrayList<>(); - IggyFlashHeader64 fh64 = null; - IggyFlashHeader32 fh32 = null; + List headers = new ArrayList<>(); + List namesAndTagLists = new ArrayList<>(); public IggyExtractor(File file) throws IOException { raf = new RandomAccessFile(file, "r"); header = new IggyHeader(this); - for (int i = 0; i < header.num_subfiles; i++) { + for (int i = 0; i < header.getNumSubfiles(); i++) { subFileEntries.add(new IggySubFileEntry(this)); } - List indexDatas = new ArrayList<>(); List flashStreams = new ArrayList<>(); for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); + ByteArrayDataStream dataStream = getEntryDataStream(i); if (entry.type == IggySubFileEntry.TYPE_INDEX) { - indexDatas.add(getEntryData(i)); + List indexTable = new ArrayList<>(); + List offsets = new ArrayList<>(); + IggyIndexParser.parseIndex(dataStream, indexTable, offsets); + indexTables.add(indexTable); + offsetTables.add(offsets); } else if (entry.type == IggySubFileEntry.TYPE_FLASH) { - flashStreams.add(getEntryDataStream(i)); + IggyFlashHeaderInterface hdr; + if (is64()) { + hdr = new IggyFlashHeader64(dataStream); + } else { + hdr = new IggyFlashHeader32(dataStream); + } + headers.add(hdr); + namesAndTagLists.add(new IggyNameAndTagList(dataStream)); + flashStreams.add(dataStream); } } - - for (byte[] index_data : indexDatas) { - List indexTableEntry = new ArrayList<>(); - List offsets = new ArrayList<>(); - parseIndex(is64(), index_data, indexTableEntry, offsets); - indexTables.add(indexTableEntry); - offsetTables.add(offsets); - } - - for (ByteArrayDataStream fs : flashStreams) { - if (is64()) { - fh64 = new IggyFlashHeader64(fs); - System.out.println("" + fh64); - } else { - fh32 = new IggyFlashHeader32(fs); - } + for (int i = 0; i < flashStreams.size(); i++) { + List offsets = offsetTables.get(i); + //TODO } } - private boolean is64() { + @Override + public boolean is64() { return header.is64(); } @@ -112,7 +112,7 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable { baos.write(buf, 0, cnt); } byte data[] = baos.toByteArray(); - return new ByteArrayDataStream(data); + return new ByteArrayDataStream(data, is64()); } public InputStream getEntryInputStream(int entryIndex) { @@ -252,7 +252,7 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable { } private static boolean updateIndex(long item_offset /*uint32_t*/, boolean is_64, byte index_bytes[], long item_size_change /*int32_t*/) throws IOException { - ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes); + ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes, is_64); /* index_table: @@ -468,7 +468,7 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable { * @throws IOException */ private static Long itemLength(long item_offset /*uint32_t*/, boolean is_64, byte index_bytes[], Long newValue) throws IOException { - ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes); + ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes, is_64); /* index_table: @@ -648,156 +648,6 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable { return null; } - /** - * - * @param is_64 - * @param index_bytes - * @param indexTableEntry - * @param offsets - * @throws IOException - */ - private static void parseIndex(boolean is_64, byte index_bytes[], List indexTableEntry, List offsets) throws IOException { - ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes); - - int index_table_size = stream.readUI8(); - int[] index_table = new int[index_table_size]; - - for (int i = 0; i < index_table_size; i++) { - int offset = stream.readUI8(); - //System.err.printf("index_table_entry: %02x\n", offset); - index_table[i] = offset; - indexTableEntry.add(offset); - int num = stream.readUI8(); - stream.seek(num * 2, SeekMode.CUR); - } - - long offset = 0; - int code; - - while ((code = stream.readUI8()) > -1) { - //DPRINTF("Code = %x\n", code); - - if (code < 0x80) // 0-0x7F - { - // code is directly an index to the index_table - if (code >= index_table_size) { - System.err.printf("< 0x80: index is greater than index_table_size. %x > %x\n", code, index_table_size); - return; - } - - offset += index_table[code]; - } else if (code < 0xC0) // 0x80-BF - { - int index; - - if ((index = stream.readUI8()) < 0) { - System.err.printf("< 0xC0: Cannot read index.\n"); - return; - } - - if (index >= index_table_size) { - System.err.printf("< 0xC0: index is greater than index_table_size. %x > %x\n", index, index_table_size); - return; - } - - int n = code - 0x7F; - offset += index_table[index] * n; - } else if (code < 0xD0) // 0xC0-0xCF - { - offset += ((code * 2) - 0x17E); - } else if (code < 0xE0) // 0xD0-0xDF - { - // 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 = stream.readUI8()) < 0) { - System.err.printf("< 0xE0: Cannot read n.\n"); - return; - } - - n = n8 + 1; - - if (is_64) { - if (i <= 2) { - offset += 8 * n; // Ptr type - } else if (i <= 4) { - offset += 2 * n; - } else if (i == 5) { - offset += 4 * n; - } else if (i == 6) { - offset += 8 * n; // 64 bits type - } else { - System.err.printf("< 0xE0: Invalid value for i (%x %x)\n", i, code); - } - } else { - switch (i) { - case 2: - offset += 4 * n; // Ptr type - break; - - case 4: - offset += 2 * n; - break; - - case 5: - offset += 4 * n; // 32 bits type - break; - - case 6: - offset += 8 * n; - break; - - default: - System.err.printf("< 0xE0: invalid value for i (%x %x)\n", i, code); - } - } - } else if (code == 0xFC) { - stream.seek(1, SeekMode.CUR); - } else if (code == 0xFD) { - int n, m; - - if ((n = stream.readUI8()) < 0) { - System.err.printf("0xFD: Cannot read n.\n"); - return; - } - - if ((m = stream.readUI8()) < 0) { - System.err.printf("0xFD: Cannot read m.\n"); - return; - } - - offset += n; - stream.seek(m * 2, SeekMode.CUR); - } else if (code == 0xFE) { - int n8; - int n; - - if ((n8 = stream.readUI8()) < 0) { - System.err.printf("0xFE: Cannot read n.\n"); - return; - } - - n = n8 + 1; - offset += n; - } else if (code == 0xFF) { - long n; - - if ((n = stream.readUI32()) < 0) { - System.err.printf("0xFF: Cannot read n.\n"); - return; - } - - offset += n; - } else { - System.err.printf("Unrecognized code: %x\n", code); - } - - offsets.add(offset); - } - } - @Override public Long available() { try { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader32.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader32.java index df0231654..599aded20 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader32.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader32.java @@ -17,7 +17,7 @@ import java.util.Map; * All relative offsets are relative from that specific field position All * relative offsets can get value "1" to indicate "nothing" */ -public class IggyFlashHeader32 implements StructureInterface { +public class IggyFlashHeader32 implements IggyFlashHeaderInterface { @IggyFieldType(DataType.uint32_t) long main_offset; // 0 Relative offset to first section (matches sizeof header) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java index 3e57f7ea0..99c9c0cf4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java @@ -14,7 +14,7 @@ import java.util.Map; * * Based of works of somebody called eternity. */ -public class IggyFlashHeader64 implements StructureInterface { +public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @IggyFieldType(DataType.uint64_t) long main_offset; // 0 Relative offset to first section (matches sizeof header); @@ -77,11 +77,6 @@ public class IggyFlashHeader64 implements StructureInterface { long unk_B0; // Maybe number of classes / as3 names @IggyFieldType(DataType.uint32_t) long unk_B4; - @IggyFieldType(value = DataType.uint16_t, count = 20) - String name; - - List tagIds = new ArrayList<>(); - List tagIdsExtendedInfo = new ArrayList<>(); /*@IggyArrayFieldType(value = DataType.uint32_t, count = 20) long unk_offsets_a[] = new long[20]; @@ -97,8 +92,25 @@ public class IggyFlashHeader64 implements StructureInterface { readFromDataStream(stream); } + private int ofs = 0; + private List offsets; + + private String currentOffset() { + return String.format(" [offset: %d]", offsets.get(ofs++)); + } + + /* + offsets: + name (UI16 chars, zero terminated) + UI16 + taglist_offset (aka main_offset) + after_taglist + + + */ @Override public void readFromDataStream(AbstractDataStream stream) throws IOException { + this.offsets = offsets; main_offset = stream.readUI64(); as3_section_offset = stream.readUI64(); unk_offset = stream.readUI64(); @@ -130,26 +142,6 @@ public class IggyFlashHeader64 implements StructureInterface { unk_AC = stream.readUI32(); unk_B0 = stream.readUI32(); unk_B4 = stream.readUI32(); - StringBuilder nameBuilder = new StringBuilder(); - do { - char c = (char) stream.readUI16(); - if (c == '\0') { - break; - } - nameBuilder.append(c); - } while (true); - name = nameBuilder.toString(); - - while (true) { - long typeLen = stream.readUI32(); - if (typeLen == 0) { - break; - } - long tagLength = stream.readUI32(); - int tagType = (int) ((typeLen >>> 6) + 10) & 0x3FF; - tagIds.add(tagType); - tagIdsExtendedInfo.add(tagLength); - } } @Override @@ -161,18 +153,18 @@ public class IggyFlashHeader64 implements StructureInterface { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[\r\n"); - sb.append("main_offset ").append(main_offset).append("\r\n"); - sb.append("as3_section_offset ").append(as3_section_offset).append("\r\n"); - sb.append("unk_offset ").append(unk_offset).append("\r\n"); - sb.append("unk_offset2 ").append(unk_offset2).append("\r\n"); - sb.append("unk_offset3 ").append(unk_offset3).append("\r\n"); - sb.append("unk_offset4 ").append(unk_offset4).append("\r\n"); - sb.append("xmin ").append(xmin).append("\r\n"); - sb.append("ymin ").append(ymin).append("\r\n"); - sb.append("xmax ").append(ymax).append("\r\n"); - sb.append("ymax ").append(ymax).append("\r\n"); - sb.append("unk_40 ").append(unk_40).append("\r\n"); - sb.append("unk_44 ").append(unk_44).append("\r\n"); + sb.append("main_offset ").append(main_offset).append(currentOffset()).append("\r\n"); + sb.append("as3_section_offset ").append(as3_section_offset).append(currentOffset()).append("\r\n"); + sb.append("unk_offset ").append(unk_offset).append(currentOffset()).append("\r\n"); + sb.append("unk_offset2 ").append(unk_offset2).append(currentOffset()).append("\r\n"); + sb.append("unk_offset3 ").append(unk_offset3).append(currentOffset()).append("\r\n"); + sb.append("unk_offset4 ").append(unk_offset4).append(currentOffset()).append("\r\n"); + sb.append("xmin ").append(xmin).append(currentOffset()).append("\r\n"); + sb.append("ymin ").append(ymin).append(currentOffset()).append("\r\n"); + sb.append("xmax ").append(ymax).append(currentOffset()).append("\r\n"); + sb.append("ymax ").append(ymax).append(currentOffset()).append("\r\n"); + sb.append("unk_40 ").append(unk_40).append(currentOffset()).append("\r\n"); + sb.append("unk_44 ").append(unk_44).append(currentOffset()).append("\r\n"); sb.append("unk_48 ").append(unk_48).append("\r\n"); sb.append("unk_4C ").append(unk_4C).append("\r\n"); sb.append("unk_50 ").append(unk_50).append("\r\n"); @@ -192,17 +184,6 @@ public class IggyFlashHeader64 implements StructureInterface { sb.append("unk_AC ").append(unk_AC).append("\r\n"); sb.append("unk_B0 ").append(unk_B0).append("\r\n"); sb.append("unk_B4 ").append(unk_B4).append("\r\n"); - sb.append("name ").append(name).append("\r\n"); - Map map = Tag.getKnownClasses(); - sb.append("tags:").append("\r\n"); - for (int i = 0; i < tagIds.size(); i++) { - TagTypeInfo tti = map.get(tagIds.get(i)); - sb.append(" tag ").append(tagIds.get(i)).append(":").append(tti == null ? "?" : tti.getName()); - if (tagIdsExtendedInfo.get(i) > 0) { - sb.append(" (special: ").append(tagIdsExtendedInfo.get(i)).append(")"); - } - sb.append("\r\n"); - } sb.append("]"); return sb.toString(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeaderInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeaderInterface.java new file mode 100644 index 000000000..b98193d81 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeaderInterface.java @@ -0,0 +1,9 @@ +package com.jpexs.decompiler.flash.iggy; + +/** + * + * @author JPEXS + */ +public interface IggyFlashHeaderInterface extends StructureInterface { + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyHeader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyHeader.java index 1db08b956..067b7cd5c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyHeader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyHeader.java @@ -3,7 +3,6 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; -import java.math.BigInteger; /** * @@ -19,51 +18,62 @@ public class IggyHeader implements StructureInterface { //Must be 0xED0A6749 @IggyFieldType(DataType.uint32_t) - public long magic = MAGIC; + private long magic = MAGIC; //Assume 0x900 @IggyFieldType(DataType.uint32_t) - public long version; + private long version; //Assuming: 1 @IggyFieldType(value = DataType.uint8_t) - public int platform1; + private int platform1; //32/64 @IggyFieldType(value = DataType.uint8_t) - public int platform2_bittness; + private int platform2; //Assuming: 1 @IggyFieldType(value = DataType.uint8_t) - public int platform3; + private int platform3; //Usually: 3 @IggyFieldType(value = DataType.uint8_t) - public int platform4; + private int platform4; //flags for platform 64? @IggyFieldType(DataType.uint32_t) - public long unk_0C; + private long unk_0C; @IggyArrayFieldType(value = DataType.uint8_t, count = 12) - public byte[] reserved; + private byte[] reserved; @IggyFieldType(value = DataType.uint32_t) - public long num_subfiles; + private long numSubfiles; public IggyHeader(AbstractDataStream stream) throws IOException { readFromDataStream(stream); } - public IggyHeader(long version, int platform1, int platform2_bittness, int platform3, int platform4, long unk_0C, byte[] reserved, long num_subfiles) { + /** + * + * @param version + * @param platform1 + * @param platform2 32/64 + * @param platform3 + * @param platform4 + * @param unk_0C + * @param reserved + * @param num_subfiles + */ + public IggyHeader(long version, int platform1, int platform2, int platform3, int platform4, long unk_0C, byte[] reserved, long num_subfiles) { this.version = version; this.platform1 = platform1; - this.platform2_bittness = platform2_bittness; + this.platform2 = platform2; this.platform3 = platform3; this.platform4 = platform4; this.unk_0C = unk_0C; this.reserved = reserved; - this.num_subfiles = num_subfiles; + this.numSubfiles = num_subfiles; } @Override @@ -71,10 +81,10 @@ public class IggyHeader implements StructureInterface { StringBuilder sb = new StringBuilder(); sb.append("["); sb.append("version: ").append(version).append(", "); - sb.append("platform: ").append(platform1).append(" ").append(platform2_bittness).append(" ").append(platform3).append(" ").append(platform4).append(", "); + sb.append("platform: ").append(platform1).append(" ").append(platform2).append(" ").append(platform3).append(" ").append(platform4).append(", "); sb.append("unk_0C: ").append(String.format("%08X", unk_0C)).append(", "); sb.append("reserved: 12 bytes").append(", "); - sb.append("num_subfiles: ").append(num_subfiles); + sb.append("num_subfiles: ").append(numSubfiles); sb.append("]"); return sb.toString(); } @@ -87,12 +97,12 @@ public class IggyHeader implements StructureInterface { } version = stream.readUI32(); platform1 = stream.readUI8(); - platform2_bittness = stream.readUI8(); + platform2 = stream.readUI8(); //32/64 platform3 = stream.readUI8(); platform4 = stream.readUI8(); unk_0C = stream.readUI32(); reserved = stream.readBytes(12); - num_subfiles = stream.readUI32(); + numSubfiles = stream.readUI32(); } @Override @@ -101,7 +111,43 @@ public class IggyHeader implements StructureInterface { } public boolean is64() { - return platform2_bittness == 64; + return platform2 == 64; + } + + public long getMagic() { + return magic; + } + + public long getVersion() { + return version; + } + + public int getPlatform1() { + return platform1; + } + + public int getPlatform2() { + return platform2; + } + + public int getPlatform3() { + return platform3; + } + + public int getPlatform4() { + return platform4; + } + + public long getUnk_0C() { + return unk_0C; + } + + public byte[] getReserved() { + return reserved; + } + + public long getNumSubfiles() { + return numSubfiles; } } 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 new file mode 100644 index 000000000..b3bbb9868 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java @@ -0,0 +1,165 @@ +package com.jpexs.decompiler.flash.iggy; + +import java.io.IOException; +import java.util.List; +import java.util.logging.Logger; + +/** + * + * @author Jindra + */ +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 + + */ + /** + * Parser for index data. It creates table of indices and table of offsets + * + * @param indexStream Stream of index + * @param indexTableEntry Output index tabke + * @param offsets Output list of offsets + * @throws IOException on error + */ + public static void parseIndex(ByteArrayDataStream indexStream, List indexTableEntry, List offsets) throws IOException { + int indexTableSize = indexStream.readUI8(); + 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)); + indexTable[i] = offset; + indexTableEntry.add(offset); + int num = indexStream.readUI8(); + indexStream.seek(num * 2, SeekMode.CUR); + } + + long offset = 0; + int code; + + while ((code = indexStream.readUI8()) > -1) { + LOGGER.finer(String.format("Code = %x\n", code)); + + if (code < 0x80) // 0-0x7F + { + // 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)); + return; + } + + offset += indexTable[code]; + } else if (code < 0xC0) // 0x80-BF + { + int index; + + if ((index = indexStream.readUI8()) < 0) { + LOGGER.severe(String.format("< 0xC0: Cannot read index.\n")); + return; + } + + if (index >= indexTableSize) { + LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x\n", index, indexTableSize)); + return; + } + + int n = code - 0x7F; + offset += indexTable[index] * n; + } else if (code < 0xD0) // 0xC0-0xCF + { + offset += ((code * 2) - 0x17E); + } else if (code < 0xE0) // 0xD0-0xDF + { + // 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")); + return; + } + + n = n8 + 1; + + if (indexStream.is64()) { + if (i <= 2) { + offset += 8 * n; // Ptr type + } else if (i <= 4) { + offset += 2 * n; + } else if (i == 5) { + offset += 4 * n; + } else if (i == 6) { + offset += 8 * n; // 64 bits type + } else { + LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)\n", i, code)); + } + } else { + switch (i) { + case 2: + offset += 4 * n; // Ptr type + break; + case 4: + offset += 2 * n; + break; + case 5: + offset += 4 * n; // 32 bits type + break; + case 6: + offset += 8 * n; + break; + default: + LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)\n", i, code)); + } + } + } else if (code == 0xFC) { + indexStream.seek(1, SeekMode.CUR); + } else if (code == 0xFD) { + int n, m; + + if ((n = indexStream.readUI8()) < 0) { + LOGGER.severe(String.format("0xFD: Cannot read n.\n")); + return; + } + + if ((m = indexStream.readUI8()) < 0) { + LOGGER.severe(String.format("0xFD: Cannot read m.\n")); + return; + } + + offset += n; + indexStream.seek(m * 2, SeekMode.CUR); + } else if (code == 0xFE) { + int n8; + int n; + + if ((n8 = indexStream.readUI8()) < 0) { + LOGGER.severe(String.format("0xFE: Cannot read n.\n")); + return; + } + + n = n8 + 1; + offset += n; + } else if (code == 0xFF) { + long n; + + if ((n = indexStream.readUI32()) < 0) { + LOGGER.severe(String.format("0xFF: Cannot read n.\n")); + return; + } + + offset += n; + } else { + LOGGER.warning(String.format("Unrecognized code: %x\n", code)); + } + + offsets.add(offset); + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyNameAndTagList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyNameAndTagList.java new file mode 100644 index 000000000..c06b3d4ba --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyNameAndTagList.java @@ -0,0 +1,77 @@ +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class IggyNameAndTagList implements StructureInterface { + + @IggyFieldType(value = DataType.widechar_t) + private String name; + + @IggyArrayFieldType(value = DataType.ubits, count = 10) + private List tagIds; + + @IggyArrayFieldType(value = DataType.uint16_t) + private List tagIdsExtendedInfo; + + public IggyNameAndTagList(String name, List tagIds, List tagIdsExtendedInfo) { + this.name = name; + this.tagIds = tagIds; + this.tagIdsExtendedInfo = tagIdsExtendedInfo; + } + + public IggyNameAndTagList(AbstractDataStream stream) throws IOException { + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + StringBuilder nameBuilder = new StringBuilder(); + do { + char c = (char) stream.readUI16(); + if (c == '\0') { + break; + } + nameBuilder.append(c); + } while (true); + name = nameBuilder.toString(); + + tagIds = new ArrayList<>(); + tagIdsExtendedInfo = new ArrayList<>(); + while (true) { + long typeLen = stream.readUI32(); + if (typeLen == 0) { + break; + } + long tagLength = stream.readUI32(); + int tagType = (int) ((typeLen >>> 6) + 10) & 0x3FF; + tagIds.add(tagType); + tagIdsExtendedInfo.add(tagLength); + } + } + + public String getName() { + return name; + } + + public List getTagIds() { + return tagIds; + } + + public List getTagIdsExtendedInfo() { + return tagIdsExtendedInfo; + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySubFileEntry.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySubFileEntry.java index 892422cfe..c1a2cd141 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySubFileEntry.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySubFileEntry.java @@ -3,6 +3,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.annotations.SWFType; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** * diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/StructureInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/StructureInterface.java index 84aaff3eb..c48ad2a1b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/StructureInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/StructureInterface.java @@ -1,6 +1,7 @@ package com.jpexs.decompiler.flash.iggy; import java.io.IOException; +import java.util.List; /** *