From 3225c62564f13e2c0ac463689a70e0c1942f419c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 23 Nov 2016 22:03:56 +0100 Subject: [PATCH] Font offsets, other refactorings --- .../flash/iggy/AbstractDataStream.java | 2 + .../flash/iggy/ByteArrayDataStream.java | 5 + .../decompiler/flash/iggy/IggyDataReader.java | 77 +++++++++++ .../jpexs/decompiler/flash/iggy/IggyFile.java | 120 ++++-------------- .../flash/iggy/IggyFlashHeader64.java | 67 ++++------ .../flash/iggy/IggyNameAndTagList.java | 89 ------------- .../iggy/conversion/IggyToSwfConvertor.java | 13 +- 7 files changed, 137 insertions(+), 236 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java delete 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 5587457b2..a1a678260 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 long position(); + public abstract boolean is64(); protected long readUI64() throws IOException { 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 a9fb716d5..750361924 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 @@ -18,6 +18,11 @@ public class ByteArrayDataStream extends AbstractDataStream { this(new byte[initialSize], use64bit); } + @Override + public long position() { + return pos; + } + public ByteArrayDataStream(byte data[], boolean use64bit) { this.data = data; pos = 0; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java new file mode 100644 index 000000000..7951e3393 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.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 IggyDataReader implements StructureInterface { + + @IggyFieldType(value = DataType.widechar_t, count = 48) + String name; + @IggyFieldType(value = DataType.uint64_t) + long unk_pad; + @IggyArrayFieldType(value = DataType.uint64_t, countField = "font_count") + long[] font_main_offsets; + @IggyArrayFieldType(value = DataType.uint64_t, countField = "font_count") + long font_info_offsets[]; + + private IggyFlashHeader64 header; + + public IggyDataReader(IggyFlashHeader64 header, AbstractDataStream stream) throws IOException { + this.header = header; + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + + stream.seek(header.swf_name_offset, SeekMode.SET); + + StringBuilder nameBuilder = new StringBuilder(); + int charCnt = 0; + do { + char c = (char) stream.readUI16(); + charCnt++; + if (c == '\0') { + break; + } + nameBuilder.append(c); + } while (true); + stream.seek(48 - charCnt * 2, SeekMode.CUR); + name = nameBuilder.toString(); + unk_pad = stream.readUI64(); //padding one + for (int i = 0; i < header.font_count; i++) { + font_main_offsets[i] = stream.readUI64(); + } + for (int i = 0; i < header.font_count; i++) { + font_info_offsets[i] = stream.readUI64(); + } + System.out.println("pos=" + stream.position()); + + } + + public String getName() { + return name; + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[\r\n"); + sb.append("name ").append(name).append("\r\n"); + sb.append("]"); + return sb.toString(); + } + +} 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 9d4376b88..1153ce074 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 @@ -30,12 +30,17 @@ public class IggyFile extends AbstractDataStream implements AutoCloseable { private IggyHeader header; private List subFileEntries = new ArrayList<>(); - private List> indexTables = new ArrayList<>(); - private List> offsetTables = new ArrayList<>(); - private List headers = new ArrayList<>(); - private List namesAndTagLists = new ArrayList<>(); - private List> tagDataTables = new ArrayList<>(); + private List flashDataReaders = new ArrayList<>(); + + @Override + public long position() { + try { + return raf.getFilePointer(); + } catch (IOException ex) { + return -1; + } + } public IggyFile(File file) throws IOException { raf = new RandomAccessFile(file, "r"); @@ -44,7 +49,9 @@ public class IggyFile extends AbstractDataStream implements AutoCloseable { subFileEntries.add(new IggySubFileEntry(this)); } - List flashStreams = new ArrayList<>(); + //TODO: use these two for something + List> indexTables = new ArrayList<>(); + List> offsetTables = new ArrayList<>(); for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); @@ -57,50 +64,19 @@ public class IggyFile extends AbstractDataStream implements AutoCloseable { offsetTables.add(offsets); } else if (entry.type == IggySubFileEntry.TYPE_FLASH) { IggyFlashHeaderInterface hdr; - if (is64()) { - hdr = new IggyFlashHeader64(dataStream); - } else { + //if (is64()) { + //FIXME: Make 32 bit version work + hdr = new IggyFlashHeader64(dataStream); + /*} else { hdr = new IggyFlashHeader32(dataStream); - } - //System.out.println("hdr=" + hdr); - IggyNameAndTagList nameTagList = new IggyNameAndTagList(dataStream); - //System.out.println("nameTagList=" + nameTagList); + }*/ + System.out.println("hdr=" + hdr); + IggyDataReader dataReader = new IggyDataReader((IggyFlashHeader64) hdr, dataStream); + System.out.println("dataReader=" + dataReader); headers.add(hdr); - namesAndTagLists.add(nameTagList); - flashStreams.add(dataStream); + flashDataReaders.add(dataReader); } } - for (int i = 0; i < flashStreams.size(); i++) { - ByteArrayDataStream flashStream = flashStreams.get(i); - List offsets = offsetTables.get(i); - List tagIds = namesAndTagLists.get(i).getTagIds(); - List tagExtraInfo = namesAndTagLists.get(i).getTagIdsExtraInfo(); - int offsetIndex = 3; //0 = SWF name, 1 = UI16 zero, 2 = tag list - - List tagDataStreams = new ArrayList<>(); - final int MAX_BUF_SIZE = 4096; - for (int t = 0; t < tagIds.size(); t++) { - long startOffset = offsets.get(offsetIndex); - long endOffset = offsets.get(offsetIndex + 1); - long dataLength = endOffset - startOffset; - long extraInfo = tagExtraInfo.get(t); //TODO: What's this for? - flashStream.seek(startOffset, SeekMode.SET); - long remLength = dataLength; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - do { - int readCount = remLength >= MAX_BUF_SIZE ? MAX_BUF_SIZE : (int) remLength; - byte[] buf = flashStream.readBytes(readCount); - baos.write(buf); - remLength -= readCount; - } while (remLength > 0); - byte tagBytes[] = baos.toByteArray(); //TODO: optimize speed - without ByteArrayOutputStream - - ByteArrayDataStream tagDataStream = new ByteArrayDataStream(tagBytes, is64()); - tagDataStreams.add(tagDataStream); - offsetIndex++; - } - tagDataTables.add(tagDataStreams); - } } @Override @@ -689,27 +665,11 @@ public class IggyFile extends AbstractDataStream implements AutoCloseable { } public int getSwfCount() { - return tagDataTables.size(); + return flashDataReaders.size(); } public String getSwfName(int swfIndex) { - return namesAndTagLists.get(swfIndex).getName(); - } - - public List getSwfTagIds(int swfIndex) { - return namesAndTagLists.get(swfIndex).getTagIds(); - } - - public Long getSwfTagId(int swfIndex, int tagIndex) { - return namesAndTagLists.get(swfIndex).getTagIds().get(tagIndex); - } - - public List getSwfTagExtraInfos(int swfIndex) { - return namesAndTagLists.get(swfIndex).getTagIdsExtraInfo(); - } - - public Long getSwfTagExtraInfo(int swfIndex, int tagIndex) { - return namesAndTagLists.get(swfIndex).getTagIdsExtraInfo().get(tagIndex); + return flashDataReaders.get(swfIndex).getName(); } public long getSwfXMin(int swfIndex) { @@ -731,36 +691,4 @@ public class IggyFile extends AbstractDataStream implements AutoCloseable { public float getSwfFrameRate(int swfIndex) { return headers.get(swfIndex).getFrameRate(); } - - public int getSwfTagCount(int swfIndex) { - return getSwfTagIds(swfIndex).size(); - } - - public AbstractDataStream gettSwfTagDataStream(int swfIndex, int tagIndex) { - return tagDataTables.get(swfIndex).get(tagIndex); - } - - public InputStream getSwfTagInputStream(int swfIndex, int tagIndex) { - return new ByteArrayInputStream(getSwfTagData(swfIndex, tagIndex)); - } - - public byte[] getSwfTagData(int swfIndex, int tagIndex) { - AbstractDataStream stream = gettSwfTagDataStream(swfIndex, tagIndex); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int bufSize = 4096; - //Assuming available() result is always known (= not returning null) - while (stream.available() > 0) { - if (stream.available() < bufSize) { - bufSize = (int) (long) stream.available(); - } - try { - byte[] buffer = stream.readBytes(bufSize); - baos.write(buffer); - } catch (IOException iex) { - //ignore - } - } - return baos.toByteArray(); - } - } 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 52a05196f..65860fec6 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 @@ -1,12 +1,7 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.TagTypeInfo; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; /** * @@ -17,7 +12,7 @@ import java.util.Map; public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @IggyFieldType(DataType.uint64_t) - long main_offset; // 0 Relative offset to first section (matches sizeof header); + long swf_name_offset; // 0 Relative offset to first section (matches sizeof header); @IggyFieldType(DataType.uint64_t) long as3_section_offset; // 8 Relative offset to as3 file names table... @IggyFieldType(DataType.uint64_t) @@ -48,15 +43,15 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { long unk_50; @IggyFieldType(DataType.uint32_t) long unk_54; - float frameRate; + float frame_rate; @IggyFieldType(DataType.uint32_t) long unk_5C; @IggyFieldType(DataType.uint64_t) - long unk_60; + long fonts_offset; @IggyFieldType(DataType.uint64_t) - long unk_68; + long font_infos_offset; @IggyFieldType(DataType.uint64_t) - long names_offset; // 0x70 relative offset to the names/import section of the file + long names_offset; // 0x70 relative offset to the names/import section of the file - end of fonts @IggyFieldType(DataType.uint64_t) long unk_offset5; // 0x78 relative offset to something @IggyFieldType(DataType.uint64_t) @@ -71,12 +66,12 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { long as3_names_offset; // 0xA0 relative offset to as3 file names table (or classes names or whatever) @IggyFieldType(DataType.uint32_t) long unk_A8; + @IggyFieldType(DataType.uint32_t) //font_main_off + long unk_AC; //font_main_size + @IggyFieldType(DataType.uint32_t) //font_info_off + long font_count; // Maybe number of classes / as3 names //font_info_size @IggyFieldType(DataType.uint32_t) - long unk_AC; - @IggyFieldType(DataType.uint32_t) - long unk_B0; // Maybe number of classes / as3 names - @IggyFieldType(DataType.uint32_t) - long unk_B4; + long unk_B4; //zero (?) // Offset 0xB8 (outside header): there are *unk_40* relative offsets that point to flash objects. // The flash objects are in a format different to swf but there is probably a way to convert between them. @@ -88,18 +83,9 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { readFromDataStream(stream); } - /* - offsets: - name (UI16 chars, zero terminated) - UI16 - taglist_offset (aka main_offset) - after_taglist - - - */ @Override public void readFromDataStream(AbstractDataStream stream) throws IOException { - main_offset = stream.readUI64(); + swf_name_offset = stream.readUI64(); as3_section_offset = stream.readUI64(); unk_offset = stream.readUI64(); unk_offset2 = stream.readUI64(); @@ -115,10 +101,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { unk_4C = stream.readUI32(); unk_50 = stream.readUI32(); unk_54 = stream.readUI32(); - frameRate = stream.readFloat(); + frame_rate = stream.readFloat(); unk_5C = stream.readUI32(); - unk_60 = stream.readUI64(); - unk_68 = stream.readUI64(); + fonts_offset = stream.readUI64(); + font_infos_offset = stream.readUI64(); names_offset = stream.readUI64(); unk_offset5 = stream.readUI64(); unk_80 = stream.readUI64(); @@ -128,8 +114,9 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { as3_names_offset = stream.readUI64(); unk_A8 = stream.readUI32(); unk_AC = stream.readUI32(); - unk_B0 = stream.readUI32(); + font_count = stream.readUI32(); unk_B4 = stream.readUI32(); + } @Override @@ -141,28 +128,28 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[\r\n"); - sb.append("main_offset ").append(main_offset).append("\r\n"); + sb.append("main_offset ").append(swf_name_offset).append("\r\n"); sb.append("as3_section_offset ").append(as3_section_offset); - sb.append(" global: ").append(main_offset + as3_section_offset); + sb.append(" global: ").append(swf_name_offset + as3_section_offset); sb.append("\r\n"); sb.append("unk_offset ").append(unk_offset); if (unk_offset != 1) { - sb.append(" global: ").append(main_offset + unk_offset); + sb.append(" global: ").append(swf_name_offset + unk_offset); } sb.append("\r\n"); sb.append("unk_offset2 ").append(unk_offset2); if (unk_offset2 != 1) { - sb.append(" global: ").append(main_offset + unk_offset2); + sb.append(" global: ").append(swf_name_offset + unk_offset2); } sb.append("\r\n"); sb.append("unk_offset3 ").append(unk_offset3); if (unk_offset3 != 1) { - sb.append(" global: ").append(main_offset + unk_offset3); + sb.append(" global: ").append(swf_name_offset + unk_offset3); } sb.append("\r\n"); sb.append("unk_offset4 ").append(unk_offset4); if (unk_offset4 != 1) { - sb.append(" global: ").append(main_offset + unk_offset4); + sb.append(" global: ").append(swf_name_offset + unk_offset4); } sb.append("\r\n"); sb.append("xmin ").append(xmin).append("\r\n"); @@ -175,10 +162,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { sb.append("unk_4C ").append(unk_4C).append("\r\n"); sb.append("unk_50 ").append(unk_50).append("\r\n"); sb.append("unk_54 ").append(unk_54).append("\r\n"); - sb.append("frameRate ").append(frameRate).append("\r\n"); + sb.append("frame_rate ").append(frame_rate).append("\r\n"); sb.append("unk_5C ").append(unk_5C).append("\r\n"); - sb.append("unk_60 ").append(unk_60).append("\r\n"); - sb.append("unk_68 ").append(unk_68).append("\r\n"); + sb.append("fonts_offset ").append(fonts_offset).append("\r\n"); + sb.append("font_infos_offset ").append(font_infos_offset).append("\r\n"); sb.append("names_offset ").append(names_offset).append("\r\n"); sb.append("unk_offset5 ").append(unk_offset5).append("\r\n"); sb.append("unk_80 ").append(unk_80).append("\r\n"); @@ -188,7 +175,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { sb.append("as3_names_offset ").append(as3_names_offset).append("\r\n"); sb.append("unk_A8 ").append(unk_A8).append("\r\n"); sb.append("unk_AC ").append(unk_AC).append("\r\n"); - sb.append("unk_B0 ").append(unk_B0).append("\r\n"); + sb.append("font_count ").append(font_count).append("\r\n"); sb.append("unk_B4 ").append(unk_B4).append("\r\n"); sb.append("]"); return sb.toString(); @@ -217,7 +204,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public float getFrameRate() { - return frameRate; + return frame_rate; } } 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 deleted file mode 100644 index 36a1cd2ee..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyNameAndTagList.java +++ /dev/null @@ -1,89 +0,0 @@ -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 tagIdsExtraInfo; - - public IggyNameAndTagList(String name, List tagIds, List tagIdsExtendedInfo) { - this.name = name; - this.tagIds = tagIds; - this.tagIdsExtraInfo = 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<>(); - tagIdsExtraInfo = new ArrayList<>(); - while (true) { - long tagType = stream.readUI32() & 0xffffffffL; - if (tagType == 0) { - break; - } - long tagLength = stream.readUI32(); - tagIds.add(tagType); - tagIdsExtraInfo.add(tagLength); - } - } - - public String getName() { - return name; - } - - public List getTagIds() { - return tagIds; - } - - public List getTagIdsExtraInfo() { - return tagIdsExtraInfo; - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[\r\n"); - sb.append("name ").append(name).append("\r\n"); - sb.append("tags:").append("\r\n"); - for (int i = 0; i < tagIds.size(); i++) { - sb.append("tag ").append(String.format("%08X", tagIds.get(i))).append(" extra ").append(tagIdsExtraInfo.get(i)).append("\r\n"); - } - sb.append("]"); - return sb.toString(); - } - -} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java index 1fbc112f8..08600b772 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java @@ -2,17 +2,8 @@ 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.SWFOutputStream; -import com.jpexs.decompiler.flash.iggy.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.IggyFile; -import com.jpexs.decompiler.flash.iggy.IggyFlashHeaderInterface; -import com.jpexs.decompiler.flash.iggy.SeekMode; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.UnknownTag; import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.helpers.ByteArrayRange; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -20,7 +11,7 @@ import java.io.OutputStream; /** * - * Unfinished WIP! + * WIP * * @author JPEXS */ @@ -70,7 +61,7 @@ public class IggyToSwfConvertor { (int) (file.getSwfYMax(swfIndex) * SWF.unitDivisor)); swf.version = 9; //FIXME - //TODO: Convert tags + //TODO!!! throw new UnsupportedOperationException("Not implemented yet"); } }