From 2608af6850d54be50d64b2c0bb0ec8ce3893dd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 27 Nov 2016 06:59:28 +0100 Subject: [PATCH 01/27] kerning to em --- .../iggy/conversion/IggyToSwfConvertor.java | 496 +++++++++--------- 1 file changed, 248 insertions(+), 248 deletions(-) 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 ee66d6c06..512eb84a0 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 @@ -1,248 +1,248 @@ -package com.jpexs.decompiler.flash.iggy.conversion; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFCompression; -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.IggyFile; -import com.jpexs.decompiler.flash.iggy.IggyFont; -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.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 java.awt.Color; -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; - -/** - * - * WIP - * - * @author JPEXS - */ -public class IggyToSwfConvertor { - - public static SWF[] getAllSwfs(IggyFile file) { - SWF[] ret = new SWF[file.getSwfCount()]; - for (int i = 0; i < ret.length; i++) { - ret[i] = getSwf(file, i); - } - return ret; - } - - public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException { - for (int swfIndex = 0; swfIndex < file.getSwfCount(); swfIndex++) { - exportSwfToDir(file, swfIndex, outputDir); - } - } - - public static void exportSwfToDir(IggyFile file, int swfIndex, File outputDir) throws IOException { - try (FileOutputStream fos = new FileOutputStream(new File(outputDir, file.getSwfName(swfIndex)))) { - exportSwf(file, swfIndex, fos); - } - } - - public static void exportSwfToFile(IggyFile file, int swfIndex, File outputFile) throws IOException { - try (FileOutputStream fos = new FileOutputStream(outputFile)) { - exportSwf(file, swfIndex, fos); - } - } - - public static void exportSwf(IggyFile file, int swfIndex, OutputStream output) throws IOException { - SWF swf = getSwf(file, swfIndex); - swf.saveTo(output); - } - - private static int makeLengthsTwip(double val) { - return (int) (val * SWF.unitDivisor); - } - - private static int makeLengthsEm(double val) { - return (int) (val * 1024.0); - } - - public static SWF getSwf(IggyFile file, int swfIndex) { - SWF swf = new SWF(); - swf.compression = SWFCompression.NONE; - swf.frameCount = 1; //FIXME!! - swf.frameRate = file.getSwfFrameRate(swfIndex); - swf.gfx = false; - swf.displayRect = new RECT( - (int) (file.getSwfXMin(swfIndex) * SWF.unitDivisor), - (int) (file.getSwfXMax(swfIndex) * SWF.unitDivisor), - (int) (file.getSwfYMin(swfIndex) * SWF.unitDivisor), - (int) (file.getSwfYMax(swfIndex) * SWF.unitDivisor)); - swf.version = 10; //FIXME - - FileAttributesTag fat = new FileAttributesTag(swf); - fat.actionScript3 = false; - fat.hasMetadata = false; - fat.useNetwork = false; - swf.addTag(fat); - - Set fontIndices = file.getFontIds(swfIndex); - - int currentCharId = 0; - Map fontIndex2CharId = new HashMap<>(); - - for (int fontIndex : fontIndices) { - IggyFont iggyFont = file.getFont(swfIndex, 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 = makeLengthsEm(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); - IggyShape glyph = iggyFont.getChars().get(i); - fontTag.codeTable.add(code); - SHAPE shp = IggyShapeToSwfConvertor.convertCharToShape(glyph); - fontTag.glyphShapeTable.add(shp); - fontTag.fontBoundsTable.add(shp.getBounds()); - fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i))); - - } - fontTag.setModified(true); - swf.addTag(fontTag); - } - - /* - //TODO: Texts, they are incomplete - - Map textIndex2CharId = new HashMap<>(); - - Set textIds = file.getTextIds(swfIndex); - for (int textId : textIds) { - IggyText iggyText = file.getText(swfIndex, textId); - DefineEditTextTag textTag = new DefineEditTextTag(swf); - currentCharId++; - textIndex2CharId.put(iggyText.getTextIndex(), 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.getPar3()), - makeLengthsTwip(iggyText.getPar1()), - makeLengthsTwip(iggyText.getPar4()), - makeLengthsTwip(iggyText.getPar2()) - ); - - //textTag.hasFont = true; - //textTag.fontId = fontIndex2CharId.get(iggyText.getFontIndex()); - textTag.setModified(true); - swf.addTag(textTag); - } - */ - 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.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.IggyFile; +import com.jpexs.decompiler.flash.iggy.IggyFont; +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.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 java.awt.Color; +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; + +/** + * + * WIP + * + * @author JPEXS + */ +public class IggyToSwfConvertor { + + public static SWF[] getAllSwfs(IggyFile file) { + SWF[] ret = new SWF[file.getSwfCount()]; + for (int i = 0; i < ret.length; i++) { + ret[i] = getSwf(file, i); + } + return ret; + } + + public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException { + for (int swfIndex = 0; swfIndex < file.getSwfCount(); swfIndex++) { + exportSwfToDir(file, swfIndex, outputDir); + } + } + + public static void exportSwfToDir(IggyFile file, int swfIndex, File outputDir) throws IOException { + try (FileOutputStream fos = new FileOutputStream(new File(outputDir, file.getSwfName(swfIndex)))) { + exportSwf(file, swfIndex, fos); + } + } + + public static void exportSwfToFile(IggyFile file, int swfIndex, File outputFile) throws IOException { + try (FileOutputStream fos = new FileOutputStream(outputFile)) { + exportSwf(file, swfIndex, fos); + } + } + + public static void exportSwf(IggyFile file, int swfIndex, OutputStream output) throws IOException { + SWF swf = getSwf(file, swfIndex); + swf.saveTo(output); + } + + private static int makeLengthsTwip(double val) { + return (int) (val * SWF.unitDivisor); + } + + private static int makeLengthsEm(double val) { + return (int) (val * 1024.0); + } + + public static SWF getSwf(IggyFile file, int swfIndex) { + SWF swf = new SWF(); + swf.compression = SWFCompression.NONE; + swf.frameCount = 1; //FIXME!! + swf.frameRate = file.getSwfFrameRate(swfIndex); + swf.gfx = false; + swf.displayRect = new RECT( + (int) (file.getSwfXMin(swfIndex) * SWF.unitDivisor), + (int) (file.getSwfXMax(swfIndex) * SWF.unitDivisor), + (int) (file.getSwfYMin(swfIndex) * SWF.unitDivisor), + (int) (file.getSwfYMax(swfIndex) * SWF.unitDivisor)); + swf.version = 10; //FIXME + + FileAttributesTag fat = new FileAttributesTag(swf); + fat.actionScript3 = false; + fat.hasMetadata = false; + fat.useNetwork = false; + swf.addTag(fat); + + Set fontIndices = file.getFontIds(swfIndex); + + int currentCharId = 0; + Map fontIndex2CharId = new HashMap<>(); + + for (int fontIndex : fontIndices) { + IggyFont iggyFont = file.getFont(swfIndex, 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 = makeLengthsEm(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); + IggyShape glyph = iggyFont.getChars().get(i); + fontTag.codeTable.add(code); + SHAPE shp = IggyShapeToSwfConvertor.convertCharToShape(glyph); + fontTag.glyphShapeTable.add(shp); + fontTag.fontBoundsTable.add(shp.getBounds()); + fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i))); + + } + fontTag.setModified(true); + swf.addTag(fontTag); + } + + /* + //TODO: Texts, they are incomplete + + Map textIndex2CharId = new HashMap<>(); + + Set textIds = file.getTextIds(swfIndex); + for (int textId : textIds) { + IggyText iggyText = file.getText(swfIndex, textId); + DefineEditTextTag textTag = new DefineEditTextTag(swf); + currentCharId++; + textIndex2CharId.put(iggyText.getTextIndex(), 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.getPar3()), + makeLengthsTwip(iggyText.getPar1()), + makeLengthsTwip(iggyText.getPar4()), + makeLengthsTwip(iggyText.getPar2()) + ); + + //textTag.hasFont = true; + //textTag.fontId = fontIndex2CharId.get(iggyText.getFontIndex()); + textTag.setModified(true); + swf.addTag(textTag); + } + */ + 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); + } + } +} From d05f1e809dd6f534944e72360854408dcc6b7b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 27 Nov 2016 07:56:08 +0100 Subject: [PATCH 02/27] writeToDataStream methods (not in IggyText yet) --- .../flash/iggy/AbstractDataStream.java | 226 +++--- .../flash/iggy/IggyCharAdvances.java | 76 +- .../flash/iggy/IggyCharIndices.java | 91 +-- .../flash/iggy/IggyCharKerning.java | 121 +-- .../decompiler/flash/iggy/IggyCharOffset.java | 209 ++--- .../jpexs/decompiler/flash/iggy/IggyFont.java | 728 ++++++++++-------- .../decompiler/flash/iggy/IggyHeader.java | 314 ++++---- .../decompiler/flash/iggy/IggyShape.java | 324 ++++---- .../decompiler/flash/iggy/IggyShapeNode.java | 252 +++--- .../flash/iggy/IggySubFileEntry.java | 143 ++-- .../jpexs/decompiler/flash/iggy/IggyTag.java | 10 + .../decompiler/flash/iggy/RawIggyTag.java | 36 + 12 files changed, 1366 insertions(+), 1164 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.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 66b21399a..ecc790b51 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 @@ -1,110 +1,116 @@ -package com.jpexs.decompiler.flash.iggy; - -import java.io.EOFException; -import java.io.IOException; - -/** - * - * @author JPEXS - */ -public abstract class AbstractDataStream { - - /** - * Available bytes - * - * @return null if unknown, long value otherwise - */ - public abstract Long available(); - - public abstract long position(); - - public abstract boolean is64(); - - protected long readUI64() throws IOException { - try { - return (readUI32() + (readUI32() << 32)) & 0xffffffffffffffffL; - } catch (EOFException ex) { - return -1; - } - } - - protected boolean writeUI64(long val) throws IOException { - write((int) (val & 0xff)); - write((int) ((val >> 8) & 0xff)); - write((int) ((val >> 16) & 0xff)); - write((int) ((val >> 24) & 0xff)); - - write((int) ((val >> 32) & 0xff)); - write((int) ((val >> 40) & 0xff)); - write((int) ((val >> 48) & 0xff)); - write((int) ((val >> 56) & 0xff)); - return true; - } - - protected long readUI32() throws IOException { - try { - return (readUI8() + (readUI8() << 8) + (readUI8() << 16) + (readUI8() << 24)); - } catch (EOFException ex) { - return -1; - } - } - - protected boolean writeUI32(long val) throws IOException { - write((int) (val & 0xff)); - write((int) ((val >> 8) & 0xff)); - write((int) ((val >> 16) & 0xff)); - write((int) ((val >> 24) & 0xff)); - return true; - } - - protected int readUI16() throws IOException { - try { - return (readUI8() + (readUI8() << 8)) & 0xffff; - } catch (EOFException ex) { - return -1; - } - } - - protected boolean writeUI16(int val) throws IOException { - write(val & 0xff); - write((val >> 8) & 0xff); - return true; - } - - protected int readUI8() throws IOException { - try { - return read() & 0xff; - } catch (EOFException ex) { - return -1; - } - } - - protected boolean writeUI8(int val) throws IOException { - write(val); - return true; - } - - protected float readFloat() throws IOException { - return Float.intBitsToFloat((int) readUI32()); - } - - protected boolean writeFloat(float val) throws IOException { - return writeUI32(Float.floatToIntBits(val)); - } - - protected byte[] readBytes(int numBytes) throws IOException { - byte[] ret = new byte[numBytes]; - for (int i = 0; i < numBytes; i++) { - ret[i] = (byte) read(); - } - return ret; - } - - protected abstract int read() throws IOException; - - protected abstract void seek(long pos, SeekMode mode) throws IOException; - - protected void write(int val) throws IOException { - //nothing - } -} +package com.jpexs.decompiler.flash.iggy; + +import java.io.EOFException; +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public abstract class AbstractDataStream { + + /** + * Available bytes + * + * @return null if unknown, long value otherwise + */ + public abstract Long available(); + + public abstract long position(); + + public abstract boolean is64(); + + protected long readUI64() throws IOException { + try { + return (readUI32() + (readUI32() << 32)) & 0xffffffffffffffffL; + } catch (EOFException ex) { + return -1; + } + } + + protected boolean writeUI64(long val) throws IOException { + write((int) (val & 0xff)); + write((int) ((val >> 8) & 0xff)); + write((int) ((val >> 16) & 0xff)); + write((int) ((val >> 24) & 0xff)); + + write((int) ((val >> 32) & 0xff)); + write((int) ((val >> 40) & 0xff)); + write((int) ((val >> 48) & 0xff)); + write((int) ((val >> 56) & 0xff)); + return true; + } + + protected long readUI32() throws IOException { + try { + return (readUI8() + (readUI8() << 8) + (readUI8() << 16) + (readUI8() << 24)); + } catch (EOFException ex) { + return -1; + } + } + + protected boolean writeUI32(long val) throws IOException { + write((int) (val & 0xff)); + write((int) ((val >> 8) & 0xff)); + write((int) ((val >> 16) & 0xff)); + write((int) ((val >> 24) & 0xff)); + return true; + } + + protected int readUI16() throws IOException { + try { + return (readUI8() + (readUI8() << 8)) & 0xffff; + } catch (EOFException ex) { + return -1; + } + } + + protected boolean writeUI16(int val) throws IOException { + write(val & 0xff); + write((val >> 8) & 0xff); + return true; + } + + protected int readUI8() throws IOException { + try { + return read() & 0xff; + } catch (EOFException ex) { + return -1; + } + } + + protected boolean writeUI8(int val) throws IOException { + write(val); + return true; + } + + protected float readFloat() throws IOException { + return Float.intBitsToFloat((int) readUI32()); + } + + protected boolean writeFloat(float val) throws IOException { + return writeUI32(Float.floatToIntBits(val)); + } + + protected byte[] readBytes(int numBytes) throws IOException { + byte[] ret = new byte[numBytes]; + for (int i = 0; i < numBytes; i++) { + ret[i] = (byte) read(); + } + return ret; + } + + protected void writeBytes(byte[] data) throws IOException { + for (int i = 0; i < data.length; i++) { + write(data[i] & 0xff); + } + } + + protected abstract int read() throws IOException; + + protected abstract void seek(long pos, SeekMode mode) throws IOException; + + protected void write(int val) throws IOException { + //nothing + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java index 7e5a4b864..d2b83fd78 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java @@ -1,37 +1,39 @@ -package com.jpexs.decompiler.flash.iggy; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class IggyCharAdvances implements StructureInterface { - - List advances; - private long charCount; - - public List getScales() { - return advances; - } - - public IggyCharAdvances(AbstractDataStream stream, long charCount) throws IOException { - this.charCount = charCount; - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - advances = new ArrayList<>(); - for (int i = 0; i < charCount; i++) { - advances.add(stream.readFloat()); - } - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } -} +package com.jpexs.decompiler.flash.iggy; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class IggyCharAdvances implements StructureInterface { + + List advances; + private long charCount; + + public List getScales() { + return advances; + } + + public IggyCharAdvances(AbstractDataStream stream, long charCount) throws IOException { + this.charCount = charCount; + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + advances = new ArrayList<>(); + for (int i = 0; i < charCount; i++) { + advances.add(stream.readFloat()); + } + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + for (int i = 0; i < advances.size(); i++) { + stream.writeFloat(advances.get(i)); + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java index 6c57824df..30afb23d7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java @@ -1,44 +1,47 @@ -package com.jpexs.decompiler.flash.iggy; - -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class IggyCharIndices implements StructureInterface { - - @IggyFieldType(value = DataType.widechar_t) - List chars; - @IggyFieldType(DataType.uint32_t) - long padd; - - public List getChars() { - return chars; - } - - private long charCount; - - public IggyCharIndices(AbstractDataStream stream, long charCount) throws IOException { - this.charCount = charCount; - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - chars = new ArrayList<>(); - for (int i = 0; i < charCount; i++) { - chars.add((char) stream.readUI16()); - } - padd = stream.readUI32(); - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class IggyCharIndices implements StructureInterface { + + @IggyFieldType(value = DataType.widechar_t) + List chars; + @IggyFieldType(DataType.uint32_t) + long padd; + + public List getChars() { + return chars; + } + + private long charCount; + + public IggyCharIndices(AbstractDataStream stream, long charCount) throws IOException { + this.charCount = charCount; + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + chars = new ArrayList<>(); + for (int i = 0; i < charCount; i++) { + chars.add((char) stream.readUI16()); + } + padd = stream.readUI32(); + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + for (int i = 0; i < chars.size(); i++) { + stream.writeUI16(chars.get(i)); + } + stream.writeUI32(padd); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index ee00e2c84..9a51e01e5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -1,58 +1,63 @@ -package com.jpexs.decompiler.flash.iggy; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class IggyCharKerning implements StructureInterface { - - private long kernCount; - List charsA; - List charsB; - List kerningOffsets; - long pad; - - public long getKernCount() { - return kernCount; - } - - public List getCharsA() { - return charsA; - } - - public List getCharsB() { - return charsB; - } - - public List getKerningOffsets() { - return kerningOffsets; - } - - public IggyCharKerning(AbstractDataStream stream, long kernCount) throws IOException { - this.kernCount = kernCount; - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - charsA = new ArrayList<>(); - charsB = new ArrayList<>(); - kerningOffsets = new ArrayList<>(); - for (int i = 0; i < kernCount; i++) { - charsA.add((char) stream.readUI16()); - charsB.add((char) stream.readUI16()); - kerningOffsets.add((short) stream.readUI16()); - } - pad = stream.readUI32(); - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - -} +package com.jpexs.decompiler.flash.iggy; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class IggyCharKerning implements StructureInterface { + + private long kernCount; + List charsA; + List charsB; + List kerningOffsets; + long pad; + + public long getKernCount() { + return kernCount; + } + + public List getCharsA() { + return charsA; + } + + public List getCharsB() { + return charsB; + } + + public List getKerningOffsets() { + return kerningOffsets; + } + + public IggyCharKerning(AbstractDataStream stream, long kernCount) throws IOException { + this.kernCount = kernCount; + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + charsA = new ArrayList<>(); + charsB = new ArrayList<>(); + kerningOffsets = new ArrayList<>(); + for (int i = 0; i < kernCount; i++) { + charsA.add((char) stream.readUI16()); + charsB.add((char) stream.readUI16()); + kerningOffsets.add((short) stream.readUI16()); + } + pad = stream.readUI32(); + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + for (int i = 0; i < kernCount; i++) { + stream.writeUI16(charsA.get(i)); + stream.writeUI16(charsB.get(i)); + stream.writeUI16(kerningOffsets.get(i)); + } + stream.writeUI32(pad); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 0899925ac..7c52ce468 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -1,99 +1,110 @@ -package com.jpexs.decompiler.flash.iggy; - -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import java.io.IOException; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - */ -public class IggyCharOffset implements StructureInterface { - - private static Logger LOGGER = Logger.getLogger(IggyCharOffset.class.getName()); - - @IggyFieldType(DataType.uint64_t) - long zero; - @IggyFieldType(DataType.uint16_t) - int ischar1; - @IggyFieldType(DataType.uint16_t) - int ischar2; - @IggyFieldType(DataType.uint32_t) - long zero2; - @IggyFieldType(DataType.uint16_t) - int xscale; - @IggyFieldType(DataType.uint16_t) - int yscale; - @IggyFieldType(DataType.uint32_t) - long zero3; - @IggyFieldType(DataType.uint64_t) - long offset; - - public IggyCharOffset(AbstractDataStream stream) throws IOException { - readFromDataStream(stream); - } - - public IggyCharOffset(long zero, int ischar1, int ischar2, long zero2, int xscale, int yscale, long zero3, long offset) { - this.zero = zero; - this.ischar1 = ischar1; - this.ischar2 = ischar2; - this.zero2 = zero2; - this.xscale = xscale; - this.yscale = yscale; - this.zero3 = zero3; - this.offset = offset; - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - zero = stream.readUI64(); - ischar1 = stream.readUI16(); - ischar2 = stream.readUI16(); - zero2 = stream.readUI32(); - xscale = stream.readUI16(); - yscale = stream.readUI16(); - zero3 = stream.readUI32(); - long cur_position = stream.position(); - long relative_offset = stream.readUI64(); - if (ischar1 > 0) { - offset = cur_position + relative_offset; - } else { - offset = 0; - LOGGER.finer(String.format("Empty char")); - } - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public long getZero() { - return zero; - } - - public boolean isChar1() { - return ischar1 > 0; - } - - public boolean isChar2() { - return ischar2 > 0; - } - - public long getZero2() { - return zero2; - } - - public int getXscale() { - return xscale; - } - - public int getYscale() { - return yscale; - } - - public long getZero3() { - return zero3; - } - -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class IggyCharOffset implements StructureInterface { + + private static Logger LOGGER = Logger.getLogger(IggyCharOffset.class.getName()); + + @IggyFieldType(DataType.uint64_t) + long zero; + @IggyFieldType(DataType.uint16_t) + int ischar1; + @IggyFieldType(DataType.uint16_t) + int ischar2; + @IggyFieldType(DataType.uint32_t) + long zero2; + @IggyFieldType(DataType.uint16_t) + int xscale; + @IggyFieldType(DataType.uint16_t) + int yscale; + @IggyFieldType(DataType.uint32_t) + long zero3; + @IggyFieldType(DataType.uint64_t) + long offset; + + public IggyCharOffset(AbstractDataStream stream) throws IOException { + readFromDataStream(stream); + } + + public IggyCharOffset(long zero, int ischar1, int ischar2, long zero2, int xscale, int yscale, long zero3, long offset) { + this.zero = zero; + this.ischar1 = ischar1; + this.ischar2 = ischar2; + this.zero2 = zero2; + this.xscale = xscale; + this.yscale = yscale; + this.zero3 = zero3; + this.offset = offset; + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + zero = stream.readUI64(); + ischar1 = stream.readUI16(); + ischar2 = stream.readUI16(); + zero2 = stream.readUI32(); + xscale = stream.readUI16(); + yscale = stream.readUI16(); + zero3 = stream.readUI32(); + long cur_position = stream.position(); + long relative_offset = stream.readUI64(); + if (ischar1 > 0) { + offset = cur_position + relative_offset; + } else { + offset = 0; + LOGGER.finer(String.format("Empty char")); + } + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + stream.writeUI64(zero); + stream.writeUI16(ischar1); + stream.writeUI16(ischar2); + stream.writeUI32(zero2); + stream.writeUI16(xscale); + stream.writeUI16(yscale); + stream.writeUI32(zero3); + if (ischar1 > 0) { + stream.writeUI64(offset - stream.position()); + } else { + stream.writeUI64(1); + } + } + + public long getZero() { + return zero; + } + + public boolean isChar1() { + return ischar1 > 0; + } + + public boolean isChar2() { + return ischar2 > 0; + } + + public long getZero2() { + return zero2; + } + + public int getXscale() { + return xscale; + } + + public int getYscale() { + return yscale; + } + + public long getZero3() { + return zero3; + } + +} 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 bd9def55c..ea9f86b00 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 @@ -1,316 +1,412 @@ -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 IggyFont implements StructureInterface { - - public static final int ID = 0xFF16; - - @IggyFieldType(DataType.uint16_t) - int type; //stejny pro rozdilne fonty - @IggyFieldType(DataType.uint16_t) - int fontId; - @IggyArrayFieldType(value = DataType.uint8_t, count = 28) - byte[] zeroone; // stejny pro rozdilne fonty - @IggyFieldType(DataType.uint16_t) - int char_count2; - @IggyFieldType(value = DataType.uint16_t) - int ascent; - @IggyFieldType(value = DataType.uint16_t) - int descent; - @IggyFieldType(value = DataType.uint16_t) - int leading; - @IggyFieldType(DataType.uint64_t) - long flags; - @IggyFieldType(DataType.uint64_t) - long start_of_char_struct; - @IggyFieldType(DataType.uint64_t) - long start_of_char_index; - @IggyFieldType(DataType.uint64_t) - long start_of_scale; - @IggyFieldType(DataType.uint32_t) - long kern_count; - @IggyArrayFieldType(value = DataType.float_t, count = 5) - float[] unk_float; - @IggyFieldType(DataType.uint64_t) - long start_of_kern; - @IggyFieldType(DataType.uint64_t) - long zero_padd; - @IggyFieldType(DataType.uint64_t) - long what_2; - @IggyFieldType(DataType.uint64_t) - long zero_padd_2; - @IggyFieldType(DataType.uint64_t) - long start_of_name; - @IggyFieldType(DataType.uint64_t) - long one_padd; - @IggyFieldType(DataType.uint16_t) - int xscale; - @IggyFieldType(DataType.uint16_t) - int yscale; - @IggyFieldType(DataType.uint64_t) - long zero_padd_3; - @IggyFieldType(DataType.float_t) - float ssr1; - @IggyFieldType(DataType.float_t) - float ssr2; - @IggyFieldType(DataType.uint32_t) - long char_count; - @IggyFieldType(DataType.uint64_t) - long zero_padd_4; - @IggyFieldType(DataType.uint64_t) - long what_3; - @IggyFieldType(value = DataType.uint8_t, count = 272) - byte[] zeroes; - @IggyFieldType(DataType.float_t) - float sss1; - @IggyFieldType(DataType.uint32_t) - long one_padd2; - @IggyFieldType(DataType.float_t) - float sss2; - @IggyFieldType(DataType.uint32_t) - long one_padd3; - @IggyFieldType(DataType.float_t) - float sss3; - @IggyFieldType(DataType.uint32_t) - long one_padd4; - @IggyFieldType(DataType.float_t) - float sss4; - @IggyFieldType(DataType.uint32_t) - long one_padd5; - - @IggyFieldType(value = DataType.widechar_t, count = 16) - String name; - - List charOffsets; - List glyphs; - IggyCharIndices codePoints; - IggyCharAdvances charScales; - IggyCharKerning charKernings; - - byte[] padTo4byteBoundary; - - public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { - this.type = type; - this.fontId = order_in_iggy_file; - this.zeroone = zeroone; - this.char_count2 = char_count2; - this.ascent = ascent; - this.descent = descent; - this.leading = leading; - this.flags = flags; - this.start_of_char_struct = start_of_char_struct; - this.start_of_char_index = start_of_char_index; - this.start_of_scale = start_of_scale; - this.kern_count = kern_count; - this.unk_float = unk_float; - this.start_of_kern = start_of_kern; - this.zero_padd = zero_padd; - this.what_2 = what_2; - this.zero_padd_2 = zero_padd_2; - this.start_of_name = start_of_name; - this.one_padd = one_padd; - this.xscale = xscale; - this.yscale = yscale; - this.zero_padd_3 = zero_padd_3; - this.ssr1 = ssr1; - this.ssr2 = ssr2; - this.char_count = char_count; - this.zero_padd_4 = zero_padd_4; - this.what_3 = what_3; - this.zeroes = zeroes; - this.sss1 = sss1; - this.one_padd2 = one_padd2; - this.sss2 = sss2; - this.one_padd3 = one_padd3; - this.sss3 = sss3; - this.one_padd4 = one_padd4; - this.sss4 = sss4; - this.one_padd5 = one_padd5; - this.name = name; - this.charOffsets = charOffsets; - this.glyphs = chars; - this.codePoints = charIndices; - this.charScales = charScales; - this.charKernings = charKernings; - this.padTo4byteBoundary = padTo4byteBoundary; - } - - public IggyFont(AbstractDataStream stream) throws IOException { - readFromDataStream(stream); - } - - private long readAbsoluteOffset(AbstractDataStream stream) throws IOException { - long offset = stream.readUI64(); - if (offset == 1) { - return 0; - } - return stream.position() - 8 + offset; - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - ByteArrayDataStream s = new ByteArrayDataStream(stream.readBytes((int) (long) stream.available()), stream.is64()); - type = s.readUI16(); - fontId = s.readUI16(); - zeroone = s.readBytes(28); - char_count2 = s.readUI16(); - ascent = s.readUI16(); - descent = s.readUI16(); - leading = s.readUI16(); - flags = s.readUI64(); - start_of_char_struct = readAbsoluteOffset(s); - start_of_char_index = readAbsoluteOffset(s); - start_of_scale = readAbsoluteOffset(s); - kern_count = s.readUI32(); - unk_float = new float[5]; - for (int i = 0; i < unk_float.length; i++) { - unk_float[i] = s.readFloat(); - } - start_of_kern = readAbsoluteOffset(s); - zero_padd = s.readUI64(); - what_2 = s.readUI64(); - zero_padd_2 = s.readUI64(); - start_of_name = readAbsoluteOffset(s); - one_padd = s.readUI64(); - xscale = s.readUI16(); - yscale = s.readUI16(); - zero_padd_3 = s.readUI64(); - ssr1 = s.readFloat(); - ssr2 = s.readFloat(); - char_count = s.readUI32(); - zero_padd_4 = s.readUI64(); - what_3 = s.readUI64(); - s.seek(272, SeekMode.CUR); - sss1 = s.readFloat(); - one_padd2 = s.readUI32(); - sss2 = s.readFloat(); - one_padd3 = s.readUI32(); - sss3 = s.readFloat(); - one_padd4 = s.readUI32(); - sss4 = s.readFloat(); - one_padd5 = s.readUI32(); - if (start_of_name != 0) { - s.seek(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(); - } - s.readUI64(); //pad zero - if (start_of_char_struct != 0) { - s.seek(start_of_char_struct, SeekMode.SET); - charOffsets = new ArrayList<>(); - for (int i = 0; i < char_count; i++) { - charOffsets.add(new IggyCharOffset(s)); - } - glyphs = new ArrayList<>(); - for (int i = 0; i < char_count; i++) { - long offset = charOffsets.get(i).offset; - glyphs.add(new IggyShape(s, offset)); - } - } - if (start_of_char_index != 0) { - s.seek(start_of_char_index, SeekMode.SET); - codePoints = new IggyCharIndices(s, char_count); - } - if (start_of_scale != 0) { - s.seek(start_of_scale, SeekMode.SET); - charScales = new IggyCharAdvances(s, char_count); - } - if (start_of_kern != 0) { - s.seek(start_of_kern, SeekMode.SET); - charKernings = new IggyCharKerning(s, kern_count); - } - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public int getType() { - return type; - } - - public long getFlags() { - return flags; - } - - public int getXscale() { - return xscale; - } - - public int getYscale() { - return yscale; - } - - public long getCharacterCount() { - return char_count; - } - - public String getName() { - return name; - } - - public List getChars() { - return glyphs; - } - - public IggyCharIndices getCharIndices() { - return codePoints; - } - - public IggyCharAdvances getCharAdvances() { - return charScales; - } - - public IggyCharKerning getCharKernings() { - return charKernings; - } - - public float[] getUnk_float() { - return unk_float; - } - - public int getAscent() { - return ascent; - } - - public int getDescent() { - return descent; - } - - public int getLeading() { - return leading; - } - - public long getWhat_2() { - return what_2; - } - - public long getWhat_3() { - return what_3; - } - - public List getCharOffsets() { - return charOffsets; - } - -} +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 IggyFont extends IggyTag { + + public static final int ID = 0xFF16; + + @IggyFieldType(DataType.uint16_t) + int type; //stejny pro rozdilne fonty + @IggyFieldType(DataType.uint16_t) + int fontId; + @IggyArrayFieldType(value = DataType.uint8_t, count = 28) + byte[] zeroone; // stejny pro rozdilne fonty + @IggyFieldType(DataType.uint16_t) + int char_count2; + @IggyFieldType(value = DataType.uint16_t) + int ascent; + @IggyFieldType(value = DataType.uint16_t) + int descent; + @IggyFieldType(value = DataType.uint16_t) + int leading; + @IggyFieldType(DataType.uint64_t) + long flags; + @IggyFieldType(DataType.uint64_t) + long start_of_char_struct; + @IggyFieldType(DataType.uint64_t) + long start_of_char_index; + @IggyFieldType(DataType.uint64_t) + long start_of_scale; + @IggyFieldType(DataType.uint32_t) + long kern_count; + @IggyArrayFieldType(value = DataType.float_t, count = 5) + float[] unk_float; + @IggyFieldType(DataType.uint64_t) + long start_of_kern; + @IggyFieldType(DataType.uint64_t) + long zero_padd; + @IggyFieldType(DataType.uint64_t) + long what_2; + @IggyFieldType(DataType.uint64_t) + long zero_padd_2; + @IggyFieldType(DataType.uint64_t) + long start_of_name; + @IggyFieldType(DataType.uint64_t) + long one_padd; + @IggyFieldType(DataType.uint16_t) + int xscale; + @IggyFieldType(DataType.uint16_t) + int yscale; + @IggyFieldType(DataType.uint64_t) + long zero_padd_3; + @IggyFieldType(DataType.float_t) + float ssr1; + @IggyFieldType(DataType.float_t) + float ssr2; + @IggyFieldType(DataType.uint32_t) + long char_count; + @IggyFieldType(DataType.uint64_t) + long zero_padd_4; + @IggyFieldType(DataType.uint64_t) + long what_3; + @IggyFieldType(value = DataType.uint8_t, count = 272) + byte[] zeroes; + @IggyFieldType(DataType.float_t) + float sss1; + @IggyFieldType(DataType.uint32_t) + long one_padd2; + @IggyFieldType(DataType.float_t) + float sss2; + @IggyFieldType(DataType.uint32_t) + long one_padd3; + @IggyFieldType(DataType.float_t) + float sss3; + @IggyFieldType(DataType.uint32_t) + long one_padd4; + @IggyFieldType(DataType.float_t) + float sss4; + @IggyFieldType(DataType.uint32_t) + long one_padd5; + + @IggyFieldType(value = DataType.widechar_t, count = 16) + String name; + + List charOffsets; + List glyphs; + IggyCharIndices codePoints; + IggyCharAdvances charScales; + IggyCharKerning charKernings; + + byte[] padTo4byteBoundary; + + public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { + this.type = type; + this.fontId = order_in_iggy_file; + this.zeroone = zeroone; + this.char_count2 = char_count2; + this.ascent = ascent; + this.descent = descent; + this.leading = leading; + this.flags = flags; + this.start_of_char_struct = start_of_char_struct; + this.start_of_char_index = start_of_char_index; + this.start_of_scale = start_of_scale; + this.kern_count = kern_count; + this.unk_float = unk_float; + this.start_of_kern = start_of_kern; + this.zero_padd = zero_padd; + this.what_2 = what_2; + this.zero_padd_2 = zero_padd_2; + this.start_of_name = start_of_name; + this.one_padd = one_padd; + this.xscale = xscale; + this.yscale = yscale; + this.zero_padd_3 = zero_padd_3; + this.ssr1 = ssr1; + this.ssr2 = ssr2; + this.char_count = char_count; + this.zero_padd_4 = zero_padd_4; + this.what_3 = what_3; + this.zeroes = zeroes; + this.sss1 = sss1; + this.one_padd2 = one_padd2; + this.sss2 = sss2; + this.one_padd3 = one_padd3; + this.sss3 = sss3; + this.one_padd4 = one_padd4; + this.sss4 = sss4; + this.one_padd5 = one_padd5; + this.name = name; + this.charOffsets = charOffsets; + this.glyphs = chars; + this.codePoints = charIndices; + this.charScales = charScales; + this.charKernings = charKernings; + this.padTo4byteBoundary = padTo4byteBoundary; + } + + public IggyFont(AbstractDataStream stream) throws IOException { + readFromDataStream(stream); + } + + private long readAbsoluteOffset(AbstractDataStream stream) throws IOException { + long offset = stream.readUI64(); + if (offset == 1) { + return 0; + } + return stream.position() - 8 + offset; + } + + private void writeAbsoluteOffset(AbstractDataStream stream, long offset) throws IOException { + if (offset == 0) { + stream.writeUI64(1); + } else { + stream.writeUI64(offset - stream.position()); + } + } + + private void writeRelativeOffset(AbstractDataStream stream, long offset) throws IOException { + if (offset == 0) { + stream.writeUI64(1); + } else { + stream.writeUI64(offset); + } + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + ByteArrayDataStream s = new ByteArrayDataStream(stream.readBytes((int) (long) stream.available()), stream.is64()); + type = s.readUI16(); + fontId = s.readUI16(); + zeroone = s.readBytes(28); + char_count2 = s.readUI16(); + ascent = s.readUI16(); + descent = s.readUI16(); + leading = s.readUI16(); + flags = s.readUI64(); + start_of_char_struct = readAbsoluteOffset(s); + start_of_char_index = readAbsoluteOffset(s); + start_of_scale = readAbsoluteOffset(s); + kern_count = s.readUI32(); + unk_float = new float[5]; + for (int i = 0; i < unk_float.length; i++) { + unk_float[i] = s.readFloat(); + } + start_of_kern = readAbsoluteOffset(s); + zero_padd = s.readUI64(); + what_2 = s.readUI64(); + zero_padd_2 = s.readUI64(); + start_of_name = readAbsoluteOffset(s); + one_padd = s.readUI64(); + xscale = s.readUI16(); + yscale = s.readUI16(); + zero_padd_3 = s.readUI64(); + ssr1 = s.readFloat(); + ssr2 = s.readFloat(); + char_count = s.readUI32(); + zero_padd_4 = s.readUI64(); + what_3 = s.readUI64(); + s.seek(272, SeekMode.CUR); + sss1 = s.readFloat(); + one_padd2 = s.readUI32(); + sss2 = s.readFloat(); + one_padd3 = s.readUI32(); + sss3 = s.readFloat(); + one_padd4 = s.readUI32(); + sss4 = s.readFloat(); + one_padd5 = s.readUI32(); + if (start_of_name != 0) { + s.seek(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(); + } + s.readUI64(); //pad zero + if (start_of_char_struct != 0) { + s.seek(start_of_char_struct, SeekMode.SET); + charOffsets = new ArrayList<>(); + for (int i = 0; i < char_count; i++) { + charOffsets.add(new IggyCharOffset(s)); + } + glyphs = new ArrayList<>(); + for (int i = 0; i < char_count; i++) { + long offset = charOffsets.get(i).offset; + glyphs.add(new IggyShape(s, offset)); + } + } + if (start_of_char_index != 0) { + s.seek(start_of_char_index, SeekMode.SET); + codePoints = new IggyCharIndices(s, char_count); + } + if (start_of_scale != 0) { + s.seek(start_of_scale, SeekMode.SET); + charScales = new IggyCharAdvances(s, char_count); + } + if (start_of_kern != 0) { + s.seek(start_of_kern, SeekMode.SET); + charKernings = new IggyCharKerning(s, kern_count); + } + } + + @Override + public void writeToDataStream(AbstractDataStream s) throws IOException { + s.writeUI16(type); + s.writeUI16(fontId); + s.writeBytes(zeroone); + s.writeUI16(char_count2); + s.writeUI16(ascent); + s.writeUI16(descent); + s.writeUI16(leading); + s.writeUI64(flags); + writeAbsoluteOffset(s, start_of_char_struct); + writeAbsoluteOffset(s, start_of_char_index); + writeAbsoluteOffset(s, start_of_scale); + s.writeUI32(kern_count); + for (int i = 0; i < unk_float.length; i++) { + s.writeFloat(unk_float[i]); + } + writeAbsoluteOffset(s, start_of_kern); + s.writeUI64(zero_padd); + s.writeUI64(what_2); + s.writeUI64(zero_padd_2); + writeAbsoluteOffset(s, start_of_name); + s.writeUI64(one_padd); + s.writeUI16(xscale); + s.writeUI16(yscale); + s.writeUI64(zero_padd_3); + s.writeFloat(ssr1); + s.writeFloat(ssr2); + s.writeUI32(char_count); + s.writeUI64(zero_padd_4); + s.writeUI64(what_3); + //s.seek(272, SeekMode.CUR); + for (int i = 0; i < 272; i++) { + s.write(0); + } + s.writeFloat(sss1); + s.writeUI32(one_padd2); + s.writeFloat(sss2); + s.writeUI32(one_padd3); + s.writeFloat(sss3); + s.writeUI32(one_padd4); + s.writeFloat(sss4); + s.writeUI32(one_padd5); + if (start_of_name != 0) { + for (char c : name.toCharArray()) { + s.writeUI16(c); + } + s.writeUI16(0); + + //align to 8 bytes boundary + int len = name.length() * 2 + 2; + int rem = 8 - (len % 8); + for (int i = 0; i < rem; i++) { + s.write(0); + } + } + s.writeUI64(0); //pad zero + if (start_of_char_struct != 0) { + //offsets of shapes + for (IggyCharOffset ofs : charOffsets) { + ofs.writeToDataStream(s); + } + for (IggyShape shp : glyphs) { + shp.writeToDataStream(s); + } + } + if (start_of_char_index != 0) { + for (char c : codePoints.chars) { + s.writeUI16(c); + } + s.writeUI32(0); + } + if (start_of_scale != 0) { + charScales.writeToDataStream(s); + } + if (start_of_kern != 0) { + charKernings.writeToDataStream(s); + } + } + + public int getType() { + return type; + } + + public long getFlags() { + return flags; + } + + public int getXscale() { + return xscale; + } + + public int getYscale() { + return yscale; + } + + public long getCharacterCount() { + return char_count; + } + + public String getName() { + return name; + } + + public List getChars() { + return glyphs; + } + + public IggyCharIndices getCharIndices() { + return codePoints; + } + + public IggyCharAdvances getCharAdvances() { + return charScales; + } + + public IggyCharKerning getCharKernings() { + return charKernings; + } + + public float[] getUnk_float() { + return unk_float; + } + + public int getAscent() { + return ascent; + } + + public int getDescent() { + return descent; + } + + public int getLeading() { + return leading; + } + + public long getWhat_2() { + return what_2; + } + + public long getWhat_3() { + return what_3; + } + + public List getCharOffsets() { + return charOffsets; + } + + @Override + public int getTagType() { + return ID; + } + +} 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 ca9b8f9a2..2bb41162d 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 @@ -1,153 +1,161 @@ -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; - -/** - * - * @author JPEXS - * - * little endian all - * - * Based of works of somebody called eternity. - */ -public class IggyHeader implements StructureInterface { - - public static long MAGIC = 0xED0A6749; - - //Must be 0xED0A6749 - @IggyFieldType(DataType.uint32_t) - private long magic = MAGIC; - - //Assume 0x900 - @IggyFieldType(DataType.uint32_t) - private long version; - - //Assuming: 1 - @IggyFieldType(value = DataType.uint8_t) - private int platform1; - - //32/64 - @IggyFieldType(value = DataType.uint8_t) - private int platform2; - - //Assuming: 1 - @IggyFieldType(value = DataType.uint8_t) - private int platform3; - - //Usually: 3 - @IggyFieldType(value = DataType.uint8_t) - private int platform4; - - //flags for platform 64? - @IggyFieldType(DataType.uint32_t) - private long unk_0C; - - @IggyArrayFieldType(value = DataType.uint8_t, count = 12) - private byte[] reserved; - - @IggyFieldType(value = DataType.uint32_t) - private long numSubfiles; - - public IggyHeader(AbstractDataStream stream) throws IOException { - readFromDataStream(stream); - } - - /** - * - * @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 = platform2; - this.platform3 = platform3; - this.platform4 = platform4; - this.unk_0C = unk_0C; - this.reserved = reserved; - this.numSubfiles = num_subfiles; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("["); - sb.append("version: ").append(version).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(numSubfiles); - sb.append("]"); - return sb.toString(); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - magic = stream.readUI32(); - if (magic != IggyHeader.MAGIC) { - throw new IOException("Invalid Iggy file"); - } - version = stream.readUI32(); - platform1 = stream.readUI8(); - platform2 = stream.readUI8(); //32/64 - platform3 = stream.readUI8(); - platform4 = stream.readUI8(); - unk_0C = stream.readUI32(); - reserved = stream.readBytes(12); - numSubfiles = stream.readUI32(); - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public boolean is64() { - 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; - } - -} +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; + +/** + * + * @author JPEXS + * + * little endian all + * + * Based of works of somebody called eternity. + */ +public class IggyHeader implements StructureInterface { + + public static long MAGIC = 0xED0A6749; + + //Must be 0xED0A6749 + @IggyFieldType(DataType.uint32_t) + private long magic = MAGIC; + + //Assume 0x900 + @IggyFieldType(DataType.uint32_t) + private long version; + + //Assuming: 1 + @IggyFieldType(value = DataType.uint8_t) + private int platform1; + + //32/64 + @IggyFieldType(value = DataType.uint8_t) + private int platform2; + + //Assuming: 1 + @IggyFieldType(value = DataType.uint8_t) + private int platform3; + + //Usually: 3 + @IggyFieldType(value = DataType.uint8_t) + private int platform4; + + //flags for platform 64? + @IggyFieldType(DataType.uint32_t) + private long unk_0C; + + @IggyArrayFieldType(value = DataType.uint8_t, count = 12) + private byte[] reserved; + + @IggyFieldType(value = DataType.uint32_t) + private long numSubfiles; + + public IggyHeader(AbstractDataStream stream) throws IOException { + readFromDataStream(stream); + } + + /** + * + * @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 = platform2; + this.platform3 = platform3; + this.platform4 = platform4; + this.unk_0C = unk_0C; + this.reserved = reserved; + this.numSubfiles = num_subfiles; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + sb.append("version: ").append(version).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(numSubfiles); + sb.append("]"); + return sb.toString(); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + magic = stream.readUI32(); + if (magic != IggyHeader.MAGIC) { + throw new IOException("Invalid Iggy file"); + } + version = stream.readUI32(); + platform1 = stream.readUI8(); + platform2 = stream.readUI8(); //32/64 + platform3 = stream.readUI8(); + platform4 = stream.readUI8(); + unk_0C = stream.readUI32(); + reserved = stream.readBytes(12); + numSubfiles = stream.readUI32(); + } + + @Override + public void writeToDataStream(AbstractDataStream s) throws IOException { + s.writeUI32(magic); + s.writeUI32(version); + s.writeUI8(platform1); + s.writeUI8(platform2); + s.writeUI8(platform3); + s.writeUI8(platform4); + s.writeUI32(unk_0C); + s.writeBytes(reserved); + s.writeUI32(numSubfiles); + } + + public boolean is64() { + 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/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index e5272877e..49d72e6a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -1,155 +1,169 @@ -package com.jpexs.decompiler.flash.iggy; - -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - */ -public class IggyShape implements StructureInterface { - - private static Logger LOGGER = Logger.getLogger(IggyShape.class.getName()); - - @IggyFieldType(DataType.float_t) - float minx; //bearing X - this is the horizontal distance from the current pen position to the glyph's left bbox edge. - @IggyFieldType(DataType.float_t) - float miny; //bearing Y - this is the vertical distance from the baseline to the top of the glyph's bbox. - @IggyFieldType(DataType.float_t) - float maxx; //advanceX - bearingX - @IggyFieldType(DataType.float_t) - float maxy; //advanceY - bearingY - @IggyFieldType(DataType.uint64_t) - long unk; // stejny vetsinou - napr. 48 - JP: to by mohlo byt advance - @IggyFieldType(DataType.uint64_t) - long count; - @IggyFieldType(DataType.uint64_t) - long one; // 1 - @IggyFieldType(DataType.uint64_t) - long one2; // 1 - @IggyFieldType(DataType.uint64_t) - long one3; // 1 - @IggyFieldType(DataType.uint32_t) - long one4; // 1 - @IggyFieldType(DataType.uint32_t) - long two1; // 2 - - public float getBearingX() { - return minx; - } - - public float getBearingY() { - return miny; - } - - public float getWidth() { - return maxx - minx; - } - - public float getHeight() { - return maxy - miny; - } - - List nodes; - - private long offset; - - public IggyShape(AbstractDataStream stream, long offset) throws IOException { - this.offset = offset; - readFromDataStream(stream); - } - - public IggyShape(float minx, float miny, float maxx, float maxy, long advance, long count, long one, long one2, long one3, long one4, long two1, List nodes) { - this.minx = minx; - this.miny = miny; - this.maxx = maxx; - this.maxy = maxy; - this.unk = advance; - this.count = count; - this.one = one; - this.one2 = one2; - this.one3 = one3; - this.one4 = one4; - this.two1 = two1; - this.nodes = nodes; - } - - @Override - public void readFromDataStream(AbstractDataStream s) throws IOException { - s.seek(offset, SeekMode.SET); - minx = s.readFloat(); - miny = s.readFloat(); - maxx = s.readFloat(); - maxy = s.readFloat(); - unk = s.readUI64(); - count = s.readUI64(); - one = s.readUI64(); - one2 = s.readUI64(); - one3 = s.readUI64(); - one4 = s.readUI32(); - two1 = s.readUI32(); - - if ((one != 1) || (one2 != 1) || (one3 != 1) || (one4 != 1) || (two1 != 2)) { - LOGGER.fine(String.format("Unique header at pos %d, one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", offset, one, one2, one3, one4, two1)); - } - - nodes = new ArrayList<>(); - for (int i = 0; i < count; i++) { - nodes.add(new IggyShapeNode(s, i == 0)); - } - - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public float getMinx() { - return minx; - } - - public float getMiny() { - return miny; - } - - public float getMaxx() { - return maxx; - } - - public float getMaxy() { - return maxy; - } - - public long getUnk() { - return unk; - } - - public long getOne() { - return one; - } - - public long getOne2() { - return one2; - } - - public long getOne3() { - return one3; - } - - public long getOne4() { - return one4; - } - - public long getTwo1() { - return two1; - } - - public List getNodes() { - return nodes; - } - -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class IggyShape implements StructureInterface { + + private static Logger LOGGER = Logger.getLogger(IggyShape.class.getName()); + + @IggyFieldType(DataType.float_t) + float minx; //bearing X - this is the horizontal distance from the current pen position to the glyph's left bbox edge. + @IggyFieldType(DataType.float_t) + float miny; //bearing Y - this is the vertical distance from the baseline to the top of the glyph's bbox. + @IggyFieldType(DataType.float_t) + float maxx; //advanceX - bearingX + @IggyFieldType(DataType.float_t) + float maxy; //advanceY - bearingY + @IggyFieldType(DataType.uint64_t) + long unk; // stejny vetsinou - napr. 48 - JP: to by mohlo byt advance + @IggyFieldType(DataType.uint64_t) + long count; + @IggyFieldType(DataType.uint64_t) + long one; // 1 + @IggyFieldType(DataType.uint64_t) + long one2; // 1 + @IggyFieldType(DataType.uint64_t) + long one3; // 1 + @IggyFieldType(DataType.uint32_t) + long one4; // 1 + @IggyFieldType(DataType.uint32_t) + long two1; // 2 + + public float getBearingX() { + return minx; + } + + public float getBearingY() { + return miny; + } + + public float getWidth() { + return maxx - minx; + } + + public float getHeight() { + return maxy - miny; + } + + List nodes; + + private long offset; + + public IggyShape(AbstractDataStream stream, long offset) throws IOException { + this.offset = offset; + readFromDataStream(stream); + } + + public IggyShape(float minx, float miny, float maxx, float maxy, long advance, long count, long one, long one2, long one3, long one4, long two1, List nodes) { + this.minx = minx; + this.miny = miny; + this.maxx = maxx; + this.maxy = maxy; + this.unk = advance; + this.count = count; + this.one = one; + this.one2 = one2; + this.one3 = one3; + this.one4 = one4; + this.two1 = two1; + this.nodes = nodes; + } + + @Override + public void readFromDataStream(AbstractDataStream s) throws IOException { + s.seek(offset, SeekMode.SET); + minx = s.readFloat(); + miny = s.readFloat(); + maxx = s.readFloat(); + maxy = s.readFloat(); + unk = s.readUI64(); + count = s.readUI64(); + one = s.readUI64(); + one2 = s.readUI64(); + one3 = s.readUI64(); + one4 = s.readUI32(); + two1 = s.readUI32(); + + if ((one != 1) || (one2 != 1) || (one3 != 1) || (one4 != 1) || (two1 != 2)) { + LOGGER.fine(String.format("Unique header at pos %d, one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", offset, one, one2, one3, one4, two1)); + } + + nodes = new ArrayList<>(); + for (int i = 0; i < count; i++) { + nodes.add(new IggyShapeNode(s, i == 0)); + } + + } + + @Override + public void writeToDataStream(AbstractDataStream s) throws IOException { + s.writeFloat(minx); + s.writeFloat(miny); + s.writeFloat(maxx); + s.writeFloat(maxy); + s.writeUI64(unk); + s.writeUI64(count); + s.writeUI64(one); + s.writeUI64(one2); + s.writeUI64(one3); + s.writeUI32(one4); + s.writeUI32(two1); + + for (IggyShapeNode node : nodes) { + node.writeToDataStream(s); + } + } + + public float getMinx() { + return minx; + } + + public float getMiny() { + return miny; + } + + public float getMaxx() { + return maxx; + } + + public float getMaxy() { + return maxy; + } + + public long getUnk() { + return unk; + } + + public long getOne() { + return one; + } + + public long getOne2() { + return one2; + } + + public long getOne3() { + return one3; + } + + public long getOne4() { + return one4; + } + + public long getTwo1() { + return two1; + } + + public List getNodes() { + return nodes; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java index d235c9562..35f7b0295 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java @@ -1,122 +1,130 @@ -package com.jpexs.decompiler.flash.iggy; - -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - */ -public class IggyShapeNode implements StructureInterface { - - private static Logger LOGGER = Logger.getLogger(IggyShapeNode.class.getName()); - - public static int NODE_TYPE_MOVE = 1; - public static int NODE_TYPE_LINE_TO = 2; - public static int NODE_TYPE_CURVE_POINT = 3; - - @IggyFieldType(DataType.float_t) - float targetX; - @IggyFieldType(DataType.float_t) - float targetY; // negative - @IggyFieldType(DataType.float_t) - float controlX; // for curves - @IggyFieldType(DataType.float_t) - float controlY; // for curves, negative - @IggyFieldType(DataType.uint8_t) //1-moveto, 2-lineto , 3 - curve to - int node_type; - @IggyFieldType(DataType.uint8_t) // 208 start smooth (for j=1 only), 61 smooth interupt (muze a nemusi byt pro novy oddeleny kus charu - kdyz je subtype predchoziho vetsi nez 0 (kupr 5) bude pro oddeleny usek 61, jinak pokud je subtype predchoziho 0 bude pro oddeleny usek 0) - int node_subtype; - @IggyFieldType(DataType.uint8_t) - int zer1; - @IggyFieldType(DataType.uint8_t) - int zer2; - @IggyFieldType(DataType.uint32_t) - long isstart; // 1 v prubehu nebo 0 pouze pro prvni (i kdyz jsou delene jako dvojtecka!!!) - - private boolean first; - - public IggyShapeNode(float x1, float y1, float x2, float y2, int node_type, int node_subtype, int zer1, int zer2, long isstart) { - this.targetX = x1; - this.targetY = y1; - this.controlX = x2; - this.controlY = y2; - this.node_type = node_type; - this.node_subtype = node_subtype; - this.zer1 = zer1; - this.zer2 = zer2; - this.isstart = isstart; - } - - public IggyShapeNode(AbstractDataStream s, boolean first) throws IOException { - this.first = first; - readFromDataStream(s); - } - - @Override - public void readFromDataStream(AbstractDataStream s) throws IOException { - targetX = s.readFloat(); - targetY = s.readFloat(); - controlX = s.readFloat(); - controlY = s.readFloat(); - node_type = s.readUI8(); - node_subtype = s.readUI8(); - zer1 = s.readUI8(); - zer2 = s.readUI8(); - isstart = s.readUI32(); - - if ((zer1 != 0) | (zer2 != 0)) { - LOGGER.fine(String.format("Unknown zeroes at pos %08X\n", s.position() - 6)); - } - if ((!first) & (isstart != 1)) { - LOGGER.fine(String.format("Unknown format at pos %08X\n", s.position() - 4)); - } - if ((first) & (isstart != 0)) { - LOGGER.fine(String.format("Unknown format at pos %08X\n", s.position() - 4)); - } - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public float getX1() { - return targetX; - } - - public float getY1() { - return targetY; - } - - public float getX2() { - return controlX; - } - - public float getY2() { - return controlY; - } - - public int getNodeType() { - return node_type; - } - - public int getNodeSubType() { - return node_subtype; - } - - public int getZer1() { - return zer1; - } - - public int getZer2() { - return zer2; - } - - public boolean isStart() { - return isstart == 1; - } - -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class IggyShapeNode implements StructureInterface { + + private static Logger LOGGER = Logger.getLogger(IggyShapeNode.class.getName()); + + public static int NODE_TYPE_MOVE = 1; + public static int NODE_TYPE_LINE_TO = 2; + public static int NODE_TYPE_CURVE_POINT = 3; + + @IggyFieldType(DataType.float_t) + float targetX; + @IggyFieldType(DataType.float_t) + float targetY; // negative + @IggyFieldType(DataType.float_t) + float controlX; // for curves + @IggyFieldType(DataType.float_t) + float controlY; // for curves, negative + @IggyFieldType(DataType.uint8_t) //1-moveto, 2-lineto , 3 - curve to + int node_type; + @IggyFieldType(DataType.uint8_t) // 208 start smooth (for j=1 only), 61 smooth interupt (muze a nemusi byt pro novy oddeleny kus charu - kdyz je subtype predchoziho vetsi nez 0 (kupr 5) bude pro oddeleny usek 61, jinak pokud je subtype predchoziho 0 bude pro oddeleny usek 0) + int node_subtype; + @IggyFieldType(DataType.uint8_t) + int zer1; + @IggyFieldType(DataType.uint8_t) + int zer2; + @IggyFieldType(DataType.uint32_t) + long isstart; // 1 v prubehu nebo 0 pouze pro prvni (i kdyz jsou delene jako dvojtecka!!!) + + private boolean first; + + public IggyShapeNode(float x1, float y1, float x2, float y2, int node_type, int node_subtype, int zer1, int zer2, long isstart) { + this.targetX = x1; + this.targetY = y1; + this.controlX = x2; + this.controlY = y2; + this.node_type = node_type; + this.node_subtype = node_subtype; + this.zer1 = zer1; + this.zer2 = zer2; + this.isstart = isstart; + } + + public IggyShapeNode(AbstractDataStream s, boolean first) throws IOException { + this.first = first; + readFromDataStream(s); + } + + @Override + public void readFromDataStream(AbstractDataStream s) throws IOException { + targetX = s.readFloat(); + targetY = s.readFloat(); + controlX = s.readFloat(); + controlY = s.readFloat(); + node_type = s.readUI8(); + node_subtype = s.readUI8(); + zer1 = s.readUI8(); + zer2 = s.readUI8(); + isstart = s.readUI32(); + + if ((zer1 != 0) | (zer2 != 0)) { + LOGGER.fine(String.format("Unknown zeroes at pos %08X\n", s.position() - 6)); + } + if ((!first) & (isstart != 1)) { + LOGGER.fine(String.format("Unknown format at pos %08X\n", s.position() - 4)); + } + if ((first) & (isstart != 0)) { + LOGGER.fine(String.format("Unknown format at pos %08X\n", s.position() - 4)); + } + } + + @Override + public void writeToDataStream(AbstractDataStream s) throws IOException { + s.writeFloat(targetX); + s.writeFloat(targetY); + s.writeFloat(controlX); + s.writeFloat(controlY); + s.writeUI8(node_type); + s.writeUI8(node_subtype); + s.writeUI8(zer1); + s.writeUI8(zer2); + s.writeUI32(isstart); + } + + public float getX1() { + return targetX; + } + + public float getY1() { + return targetY; + } + + public float getX2() { + return controlX; + } + + public float getY2() { + return controlY; + } + + public int getNodeType() { + return node_type; + } + + public int getNodeSubType() { + return node_subtype; + } + + public int getZer1() { + return zer1; + } + + public int getZer2() { + return zer2; + } + + public boolean isStart() { + return isstart == 1; + } + +} 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 e08a16cf9..b673cccaa 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 @@ -1,70 +1,73 @@ -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; - -/** - * - * @author JPEXS - * - * Based of works of somebody called eternity. - */ -public class IggySubFileEntry implements StructureInterface { - - public static final int TYPE_INDEX = 0; - public static final int TYPE_FLASH = 1; - - @SWFType(BasicType.UI32) - long type; - - @SWFType(BasicType.UI32) - long size; - - //apparently same as size, maybe (un)compressed (?) - @SWFType(BasicType.UI32) - long size2; - - //absolute offset - @SWFType(BasicType.UI32) - long offset; - - public IggySubFileEntry(AbstractDataStream stream) throws IOException { - readFromDataStream(stream); - } - - public IggySubFileEntry(long type, long size, long size2, long offset) { - this.type = type; - this.size = size; - this.size2 = size2; - this.offset = offset; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("["); - sb.append("id: ").append(type).append(", "); - sb.append("size: ").append(size).append(", "); - sb.append("size2: ").append(size2).append(", "); - sb.append("offset: ").append(offset); - sb.append("]"); - return sb.toString(); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - type = stream.readUI32(); - size = stream.readUI32(); - size2 = stream.readUI32(); - offset = stream.readUI32(); - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - -} +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; + +/** + * + * @author JPEXS + * + * Based of works of somebody called eternity. + */ +public class IggySubFileEntry implements StructureInterface { + + public static final int TYPE_INDEX = 0; + public static final int TYPE_FLASH = 1; + + @SWFType(BasicType.UI32) + long type; + + @SWFType(BasicType.UI32) + long size; + + //apparently same as size, maybe (un)compressed (?) + @SWFType(BasicType.UI32) + long size2; + + //absolute offset + @SWFType(BasicType.UI32) + long offset; + + public IggySubFileEntry(AbstractDataStream stream) throws IOException { + readFromDataStream(stream); + } + + public IggySubFileEntry(long type, long size, long size2, long offset) { + this.type = type; + this.size = size; + this.size2 = size2; + this.offset = offset; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + sb.append("id: ").append(type).append(", "); + sb.append("size: ").append(size).append(", "); + sb.append("size2: ").append(size2).append(", "); + sb.append("offset: ").append(offset); + sb.append("]"); + return sb.toString(); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + type = stream.readUI32(); + size = stream.readUI32(); + size2 = stream.readUI32(); + offset = stream.readUI32(); + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + stream.writeUI32(type); + stream.writeUI32(size); + stream.writeUI32(size2); + stream.writeUI32(offset); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java new file mode 100644 index 000000000..5dec7c3f2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java @@ -0,0 +1,10 @@ +package com.jpexs.decompiler.flash.iggy; + +/** + * + * @author JPEXS + */ +public abstract class IggyTag implements StructureInterface { + + public abstract int getTagType(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java new file mode 100644 index 000000000..af0e58ec8 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java @@ -0,0 +1,36 @@ +package com.jpexs.decompiler.flash.iggy; + +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public class RawIggyTag extends IggyTag { + + byte[] rawData; + int tagType; + private int length; + + public RawIggyTag(int tagType, AbstractDataStream stream, int length) throws IOException { + this.length = length; + this.tagType = tagType; + readFromDataStream(stream); + } + + @Override + public int getTagType() { + return tagType; + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + rawData = stream.readBytes(length); + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + stream.writeBytes(rawData); + } + +} From d71416ea8ef9e17cfc77ab1e987c38d0b8c6b444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 27 Nov 2016 08:47:02 +0100 Subject: [PATCH 03/27] kerning is short always --- .../decompiler/flash/iggy/conversion/IggyToSwfConvertor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 512eb84a0..f48758673 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 @@ -131,7 +131,7 @@ public class IggyToSwfConvertor { for (int i = 0; i < ker.getKernCount(); i++) { int kerningCode1 = ker.getCharsA().get(i); int kerningCode2 = ker.getCharsA().get(i); - int kerningOffset = makeLengthsEm(ker.getKerningOffsets().get(i)); + int kerningOffset = ker.getKerningOffsets().get(i); fontTag.fontKerningTable.add(new KERNINGRECORD(kerningCode1, kerningCode2, kerningOffset)); } } From d2bdf8eb94fa5c23955b0a66ce916774d2bba125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 27 Nov 2016 09:12:22 +0100 Subject: [PATCH 04/27] streams refactoring - separate package --- .../flash/iggy/IggyCharAdvances.java | 2 + .../flash/iggy/IggyCharIndices.java | 2 + .../flash/iggy/IggyCharKerning.java | 2 + .../decompiler/flash/iggy/IggyCharOffset.java | 2 + .../decompiler/flash/iggy/IggyDataReader.java | 181 +-- .../jpexs/decompiler/flash/iggy/IggyFile.java | 1371 ++++++++--------- .../flash/iggy/IggyFlashHeader32.java | 391 ++--- .../flash/iggy/IggyFlashHeader64.java | 423 ++--- .../flash/iggy/IggyFlashHeaderInterface.java | 38 +- .../jpexs/decompiler/flash/iggy/IggyFont.java | 3 + .../decompiler/flash/iggy/IggyHeader.java | 2 + .../flash/iggy/IggyIndexParser.java | 332 ++-- .../decompiler/flash/iggy/IggyShape.java | 3 + .../decompiler/flash/iggy/IggyShapeNode.java | 2 + .../flash/iggy/IggySubFileEntry.java | 2 + .../jpexs/decompiler/flash/iggy/IggyTag.java | 2 + .../jpexs/decompiler/flash/iggy/IggyText.java | 390 ++--- .../decompiler/flash/iggy/RawIggyTag.java | 1 + .../{ => streams}/AbstractDataStream.java | 58 +- .../{ => streams}/ByteArrayDataStream.java | 175 ++- .../iggy/streams/DataStreamInterface.java | 9 + .../streams/RandomAccessFileDataStream.java | 88 ++ .../iggy/streams/ReadDataStreamInterface.java | 40 + .../flash/iggy/{ => streams}/SeekMode.java | 18 +- .../{ => streams}/StructureInterface.java | 31 +- .../streams/WriteDataStreamInterface.java | 40 + 26 files changed, 1895 insertions(+), 1713 deletions(-) rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{ => streams}/AbstractDataStream.java (58%) rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{ => streams}/ByteArrayDataStream.java (83%) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/DataStreamInterface.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{ => streams}/SeekMode.java (55%) rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{ => streams}/StructureInterface.java (68%) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java index d2b83fd78..6b4b4d73a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java index 30afb23d7..265539592 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; import java.util.ArrayList; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index 9a51e01e5..67da2c29b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 7c52ce468..46a27b722 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; import java.util.logging.Logger; 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 index 179062ea9..6d3b4e28b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java @@ -1,89 +1,92 @@ -package com.jpexs.decompiler.flash.iggy; - -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * - * @author JPEXS - */ -public class IggyDataReader implements StructureInterface { - - final static int NO_OFFSET = 1; - - @IggyFieldType(value = DataType.widechar_t, count = 48) - String name; - - Map fonts; - Map texts; - Map text2Font; - - private IggyFlashHeader64 header; - private Map sizesOfOffsets; - private List allOffsets; - - public IggyDataReader(IggyFlashHeader64 header, AbstractDataStream stream, List offsets) throws IOException { - this.header = header; - sizesOfOffsets = new HashMap<>(); - for (int i = 0; i < offsets.size() - 1; i++) { - sizesOfOffsets.put(offsets.get(i), offsets.get(i + 1) - offsets.get(i)); - } - sizesOfOffsets.put(offsets.get(offsets.size() - 1), 0L); //Last offset has 0L length? - this.allOffsets = offsets; - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - //here is offset[0] - StringBuilder nameBuilder = new StringBuilder(); - do { - char c = (char) stream.readUI16(); - if (c == '\0') { - break; - } - nameBuilder.append(c); - } while (true); - name = nameBuilder.toString(); - //here is offset[1] - int pad8 = 8 - (int) (stream.position() % 8); - stream.seek(pad8, SeekMode.CUR); - //here is offset [2] - fonts = new HashMap<>(); - int fontIndex = 0; - for (int i = 2; i < allOffsets.size(); i++) { - long offset = allOffsets.get(i); - stream.seek(offset, SeekMode.SET); - int type = stream.readUI16(); - stream.seek(-2, SeekMode.CUR); - if (type == IggyFont.ID) { - IggyFont font = new IggyFont(stream); - fonts.put(fontIndex++, font); - } - if (type == IggyText.ID) { - //TODO: Texts - incomplete - } - } - } - - 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"); - return sb.toString(); - } - -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.SeekMode; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + * @author JPEXS + */ +public class IggyDataReader implements StructureInterface { + + final static int NO_OFFSET = 1; + + @IggyFieldType(value = DataType.widechar_t, count = 48) + String name; + + Map fonts; + Map texts; + Map text2Font; + + private IggyFlashHeader64 header; + private Map sizesOfOffsets; + private List allOffsets; + + public IggyDataReader(IggyFlashHeader64 header, AbstractDataStream stream, List offsets) throws IOException { + this.header = header; + sizesOfOffsets = new HashMap<>(); + for (int i = 0; i < offsets.size() - 1; i++) { + sizesOfOffsets.put(offsets.get(i), offsets.get(i + 1) - offsets.get(i)); + } + sizesOfOffsets.put(offsets.get(offsets.size() - 1), 0L); //Last offset has 0L length? + this.allOffsets = offsets; + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + //here is offset[0] + StringBuilder nameBuilder = new StringBuilder(); + do { + char c = (char) stream.readUI16(); + if (c == '\0') { + break; + } + nameBuilder.append(c); + } while (true); + name = nameBuilder.toString(); + //here is offset[1] + int pad8 = 8 - (int) (stream.position() % 8); + stream.seek(pad8, SeekMode.CUR); + //here is offset [2] + fonts = new HashMap<>(); + int fontIndex = 0; + for (int i = 2; i < allOffsets.size(); i++) { + long offset = allOffsets.get(i); + stream.seek(offset, SeekMode.SET); + int type = stream.readUI16(); + stream.seek(-2, SeekMode.CUR); + if (type == IggyFont.ID) { + IggyFont font = new IggyFont(stream); + fonts.put(fontIndex++, font); + } + if (type == IggyText.ID) { + //TODO: Texts - incomplete + } + } + } + + 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"); + 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 fb1a9f239..3744bd315 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 @@ -1,715 +1,656 @@ -package com.jpexs.decompiler.flash.iggy; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -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.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - * - * Based of works of somebody called eternity. - * - */ -public class IggyFile extends AbstractDataStream implements AutoCloseable { - - final static Logger LOGGER = Logger.getLogger(IggyFile.class.getName()); - - private RandomAccessFile raf; - private IggyHeader header; - private List subFileEntries = new ArrayList<>(); - - private List headers = new ArrayList<>(); - private List flashDataReaders = new ArrayList<>(); - - public Set getFontIds(int swfIndex) { - return flashDataReaders.get(swfIndex).fonts.keySet(); - } - - public IggyFont getFont(int swfIndex, int fontId) { - return flashDataReaders.get(swfIndex).fonts.get(fontId); - } - - public IggyText getText(int swfIndex, int textId) { - return flashDataReaders.get(swfIndex).texts.get(textId); - } - - public Set getTextIds(int swfIndex) { - return flashDataReaders.get(swfIndex).texts.keySet(); - } - - @Override - public long position() { - try { - return raf.getFilePointer(); - } catch (IOException ex) { - return -1; - } - } - - public IggyFile(File file) throws IOException { - raf = new RandomAccessFile(file, "r"); - header = new IggyHeader(this); - for (int i = 0; i < header.getNumSubfiles(); i++) { - subFileEntries.add(new IggySubFileEntry(this)); - } - - List> indexTables = new ArrayList<>(); //TODO: use this two for something ?? - List> offsetTables = new ArrayList<>(); - List flashDataStreams = 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) { - 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) { - IggyFlashHeaderInterface hdr; - if (is64()) { - hdr = new IggyFlashHeader64(dataStream); - } else { - hdr = new IggyFlashHeader32(dataStream); - } - headers.add(hdr); - flashDataStreams.add(dataStream); - } - } - - for (int swfIndex = 0; swfIndex < headers.size(); swfIndex++) { - IggyFlashHeaderInterface hdr = headers.get(swfIndex); - IggyDataReader dataReader = new IggyDataReader((IggyFlashHeader64) hdr /*FIXME for 32*/, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex)); - flashDataReaders.add(dataReader); - } - } - - @Override - public boolean is64() { - return header.is64(); - } - - 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) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InputStream is = getEntryInputStream(entryIndex); - byte buf[] = new byte[1024]; - int cnt; - while ((cnt = is.read(buf)) > 0) { - baos.write(buf, 0, cnt); - } - return baos.toByteArray(); - } - - public ByteArrayDataStream getEntryDataStream(int entryIndex) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InputStream is = getEntryInputStream(entryIndex); - byte buf[] = new byte[1024]; - int cnt; - while ((cnt = is.read(buf)) > 0) { - baos.write(buf, 0, cnt); - } - byte data[] = baos.toByteArray(); - return new ByteArrayDataStream(data, is64()); - } - - public InputStream getEntryInputStream(int entryIndex) { - IggySubFileEntry entry = getSubFileEntry(entryIndex); - - return new InputStream() { - long offset = entry.offset; - long maxOffset = entry.offset + entry.size; - - @Override - public synchronized int read() throws IOException { - if (offset < maxOffset) { - raf.seek(offset); - offset++; - return raf.read(); - } - return -1; - } - }; - } - - @Override - protected int read() throws IOException { - int val = raf.read(); - if (val == -1) { - throw new EOFException(); - } - return val; - } - - @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"; - try (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)); - } - } - } - } - - private static void processFile(File f) { - if (f.isDirectory()) { - System.out.println("Processing directory " + f + ":"); - File iggyFiles[] = f.listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".iggy"); - } - }); - for (File sf : iggyFiles) { - processFile(sf); - } - return; - } - System.out.print("Processing file " + f + "..."); - try { - File dir = f.getParentFile(); - File extractDir = new File(dir, "extracted_" + (f.getName()).replace(".iggy", "")); - extractDir.mkdir(); - extractIggyFile(f, extractDir); - System.out.println("OK"); - } catch (Exception ex) { - System.err.println("FAIL"); - System.exit(1); - } - } - - public static void main(String[] args) throws IOException { - System.out.println("Iggy file splitter"); - if (args.length == 0) { - System.err.println("No file specified"); - System.exit(1); - } - - for (String s : args) { - File f = new File(s); - if (!f.exists()) { - System.err.println("File " + f + " does not exists"); - System.exit(1); - } - processFile(f); - - } - System.exit(0); - } - - private static void copyStream(InputStream is, OutputStream os) { - try { - final int bufSize = 4096; - byte[] buf = new byte[bufSize]; - int cnt; - while ((cnt = is.read(buf)) > 0) { - os.write(buf, 0, cnt); - } - } catch (IOException ex) { - // ignore - } - } - - @Override - public void close() { - try { - raf.close(); - } catch (IOException ex) { - //ignore - } - } - - @Override - protected void seek(long pos, SeekMode mode) throws IOException { - long newpos = pos; - if (mode == SeekMode.CUR) { - newpos = raf.getFilePointer() + pos; - } else if (mode == SeekMode.END) { - newpos = raf.length() - pos; - } - if (newpos > raf.length()) { - throw new ArrayIndexOutOfBoundsException("Position outside bounds accessed: " + pos + ". Size: " + raf.length()); - } else if (newpos < 0) { - throw new ArrayIndexOutOfBoundsException("Negative position accessed: " + pos); - } else { - raf.seek(newpos); - } - } - - 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, is_64); - - /* - index_table: - n = UI8 - for i=0..n-1 - table[i] = UI8 - cnt = UI8 - cnt * UI16 - - */ - int index_table_size = stream.readUI8(); - int index_table[] = new int[index_table_size]; - - for (int i = 0; i < index_table_size; i++) { - index_table[i] = stream.readUI8(); - int num = stream.readUI8(); - stream.seek(num * 2, SeekMode.CUR); - //num * UI16 - } - - int state = 0; - long offset = 0;//uint32_t - int code; //uint8_t - - while ((code = stream.readUI8()) >= 0) { - if (state == 1) { - if (code != 0xFD) { - LOGGER.log(Level.WARNING, "We were expecting code 0xFD in state 1."); - return false; - } - } else if (state == 2) { - if (code != 0xFF) { - LOGGER.log(Level.WARNING, "We were expecting code 0xFF in state 2."); - return false; - } - } - - if (code < 0x80) // 0-0x7F - { - // code is directly an index to the index_table - if (code >= index_table_size) { - LOGGER.log(Level.WARNING, String.format("< 0x80: index is greater than index_table_size. %x > %x", code, index_table_size)); - return false; - } - - offset += index_table[code]; - } else if (code < 0xC0) // 0x80-BF - { - int index; //uint8_t - - if ((index = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "< 0xC0: Cannot read index."); - return false; - } - - if (index >= index_table_size) { - LOGGER.log(Level.WARNING, String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, index_table_size)); - return false; - } - - 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; //uint8_t - int n8; //uint8_t - int n; - - if ((n8 = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "< 0xE0: Cannot read n."); - return false; - } - - 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 { - LOGGER.log(Level.WARNING, String.format("< 0xE0: Invalid value for i (%x %x)", 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.log(Level.WARNING, String.format("< 0xE0: invalid value for i (%x %x)", i, code)); - } - } - } else if (code == 0xFC) { - stream.seek(1, SeekMode.CUR); - } else if (code == 0xFD) { - int n, m; //uint8_t - - if ((n = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "0xFD: Cannot read n."); - return false; - } - - if (state == 1) { - if (is_64) { - if (n != 0xF) { - LOGGER.log(Level.WARNING, String.format("We were expecting an offset of 0xF in state 1.")); - return false; - } - } else if (n != 0xB) { - LOGGER.log(Level.WARNING, "We were expecting an offset of 0xB in state 1."); - return false; - } - - state = 2; - } - - if ((m = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "0xFD: Cannot read m."); - return false; - } - - offset += n; - stream.seek(m * 2, SeekMode.CUR); - } else if (code == 0xFE) { - int n8; //uint8_t - int n; - - if ((n8 = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "0xFE: Cannot read n."); - return false; - } - - n = n8 + 1; - offset += n; - } else if (code == 0xFF) { - long n; //uint32_t - - if ((n = stream.readUI32()) < 0) { - LOGGER.log(Level.WARNING, "0xFF: Cannot read n."); - return false; - } - - if (state == 2) { - n += item_size_change; - stream.seek(-4, SeekMode.CUR); - return stream.writeUI32(n); - } - - offset += n; - } else { - LOGGER.log(Level.WARNING, String.format("Unrecognized code: %x", code)); - } - - if (state == 0 && offset == item_offset) { - state = 1; - } - } - return false; - } - - /** - * Gets length of an item. - * - * @param item_offset - * @param is_64 - * @param index_bytes - * @return null when item not exists, item length otherwise - * @throws IOException - */ - private static Long getItemLength(long item_offset /*uint32_t*/, boolean is_64, byte index_bytes[]) throws IOException { - return itemLength(item_offset, is_64, index_bytes, null); - } - - /** - * Sets new length of an item. - * - * @param item_offset - * @param is_64 - * @param index_bytes - * @param newLength - * @return null when item not exists, old item length otherwise - * @throws IOException - */ - private static Long setItemLength(long item_offset /*uint32_t*/, boolean is_64, byte index_bytes[], long newLength) throws IOException { - return itemLength(item_offset, is_64, index_bytes, newLength); - } - - /** - * Sets/Gets length of an item - * - * @param item_offset - * @param is_64 - * @param index_bytes - * @param newValue New value to set. If null then no change. - * @return null when item does not exists, old item length otherwise - * @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, is_64); - - /* - index_table: - n = UI8 - for i=0..n-1 - table[i] = UI8 - cnt = UI8 - cnt * UI16 - - */ - int index_table_size = stream.readUI8(); - int index_table[] = new int[index_table_size]; - - for (int i = 0; i < index_table_size; i++) { - index_table[i] = stream.readUI8(); - int num = stream.readUI8(); - stream.seek(num * 2, SeekMode.CUR); - //num * UI16 - } - - int state = 0; - long offset = 0;//uint32_t - int code; //uint8_t - - while ((code = stream.readUI8()) >= 0) { - if (state == 1) { - if (code != 0xFD) { - LOGGER.log(Level.WARNING, "We were expecting code 0xFD in state 1."); - return null; - } - } else if (state == 2) { - if (code != 0xFF) { - LOGGER.log(Level.WARNING, "We were expecting code 0xFF in state 2."); - return null; - } - } - - if (code < 0x80) // 0-0x7F - { - // code is directly an index to the index_table - if (code >= index_table_size) { - LOGGER.log(Level.WARNING, String.format("< 0x80: index is greater than index_table_size. %x > %x", code, index_table_size)); - return null; - } - - offset += index_table[code]; - } else if (code < 0xC0) // 0x80-BF - { - int index; //uint8_t - - if ((index = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "< 0xC0: Cannot read index."); - return null; - } - - if (index >= index_table_size) { - LOGGER.log(Level.WARNING, String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, index_table_size)); - return null; - } - - 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; //uint8_t - int n8; //uint8_t - int n; - - if ((n8 = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "< 0xE0: Cannot read n."); - return null; - } - - 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 { - LOGGER.log(Level.WARNING, String.format("< 0xE0: Invalid value for i (%x %x)", 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.log(Level.WARNING, String.format("< 0xE0: invalid value for i (%x %x)", i, code)); - } - } - } else if (code == 0xFC) { - stream.seek(1, SeekMode.CUR); - } else if (code == 0xFD) { - int n, m; //uint8_t - - if ((n = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "0xFD: Cannot read n."); - return null; - } - - if (state == 1) { - if (is_64) { - if (n != 0xF) { - LOGGER.log(Level.WARNING, String.format("We were expecting an offset of 0xF in state 1.")); - return null; - } - } else if (n != 0xB) { - LOGGER.log(Level.WARNING, "We were expecting an offset of 0xB in state 1."); - return null; - } - - state = 2; - } - - if ((m = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "0xFD: Cannot read m."); - return null; - } - - offset += n; - stream.seek(m * 2, SeekMode.CUR); - } else if (code == 0xFE) { - int n8; //uint8_t - int n; - - if ((n8 = stream.readUI8()) < 0) { - LOGGER.log(Level.WARNING, "0xFE: Cannot read n."); - return null; - } - - n = n8 + 1; - offset += n; - } else if (code == 0xFF) { - long n; //uint32_t - - if ((n = stream.readUI32()) < 0) { - LOGGER.log(Level.WARNING, "0xFF: Cannot read n."); - return null; - } - - if (state == 2) { - if (newValue != null) { - stream.seek(-4, SeekMode.CUR); - stream.writeUI32(newValue); - } - return n; - } - - offset += n; - } else { - LOGGER.log(Level.WARNING, String.format("Unrecognized code: %x", code)); - } - - if (state == 0 && offset == item_offset) { - state = 1; - } - } - return null; - } - - @Override - public Long available() { - try { - return raf.length() - raf.getFilePointer(); - } catch (IOException ex) { - return null; - } - } - - public int getSwfCount() { - return flashDataReaders.size(); - } - - public String getSwfName(int swfIndex) { - return flashDataReaders.get(swfIndex).getName(); - } - - public long getSwfXMin(int swfIndex) { - return headers.get(swfIndex).getXMin(); - } - - public long getSwfYMin(int swfIndex) { - return headers.get(swfIndex).getYMin(); - } - - public long getSwfXMax(int swfIndex) { - return headers.get(swfIndex).getXMax(); - } - - public long getSwfYMax(int swfIndex) { - return headers.get(swfIndex).getYMax(); - } - - public float getSwfFrameRate(int swfIndex) { - return headers.get(swfIndex).getFrameRate(); - } -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.SeekMode; +import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; +import com.jpexs.decompiler.flash.iggy.streams.ByteArrayDataStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +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.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +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 IggyHeader header; + private List subFileEntries = new ArrayList<>(); + private List subFileEntriesData = new ArrayList<>(); + + private List headers = new ArrayList<>(); + private List flashDataReaders = new ArrayList<>(); + + public Set getFontIds(int swfIndex) { + return flashDataReaders.get(swfIndex).fonts.keySet(); + } + + public IggyFont getFont(int swfIndex, int fontId) { + return flashDataReaders.get(swfIndex).fonts.get(fontId); + } + + public IggyText getText(int swfIndex, int textId) { + return flashDataReaders.get(swfIndex).texts.get(textId); + } + + public Set getTextIds(int swfIndex) { + return flashDataReaders.get(swfIndex).texts.keySet(); + } + + public IggyFile(File file) throws IOException { + try (AbstractDataStream stream = new RandomAccessFileDataStream(file)) { + readFromDataStream(stream); + } + } + + public IggyFile(RandomAccessFile rafile) throws IOException { + try (AbstractDataStream stream = new RandomAccessFileDataStream(rafile)) { + readFromDataStream(stream); + } + } + + 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)); + } + } + } + + private static void processFile(File f) { + if (f.isDirectory()) { + System.out.println("Processing directory " + f + ":"); + File iggyFiles[] = f.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".iggy"); + } + }); + for (File sf : iggyFiles) { + processFile(sf); + } + return; + } + System.out.print("Processing file " + f + "..."); + try { + File dir = f.getParentFile(); + File extractDir = new File(dir, "extracted_" + (f.getName()).replace(".iggy", "")); + extractDir.mkdir(); + extractIggyFile(f, extractDir); + System.out.println("OK"); + } catch (Exception ex) { + System.err.println("FAIL"); + System.exit(1); + } + } + + public static void main(String[] args) throws IOException { + System.out.println("Iggy file splitter"); + if (args.length == 0) { + System.err.println("No file specified"); + System.exit(1); + } + + for (String s : args) { + File f = new File(s); + if (!f.exists()) { + System.err.println("File " + f + " does not exists"); + System.exit(1); + } + processFile(f); + + } + System.exit(0); + } + + private static void copyStream(InputStream is, OutputStream os) { + try { + final int bufSize = 4096; + byte[] buf = new byte[bufSize]; + int cnt; + while ((cnt = is.read(buf)) > 0) { + os.write(buf, 0, cnt); + } + } catch (IOException ex) { + // ignore + } + } + + 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, is_64); + + /* + index_table: + n = UI8 + for i=0..n-1 + table[i] = UI8 + cnt = UI8 + cnt * UI16 + + */ + int index_table_size = stream.readUI8(); + int index_table[] = new int[index_table_size]; + + for (int i = 0; i < index_table_size; i++) { + index_table[i] = stream.readUI8(); + int num = stream.readUI8(); + stream.seek(num * 2, SeekMode.CUR); + //num * UI16 + } + + int state = 0; + long offset = 0;//uint32_t + int code; //uint8_t + + while ((code = stream.readUI8()) >= 0) { + if (state == 1) { + if (code != 0xFD) { + LOGGER.log(Level.WARNING, "We were expecting code 0xFD in state 1."); + return false; + } + } else if (state == 2) { + if (code != 0xFF) { + LOGGER.log(Level.WARNING, "We were expecting code 0xFF in state 2."); + return false; + } + } + + if (code < 0x80) // 0-0x7F + { + // code is directly an index to the index_table + if (code >= index_table_size) { + LOGGER.log(Level.WARNING, String.format("< 0x80: index is greater than index_table_size. %x > %x", code, index_table_size)); + return false; + } + + offset += index_table[code]; + } else if (code < 0xC0) // 0x80-BF + { + int index; //uint8_t + + if ((index = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "< 0xC0: Cannot read index."); + return false; + } + + if (index >= index_table_size) { + LOGGER.log(Level.WARNING, String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, index_table_size)); + return false; + } + + 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; //uint8_t + int n8; //uint8_t + int n; + + if ((n8 = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "< 0xE0: Cannot read n."); + return false; + } + + 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 { + LOGGER.log(Level.WARNING, String.format("< 0xE0: Invalid value for i (%x %x)", 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.log(Level.WARNING, String.format("< 0xE0: invalid value for i (%x %x)", i, code)); + } + } + } else if (code == 0xFC) { + stream.seek(1, SeekMode.CUR); + } else if (code == 0xFD) { + int n, m; //uint8_t + + if ((n = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "0xFD: Cannot read n."); + return false; + } + + if (state == 1) { + if (is_64) { + if (n != 0xF) { + LOGGER.log(Level.WARNING, String.format("We were expecting an offset of 0xF in state 1.")); + return false; + } + } else if (n != 0xB) { + LOGGER.log(Level.WARNING, "We were expecting an offset of 0xB in state 1."); + return false; + } + + state = 2; + } + + if ((m = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "0xFD: Cannot read m."); + return false; + } + + offset += n; + stream.seek(m * 2, SeekMode.CUR); + } else if (code == 0xFE) { + int n8; //uint8_t + int n; + + if ((n8 = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "0xFE: Cannot read n."); + return false; + } + + n = n8 + 1; + offset += n; + } else if (code == 0xFF) { + long n; //uint32_t + + if ((n = stream.readUI32()) < 0) { + LOGGER.log(Level.WARNING, "0xFF: Cannot read n."); + return false; + } + + if (state == 2) { + n += item_size_change; + stream.seek(-4, SeekMode.CUR); + return stream.writeUI32(n); + } + + offset += n; + } else { + LOGGER.log(Level.WARNING, String.format("Unrecognized code: %x", code)); + } + + if (state == 0 && offset == item_offset) { + state = 1; + } + } + return false; + } + + /** + * Gets length of an item. + * + * @param item_offset + * @param is_64 + * @param index_bytes + * @return null when item not exists, item length otherwise + * @throws IOException + */ + private static Long getItemLength(long item_offset /*uint32_t*/, boolean is_64, byte index_bytes[]) throws IOException { + return itemLength(item_offset, is_64, index_bytes, null); + } + + /** + * Sets new length of an item. + * + * @param item_offset + * @param is_64 + * @param index_bytes + * @param newLength + * @return null when item not exists, old item length otherwise + * @throws IOException + */ + private static Long setItemLength(long item_offset /*uint32_t*/, boolean is_64, byte index_bytes[], long newLength) throws IOException { + return itemLength(item_offset, is_64, index_bytes, newLength); + } + + /** + * Sets/Gets length of an item + * + * @param item_offset + * @param is_64 + * @param index_bytes + * @param newValue New value to set. If null then no change. + * @return null when item does not exists, old item length otherwise + * @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, is_64); + + /* + index_table: + n = UI8 + for i=0..n-1 + table[i] = UI8 + cnt = UI8 + cnt * UI16 + + */ + int index_table_size = stream.readUI8(); + int index_table[] = new int[index_table_size]; + + for (int i = 0; i < index_table_size; i++) { + index_table[i] = stream.readUI8(); + int num = stream.readUI8(); + stream.seek(num * 2, SeekMode.CUR); + //num * UI16 + } + + int state = 0; + long offset = 0;//uint32_t + int code; //uint8_t + + while ((code = stream.readUI8()) >= 0) { + if (state == 1) { + if (code != 0xFD) { + LOGGER.log(Level.WARNING, "We were expecting code 0xFD in state 1."); + return null; + } + } else if (state == 2) { + if (code != 0xFF) { + LOGGER.log(Level.WARNING, "We were expecting code 0xFF in state 2."); + return null; + } + } + + if (code < 0x80) // 0-0x7F + { + // code is directly an index to the index_table + if (code >= index_table_size) { + LOGGER.log(Level.WARNING, String.format("< 0x80: index is greater than index_table_size. %x > %x", code, index_table_size)); + return null; + } + + offset += index_table[code]; + } else if (code < 0xC0) // 0x80-BF + { + int index; //uint8_t + + if ((index = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "< 0xC0: Cannot read index."); + return null; + } + + if (index >= index_table_size) { + LOGGER.log(Level.WARNING, String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, index_table_size)); + return null; + } + + 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; //uint8_t + int n8; //uint8_t + int n; + + if ((n8 = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "< 0xE0: Cannot read n."); + return null; + } + + 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 { + LOGGER.log(Level.WARNING, String.format("< 0xE0: Invalid value for i (%x %x)", 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.log(Level.WARNING, String.format("< 0xE0: invalid value for i (%x %x)", i, code)); + } + } + } else if (code == 0xFC) { + stream.seek(1, SeekMode.CUR); + } else if (code == 0xFD) { + int n, m; //uint8_t + + if ((n = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "0xFD: Cannot read n."); + return null; + } + + if (state == 1) { + if (is_64) { + if (n != 0xF) { + LOGGER.log(Level.WARNING, String.format("We were expecting an offset of 0xF in state 1.")); + return null; + } + } else if (n != 0xB) { + LOGGER.log(Level.WARNING, "We were expecting an offset of 0xB in state 1."); + return null; + } + + state = 2; + } + + if ((m = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "0xFD: Cannot read m."); + return null; + } + + offset += n; + stream.seek(m * 2, SeekMode.CUR); + } else if (code == 0xFE) { + int n8; //uint8_t + int n; + + if ((n8 = stream.readUI8()) < 0) { + LOGGER.log(Level.WARNING, "0xFE: Cannot read n."); + return null; + } + + n = n8 + 1; + offset += n; + } else if (code == 0xFF) { + long n; //uint32_t + + if ((n = stream.readUI32()) < 0) { + LOGGER.log(Level.WARNING, "0xFF: Cannot read n."); + return null; + } + + if (state == 2) { + if (newValue != null) { + stream.seek(-4, SeekMode.CUR); + stream.writeUI32(newValue); + } + return n; + } + + offset += n; + } else { + LOGGER.log(Level.WARNING, String.format("Unrecognized code: %x", code)); + } + + if (state == 0 && offset == item_offset) { + state = 1; + } + } + return null; + } + + public int getSwfCount() { + return flashDataReaders.size(); + } + + public String getSwfName(int swfIndex) { + return flashDataReaders.get(swfIndex).getName(); + } + + public long getSwfXMin(int swfIndex) { + return headers.get(swfIndex).getXMin(); + } + + public long getSwfYMin(int swfIndex) { + return headers.get(swfIndex).getYMin(); + } + + public long getSwfXMax(int swfIndex) { + return headers.get(swfIndex).getXMax(); + } + + public long getSwfYMax(int swfIndex) { + return headers.get(swfIndex).getYMax(); + } + + public float getSwfFrameRate(int swfIndex) { + return headers.get(swfIndex).getFrameRate(); + } + + private void parseEntries() throws IOException { + List> indexTables = new ArrayList<>(); //TODO: use this for something ?? + List> offsetTables = new ArrayList<>(); + List flashDataStreams = new ArrayList<>(); + + for (int i = 0; i < subFileEntries.size(); i++) { + IggySubFileEntry entry = subFileEntries.get(i); + AbstractDataStream dataStream = new ByteArrayDataStream(getEntryData(i), header.is64()); + if (entry.type == IggySubFileEntry.TYPE_INDEX) { + 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) { + IggyFlashHeaderInterface hdr; + if (header.is64()) { + hdr = new IggyFlashHeader64(dataStream); + } else { + hdr = new IggyFlashHeader32(dataStream); + throw new UnsupportedOperationException("Iggy 32bit files are not supported"); //TODO + } + headers.add(hdr); + flashDataStreams.add(dataStream); + } + } + + for (int swfIndex = 0; swfIndex < headers.size(); swfIndex++) { + IggyFlashHeaderInterface hdr = headers.get(swfIndex); + IggyDataReader dataReader = new IggyDataReader((IggyFlashHeader64) hdr, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex)); + flashDataReaders.add(dataReader); + } + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + header = new IggyHeader(stream); + 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(); + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + header.writeToDataStream(stream); + for (IggySubFileEntry entry : subFileEntries) { + entry.writeToDataStream(stream); + } + } + +} 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 433900e90..5cd77f11f 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 @@ -1,195 +1,196 @@ -package com.jpexs.decompiler.flash.iggy; - -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import java.io.IOException; - -/** - * - * @author JPEXS - * - * Based of works of somebody called eternity. - * - * All relative offsets are relative from that specific field position All - * relative offsets can get value "1" to indicate "nothing" - */ -public class IggyFlashHeader32 implements IggyFlashHeaderInterface { - - @IggyFieldType(DataType.uint32_t) - long main_offset; // 0 Relative offset to first section (matches sizeof header) - @IggyFieldType(DataType.uint32_t) - long as3_section_offset; // 4 Relative offset to as3 file names table... - @IggyFieldType(DataType.uint32_t) - long unk_offset; // 8 relative offset to something - @IggyFieldType(DataType.uint32_t) - long unk_offset2; // 0xC relative offset to something - @IggyFieldType(DataType.uint32_t) - long unk_offset3; // 0x10 relative offset to something - @IggyFieldType(DataType.uint32_t) - long unk_offset4; // 0x14 relative offset to something - @IggyFieldType(DataType.uint32_t) - long xmin; //0x18 in pixels - @IggyFieldType(DataType.uint32_t) - long ymin; //0x0C in pixels - @IggyFieldType(DataType.uint32_t) - long xmax; // 0x20 in pixels - @IggyFieldType(DataType.uint32_t) - long ymax; // 0x24 in pixels - @IggyFieldType(DataType.uint32_t) - long unk_28; // probably number of blocks/objects after header - @IggyFieldType(DataType.uint32_t) - long unk_2C; - @IggyFieldType(DataType.uint32_t) - long unk_30; - @IggyFieldType(DataType.uint32_t) - long unk_34; - @IggyFieldType(DataType.uint32_t) - long unk_38; - @IggyFieldType(DataType.uint32_t) - long unk_3C; - @IggyFieldType(DataType.float_t) - float frameRate; - @IggyFieldType(DataType.uint32_t) - long unk_44; - @IggyFieldType(DataType.uint32_t) - long unk_48; - @IggyFieldType(DataType.uint32_t) - long unk_4C; - @IggyFieldType(DataType.uint32_t) - long names_offset; // 0x50 relative offset to the names/import section of the file - @IggyFieldType(DataType.uint32_t) - long unk_offset5; // 0x54 relative offset to something - @IggyFieldType(DataType.uint64_t) - long unk_58; // Maybe number of imports/names pointed by names_offset - @IggyFieldType(DataType.uint32_t) - long last_section_offset; // 0x60 relative offset, points to the small last section of the file - @IggyFieldType(DataType.uint32_t) - long unk_offset6; // 0x64 relative offset to something - @IggyFieldType(DataType.uint32_t) - long as3_code_offset; // 0x68 relative offset to as3 code (8 bytes header + abc blob) - @IggyFieldType(DataType.uint32_t) - long as3_names_offset; // 0x6C relative offset to as3 file names table (or classes names or whatever) - @IggyFieldType(DataType.uint32_t) - long unk_70; - @IggyFieldType(DataType.uint32_t) - long unk_74; - @IggyFieldType(DataType.uint32_t) - long unk_78; // Maybe number of classes / as3 names - @IggyFieldType(DataType.uint32_t) - long unk_7C; - - // Offset 0x80 (outside header): there are *unk_28* 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. - // After the offsets, the bodies of objects pointed above, which apparently have a code like 0xFFXX to identify the type of object, followed by a (unique?) identifier - // for the object. - // A DefineEditText-like object can be easily spotted and apparently uses type code 0x06 (or 0xFF06) but as stated above, - // it is written in a different way. - public IggyFlashHeader32(AbstractDataStream stream) throws IOException { - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - main_offset = stream.readUI32(); - as3_section_offset = stream.readUI32(); - unk_offset = stream.readUI32(); - unk_offset2 = stream.readUI32(); - unk_offset3 = stream.readUI32(); - unk_offset4 = stream.readUI32(); - xmin = stream.readUI32(); - ymin = stream.readUI32(); - xmax = stream.readUI32(); - ymax = stream.readUI32(); - unk_28 = stream.readUI32(); - unk_2C = stream.readUI32(); - unk_30 = stream.readUI32(); - unk_34 = stream.readUI32(); - unk_38 = stream.readUI32(); - unk_3C = stream.readUI32(); - frameRate = stream.readFloat(); - unk_44 = stream.readUI32(); - unk_48 = stream.readUI32(); - unk_4C = stream.readUI32(); - unk_3C = stream.readUI32(); - names_offset = stream.readUI32(); - unk_offset5 = stream.readUI32(); - unk_58 = stream.readUI64(); - last_section_offset = stream.readUI32(); - unk_offset6 = stream.readUI32(); - as3_code_offset = stream.readUI32(); - as3_names_offset = stream.readUI32(); - unk_70 = stream.readUI32(); - unk_74 = stream.readUI32(); - unk_78 = stream.readUI32(); - unk_7C = stream.readUI32(); - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - 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(xmax).append("\r\n"); - sb.append("ymax ").append(ymax).append("\r\n"); - sb.append("unk_28 ").append(unk_28).append("\r\n"); - sb.append("unk_2C ").append(unk_2C).append("\r\n"); - sb.append("unk_30 ").append(unk_30).append("\r\n"); - sb.append("unk_34 ").append(unk_34).append("\r\n"); - sb.append("unk_38 ").append(unk_38).append("\r\n"); - sb.append("unk_3C ").append(unk_3C).append("\r\n"); - sb.append("frameRate ").append(frameRate).append("\r\n"); - sb.append("unk_44 ").append(unk_44).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("names_offset ").append(names_offset).append("\r\n"); - sb.append("unk_offset5 ").append(unk_offset5).append("\r\n"); - sb.append("unk_58 ").append(unk_58).append("\r\n"); - sb.append("last_section_offset ").append(last_section_offset).append("\r\n"); - sb.append("unk_offset6 ").append(unk_offset6).append("\r\n"); - sb.append("as3_code_offset ").append(as3_code_offset).append("\r\n"); - sb.append("as3_names_offset ").append(as3_names_offset).append("\r\n"); - sb.append("unk_70 ").append(unk_70).append("\r\n"); - sb.append("unk_74 ").append(unk_74).append("\r\n"); - sb.append("unk_78 ").append(unk_78).append("\r\n"); - sb.append("unk_7C ").append(unk_7C).append("\r\n"); - sb.append("]"); - return sb.toString(); - } - - @Override - public long getXMin() { - return xmin; - } - - @Override - public long getYMin() { - return ymin; - } - - @Override - public long getXMax() { - return xmax; - } - - @Override - public long getYMax() { - return ymax; - } - - @Override - public float getFrameRate() { - return frameRate; - } -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; + +/** + * + * @author JPEXS + * + * Based of works of somebody called eternity. + * + * All relative offsets are relative from that specific field position All + * relative offsets can get value "1" to indicate "nothing" + */ +public class IggyFlashHeader32 implements IggyFlashHeaderInterface { + + @IggyFieldType(DataType.uint32_t) + long main_offset; // 0 Relative offset to first section (matches sizeof header) + @IggyFieldType(DataType.uint32_t) + long as3_section_offset; // 4 Relative offset to as3 file names table... + @IggyFieldType(DataType.uint32_t) + long unk_offset; // 8 relative offset to something + @IggyFieldType(DataType.uint32_t) + long unk_offset2; // 0xC relative offset to something + @IggyFieldType(DataType.uint32_t) + long unk_offset3; // 0x10 relative offset to something + @IggyFieldType(DataType.uint32_t) + long unk_offset4; // 0x14 relative offset to something + @IggyFieldType(DataType.uint32_t) + long xmin; //0x18 in pixels + @IggyFieldType(DataType.uint32_t) + long ymin; //0x0C in pixels + @IggyFieldType(DataType.uint32_t) + long xmax; // 0x20 in pixels + @IggyFieldType(DataType.uint32_t) + long ymax; // 0x24 in pixels + @IggyFieldType(DataType.uint32_t) + long unk_28; // probably number of blocks/objects after header + @IggyFieldType(DataType.uint32_t) + long unk_2C; + @IggyFieldType(DataType.uint32_t) + long unk_30; + @IggyFieldType(DataType.uint32_t) + long unk_34; + @IggyFieldType(DataType.uint32_t) + long unk_38; + @IggyFieldType(DataType.uint32_t) + long unk_3C; + @IggyFieldType(DataType.float_t) + float frameRate; + @IggyFieldType(DataType.uint32_t) + long unk_44; + @IggyFieldType(DataType.uint32_t) + long unk_48; + @IggyFieldType(DataType.uint32_t) + long unk_4C; + @IggyFieldType(DataType.uint32_t) + long names_offset; // 0x50 relative offset to the names/import section of the file + @IggyFieldType(DataType.uint32_t) + long unk_offset5; // 0x54 relative offset to something + @IggyFieldType(DataType.uint64_t) + long unk_58; // Maybe number of imports/names pointed by names_offset + @IggyFieldType(DataType.uint32_t) + long last_section_offset; // 0x60 relative offset, points to the small last section of the file + @IggyFieldType(DataType.uint32_t) + long unk_offset6; // 0x64 relative offset to something + @IggyFieldType(DataType.uint32_t) + long as3_code_offset; // 0x68 relative offset to as3 code (8 bytes header + abc blob) + @IggyFieldType(DataType.uint32_t) + long as3_names_offset; // 0x6C relative offset to as3 file names table (or classes names or whatever) + @IggyFieldType(DataType.uint32_t) + long unk_70; + @IggyFieldType(DataType.uint32_t) + long unk_74; + @IggyFieldType(DataType.uint32_t) + long unk_78; // Maybe number of classes / as3 names + @IggyFieldType(DataType.uint32_t) + long unk_7C; + + // Offset 0x80 (outside header): there are *unk_28* 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. + // After the offsets, the bodies of objects pointed above, which apparently have a code like 0xFFXX to identify the type of object, followed by a (unique?) identifier + // for the object. + // A DefineEditText-like object can be easily spotted and apparently uses type code 0x06 (or 0xFF06) but as stated above, + // it is written in a different way. + public IggyFlashHeader32(AbstractDataStream stream) throws IOException { + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + main_offset = stream.readUI32(); + as3_section_offset = stream.readUI32(); + unk_offset = stream.readUI32(); + unk_offset2 = stream.readUI32(); + unk_offset3 = stream.readUI32(); + unk_offset4 = stream.readUI32(); + xmin = stream.readUI32(); + ymin = stream.readUI32(); + xmax = stream.readUI32(); + ymax = stream.readUI32(); + unk_28 = stream.readUI32(); + unk_2C = stream.readUI32(); + unk_30 = stream.readUI32(); + unk_34 = stream.readUI32(); + unk_38 = stream.readUI32(); + unk_3C = stream.readUI32(); + frameRate = stream.readFloat(); + unk_44 = stream.readUI32(); + unk_48 = stream.readUI32(); + unk_4C = stream.readUI32(); + unk_3C = stream.readUI32(); + names_offset = stream.readUI32(); + unk_offset5 = stream.readUI32(); + unk_58 = stream.readUI64(); + last_section_offset = stream.readUI32(); + unk_offset6 = stream.readUI32(); + as3_code_offset = stream.readUI32(); + as3_names_offset = stream.readUI32(); + unk_70 = stream.readUI32(); + unk_74 = stream.readUI32(); + unk_78 = stream.readUI32(); + unk_7C = stream.readUI32(); + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + 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(xmax).append("\r\n"); + sb.append("ymax ").append(ymax).append("\r\n"); + sb.append("unk_28 ").append(unk_28).append("\r\n"); + sb.append("unk_2C ").append(unk_2C).append("\r\n"); + sb.append("unk_30 ").append(unk_30).append("\r\n"); + sb.append("unk_34 ").append(unk_34).append("\r\n"); + sb.append("unk_38 ").append(unk_38).append("\r\n"); + sb.append("unk_3C ").append(unk_3C).append("\r\n"); + sb.append("frameRate ").append(frameRate).append("\r\n"); + sb.append("unk_44 ").append(unk_44).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("names_offset ").append(names_offset).append("\r\n"); + sb.append("unk_offset5 ").append(unk_offset5).append("\r\n"); + sb.append("unk_58 ").append(unk_58).append("\r\n"); + sb.append("last_section_offset ").append(last_section_offset).append("\r\n"); + sb.append("unk_offset6 ").append(unk_offset6).append("\r\n"); + sb.append("as3_code_offset ").append(as3_code_offset).append("\r\n"); + sb.append("as3_names_offset ").append(as3_names_offset).append("\r\n"); + sb.append("unk_70 ").append(unk_70).append("\r\n"); + sb.append("unk_74 ").append(unk_74).append("\r\n"); + sb.append("unk_78 ").append(unk_78).append("\r\n"); + sb.append("unk_7C ").append(unk_7C).append("\r\n"); + sb.append("]"); + return sb.toString(); + } + + @Override + public long getXMin() { + return xmin; + } + + @Override + public long getYMin() { + return ymin; + } + + @Override + public long getXMax() { + return xmax; + } + + @Override + public long getYMax() { + return ymax; + } + + @Override + public float getFrameRate() { + return frameRate; + } +} 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 bebb70cd5..d9f4467f7 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,211 +1,212 @@ -package com.jpexs.decompiler.flash.iggy; - -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import java.io.IOException; - -/** - * - * @author Jindra - * - * Based of works of somebody called eternity. - */ -public class IggyFlashHeader64 implements IggyFlashHeaderInterface { - - @IggyFieldType(DataType.uint64_t) - long main_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) - long unk_offset; // 0x10 relative offset to something - @IggyFieldType(DataType.uint64_t) - long unk_offset2; // 0x18 relative offset to something - @IggyFieldType(DataType.uint64_t) - long unk_offset3; // 0x20 relative offset to something - @IggyFieldType(DataType.uint64_t) - long unk_offset4; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file - @IggyFieldType(DataType.uint32_t) - long xmin; // 0x30 in pixels - @IggyFieldType(DataType.uint32_t) - long ymin; // 0x34 in pixels - @IggyFieldType(DataType.uint32_t) - long xmax; // 0x38 in pixels - @IggyFieldType(DataType.uint32_t) - long ymax; // 0x3C in pixels - @IggyFieldType(DataType.uint32_t) - long unk_40; // probably numer of blocks/objects after header - @IggyFieldType(DataType.uint32_t) - long unk_44; - @IggyFieldType(DataType.uint32_t) - long unk_48; - @IggyFieldType(DataType.uint32_t) - long unk_4C; - @IggyFieldType(DataType.uint32_t) - long unk_50; - @IggyFieldType(DataType.uint32_t) - long unk_54; - @IggyFieldType(DataType.float_t) - float frame_rate; - @IggyFieldType(DataType.uint32_t) - long unk_5C; - @IggyFieldType(DataType.uint64_t) - long fonts_offset; - @IggyFieldType(DataType.uint64_t) - long unk_68; - @IggyFieldType(DataType.uint64_t) - 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) - long unk_80; // Maybe number of imports/names pointed by names_offset - @IggyFieldType(DataType.uint64_t) - long last_section_offset; // 0x88 relative offset, points to the small last section of the file - @IggyFieldType(DataType.uint64_t) - long unk_offset6; // 0x90 relative offset to something - @IggyFieldType(DataType.uint64_t) - long as3_code_offset; // 0x98 relative offset to as3 code (16 bytes header + abc blob) - @IggyFieldType(DataType.uint64_t) - 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_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. - // After the offsets, the bodies of objects pointed above, which apparently have a code like 0xFFXX to identify the type of object, followed by a (unique?) identifier - // for the object. - // A DefineEditText-like object can be easily spotted and apparently uses type code 0x06 (or 0xFF06) but as stated above, - // it is written in a different way. - public IggyFlashHeader64(AbstractDataStream stream) throws IOException { - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - main_offset = stream.readUI64(); - as3_section_offset = stream.readUI64(); - unk_offset = stream.readUI64(); - unk_offset2 = stream.readUI64(); - unk_offset3 = stream.readUI64(); - unk_offset4 = stream.readUI64(); - xmin = stream.readUI32(); - ymin = stream.readUI32(); - xmax = stream.readUI32(); - ymax = stream.readUI32(); - unk_40 = stream.readUI32(); - unk_44 = stream.readUI32(); - unk_48 = stream.readUI32(); - unk_4C = stream.readUI32(); - unk_50 = stream.readUI32(); - unk_54 = stream.readUI32(); - frame_rate = stream.readFloat(); - unk_5C = stream.readUI32(); - fonts_offset = stream.readUI64(); - unk_68 = stream.readUI64(); - names_offset = stream.readUI64(); - unk_offset5 = stream.readUI64(); - unk_80 = stream.readUI64(); - last_section_offset = stream.readUI64(); - unk_offset6 = stream.readUI64(); - as3_code_offset = stream.readUI64(); - as3_names_offset = stream.readUI64(); - unk_A8 = stream.readUI32(); - unk_AC = stream.readUI32(); - font_count = stream.readUI32(); - unk_B4 = stream.readUI32(); - - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - 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); - sb.append(" global: ").append(main_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("\r\n"); - sb.append("unk_offset2 ").append(unk_offset2); - if (unk_offset2 != 1) { - sb.append(" global: ").append(main_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("\r\n"); - sb.append("unk_offset4 ").append(unk_offset4); - if (unk_offset4 != 1) { - sb.append(" global: ").append(main_offset + unk_offset4); - } - sb.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("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"); - sb.append("unk_54 ").append(unk_54).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("fonts_offset ").append(fonts_offset).append("\r\n"); - sb.append("unk_68 ").append(unk_68).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"); - sb.append("last_section_offset ").append(last_section_offset).append("\r\n"); - sb.append("unk_offset6 ").append(unk_offset6).append("\r\n"); - sb.append("as3_code_offset ").append(as3_code_offset).append("\r\n"); - 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("font_count ").append(font_count).append("\r\n"); - sb.append("unk_B4 ").append(unk_B4).append("\r\n"); - sb.append("]"); - return sb.toString(); - - } - - @Override - public long getXMin() { - return xmin; - } - - @Override - public long getYMin() { - return ymin; - } - - @Override - public long getXMax() { - return xmax; - } - - @Override - public long getYMax() { - return ymax; - } - - @Override - public float getFrameRate() { - return frame_rate; - } - -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; + +/** + * + * @author Jindra + * + * Based of works of somebody called eternity. + */ +public class IggyFlashHeader64 implements IggyFlashHeaderInterface { + + @IggyFieldType(DataType.uint64_t) + long main_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) + long unk_offset; // 0x10 relative offset to something + @IggyFieldType(DataType.uint64_t) + long unk_offset2; // 0x18 relative offset to something + @IggyFieldType(DataType.uint64_t) + long unk_offset3; // 0x20 relative offset to something + @IggyFieldType(DataType.uint64_t) + long unk_offset4; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file + @IggyFieldType(DataType.uint32_t) + long xmin; // 0x30 in pixels + @IggyFieldType(DataType.uint32_t) + long ymin; // 0x34 in pixels + @IggyFieldType(DataType.uint32_t) + long xmax; // 0x38 in pixels + @IggyFieldType(DataType.uint32_t) + long ymax; // 0x3C in pixels + @IggyFieldType(DataType.uint32_t) + long unk_40; // probably numer of blocks/objects after header + @IggyFieldType(DataType.uint32_t) + long unk_44; + @IggyFieldType(DataType.uint32_t) + long unk_48; + @IggyFieldType(DataType.uint32_t) + long unk_4C; + @IggyFieldType(DataType.uint32_t) + long unk_50; + @IggyFieldType(DataType.uint32_t) + long unk_54; + @IggyFieldType(DataType.float_t) + float frame_rate; + @IggyFieldType(DataType.uint32_t) + long unk_5C; + @IggyFieldType(DataType.uint64_t) + long fonts_offset; + @IggyFieldType(DataType.uint64_t) + long unk_68; + @IggyFieldType(DataType.uint64_t) + 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) + long unk_80; // Maybe number of imports/names pointed by names_offset + @IggyFieldType(DataType.uint64_t) + long last_section_offset; // 0x88 relative offset, points to the small last section of the file + @IggyFieldType(DataType.uint64_t) + long unk_offset6; // 0x90 relative offset to something + @IggyFieldType(DataType.uint64_t) + long as3_code_offset; // 0x98 relative offset to as3 code (16 bytes header + abc blob) + @IggyFieldType(DataType.uint64_t) + 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_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. + // After the offsets, the bodies of objects pointed above, which apparently have a code like 0xFFXX to identify the type of object, followed by a (unique?) identifier + // for the object. + // A DefineEditText-like object can be easily spotted and apparently uses type code 0x06 (or 0xFF06) but as stated above, + // it is written in a different way. + public IggyFlashHeader64(AbstractDataStream stream) throws IOException { + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream stream) throws IOException { + main_offset = stream.readUI64(); + as3_section_offset = stream.readUI64(); + unk_offset = stream.readUI64(); + unk_offset2 = stream.readUI64(); + unk_offset3 = stream.readUI64(); + unk_offset4 = stream.readUI64(); + xmin = stream.readUI32(); + ymin = stream.readUI32(); + xmax = stream.readUI32(); + ymax = stream.readUI32(); + unk_40 = stream.readUI32(); + unk_44 = stream.readUI32(); + unk_48 = stream.readUI32(); + unk_4C = stream.readUI32(); + unk_50 = stream.readUI32(); + unk_54 = stream.readUI32(); + frame_rate = stream.readFloat(); + unk_5C = stream.readUI32(); + fonts_offset = stream.readUI64(); + unk_68 = stream.readUI64(); + names_offset = stream.readUI64(); + unk_offset5 = stream.readUI64(); + unk_80 = stream.readUI64(); + last_section_offset = stream.readUI64(); + unk_offset6 = stream.readUI64(); + as3_code_offset = stream.readUI64(); + as3_names_offset = stream.readUI64(); + unk_A8 = stream.readUI32(); + unk_AC = stream.readUI32(); + font_count = stream.readUI32(); + unk_B4 = stream.readUI32(); + + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + 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); + sb.append(" global: ").append(main_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("\r\n"); + sb.append("unk_offset2 ").append(unk_offset2); + if (unk_offset2 != 1) { + sb.append(" global: ").append(main_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("\r\n"); + sb.append("unk_offset4 ").append(unk_offset4); + if (unk_offset4 != 1) { + sb.append(" global: ").append(main_offset + unk_offset4); + } + sb.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("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"); + sb.append("unk_54 ").append(unk_54).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("fonts_offset ").append(fonts_offset).append("\r\n"); + sb.append("unk_68 ").append(unk_68).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"); + sb.append("last_section_offset ").append(last_section_offset).append("\r\n"); + sb.append("unk_offset6 ").append(unk_offset6).append("\r\n"); + sb.append("as3_code_offset ").append(as3_code_offset).append("\r\n"); + 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("font_count ").append(font_count).append("\r\n"); + sb.append("unk_B4 ").append(unk_B4).append("\r\n"); + sb.append("]"); + return sb.toString(); + + } + + @Override + public long getXMin() { + return xmin; + } + + @Override + public long getYMin() { + return ymin; + } + + @Override + public long getXMax() { + return xmax; + } + + @Override + public long getYMax() { + return ymax; + } + + @Override + public float getFrameRate() { + return frame_rate; + } + +} 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 index 0cde6ac8a..42dabf338 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeaderInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeaderInterface.java @@ -1,18 +1,20 @@ -package com.jpexs.decompiler.flash.iggy; - -/** - * - * @author JPEXS - */ -public interface IggyFlashHeaderInterface extends StructureInterface { - - public long getXMin(); - - public long getYMin(); - - public long getXMax(); - - public long getYMax(); - - public float getFrameRate(); -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; + +/** + * + * @author JPEXS + */ +public interface IggyFlashHeaderInterface extends StructureInterface { + + public long getXMin(); + + public long getYMin(); + + public long getXMax(); + + public long getYMax(); + + public float getFrameRate(); +} 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 ea9f86b00..a5e1f9cb2 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 @@ -1,5 +1,8 @@ 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.ByteArrayDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; 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 2bb41162d..057ad0bd6 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 @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; 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 f5c963b7f..6b52e13fc 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 @@ -1,165 +1,167 @@ -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); - } - } -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.streams.SeekMode; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; +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(AbstractDataStream 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/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index 49d72e6a4..c5f61ba2f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -1,5 +1,8 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.SeekMode; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; import java.util.ArrayList; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java index 35f7b0295..eaae35f84 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; import java.util.logging.Level; 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 b673cccaa..a4f7d4823 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 @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.annotations.SWFType; import java.io.IOException; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java index 5dec7c3f2..c3a39aa6e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java @@ -1,5 +1,7 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; + /** * * @author JPEXS diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java index 9931df6ea..b95f369b0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java @@ -1,194 +1,196 @@ -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; - -/** - * - * @author JPEXS - */ -public class IggyText implements StructureInterface { - - 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 - @IggyArrayFieldType(value = DataType.widechar_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(AbstractDataStream stream) throws IOException { - this.readFromDataStream(stream); - } - - @Override - public void readFromDataStream(AbstractDataStream 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(); - - //flags - enum_hex = s.readUI16(); - - int en = enum_hex; - - //guessing - it could be like DefineEditText?... - hasText = ((en >> 0) & 1) == 1; - wordWrap = ((en >> 1) & 1) == 1; - multiline = ((en >> 2) & 1) == 1; - password = ((en >> 3) & 1) == 1; - readOnly = ((en >> 4) & 1) == 1; - hasTextColor = ((en >> 5) & 1) == 1; - hasMaxLength = ((en >> 6) & 1) == 1; - hasFont = ((en >> 7) & 1) == 1; - hasFontClass = ((en >> 8) & 1) == 1; - autosize = ((en >> 9) & 1) == 1; - hasLayout = ((en >> 10) & 1) == 1; - noSelect = ((en >> 11) & 1) == 1; - border = ((en >> 12) & 1) == 1; - wasStatic = ((en >> 13) & 1) == 1; - html = ((en >> 14) & 1) == 1; - useOutlines = ((en >> 15) & 1) == 1; - - //if hasFont? - fontIndex = s.readUI16(); //fontId - //if hasFontClass - readString? - //if hasFont || hasFontClass - readFontHeight? - //if hasTextColor....? - zero = s.readUI32(); - one = s.readUI64(); //01CB FF33 3333 - some = s.readBytes(32); // [6] => 40, [24] => 8 - StringBuilder textBuilder = new StringBuilder(); - do { - char c = (char) s.readUI16(); - if (c == '\0') { - break; - } - textBuilder.append(c); - } while (true); - initialText = textBuilder.toString(); - } - - @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - 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; - } - -} +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; +import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public class IggyText implements StructureInterface { + + 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 + @IggyArrayFieldType(value = DataType.widechar_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(AbstractDataStream stream) throws IOException { + this.readFromDataStream(stream); + } + + @Override + public void readFromDataStream(AbstractDataStream 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(); + + //flags + enum_hex = s.readUI16(); + + int en = enum_hex; + + //guessing - it could be like DefineEditText?... + hasText = ((en >> 0) & 1) == 1; + wordWrap = ((en >> 1) & 1) == 1; + multiline = ((en >> 2) & 1) == 1; + password = ((en >> 3) & 1) == 1; + readOnly = ((en >> 4) & 1) == 1; + hasTextColor = ((en >> 5) & 1) == 1; + hasMaxLength = ((en >> 6) & 1) == 1; + hasFont = ((en >> 7) & 1) == 1; + hasFontClass = ((en >> 8) & 1) == 1; + autosize = ((en >> 9) & 1) == 1; + hasLayout = ((en >> 10) & 1) == 1; + noSelect = ((en >> 11) & 1) == 1; + border = ((en >> 12) & 1) == 1; + wasStatic = ((en >> 13) & 1) == 1; + html = ((en >> 14) & 1) == 1; + useOutlines = ((en >> 15) & 1) == 1; + + //if hasFont? + fontIndex = s.readUI16(); //fontId + //if hasFontClass - readString? + //if hasFont || hasFontClass - readFontHeight? + //if hasTextColor....? + zero = s.readUI32(); + one = s.readUI64(); //01CB FF33 3333 + some = s.readBytes(32); // [6] => 40, [24] => 8 + StringBuilder textBuilder = new StringBuilder(); + do { + char c = (char) s.readUI16(); + if (c == '\0') { + break; + } + textBuilder.append(c); + } while (true); + initialText = textBuilder.toString(); + } + + @Override + public void writeToDataStream(AbstractDataStream stream) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + 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; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java index af0e58ec8..132d57e4c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java @@ -1,5 +1,6 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import java.io.IOException; /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/AbstractDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/AbstractDataStream.java similarity index 58% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/AbstractDataStream.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/AbstractDataStream.java index ecc790b51..dd4b750f2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/AbstractDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/AbstractDataStream.java @@ -1,4 +1,4 @@ -package com.jpexs.decompiler.flash.iggy; +package com.jpexs.decompiler.flash.iggy.streams; import java.io.EOFException; import java.io.IOException; @@ -7,20 +7,24 @@ import java.io.IOException; * * @author JPEXS */ -public abstract class AbstractDataStream { +public abstract class AbstractDataStream implements DataStreamInterface { /** * Available bytes * * @return null if unknown, long value otherwise */ + @Override public abstract Long available(); + @Override public abstract long position(); + @Override public abstract boolean is64(); - protected long readUI64() throws IOException { + @Override + public long readUI64() throws IOException { try { return (readUI32() + (readUI32() << 32)) & 0xffffffffffffffffL; } catch (EOFException ex) { @@ -28,7 +32,8 @@ public abstract class AbstractDataStream { } } - protected boolean writeUI64(long val) throws IOException { + @Override + public boolean writeUI64(long val) throws IOException { write((int) (val & 0xff)); write((int) ((val >> 8) & 0xff)); write((int) ((val >> 16) & 0xff)); @@ -41,7 +46,8 @@ public abstract class AbstractDataStream { return true; } - protected long readUI32() throws IOException { + @Override + public long readUI32() throws IOException { try { return (readUI8() + (readUI8() << 8) + (readUI8() << 16) + (readUI8() << 24)); } catch (EOFException ex) { @@ -49,7 +55,8 @@ public abstract class AbstractDataStream { } } - protected boolean writeUI32(long val) throws IOException { + @Override + public boolean writeUI32(long val) throws IOException { write((int) (val & 0xff)); write((int) ((val >> 8) & 0xff)); write((int) ((val >> 16) & 0xff)); @@ -57,7 +64,8 @@ public abstract class AbstractDataStream { return true; } - protected int readUI16() throws IOException { + @Override + public int readUI16() throws IOException { try { return (readUI8() + (readUI8() << 8)) & 0xffff; } catch (EOFException ex) { @@ -65,13 +73,15 @@ public abstract class AbstractDataStream { } } - protected boolean writeUI16(int val) throws IOException { + @Override + public boolean writeUI16(int val) throws IOException { write(val & 0xff); write((val >> 8) & 0xff); return true; } - protected int readUI8() throws IOException { + @Override + public int readUI8() throws IOException { try { return read() & 0xff; } catch (EOFException ex) { @@ -79,20 +89,24 @@ public abstract class AbstractDataStream { } } - protected boolean writeUI8(int val) throws IOException { + @Override + public boolean writeUI8(int val) throws IOException { write(val); return true; } - protected float readFloat() throws IOException { + @Override + public float readFloat() throws IOException { return Float.intBitsToFloat((int) readUI32()); } - protected boolean writeFloat(float val) throws IOException { + @Override + public boolean writeFloat(float val) throws IOException { return writeUI32(Float.floatToIntBits(val)); } - protected byte[] readBytes(int numBytes) throws IOException { + @Override + public byte[] readBytes(int numBytes) throws IOException { byte[] ret = new byte[numBytes]; for (int i = 0; i < numBytes; i++) { ret[i] = (byte) read(); @@ -100,17 +114,27 @@ public abstract class AbstractDataStream { return ret; } - protected void writeBytes(byte[] data) throws IOException { + @Override + public void writeBytes(byte[] data) throws IOException { for (int i = 0; i < data.length; i++) { write(data[i] & 0xff); } } - protected abstract int read() throws IOException; + @Override + public abstract int read() throws IOException; - protected abstract void seek(long pos, SeekMode mode) throws IOException; + @Override + public abstract void seek(long pos, SeekMode mode) throws IOException; - protected void write(int val) throws IOException { + @Override + public void write(int val) throws IOException { //nothing } + + @Override + public void close() { + //nothing + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/ByteArrayDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java similarity index 83% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/ByteArrayDataStream.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java index b8327fb52..9f75d647e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/ByteArrayDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java @@ -1,85 +1,90 @@ -package com.jpexs.decompiler.flash.iggy; - -import java.io.EOFException; -import java.io.IOException; -import java.util.Arrays; - -/** - * - * @author JPEXS - */ -public class ByteArrayDataStream extends AbstractDataStream { - - private byte[] data; - private long pos; - private boolean use64bit; - - public ByteArrayDataStream(int initialSize, boolean use64bit) { - this(new byte[initialSize], use64bit); - } - - @Override - public long position() { - return pos; - } - - public ByteArrayDataStream(byte data[], boolean use64bit) { - this.data = data; - pos = 0; - this.use64bit = use64bit; - } - - @Override - public boolean is64() { - return use64bit; - } - - @Override - protected int read() throws IOException { - if (pos >= data.length) { - throw new EOFException("End of stream reached"); - } - int ret = data[(int) pos] & 0xff; - pos++; - return ret; - } - - public void resize(int newsize) { - data = Arrays.copyOf(data, newsize); - if (pos > data.length) { - pos = data.length; - } - } - - @Override - protected void write(int val) throws IOException { - if (pos >= data.length) { - throw new EOFException("End of stream reached"); - } - data[(int) pos] = (byte) val; - pos++; - } - - @Override - protected void seek(long pos, SeekMode mode) throws IOException { - long newpos = pos; - if (mode == SeekMode.CUR) { - newpos = this.pos + pos; - } else if (mode == SeekMode.END) { - newpos = data.length - pos; - } - if (newpos > data.length) { - throw new ArrayIndexOutOfBoundsException("Position outside bounds accessed: " + pos + ". Size: " + data.length); - } else if (newpos < 0) { - throw new ArrayIndexOutOfBoundsException("Negative position accessed: " + pos); - } else { - this.pos = (int) newpos; - } - } - - @Override - public Long available() { - return (long) (data.length - pos); - } - -} +package com.jpexs.decompiler.flash.iggy.streams; + +import java.io.EOFException; +import java.io.IOException; +import java.util.Arrays; + +/** + * + * @author JPEXS + */ +public class ByteArrayDataStream extends AbstractDataStream { + + private byte[] data; + private long pos; + private boolean use64bit; + + public ByteArrayDataStream(int initialSize, boolean use64bit) { + this(new byte[initialSize], use64bit); + } + + @Override + public long position() { + return pos; + } + + public ByteArrayDataStream(byte data[], boolean use64bit) { + this.data = data; + pos = 0; + this.use64bit = use64bit; + } + + @Override + public boolean is64() { + return use64bit; + } + + @Override + public int read() throws IOException { + if (pos >= data.length) { + throw new EOFException("End of stream reached"); + } + int ret = data[(int) pos] & 0xff; + pos++; + return ret; + } + + public void resize(int newsize) { + data = Arrays.copyOf(data, newsize); + if (pos > data.length) { + pos = data.length; + } + } + + @Override + public void write(int val) throws IOException { + if (pos >= data.length) { + throw new EOFException("End of stream reached"); + } + data[(int) pos] = (byte) val; + pos++; + } + + @Override + public void seek(long pos, SeekMode mode) throws IOException { + long newpos = pos; + if (mode == SeekMode.CUR) { + newpos = this.pos + pos; + } else if (mode == SeekMode.END) { + newpos = data.length - pos; + } + if (newpos > data.length) { + throw new ArrayIndexOutOfBoundsException("Position outside bounds accessed: " + pos + ". Size: " + data.length); + } else if (newpos < 0) { + throw new ArrayIndexOutOfBoundsException("Negative position accessed: " + pos); + } else { + this.pos = (int) newpos; + } + } + + @Override + public Long available() { + return (long) (data.length - pos); + } + + @Override + public void close() { + //nothing + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/DataStreamInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/DataStreamInterface.java new file mode 100644 index 000000000..d3a4f2916 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/DataStreamInterface.java @@ -0,0 +1,9 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +/** + * + * @author JPEXS + */ +public interface DataStreamInterface extends ReadDataStreamInterface, WriteDataStreamInterface { + +} 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 new file mode 100644 index 000000000..88f5d1355 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java @@ -0,0 +1,88 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +import java.io.EOFException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author JPEXS + */ +public class RandomAccessFileDataStream extends AbstractDataStream { + + private RandomAccessFile raf; + private boolean is64; + + public RandomAccessFileDataStream(File file) throws FileNotFoundException { + this(new RandomAccessFile(file, "rw")); + } + + public RandomAccessFileDataStream(RandomAccessFile rafile) { + this.raf = rafile; + } + + @Override + public Long available() { + try { + return raf.length() - raf.getFilePointer(); + } catch (IOException ex) { + return null; + } + } + + @Override + public long position() { + try { + return raf.getFilePointer(); + } catch (IOException ex) { + return -1; + } + } + + public void set64(boolean is64) { + this.is64 = is64; + } + + @Override + public boolean is64() { + return is64; + } + + @Override + public int read() throws IOException { + int val = raf.read(); + if (val == -1) { + throw new EOFException(); + } + return val; + } + + @Override + public void seek(long pos, SeekMode mode) throws IOException { + long newpos = pos; + if (mode == SeekMode.CUR) { + newpos = raf.getFilePointer() + pos; + } else if (mode == SeekMode.END) { + newpos = raf.length() - pos; + } + if (newpos > raf.length()) { + throw new ArrayIndexOutOfBoundsException("Position outside bounds accessed: " + pos + ". Size: " + raf.length()); + } else if (newpos < 0) { + throw new ArrayIndexOutOfBoundsException("Negative position accessed: " + pos); + } else { + raf.seek(newpos); + } + } + + @Override + public void close() { + try { + raf.close(); + } catch (IOException ex) { + //ignore + } + } + +} 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 new file mode 100644 index 000000000..b6bdf7bd8 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java @@ -0,0 +1,40 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public interface ReadDataStreamInterface extends AutoCloseable { + + /** + * Available bytes + * + * @return null if unknown, long value otherwise + */ + public Long available(); + + public long position(); + + public boolean is64(); + + public long readUI64() throws IOException; + + public long readUI32() throws IOException; + + public int readUI16() throws IOException; + + public int readUI8() throws IOException; + + public int read() throws IOException; + + public byte[] readBytes(int numBytes) throws IOException; + + public float readFloat() throws IOException; + + public void seek(long pos, SeekMode mode) throws IOException; + + @Override + public void close(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/SeekMode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/SeekMode.java similarity index 55% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/SeekMode.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/SeekMode.java index 449abf4ea..237fb8c7f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/SeekMode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/SeekMode.java @@ -1,9 +1,9 @@ -package com.jpexs.decompiler.flash.iggy; - -/** - * - * @author Jindra - */ -public enum SeekMode { - SET, CUR, END -} +package com.jpexs.decompiler.flash.iggy.streams; + +/** + * + * @author Jindra + */ +public enum SeekMode { + SET, CUR, END +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/StructureInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/StructureInterface.java similarity index 68% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/StructureInterface.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/StructureInterface.java index 8638c42e0..f16952a86 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/StructureInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/StructureInterface.java @@ -1,15 +1,16 @@ -package com.jpexs.decompiler.flash.iggy; - -import java.io.IOException; -import java.util.List; - -/** - * - * @author JPEXS - */ -public interface StructureInterface { - - public void readFromDataStream(AbstractDataStream stream) throws IOException; - - public void writeToDataStream(AbstractDataStream stream) throws IOException; -} +package com.jpexs.decompiler.flash.iggy.streams; + +import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; +import java.io.IOException; +import java.util.List; + +/** + * + * @author JPEXS + */ +public interface StructureInterface { + + public void readFromDataStream(AbstractDataStream stream) throws IOException; + + public void writeToDataStream(AbstractDataStream stream) throws IOException; +} 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 new file mode 100644 index 000000000..cd157ca98 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java @@ -0,0 +1,40 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public interface WriteDataStreamInterface extends AutoCloseable { + + /** + * Available bytes + * + * @return null if unknown, long value otherwise + */ + public Long available(); + + public long position(); + + public boolean is64(); + + public boolean writeUI64(long val) throws IOException; + + public boolean writeUI32(long val) throws IOException; + + public boolean writeUI16(int val) throws IOException; + + public boolean writeUI8(int val) throws IOException; + + public void write(int val) throws IOException; + + public void writeBytes(byte[] data) throws IOException; + + public boolean writeFloat(float val) throws IOException; + + public void seek(long pos, SeekMode mode) throws IOException; + + @Override + public void close(); +} From 7fcb962809250f9f50a5928eb3ed8571d8eb2620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 27 Nov 2016 09:21:35 +0100 Subject: [PATCH 05/27] removing 64bit parameter where unnecessary --- .../com/jpexs/decompiler/flash/iggy/IggyFile.java | 8 ++++---- .../com/jpexs/decompiler/flash/iggy/IggyFont.java | 2 +- .../decompiler/flash/iggy/IggyIndexParser.java | 4 ++-- .../flash/iggy/streams/AbstractDataStream.java | 3 --- .../flash/iggy/streams/ByteArrayDataStream.java | 13 +++---------- .../iggy/streams/RandomAccessFileDataStream.java | 9 --------- .../flash/iggy/streams/ReadDataStreamInterface.java | 2 -- .../iggy/streams/WriteDataStreamInterface.java | 2 -- 8 files changed, 10 insertions(+), 33 deletions(-) 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 3744bd315..5245301bc 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 @@ -173,7 +173,7 @@ public class IggyFile implements StructureInterface { } 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, is_64); + ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes); /* index_table: @@ -389,7 +389,7 @@ public class IggyFile implements StructureInterface { * @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, is_64); + ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes); /* index_table: @@ -604,11 +604,11 @@ public class IggyFile implements StructureInterface { for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); - AbstractDataStream dataStream = new ByteArrayDataStream(getEntryData(i), header.is64()); + AbstractDataStream dataStream = new ByteArrayDataStream(getEntryData(i)); if (entry.type == IggySubFileEntry.TYPE_INDEX) { List indexTable = new ArrayList<>(); List offsets = new ArrayList<>(); - IggyIndexParser.parseIndex(dataStream, indexTable, offsets); + IggyIndexParser.parseIndex(header.is64(), dataStream, indexTable, offsets); indexTables.add(indexTable); offsetTables.add(offsets); } else if (entry.type == IggySubFileEntry.TYPE_FLASH) { 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 a5e1f9cb2..86b61b103 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 @@ -177,7 +177,7 @@ public class IggyFont extends IggyTag { @Override public void readFromDataStream(AbstractDataStream stream) throws IOException { - ByteArrayDataStream s = new ByteArrayDataStream(stream.readBytes((int) (long) stream.available()), stream.is64()); + ByteArrayDataStream s = new ByteArrayDataStream(stream.readBytes((int) (long) stream.available())); type = s.readUI16(); fontId = s.readUI16(); zeroone = s.readBytes(28); 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 6b52e13fc..9e80df53f 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 @@ -30,7 +30,7 @@ public class IggyIndexParser { * @param offsets Output list of offsets * @throws IOException on error */ - public static void parseIndex(AbstractDataStream indexStream, List indexTableEntry, List offsets) throws IOException { + public static void parseIndex(boolean is64, AbstractDataStream indexStream, List indexTableEntry, List offsets) throws IOException { int indexTableSize = indexStream.readUI8(); int[] indexTable = new int[indexTableSize]; for (int i = 0; i < indexTableSize; i++) { @@ -90,7 +90,7 @@ public class IggyIndexParser { n = n8 + 1; - if (indexStream.is64()) { + if (is64) { if (i <= 2) { offset += 8 * n; // Ptr type } else if (i <= 4) { 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 dd4b750f2..bd075cfb5 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 @@ -20,9 +20,6 @@ public abstract class AbstractDataStream implements DataStreamInterface { @Override public abstract long position(); - @Override - public abstract boolean is64(); - @Override public long readUI64() throws IOException { try { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java index 9f75d647e..af7dcc0c5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java @@ -12,10 +12,9 @@ public class ByteArrayDataStream extends AbstractDataStream { private byte[] data; private long pos; - private boolean use64bit; - public ByteArrayDataStream(int initialSize, boolean use64bit) { - this(new byte[initialSize], use64bit); + public ByteArrayDataStream(int initialSize) { + this(new byte[initialSize]); } @Override @@ -23,15 +22,9 @@ public class ByteArrayDataStream extends AbstractDataStream { return pos; } - public ByteArrayDataStream(byte data[], boolean use64bit) { + public ByteArrayDataStream(byte data[]) { 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/streams/RandomAccessFileDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java index 88f5d1355..d46efbe6f 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 @@ -41,15 +41,6 @@ public class RandomAccessFileDataStream extends AbstractDataStream { } } - public void set64(boolean is64) { - this.is64 = is64; - } - - @Override - public boolean is64() { - return is64; - } - @Override public int read() throws IOException { int val = raf.read(); 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 b6bdf7bd8..0682218d8 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 @@ -17,8 +17,6 @@ public interface ReadDataStreamInterface extends AutoCloseable { public long position(); - public boolean is64(); - public long readUI64() throws IOException; public long readUI32() throws IOException; 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 cd157ca98..2bcbd6872 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 @@ -17,8 +17,6 @@ public interface WriteDataStreamInterface extends AutoCloseable { public long position(); - public boolean is64(); - public boolean writeUI64(long val) throws IOException; public boolean writeUI32(long val) throws IOException; From 4dfcef525f5c988506b77b394f5c9bcd6f30e36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 27 Nov 2016 11:34:27 +0100 Subject: [PATCH 06/27] Streams refactoring. Replace Iggy Swf stub --- .../flash/iggy/IggyCharAdvances.java | 9 +- .../flash/iggy/IggyCharIndices.java | 9 +- .../flash/iggy/IggyCharKerning.java | 9 +- .../decompiler/flash/iggy/IggyCharOffset.java | 9 +- .../jpexs/decompiler/flash/iggy/IggyFile.java | 96 ++++++++++++------- .../flash/iggy/IggyFlashHeader32.java | 9 +- .../flash/iggy/IggyFlashHeader64.java | 9 +- .../jpexs/decompiler/flash/iggy/IggyFont.java | 19 ++-- .../decompiler/flash/iggy/IggyHeader.java | 9 +- .../flash/iggy/IggyIndexParser.java | 3 +- .../decompiler/flash/iggy/IggyShape.java | 6 +- .../decompiler/flash/iggy/IggyShapeNode.java | 8 +- .../flash/iggy/IggySubFileEntry.java | 9 +- .../{IggyDataReader.java => IggySwf.java} | 14 +-- .../jpexs/decompiler/flash/iggy/IggyText.java | 9 +- .../decompiler/flash/iggy/RawIggyTag.java | 9 +- .../iggy/streams/AbstractDataStream.java | 8 ++ .../iggy/streams/ByteArrayDataStream.java | 83 ---------------- .../streams/RandomAccessFileDataStream.java | 16 +++- .../iggy/streams/ReadDataStreamInterface.java | 2 + .../iggy/streams/StructureInterface.java | 4 +- .../iggy/streams/TemporaryDataStream.java | 31 ++++++ 22 files changed, 196 insertions(+), 184 deletions(-) rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{IggyDataReader.java => IggySwf.java} (78%) delete mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/TemporaryDataStream.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java index 6b4b4d73a..537e6be3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java @@ -1,7 +1,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -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.ArrayList; import java.util.List; @@ -19,13 +20,13 @@ public class IggyCharAdvances implements StructureInterface { return advances; } - public IggyCharAdvances(AbstractDataStream stream, long charCount) throws IOException { + public IggyCharAdvances(ReadDataStreamInterface stream, long charCount) throws IOException { this.charCount = charCount; readFromDataStream(stream); } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { advances = new ArrayList<>(); for (int i = 0; i < charCount; i++) { advances.add(stream.readFloat()); @@ -33,7 +34,7 @@ public class IggyCharAdvances implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { for (int i = 0; i < advances.size(); i++) { stream.writeFloat(advances.get(i)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java index 265539592..f4cfd4e3c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java @@ -1,7 +1,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -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 com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; import java.util.ArrayList; @@ -24,13 +25,13 @@ public class IggyCharIndices implements StructureInterface { private long charCount; - public IggyCharIndices(AbstractDataStream stream, long charCount) throws IOException { + public IggyCharIndices(ReadDataStreamInterface stream, long charCount) throws IOException { this.charCount = charCount; readFromDataStream(stream); } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { chars = new ArrayList<>(); for (int i = 0; i < charCount; i++) { chars.add((char) stream.readUI16()); @@ -39,7 +40,7 @@ public class IggyCharIndices implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { for (int i = 0; i < chars.size(); i++) { stream.writeUI16(chars.get(i)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index 67da2c29b..d1987d2b1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -1,7 +1,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -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.ArrayList; import java.util.List; @@ -34,13 +35,13 @@ public class IggyCharKerning implements StructureInterface { return kerningOffsets; } - public IggyCharKerning(AbstractDataStream stream, long kernCount) throws IOException { + public IggyCharKerning(ReadDataStreamInterface stream, long kernCount) throws IOException { this.kernCount = kernCount; readFromDataStream(stream); } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { charsA = new ArrayList<>(); charsB = new ArrayList<>(); kerningOffsets = new ArrayList<>(); @@ -53,7 +54,7 @@ public class IggyCharKerning implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { for (int i = 0; i < kernCount; i++) { stream.writeUI16(charsA.get(i)); stream.writeUI16(charsB.get(i)); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 46a27b722..3f2ab4ffd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -1,7 +1,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -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 com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; import java.util.logging.Logger; @@ -31,7 +32,7 @@ public class IggyCharOffset implements StructureInterface { @IggyFieldType(DataType.uint64_t) long offset; - public IggyCharOffset(AbstractDataStream stream) throws IOException { + public IggyCharOffset(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -47,7 +48,7 @@ public class IggyCharOffset implements StructureInterface { } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { zero = stream.readUI64(); ischar1 = stream.readUI16(); ischar2 = stream.readUI16(); @@ -66,7 +67,7 @@ public class IggyCharOffset implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { stream.writeUI64(zero); stream.writeUI16(ischar1); stream.writeUI16(ischar2); 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 5245301bc..eef892111 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 @@ -3,11 +3,10 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; import com.jpexs.decompiler.flash.iggy.streams.SeekMode; import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream; -import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; -import com.jpexs.decompiler.flash.iggy.streams.ByteArrayDataStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; +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.TemporaryDataStream; import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; @@ -37,7 +36,7 @@ public class IggyFile implements StructureInterface { private List subFileEntriesData = new ArrayList<>(); private List headers = new ArrayList<>(); - private List flashDataReaders = new ArrayList<>(); + private List flashDataReaders = new ArrayList<>(); public Set getFontIds(int swfIndex) { return flashDataReaders.get(swfIndex).fonts.keySet(); @@ -55,14 +54,12 @@ public class IggyFile implements StructureInterface { return flashDataReaders.get(swfIndex).texts.keySet(); } - public IggyFile(File file) throws IOException { - try (AbstractDataStream stream = new RandomAccessFileDataStream(file)) { - readFromDataStream(stream); - } + public IggyFile(String filePath) throws IOException { + this(new File(filePath)); } - public IggyFile(RandomAccessFile rafile) throws IOException { - try (AbstractDataStream stream = new RandomAccessFileDataStream(rafile)) { + public IggyFile(File file) throws IOException { + try (ReadDataStreamInterface stream = new RandomAccessFileDataStream(file)) { readFromDataStream(stream); } } @@ -141,22 +138,15 @@ public class IggyFile implements StructureInterface { } public static void main(String[] args) throws IOException { - System.out.println("Iggy file splitter"); - if (args.length == 0) { - System.err.println("No file specified"); - System.exit(1); - } - - for (String s : args) { - File f = new File(s); - if (!f.exists()) { - System.err.println("File " + f + " does not exists"); - System.exit(1); - } - processFile(f); + 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 inFile = new File(inFileName); + File outFile = new File(outFileName); + IggyFile iggyFile = new IggyFile(inFile); + try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { + iggyFile.writeToDataStream(outputStream); } - System.exit(0); } private static void copyStream(InputStream is, OutputStream os) { @@ -173,7 +163,7 @@ public class IggyFile implements StructureInterface { } 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); + TemporaryDataStream stream = new TemporaryDataStream(index_bytes); /* index_table: @@ -389,7 +379,7 @@ public class IggyFile implements StructureInterface { * @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); + TemporaryDataStream stream = new TemporaryDataStream(index_bytes); /* index_table: @@ -597,14 +587,47 @@ public class IggyFile implements StructureInterface { return headers.get(swfIndex).getFrameRate(); } + //WIP + public boolean replaceSwf(int targetSwfIndex, IggySwf iggySwf) { + if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) { + throw new ArrayIndexOutOfBoundsException("No such SWF file index"); + } + byte replacementData[]; + try (DataStreamInterface stream = new TemporaryDataStream()) { + iggySwf.writeToDataStream(stream); + replacementData = stream.getAllBytes(); + } catch (IOException ex) { + Logger.getLogger(IggyFile.class.getName()).log(Level.SEVERE, "Error during updating SWF", ex); + return false; + } + + int swfIndex = 0; + 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) { + if (swfIndex == targetSwfIndex) { + long oldSize = entry.size; + long newSize = replacementData.length; + offsetsChange = offsetsChange + (newSize - oldSize); + //entries after this one will have modified offsets + } + swfIndex++; + } + } + subFileEntriesData.set(targetSwfIndex, replacementData); + return true; + } + private void parseEntries() throws IOException { List> indexTables = new ArrayList<>(); //TODO: use this for something ?? List> offsetTables = new ArrayList<>(); - List flashDataStreams = new ArrayList<>(); + List flashDataStreams = new ArrayList<>(); for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); - AbstractDataStream dataStream = new ByteArrayDataStream(getEntryData(i)); + DataStreamInterface dataStream = new TemporaryDataStream(getEntryData(i)); if (entry.type == IggySubFileEntry.TYPE_INDEX) { List indexTable = new ArrayList<>(); List offsets = new ArrayList<>(); @@ -626,13 +649,13 @@ public class IggyFile implements StructureInterface { for (int swfIndex = 0; swfIndex < headers.size(); swfIndex++) { IggyFlashHeaderInterface hdr = headers.get(swfIndex); - IggyDataReader dataReader = new IggyDataReader((IggyFlashHeader64) hdr, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex)); + IggySwf dataReader = new IggySwf((IggyFlashHeader64) hdr, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex)); flashDataReaders.add(dataReader); } } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { header = new IggyHeader(stream); for (int i = 0; i < header.getNumSubfiles(); i++) { subFileEntries.add(new IggySubFileEntry(stream)); @@ -646,11 +669,18 @@ public class IggyFile implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { header.writeToDataStream(stream); for (IggySubFileEntry entry : subFileEntries) { entry.writeToDataStream(stream); } + for (int i = 0; i < subFileEntries.size(); i++) { + IggySubFileEntry entry = subFileEntries.get(i); + byte[] entryData = subFileEntriesData.get(i); + + stream.seek(entry.offset, SeekMode.SET); + stream.writeBytes(entryData); + } } } 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 5cd77f11f..0c913fd0d 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 @@ -1,6 +1,7 @@ package com.jpexs.decompiler.flash.iggy; -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 com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; @@ -84,12 +85,12 @@ public class IggyFlashHeader32 implements IggyFlashHeaderInterface { // for the object. // A DefineEditText-like object can be easily spotted and apparently uses type code 0x06 (or 0xFF06) but as stated above, // it is written in a different way. - public IggyFlashHeader32(AbstractDataStream stream) throws IOException { + public IggyFlashHeader32(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { main_offset = stream.readUI32(); as3_section_offset = stream.readUI32(); unk_offset = stream.readUI32(); @@ -125,7 +126,7 @@ public class IggyFlashHeader32 implements IggyFlashHeaderInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } 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 d9f4467f7..1cc8c1156 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,6 +1,7 @@ package com.jpexs.decompiler.flash.iggy; -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 com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; @@ -81,12 +82,12 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { // for the object. // A DefineEditText-like object can be easily spotted and apparently uses type code 0x06 (or 0xFF06) but as stated above, // it is written in a different way. - public IggyFlashHeader64(AbstractDataStream stream) throws IOException { + public IggyFlashHeader64(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { main_offset = stream.readUI64(); as3_section_offset = stream.readUI64(); unk_offset = stream.readUI64(); @@ -122,7 +123,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } 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 86b61b103..e939b9c23 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 @@ -1,8 +1,9 @@ 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.ByteArrayDataStream; +import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; @@ -147,11 +148,11 @@ public class IggyFont extends IggyTag { this.padTo4byteBoundary = padTo4byteBoundary; } - public IggyFont(AbstractDataStream stream) throws IOException { + public IggyFont(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } - private long readAbsoluteOffset(AbstractDataStream stream) throws IOException { + private long readAbsoluteOffset(ReadDataStreamInterface stream) throws IOException { long offset = stream.readUI64(); if (offset == 1) { return 0; @@ -159,7 +160,7 @@ public class IggyFont extends IggyTag { return stream.position() - 8 + offset; } - private void writeAbsoluteOffset(AbstractDataStream stream, long offset) throws IOException { + private void writeAbsoluteOffset(WriteDataStreamInterface stream, long offset) throws IOException { if (offset == 0) { stream.writeUI64(1); } else { @@ -167,7 +168,7 @@ public class IggyFont extends IggyTag { } } - private void writeRelativeOffset(AbstractDataStream stream, long offset) throws IOException { + private void writeRelativeOffset(WriteDataStreamInterface stream, long offset) throws IOException { if (offset == 0) { stream.writeUI64(1); } else { @@ -176,8 +177,8 @@ public class IggyFont extends IggyTag { } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { - ByteArrayDataStream s = new ByteArrayDataStream(stream.readBytes((int) (long) stream.available())); + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { + TemporaryDataStream s = new TemporaryDataStream(stream.readBytes((int) (long) stream.available())); type = s.readUI16(); fontId = s.readUI16(); zeroone = s.readBytes(28); @@ -260,7 +261,7 @@ public class IggyFont extends IggyTag { } @Override - public void writeToDataStream(AbstractDataStream s) throws IOException { + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { s.writeUI16(type); s.writeUI16(fontId); s.writeBytes(zeroone); 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 057ad0bd6..f6dff51f6 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 @@ -1,7 +1,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -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 com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; @@ -52,7 +53,7 @@ public class IggyHeader implements StructureInterface { @IggyFieldType(value = DataType.uint32_t) private long numSubfiles; - public IggyHeader(AbstractDataStream stream) throws IOException { + public IggyHeader(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -92,7 +93,7 @@ public class IggyHeader implements StructureInterface { } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { magic = stream.readUI32(); if (magic != IggyHeader.MAGIC) { throw new IOException("Invalid Iggy file"); @@ -108,7 +109,7 @@ public class IggyHeader implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream s) throws IOException { + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { s.writeUI32(magic); s.writeUI32(version); s.writeUI8(platform1); 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 9e80df53f..7757d0772 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 @@ -2,6 +2,7 @@ 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 java.io.IOException; import java.util.List; import java.util.logging.Logger; @@ -30,7 +31,7 @@ public class IggyIndexParser { * @param offsets Output list of offsets * @throws IOException on error */ - public static void parseIndex(boolean is64, AbstractDataStream indexStream, List indexTableEntry, List offsets) throws IOException { + public static void parseIndex(boolean is64, ReadDataStreamInterface indexStream, List indexTableEntry, List offsets) throws IOException { int indexTableSize = indexStream.readUI8(); int[] indexTable = new int[indexTableSize]; for (int i = 0; i < indexTableSize; i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index c5f61ba2f..e7abed276 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -4,6 +4,8 @@ import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; import com.jpexs.decompiler.flash.iggy.streams.SeekMode; import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -81,7 +83,7 @@ public class IggyShape implements StructureInterface { } @Override - public void readFromDataStream(AbstractDataStream s) throws IOException { + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { s.seek(offset, SeekMode.SET); minx = s.readFloat(); miny = s.readFloat(); @@ -107,7 +109,7 @@ public class IggyShape implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream s) throws IOException { + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { s.writeFloat(minx); s.writeFloat(miny); s.writeFloat(maxx); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java index eaae35f84..9507acd9e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java @@ -3,6 +3,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; @@ -52,13 +54,13 @@ public class IggyShapeNode implements StructureInterface { this.isstart = isstart; } - public IggyShapeNode(AbstractDataStream s, boolean first) throws IOException { + public IggyShapeNode(ReadDataStreamInterface s, boolean first) throws IOException { this.first = first; readFromDataStream(s); } @Override - public void readFromDataStream(AbstractDataStream s) throws IOException { + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { targetX = s.readFloat(); targetY = s.readFloat(); controlX = s.readFloat(); @@ -81,7 +83,7 @@ public class IggyShapeNode implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream s) throws IOException { + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { s.writeFloat(targetX); s.writeFloat(targetY); s.writeFloat(controlX); 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 a4f7d4823..c87b3598b 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 @@ -1,7 +1,8 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -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 com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.annotations.SWFType; import java.io.IOException; @@ -33,7 +34,7 @@ public class IggySubFileEntry implements StructureInterface { @SWFType(BasicType.UI32) long offset; - public IggySubFileEntry(AbstractDataStream stream) throws IOException { + public IggySubFileEntry(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -57,7 +58,7 @@ public class IggySubFileEntry implements StructureInterface { } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { type = stream.readUI32(); size = stream.readUI32(); size2 = stream.readUI32(); @@ -65,7 +66,7 @@ public class IggySubFileEntry implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { stream.writeUI32(type); stream.writeUI32(size); stream.writeUI32(size2); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java similarity index 78% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java index 6d3b4e28b..ee54f21db 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDataReader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java @@ -2,8 +2,10 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; 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 com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; import java.io.IOException; import java.util.HashMap; import java.util.List; @@ -13,7 +15,7 @@ import java.util.Map; * * @author JPEXS */ -public class IggyDataReader implements StructureInterface { +public class IggySwf implements StructureInterface { final static int NO_OFFSET = 1; @@ -28,7 +30,7 @@ public class IggyDataReader implements StructureInterface { private Map sizesOfOffsets; private List allOffsets; - public IggyDataReader(IggyFlashHeader64 header, AbstractDataStream stream, List offsets) throws IOException { + public IggySwf(IggyFlashHeader64 header, ReadDataStreamInterface stream, List offsets) throws IOException { this.header = header; sizesOfOffsets = new HashMap<>(); for (int i = 0; i < offsets.size() - 1; i++) { @@ -40,7 +42,7 @@ public class IggyDataReader implements StructureInterface { } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { //here is offset[0] StringBuilder nameBuilder = new StringBuilder(); do { @@ -77,8 +79,8 @@ public class IggyDataReader implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); //TODO!!! } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java index b95f369b0..746919b1d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java @@ -1,9 +1,10 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import java.io.IOException; /** @@ -76,12 +77,12 @@ public class IggyText implements StructureInterface { this.initialText = name; } - public IggyText(AbstractDataStream stream) throws IOException { + public IggyText(ReadDataStreamInterface stream) throws IOException { this.readFromDataStream(stream); } @Override - public void readFromDataStream(AbstractDataStream s) throws IOException { + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { type = s.readUI16(); //characterId - iggy Id @@ -137,7 +138,7 @@ public class IggyText implements StructureInterface { } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java index 132d57e4c..81b57474b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java @@ -1,6 +1,7 @@ package com.jpexs.decompiler.flash.iggy; -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; /** @@ -13,7 +14,7 @@ public class RawIggyTag extends IggyTag { int tagType; private int length; - public RawIggyTag(int tagType, AbstractDataStream stream, int length) throws IOException { + public RawIggyTag(int tagType, ReadDataStreamInterface stream, int length) throws IOException { this.length = length; this.tagType = tagType; readFromDataStream(stream); @@ -25,12 +26,12 @@ public class RawIggyTag extends IggyTag { } @Override - public void readFromDataStream(AbstractDataStream stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { rawData = stream.readBytes(length); } @Override - public void writeToDataStream(AbstractDataStream stream) throws IOException { + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { stream.writeBytes(rawData); } 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 bd075cfb5..b11de5655 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 @@ -111,6 +111,14 @@ public abstract class AbstractDataStream implements DataStreamInterface { return ret; } + public byte[] getAllBytes() throws IOException { + long oldPos = position(); + seek(0, SeekMode.SET); + byte[] ret = readBytes((int) (long) available()); + seek(oldPos, SeekMode.SET); + return ret; + } + @Override public void writeBytes(byte[] data) throws IOException { for (int i = 0; i < data.length; i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java deleted file mode 100644 index af7dcc0c5..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ByteArrayDataStream.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.jpexs.decompiler.flash.iggy.streams; - -import java.io.EOFException; -import java.io.IOException; -import java.util.Arrays; - -/** - * - * @author JPEXS - */ -public class ByteArrayDataStream extends AbstractDataStream { - - private byte[] data; - private long pos; - - public ByteArrayDataStream(int initialSize) { - this(new byte[initialSize]); - } - - @Override - public long position() { - return pos; - } - - public ByteArrayDataStream(byte data[]) { - this.data = data; - pos = 0; - } - - @Override - public int read() throws IOException { - if (pos >= data.length) { - throw new EOFException("End of stream reached"); - } - int ret = data[(int) pos] & 0xff; - pos++; - return ret; - } - - public void resize(int newsize) { - data = Arrays.copyOf(data, newsize); - if (pos > data.length) { - pos = data.length; - } - } - - @Override - public void write(int val) throws IOException { - if (pos >= data.length) { - throw new EOFException("End of stream reached"); - } - data[(int) pos] = (byte) val; - pos++; - } - - @Override - public void seek(long pos, SeekMode mode) throws IOException { - long newpos = pos; - if (mode == SeekMode.CUR) { - newpos = this.pos + pos; - } else if (mode == SeekMode.END) { - newpos = data.length - pos; - } - if (newpos > data.length) { - throw new ArrayIndexOutOfBoundsException("Position outside bounds accessed: " + pos + ". Size: " + data.length); - } else if (newpos < 0) { - throw new ArrayIndexOutOfBoundsException("Negative position accessed: " + pos); - } else { - this.pos = (int) newpos; - } - } - - @Override - public Long available() { - return (long) (data.length - pos); - } - - @Override - public void close() { - //nothing - } - -} 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 d46efbe6f..b341fc015 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 @@ -12,15 +12,16 @@ import java.io.RandomAccessFile; */ public class RandomAccessFileDataStream extends AbstractDataStream { + private File file; private RandomAccessFile raf; - private boolean is64; - public RandomAccessFileDataStream(File file) throws FileNotFoundException { - this(new RandomAccessFile(file, "rw")); + protected File getFile() { + return file; } - public RandomAccessFileDataStream(RandomAccessFile rafile) { - this.raf = rafile; + public RandomAccessFileDataStream(File file) throws FileNotFoundException { + this.file = file; + raf = new RandomAccessFile(file, "rw"); } @Override @@ -76,4 +77,9 @@ public class RandomAccessFileDataStream extends AbstractDataStream { } } + @Override + public void write(int val) throws IOException { + raf.write(val); + } + } 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 0682218d8..b9049c124 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 @@ -33,6 +33,8 @@ public interface ReadDataStreamInterface extends AutoCloseable { public void seek(long pos, SeekMode mode) throws IOException; + public byte[] getAllBytes() throws IOException; + @Override public void close(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/StructureInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/StructureInterface.java index f16952a86..526445ddd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/StructureInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/StructureInterface.java @@ -10,7 +10,7 @@ import java.util.List; */ public interface StructureInterface { - public void readFromDataStream(AbstractDataStream stream) throws IOException; + public void readFromDataStream(ReadDataStreamInterface stream) throws IOException; - public void writeToDataStream(AbstractDataStream stream) throws IOException; + public void writeToDataStream(WriteDataStreamInterface stream) throws IOException; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/TemporaryDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/TemporaryDataStream.java new file mode 100644 index 000000000..adb99afdd --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/TemporaryDataStream.java @@ -0,0 +1,31 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +import java.io.File; +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public class TemporaryDataStream extends RandomAccessFileDataStream { + + public TemporaryDataStream() throws IOException { + this(new byte[0]); + } + + public TemporaryDataStream(byte[] data) throws IOException { + super(File.createTempFile("tempdatastream", ".bin")); + this.getFile().deleteOnExit(); + writeBytes(data); + seek(0, SeekMode.SET); + } + + @Override + public void close() { + try { + this.getFile().delete(); + } catch (Exception ex) { + //ignore + } + } +} From 398d12d9e95826f3a80142e851dd2035e4779e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 27 Nov 2016 21:55:40 +0100 Subject: [PATCH 07/27] read/write abs adresses - WIP --- .../decompiler/flash/iggy/IggyCharOffset.java | 4 + .../jpexs/decompiler/flash/iggy/IggyFile.java | 82 ++++++++++++-- .../flash/iggy/IggyFlashHeader64.java | 32 +++++- .../jpexs/decompiler/flash/iggy/IggyFont.java | 100 ++++++++++++------ .../decompiler/flash/iggy/IggyShape.java | 2 +- .../jpexs/decompiler/flash/iggy/IggySwf.java | 58 ++++++++-- .../jpexs/decompiler/flash/iggy/IggyTag.java | 5 + .../{RawIggyTag.java => RawIggyPart.java} | 4 +- .../iggy/conversion/IggyToSwfConvertor.java | 15 ++- .../streams/RandomAccessFileDataStream.java | 24 ++++- .../iggy/streams/ReadDataStreamInterface.java | 2 + .../streams/WriteDataStreamInterface.java | 2 + 12 files changed, 267 insertions(+), 63 deletions(-) rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{RawIggyTag.java => RawIggyPart.java} (81%) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 3f2ab4ffd..564531c85 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -82,6 +82,10 @@ public class IggyCharOffset implements StructureInterface { } } + public boolean hasGlyph() { + return offset > 0; + } + public long getZero() { return zero; } 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 eef892111..19ee321a6 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 @@ -36,22 +36,79 @@ public class IggyFile implements StructureInterface { private List subFileEntriesData = new ArrayList<>(); private List headers = new ArrayList<>(); - private List flashDataReaders = new ArrayList<>(); + private List iggySwfs = new ArrayList<>(); + private List> indexTables = new ArrayList<>(); + private List> offsetTables = new ArrayList<>(); + private List indexDataStreams = new ArrayList<>(); + + public static final int FIRST_TAG_POSITION = 3; + + public void replaceTag(int swfIndex, int tagIndex, IggyTag newTag) throws IOException { + WriteDataStreamInterface stream = new TemporaryDataStream(); + newTag.writeToDataStream(stream); + + setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize()); + } + + public void saveTag(int swfIndex, IggyTag newTag) throws IOException { + WriteDataStreamInterface stream = new TemporaryDataStream(); + newTag.writeToDataStream(stream); + + int tagIndex = 0; + List taglist = iggySwfs.get(swfIndex).getTags(); + for (IggyTag t : taglist) { + if (t == newTag) { + break; + } + tagIndex++; + } + if (tagIndex < taglist.size()) { + setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize()); + } else { + throw new IllegalArgumentException("Tag does not exists in this iggy file"); + } + } + + private boolean setSwfItemLength(int swfIndex, int itemindex, long newLength) { + DataStreamInterface stream = indexDataStreams.get(swfIndex); + + List offsetTable = offsetTables.get(swfIndex); + + long offset = offsetTable.get(itemindex); + long nextOffset = itemindex == offsetTable.size() - 1 ? stream.totalSize() : offsetTable.get(itemindex + 1); + long currentSize = nextOffset - offset; + try { + byte indexData[] = stream.getAllBytes(); + setItemLength(offset, header.is64(), indexData, newLength); + indexDataStreams.set(swfIndex, new TemporaryDataStream(indexData)); //TODO: optimize! + long lengthDelta = newLength - currentSize; + for (int i = itemindex + 1; i < offsetTable.size(); i++) { + offsetTable.set(i, offsetTable.get(i) + lengthDelta); + } + return true; + } catch (IOException ex) { + return false; + } + } + + public IggySwf getSwf(int swfIndex) { + return iggySwfs.get(swfIndex); + } public Set getFontIds(int swfIndex) { - return flashDataReaders.get(swfIndex).fonts.keySet(); + return iggySwfs.get(swfIndex).fonts.keySet(); } public IggyFont getFont(int swfIndex, int fontId) { - return flashDataReaders.get(swfIndex).fonts.get(fontId); + return iggySwfs.get(swfIndex).fonts.get(fontId); } public IggyText getText(int swfIndex, int textId) { - return flashDataReaders.get(swfIndex).texts.get(textId); + return iggySwfs.get(swfIndex).texts.get(textId); } public Set getTextIds(int swfIndex) { - return flashDataReaders.get(swfIndex).texts.keySet(); + return iggySwfs.get(swfIndex).texts.keySet(); } public IggyFile(String filePath) throws IOException { @@ -144,6 +201,9 @@ public class IggyFile implements StructureInterface { File inFile = new File(inFileName); File outFile = new File(outFileName); IggyFile iggyFile = new IggyFile(inFile); + IggySwf iswf = iggyFile.getSwf(0); + iggyFile.replaceSwf(0, iswf); + outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); } @@ -560,11 +620,11 @@ public class IggyFile implements StructureInterface { } public int getSwfCount() { - return flashDataReaders.size(); + return iggySwfs.size(); } public String getSwfName(int swfIndex) { - return flashDataReaders.get(swfIndex).getName(); + return iggySwfs.get(swfIndex).getName(); } public long getSwfXMin(int swfIndex) { @@ -594,6 +654,7 @@ public class IggyFile implements StructureInterface { } byte replacementData[]; try (DataStreamInterface stream = new TemporaryDataStream()) { + headers.get(targetSwfIndex).writeToDataStream(stream); iggySwf.writeToDataStream(stream); replacementData = stream.getAllBytes(); } catch (IOException ex) { @@ -611,6 +672,8 @@ public class IggyFile implements StructureInterface { long oldSize = entry.size; long newSize = replacementData.length; offsetsChange = offsetsChange + (newSize - oldSize); + entry.size = newSize; + entry.size2 = newSize; //entries after this one will have modified offsets } swfIndex++; @@ -621,8 +684,6 @@ public class IggyFile implements StructureInterface { } private void parseEntries() throws IOException { - List> indexTables = new ArrayList<>(); //TODO: use this for something ?? - List> offsetTables = new ArrayList<>(); List flashDataStreams = new ArrayList<>(); for (int i = 0; i < subFileEntries.size(); i++) { @@ -632,6 +693,7 @@ public class IggyFile implements StructureInterface { List indexTable = new ArrayList<>(); List offsets = new ArrayList<>(); IggyIndexParser.parseIndex(header.is64(), dataStream, indexTable, offsets); + indexDataStreams.add(dataStream); indexTables.add(indexTable); offsetTables.add(offsets); } else if (entry.type == IggySubFileEntry.TYPE_FLASH) { @@ -650,7 +712,7 @@ public class IggyFile implements StructureInterface { for (int swfIndex = 0; swfIndex < headers.size(); swfIndex++) { IggyFlashHeaderInterface hdr = headers.get(swfIndex); IggySwf dataReader = new IggySwf((IggyFlashHeader64) hdr, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex)); - flashDataReaders.add(dataReader); + iggySwfs.add(dataReader); } } 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 1cc8c1156..7700ca377 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 @@ -124,7 +124,37 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + stream.writeUI64(main_offset); + stream.writeUI64(as3_section_offset); + stream.writeUI64(unk_offset); + stream.writeUI64(unk_offset2); + stream.writeUI64(unk_offset3); + stream.writeUI64(unk_offset4); + stream.writeUI32(xmin); + stream.writeUI32(ymin); + stream.writeUI32(xmax); + stream.writeUI32(ymax); + stream.writeUI32(unk_40); + stream.writeUI32(unk_44); + stream.writeUI32(unk_48); + stream.writeUI32(unk_4C); + stream.writeUI32(unk_50); + stream.writeUI32(unk_54); + stream.writeFloat(frame_rate); + stream.writeUI32(unk_5C); + stream.writeUI64(fonts_offset); + stream.writeUI64(unk_68); + stream.writeUI64(names_offset); + stream.writeUI64(unk_offset5); + stream.writeUI64(unk_80); + stream.writeUI64(last_section_offset); + stream.writeUI64(unk_offset6); + stream.writeUI64(as3_code_offset); + stream.writeUI64(as3_names_offset); + stream.writeUI32(unk_A8); + stream.writeUI32(unk_AC); + stream.writeUI32(font_count); + stream.writeUI32(unk_B4); } @Override 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 e939b9c23..d209c2947 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 @@ -176,9 +176,13 @@ public class IggyFont extends IggyTag { } } + private long makeAbsOffset(ReadDataStreamInterface s, long offset) { + return offset == 1 ? 0 : s.position() - 8 + offset; + } + @Override - public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { - TemporaryDataStream s = new TemporaryDataStream(stream.readBytes((int) (long) stream.available())); + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + long basePos = s.position(); type = s.readUI16(); fontId = s.readUI16(); zeroone = s.readBytes(28); @@ -187,19 +191,25 @@ public class IggyFont extends IggyTag { descent = s.readUI16(); leading = s.readUI16(); flags = s.readUI64(); - start_of_char_struct = readAbsoluteOffset(s); - start_of_char_index = readAbsoluteOffset(s); - start_of_scale = readAbsoluteOffset(s); + start_of_char_struct = s.readUI64(); + long abs_start_of_char_struct = makeAbsOffset(s, start_of_char_struct); + start_of_char_index = s.readUI64(); + long abs_start_of_char_index = makeAbsOffset(s, start_of_char_struct); + start_of_scale = s.readUI64(); + long abs_start_of_scale = makeAbsOffset(s, start_of_char_struct); + kern_count = s.readUI32(); unk_float = new float[5]; for (int i = 0; i < unk_float.length; i++) { unk_float[i] = s.readFloat(); } - start_of_kern = readAbsoluteOffset(s); + start_of_kern = s.readUI64(); + long abs_start_of_kern = makeAbsOffset(s, start_of_kern); zero_padd = s.readUI64(); what_2 = s.readUI64(); zero_padd_2 = s.readUI64(); - start_of_name = readAbsoluteOffset(s); + start_of_name = s.readUI64(); + long abs_start_of_name = makeAbsOffset(s, start_of_name); one_padd = s.readUI64(); xscale = s.readUI16(); yscale = s.readUI16(); @@ -209,7 +219,7 @@ public class IggyFont extends IggyTag { char_count = s.readUI32(); zero_padd_4 = s.readUI64(); what_3 = s.readUI64(); - s.seek(272, SeekMode.CUR); + s.seek(basePos + 272, SeekMode.SET); sss1 = s.readFloat(); one_padd2 = s.readUI32(); sss2 = s.readFloat(); @@ -218,8 +228,8 @@ public class IggyFont extends IggyTag { one_padd4 = s.readUI32(); sss4 = s.readFloat(); one_padd5 = s.readUI32(); - if (start_of_name != 0) { - s.seek(start_of_name, SeekMode.SET); + if (abs_start_of_name != 0) { + s.seek(abs_start_of_name, SeekMode.SET); StringBuilder nameBuilder = new StringBuilder(); int nameCharCnt = 0; do { @@ -234,8 +244,8 @@ public class IggyFont extends IggyTag { name = nameBuilder.toString(); } s.readUI64(); //pad zero - if (start_of_char_struct != 0) { - s.seek(start_of_char_struct, SeekMode.SET); + if (abs_start_of_char_struct != 0) { + s.seek(abs_start_of_char_struct, SeekMode.SET); charOffsets = new ArrayList<>(); for (int i = 0; i < char_count; i++) { charOffsets.add(new IggyCharOffset(s)); @@ -243,19 +253,23 @@ public class IggyFont extends IggyTag { glyphs = new ArrayList<>(); for (int i = 0; i < char_count; i++) { long offset = charOffsets.get(i).offset; - glyphs.add(new IggyShape(s, offset)); + if (offset != 0) { + glyphs.add(new IggyShape(s, offset)); + } else { + glyphs.add(null); + } } } - if (start_of_char_index != 0) { - s.seek(start_of_char_index, SeekMode.SET); + if (abs_start_of_char_index != 0) { + s.seek(abs_start_of_char_index, SeekMode.SET); codePoints = new IggyCharIndices(s, char_count); } - if (start_of_scale != 0) { - s.seek(start_of_scale, SeekMode.SET); + if (abs_start_of_scale != 0) { + s.seek(abs_start_of_scale, SeekMode.SET); charScales = new IggyCharAdvances(s, char_count); } - if (start_of_kern != 0) { - s.seek(start_of_kern, SeekMode.SET); + if (abs_start_of_kern != 0) { + s.seek(abs_start_of_kern, SeekMode.SET); charKernings = new IggyCharKerning(s, kern_count); } } @@ -270,18 +284,23 @@ public class IggyFont extends IggyTag { s.writeUI16(descent); s.writeUI16(leading); s.writeUI64(flags); - writeAbsoluteOffset(s, start_of_char_struct); - writeAbsoluteOffset(s, start_of_char_index); - writeAbsoluteOffset(s, start_of_scale); + long abs_start_of_char_struct = s.position() + start_of_char_struct; + s.writeUI64(start_of_char_struct); + long abs_start_of_char_index = s.position() + start_of_char_index; + s.writeUI64(start_of_char_index); + long abs_start_of_scale = s.position() + start_of_scale; + s.writeUI64(start_of_scale); s.writeUI32(kern_count); for (int i = 0; i < unk_float.length; i++) { s.writeFloat(unk_float[i]); } - writeAbsoluteOffset(s, start_of_kern); + long abs_start_of_kern = s.position() + start_of_kern; + s.writeUI64(start_of_kern); s.writeUI64(zero_padd); s.writeUI64(what_2); s.writeUI64(zero_padd_2); - writeAbsoluteOffset(s, start_of_name); + long abs_start_of_name = s.position() + start_of_name; + s.writeUI64(start_of_name); s.writeUI64(one_padd); s.writeUI16(xscale); s.writeUI16(yscale); @@ -291,10 +310,7 @@ public class IggyFont extends IggyTag { s.writeUI32(char_count); s.writeUI64(zero_padd_4); s.writeUI64(what_3); - //s.seek(272, SeekMode.CUR); - for (int i = 0; i < 272; i++) { - s.write(0); - } + s.seek(272, SeekMode.SET); s.writeFloat(sss1); s.writeUI32(one_padd2); s.writeFloat(sss2); @@ -303,7 +319,8 @@ public class IggyFont extends IggyTag { s.writeUI32(one_padd4); s.writeFloat(sss4); s.writeUI32(one_padd5); - if (start_of_name != 0) { + if (abs_start_of_name != 0) { + s.seek(abs_start_of_name, SeekMode.SET); for (char c : name.toCharArray()) { s.writeUI16(c); } @@ -317,25 +334,33 @@ public class IggyFont extends IggyTag { } } s.writeUI64(0); //pad zero - if (start_of_char_struct != 0) { + if (abs_start_of_char_struct != 0) { + s.seek(abs_start_of_char_struct, SeekMode.SET); //offsets of shapes for (IggyCharOffset ofs : charOffsets) { ofs.writeToDataStream(s); } - for (IggyShape shp : glyphs) { - shp.writeToDataStream(s); + for (int i = 0; i < glyphs.size(); i++) { + IggyShape shp = glyphs.get(i); + if (shp != null) { + s.seek(charOffsets.get(i).offset, SeekMode.SET); + shp.writeToDataStream(s); + } } } - if (start_of_char_index != 0) { + if (abs_start_of_char_index != 0) { + s.seek(abs_start_of_char_index, SeekMode.SET); for (char c : codePoints.chars) { s.writeUI16(c); } s.writeUI32(0); } - if (start_of_scale != 0) { + if (abs_start_of_scale != 0) { + s.seek(abs_start_of_scale, SeekMode.SET); charScales.writeToDataStream(s); } - if (start_of_kern != 0) { + if (abs_start_of_kern != 0) { + s.seek(abs_start_of_kern, SeekMode.SET); charKernings.writeToDataStream(s); } } @@ -413,4 +438,9 @@ public class IggyFont extends IggyTag { return ID; } + @Override + public String toString() { + return String.format("IggyFontTag (%04X)", ID); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index e7abed276..7fa2aa585 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -62,7 +62,7 @@ public class IggyShape implements StructureInterface { private long offset; - public IggyShape(AbstractDataStream stream, long offset) throws IOException { + public IggyShape(ReadDataStreamInterface stream, long offset) throws IOException { this.offset = offset; readFromDataStream(stream); } 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 ee54f21db..e6d85a4bf 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 @@ -6,7 +6,9 @@ import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,17 +30,26 @@ public class IggySwf implements StructureInterface { private IggyFlashHeader64 header; private Map sizesOfOffsets; - private List allOffsets; + private List offsets; + private List tags = new ArrayList<>(); + + public List getTags() { + return tags; + } public IggySwf(IggyFlashHeader64 header, ReadDataStreamInterface stream, List offsets) throws IOException { this.header = header; + this.offsets = offsets; + calcSizesFromOffsets(); + readFromDataStream(stream); + } + + private void calcSizesFromOffsets() { sizesOfOffsets = new HashMap<>(); for (int i = 0; i < offsets.size() - 1; i++) { sizesOfOffsets.put(offsets.get(i), offsets.get(i + 1) - offsets.get(i)); } sizesOfOffsets.put(offsets.get(offsets.size() - 1), 0L); //Last offset has 0L length? - this.allOffsets = offsets; - readFromDataStream(stream); } @Override @@ -56,20 +67,25 @@ public class IggySwf implements StructureInterface { //here is offset[1] int pad8 = 8 - (int) (stream.position() % 8); stream.seek(pad8, SeekMode.CUR); - //here is offset [2] + //here is offset [2] fonts = new HashMap<>(); int fontIndex = 0; - for (int i = 2; i < allOffsets.size(); i++) { - long offset = allOffsets.get(i); + for (int ofs = 2; ofs < offsets.size(); ofs++) { + long offset = offsets.get(ofs); + if (offset < stream.position()) { + continue; + } stream.seek(offset, SeekMode.SET); int type = stream.readUI16(); stream.seek(-2, SeekMode.CUR); if (type == IggyFont.ID) { IggyFont font = new IggyFont(stream); fonts.put(fontIndex++, font); - } - if (type == IggyText.ID) { - //TODO: Texts - incomplete + tags.add(font); + } else if (ofs < offsets.size() - 1) { + int len = (int) (offsets.get(ofs + 1) - offsets.get(ofs)); + RawIggyPart rtag = new RawIggyPart(type, stream, len); + tags.add(rtag); } } } @@ -80,7 +96,29 @@ public class IggySwf implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //TODO!!! + List newOffsets = new ArrayList<>(); + + try { + newOffsets.add(stream.position()); + for (int i = 0; i < name.length(); i++) { + stream.writeUI16(name.charAt(i)); + } + stream.writeUI16(0); + newOffsets.add(stream.position()); + long pad8 = 8 - (stream.position() % 8); + for (int i = 0; i < pad8; i++) { + stream.write(0); + } + newOffsets.add(stream.position()); + for (IggyTag tag : tags) { + tag.writeToDataStream(stream); + newOffsets.add(stream.position()); + } + } catch (IOException ex) { + //ignore + } + this.offsets = newOffsets; + calcSizesFromOffsets(); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java index c3a39aa6e..eeae0f3cb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java @@ -9,4 +9,9 @@ import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; public abstract class IggyTag implements StructureInterface { public abstract int getTagType(); + + @Override + public String toString() { + return String.format("IggyTag (%04X)", getTagType()); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyPart.java similarity index 81% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyPart.java index 81b57474b..9f1e0aeaa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyPart.java @@ -8,13 +8,13 @@ import java.io.IOException; * * @author JPEXS */ -public class RawIggyTag extends IggyTag { +public class RawIggyPart extends IggyTag { byte[] rawData; int tagType; private int length; - public RawIggyTag(int tagType, ReadDataStreamInterface stream, int length) throws IOException { + public RawIggyPart(int tagType, ReadDataStreamInterface stream, int length) throws IOException { this.length = length; this.tagType = tagType; readFromDataStream(stream); 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 f48758673..7acf46afb 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 @@ -150,11 +150,20 @@ public class IggyToSwfConvertor { IggyCharAdvances advanceValues = iggyFont.getCharAdvances(); for (int i = 0; i < iggyFont.getCharacterCount(); i++) { int code = iggyFont.getCharIndices().getChars().get(i); - IggyShape glyph = iggyFont.getChars().get(i); fontTag.codeTable.add(code); - SHAPE shp = IggyShapeToSwfConvertor.convertCharToShape(glyph); + 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.fontBoundsTable.add(shp.getBounds()); + fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i))); } 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 b341fc015..199dc8c93 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 @@ -5,6 +5,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -24,6 +26,15 @@ public class RandomAccessFileDataStream extends AbstractDataStream { raf = new RandomAccessFile(file, "rw"); } + @Override + public Long totalSize() { + try { + return raf.length(); + } catch (IOException ex) { + return null; + } + } + @Override public Long available() { try { @@ -51,6 +62,13 @@ public class RandomAccessFileDataStream extends AbstractDataStream { return val; } + @Override + public byte[] readBytes(int numBytes) throws IOException { + byte buf[] = new byte[numBytes]; + raf.readFully(buf); + return buf; + } + @Override public void seek(long pos, SeekMode mode) throws IOException { long newpos = pos; @@ -60,7 +78,11 @@ public class RandomAccessFileDataStream extends AbstractDataStream { newpos = raf.length() - pos; } if (newpos > raf.length()) { - throw new ArrayIndexOutOfBoundsException("Position outside bounds accessed: " + pos + ". Size: " + raf.length()); + raf.seek(raf.length()); + long curpos = raf.length(); + for (long i = curpos; i < newpos; i++) { + raf.write(0); + } } else if (newpos < 0) { throw new ArrayIndexOutOfBoundsException("Negative position accessed: " + pos); } else { 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 b9049c124..1b22ba523 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 @@ -15,6 +15,8 @@ public interface ReadDataStreamInterface extends AutoCloseable { */ public Long available(); + public Long totalSize(); + public long position(); public long readUI64() throws IOException; 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 2bcbd6872..1b3e47e61 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 @@ -15,6 +15,8 @@ public interface WriteDataStreamInterface extends AutoCloseable { */ public Long available(); + public Long totalSize(); + public long position(); public boolean writeUI64(long val) throws IOException; From 74b7273da611351df74f7a0fbcc97cfdf10be114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 28 Nov 2016 05:45:43 +0100 Subject: [PATCH 08/27] abs adresses fix --- .../src/com/jpexs/decompiler/flash/iggy/IggyFont.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 d209c2947..ae9ae38b6 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 @@ -194,9 +194,9 @@ public class IggyFont extends IggyTag { start_of_char_struct = s.readUI64(); long abs_start_of_char_struct = makeAbsOffset(s, start_of_char_struct); start_of_char_index = s.readUI64(); - long abs_start_of_char_index = makeAbsOffset(s, start_of_char_struct); + long abs_start_of_char_index = makeAbsOffset(s, start_of_char_index); start_of_scale = s.readUI64(); - long abs_start_of_scale = makeAbsOffset(s, start_of_char_struct); + long abs_start_of_scale = makeAbsOffset(s, start_of_scale); kern_count = s.readUI32(); unk_float = new float[5]; From 321d6982c8218daa766900afc40fceb9f2b44c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 28 Nov 2016 05:56:12 +0100 Subject: [PATCH 09/27] abs adresses fix --- .../com/jpexs/decompiler/flash/iggy/IggyFont.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) 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 ae9ae38b6..dfedbd954 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 @@ -6,6 +6,7 @@ import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -180,6 +181,10 @@ public class IggyFont extends IggyTag { return offset == 1 ? 0 : s.position() - 8 + offset; } + private long makeAbsOffset(WriteDataStreamInterface s, long offset) { + return offset == 1 ? 0 : s.position() - 8 + offset; + } + @Override public void readFromDataStream(ReadDataStreamInterface s) throws IOException { long basePos = s.position(); @@ -284,23 +289,23 @@ public class IggyFont extends IggyTag { s.writeUI16(descent); s.writeUI16(leading); s.writeUI64(flags); - long abs_start_of_char_struct = s.position() + start_of_char_struct; s.writeUI64(start_of_char_struct); - long abs_start_of_char_index = s.position() + start_of_char_index; + long abs_start_of_char_struct = makeAbsOffset(s, start_of_char_struct); s.writeUI64(start_of_char_index); - long abs_start_of_scale = s.position() + start_of_scale; + long abs_start_of_char_index = makeAbsOffset(s, start_of_char_index); s.writeUI64(start_of_scale); + long abs_start_of_scale = makeAbsOffset(s, start_of_scale); s.writeUI32(kern_count); for (int i = 0; i < unk_float.length; i++) { s.writeFloat(unk_float[i]); } - long abs_start_of_kern = s.position() + start_of_kern; s.writeUI64(start_of_kern); + long abs_start_of_kern = makeAbsOffset(s, start_of_kern); s.writeUI64(zero_padd); s.writeUI64(what_2); s.writeUI64(zero_padd_2); - long abs_start_of_name = s.position() + start_of_name; s.writeUI64(start_of_name); + long abs_start_of_name = makeAbsOffset(s, start_of_name); s.writeUI64(one_padd); s.writeUI16(xscale); s.writeUI16(yscale); From 20da73645379480f7de3d1360542495d0f5d83f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 28 Nov 2016 11:33:23 +0100 Subject: [PATCH 10/27] Fixing header fields, fields printer --- .../flash/iggy/IggyFlashHeader64.java | 267 ++++++++++-------- .../flash/iggy/annotations/FieldPrinter.java | 80 ++++++ 2 files changed, 226 insertions(+), 121 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java 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 7700ca377..6df20387c 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,9 +1,11 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.annotations.FieldPrinter; import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; +import java.lang.reflect.Field; /** * @@ -14,17 +16,17 @@ import java.io.IOException; public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @IggyFieldType(DataType.uint64_t) - long main_offset; // 0 Relative offset to first section (matches sizeof header); + long off_start; // 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... + long off_seq_end; // 8 Relative offset to as3 file names table... @IggyFieldType(DataType.uint64_t) - long unk_offset; // 0x10 relative offset to something + long off_font_end; // 0x10 relative offset to something @IggyFieldType(DataType.uint64_t) - long unk_offset2; // 0x18 relative offset to something + long off_seq_start1; // 0x18 relative offset to something @IggyFieldType(DataType.uint64_t) - long unk_offset3; // 0x20 relative offset to something + long pad_to_match; // 0x20 relative offset to something @IggyFieldType(DataType.uint64_t) - long unk_offset4; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file + long off_seq_start2; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file @IggyFieldType(DataType.uint32_t) long xmin; // 0x30 in pixels @IggyFieldType(DataType.uint32_t) @@ -49,32 +51,34 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { float frame_rate; @IggyFieldType(DataType.uint32_t) long unk_5C; - @IggyFieldType(DataType.uint64_t) - long fonts_offset; - @IggyFieldType(DataType.uint64_t) - long unk_68; - @IggyFieldType(DataType.uint64_t) - 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) - long unk_80; // Maybe number of imports/names pointed by names_offset - @IggyFieldType(DataType.uint64_t) - long last_section_offset; // 0x88 relative offset, points to the small last section of the file - @IggyFieldType(DataType.uint64_t) - long unk_offset6; // 0x90 relative offset to something - @IggyFieldType(DataType.uint64_t) - long as3_code_offset; // 0x98 relative offset to as3 code (16 bytes header + abc blob) - @IggyFieldType(DataType.uint64_t) - 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 + long additional_import1; @IggyFieldType(DataType.uint32_t) - long unk_B4; //zero (?) + long zero1; + //boolean imported = false; + //if( additional_import1 > 0 ) imported = true + @IggyFieldType(DataType.uint64_t) + long unk_guid; // same for some fonts (eng + chinese) + @IggyFieldType(DataType.uint64_t) + long off_names; // 0x70 relative offset to the names/import section of the file - end of fonts + @IggyFieldType(DataType.uint64_t) + long off_unk8C; // 0x78 relative offset to something + @IggyFieldType(DataType.uint64_t) + long off_unk80; + @IggyFieldType(DataType.uint64_t) + long off_last_section; + @IggyFieldType(DataType.uint64_t) + long off_flash_filename; + @IggyFieldType(DataType.uint64_t) + long off_decl_strings; + @IggyFieldType(DataType.uint64_t) + long off_type_of_fonts; + @IggyFieldType(DataType.uint64_t) + long flags; + @IggyFieldType(DataType.uint32_t) + long font_count; + @IggyFieldType(DataType.uint32_t) + long zero2; // 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. @@ -86,14 +90,80 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { readFromDataStream(stream); } + private long base_address; + private long sequence_end_address; + private long font_end_address; + private long sequence_start_address; + private long names_address; + private long unk8C_address; + private long unk80_address; + private long last_section_address; + private long flash_filename_address; + private long decl_strings_address; + private long type_fonts_address; + + public long getBaseAddress() { + return base_address; + } + + public long getSequenceEndAddress() { + return sequence_end_address; + } + + public long getFontEndAddress() { + return font_end_address; + } + + public long getSequenceStartAddress() { + return sequence_start_address; + } + + public long getNamesAddress() { + return names_address; + } + + public long getUnk8CAddress() { + return unk8C_address; + } + + public long getUnk80Address() { + return unk80_address; + } + + public long getLastSectionAddress() { + return last_section_address; + } + + public long getFlashFilenameAddress() { + return flash_filename_address; + } + + public long getDeclStringsAddress() { + return decl_strings_address; + } + + public long getTypeFontsAddress() { + return type_fonts_address; + } + @Override public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { - main_offset = stream.readUI64(); - as3_section_offset = stream.readUI64(); - unk_offset = stream.readUI64(); - unk_offset2 = stream.readUI64(); - unk_offset3 = stream.readUI64(); - unk_offset4 = stream.readUI64(); + off_start = stream.readUI64(); + base_address = off_start + stream.position() - 8; + off_seq_end = stream.readUI64(); + sequence_end_address = off_seq_end + stream.position() - 8; + off_font_end = stream.readUI64(); + font_end_address = off_font_end + stream.position() - 8; + off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times) + pad_to_match = stream.readUI64(); + if (pad_to_match != 1) { + throw new IOException("Wrong iggy file - no pad to match 1"); + } + off_seq_start2 = stream.readUI64(); + if (off_seq_start1 != off_seq_start2) { + throw new IOException("Wrong iggy font format (sequence_start)!\n"); + } + sequence_start_address = off_seq_start2 + stream.position() - 8; xmin = stream.readUI32(); ymin = stream.readUI32(); xmax = stream.readUI32(); @@ -106,30 +176,38 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { unk_54 = stream.readUI32(); frame_rate = stream.readFloat(); unk_5C = stream.readUI32(); - fonts_offset = stream.readUI64(); - unk_68 = stream.readUI64(); - names_offset = stream.readUI64(); - unk_offset5 = stream.readUI64(); - unk_80 = stream.readUI64(); - last_section_offset = stream.readUI64(); - unk_offset6 = stream.readUI64(); - as3_code_offset = stream.readUI64(); - as3_names_offset = stream.readUI64(); - unk_A8 = stream.readUI32(); - unk_AC = stream.readUI32(); - font_count = stream.readUI32(); - unk_B4 = stream.readUI32(); + additional_import1 = stream.readUI32(); + zero1 = stream.readUI32(); + unk_guid = stream.readUI64(); + off_names = stream.readUI64(); + names_address = off_names + stream.position() - 8; + off_unk8C = stream.readUI64(); + unk8C_address = off_unk8C + stream.position() - 8; + off_unk80 = stream.readUI64(); + unk80_address = off_unk80 + stream.position() - 8; + off_last_section = stream.readUI64(); + last_section_address = off_last_section + stream.position() - 8; + off_flash_filename = stream.readUI64(); + flash_filename_address = off_flash_filename + stream.position() - 8; + off_decl_strings = stream.readUI64(); + decl_strings_address = off_decl_strings + stream.position() - 8; + off_type_of_fonts = stream.readUI64(); + type_fonts_address = off_type_of_fonts + stream.position() - 8; + + flags = stream.readUI64(); + font_count = stream.readUI32(); + zero2 = stream.readUI32(); } @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { - stream.writeUI64(main_offset); - stream.writeUI64(as3_section_offset); - stream.writeUI64(unk_offset); - stream.writeUI64(unk_offset2); - stream.writeUI64(unk_offset3); - stream.writeUI64(unk_offset4); + stream.writeUI64(off_start); + stream.writeUI64(off_seq_end); + stream.writeUI64(off_font_end); + stream.writeUI64(off_seq_start1); + stream.writeUI64(pad_to_match); + stream.writeUI64(off_seq_start2); stream.writeUI32(xmin); stream.writeUI32(ymin); stream.writeUI32(xmax); @@ -142,77 +220,24 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { stream.writeUI32(unk_54); stream.writeFloat(frame_rate); stream.writeUI32(unk_5C); - stream.writeUI64(fonts_offset); - stream.writeUI64(unk_68); - stream.writeUI64(names_offset); - stream.writeUI64(unk_offset5); - stream.writeUI64(unk_80); - stream.writeUI64(last_section_offset); - stream.writeUI64(unk_offset6); - stream.writeUI64(as3_code_offset); - stream.writeUI64(as3_names_offset); - stream.writeUI32(unk_A8); - stream.writeUI32(unk_AC); + stream.writeUI32(additional_import1); + stream.writeUI32(zero1); + stream.writeUI64(unk_guid); + stream.writeUI64(off_names); + stream.writeUI64(off_unk8C); + stream.writeUI64(off_unk80); + stream.writeUI64(off_last_section); + stream.writeUI64(off_flash_filename); + stream.writeUI64(off_decl_strings); + stream.writeUI64(off_type_of_fonts); + stream.writeUI64(flags); stream.writeUI32(font_count); - stream.writeUI32(unk_B4); + stream.writeUI32(zero2); } @Override 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); - sb.append(" global: ").append(main_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("\r\n"); - sb.append("unk_offset2 ").append(unk_offset2); - if (unk_offset2 != 1) { - sb.append(" global: ").append(main_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("\r\n"); - sb.append("unk_offset4 ").append(unk_offset4); - if (unk_offset4 != 1) { - sb.append(" global: ").append(main_offset + unk_offset4); - } - sb.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("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"); - sb.append("unk_54 ").append(unk_54).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("fonts_offset ").append(fonts_offset).append("\r\n"); - sb.append("unk_68 ").append(unk_68).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"); - sb.append("last_section_offset ").append(last_section_offset).append("\r\n"); - sb.append("unk_offset6 ").append(unk_offset6).append("\r\n"); - sb.append("as3_code_offset ").append(as3_code_offset).append("\r\n"); - 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("font_count ").append(font_count).append("\r\n"); - sb.append("unk_B4 ").append(unk_B4).append("\r\n"); - sb.append("]"); - return sb.toString(); - + return FieldPrinter.getObjectSummary(this); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java new file mode 100644 index 000000000..ada8192b9 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java @@ -0,0 +1,80 @@ +package com.jpexs.decompiler.flash.iggy.annotations; + +import java.lang.reflect.Field; + +/** + * + * @author JPEXS + */ +public class FieldPrinter { + + public static String getObjectSummary(Object val) { + StringBuilder sb = new StringBuilder(); + sb.append("/---" + val.getClass().getSimpleName() + "---\r\n"); + for (Field f : val.getClass().getDeclaredFields()) { + sb.append(f.getName()).append(": "); + IggyFieldType an = f.getAnnotation(IggyFieldType.class); + if (an != null) { + f.setAccessible(true); + try { + switch (an.value()) { + case float_t: + sb.append(f.getFloat(val)); + break; + case uint8_t: + case uint16_t: + sb.append(f.getInt(val)); + break; + case uint32_t: + case uint64_t: + sb.append(f.getLong(val)); + break; + case widechar_t: + sb.append("\"").append(f.get(val)).append("\""); + break; + } + } catch (IllegalAccessException ex) { + + } + } + sb.append("\r\n"); + } + sb.append("---/"); + return sb.toString(); + } + + public static String getObjectWriteTo(Class cls) { + StringBuilder sb = new StringBuilder(); + for (Field f : cls.getDeclaredFields()) { + sb.append("stream.write"); + IggyFieldType an = f.getAnnotation(IggyFieldType.class); + if (an != null) { + switch (an.value()) { + case float_t: + sb.append("Float"); + break; + case uint8_t: + sb.append("UI8"); + break; + case uint16_t: + sb.append("UI16"); + break; + case uint32_t: + sb.append("UI32"); + break; + case uint64_t: + sb.append("UI64"); + break; + case widechar_t: + sb.append("//FIXME"); + break; + } + sb.append("(").append(f.getName()).append(");\r\n"); + if (an.count() > 0) { + sb.append("//FIXME count"); + } + } + } + return sb.toString(); + } +} From 29147348d6b3644619525bc8f70f12549d763e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 28 Nov 2016 13:07:22 +0100 Subject: [PATCH 11/27] reading fixed --- .../flash/iggy/IggyFlashHeader64.java | 13 ++- .../jpexs/decompiler/flash/iggy/IggySwf.java | 106 +++++++++++++----- .../iggy/streams/AbstractDataStream.java | 9 ++ .../iggy/streams/ReadDataStreamInterface.java | 2 + 4 files changed, 103 insertions(+), 27 deletions(-) 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 6df20387c..aa8cf2e96 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 @@ -55,8 +55,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { long additional_import1; @IggyFieldType(DataType.uint32_t) long zero1; - //boolean imported = false; - //if( additional_import1 > 0 ) imported = true + + //local + private int imported = 0; + @IggyFieldType(DataType.uint64_t) long unk_guid; // same for some fonts (eng + chinese) @IggyFieldType(DataType.uint64_t) @@ -102,6 +104,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { private long decl_strings_address; private long type_fonts_address; + public boolean isImported() { + return imported == 1; + } + public long getBaseAddress() { return base_address; } @@ -177,6 +183,9 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { frame_rate = stream.readFloat(); unk_5C = stream.readUI32(); additional_import1 = stream.readUI32(); + if (additional_import1 > 0) { + imported = 1; + } zero1 = stream.readUI32(); unk_guid = stream.readUI64(); 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 e6d85a4bf..c9b969e83 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 @@ -28,7 +28,7 @@ public class IggySwf implements StructureInterface { Map texts; Map text2Font; - private IggyFlashHeader64 header; + private IggyFlashHeader64 hdr; private Map sizesOfOffsets; private List offsets; private List tags = new ArrayList<>(); @@ -38,7 +38,7 @@ public class IggySwf implements StructureInterface { } public IggySwf(IggyFlashHeader64 header, ReadDataStreamInterface stream, List offsets) throws IOException { - this.header = header; + this.hdr = header; this.offsets = offsets; calcSizesFromOffsets(); readFromDataStream(stream); @@ -53,11 +53,11 @@ public class IggySwf implements StructureInterface { } @Override - public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { //here is offset[0] StringBuilder nameBuilder = new StringBuilder(); do { - char c = (char) stream.readUI16(); + char c = (char) s.readUI16(); if (c == '\0') { break; } @@ -65,29 +65,85 @@ public class IggySwf implements StructureInterface { } while (true); name = nameBuilder.toString(); //here is offset[1] - int pad8 = 8 - (int) (stream.position() % 8); - stream.seek(pad8, SeekMode.CUR); - //here is offset [2] - fonts = new HashMap<>(); - int fontIndex = 0; - for (int ofs = 2; ofs < offsets.size(); ofs++) { - long offset = offsets.get(ofs); - if (offset < stream.position()) { - continue; - } - stream.seek(offset, SeekMode.SET); - int type = stream.readUI16(); - stream.seek(-2, SeekMode.CUR); - if (type == IggyFont.ID) { - IggyFont font = new IggyFont(stream); - fonts.put(fontIndex++, font); - tags.add(font); - } else if (ofs < offsets.size() - 1) { - int len = (int) (offsets.get(ofs + 1) - offsets.get(ofs)); - RawIggyPart rtag = new RawIggyPart(type, stream, len); - tags.add(rtag); + int pad8 = 8 - (int) (s.position() % 8); + s.seek(pad8, SeekMode.CUR); + //here is offset [2] + s.seek(hdr.getBaseAddress(), SeekMode.SET); + s.readUI64(); //one pad + + long font_data_addresses[] = new long[(int) hdr.font_count]; + long font_data_sizes[] = new long[(int) hdr.font_count]; + + for (int i = 0; i < hdr.font_count; i++) { + long offset = s.readUI64(); + font_data_addresses[i] = offset + s.position() - 8; + long next_offset = s.readUI64(); + s.seek(-8, SeekMode.CUR); + if (next_offset == 1) { + font_data_sizes[i] = hdr.getFontEndAddress() - font_data_addresses[i]; + } else { + font_data_sizes[i] = next_offset - offset; } } + List text_addresses = new ArrayList<>(); + List text_data_sizes = new ArrayList<>(); + while (true) { + long offset = s.readUI64(); + long text_addr = offset + s.position() - 8; + text_addresses.add(text_addr); + long next_offset = s.readUI64(); + s.seek(-8, SeekMode.CUR); + if (next_offset == 1) { + text_data_sizes.add(hdr.getFontEndAddress() - text_addr); + break; + } else { + text_data_sizes.add(next_offset - offset); + } + } + + List font_add_off = new ArrayList<>(); + List font_add_size = new ArrayList<>(); + if (hdr.isImported()) { // tohle muze narusit iggy order, ale oni to pak stejne pocitaji dle infa + long additionalOffset = s.readUI64(); + font_add_off.add(additionalOffset + s.position() - 8); + font_add_size.add(hdr.getFontEndAddress() - font_add_off.get(0)); + if (s.readUI8(font_add_off.get(0)) != 22) { //22 = Text + for (int i = 0; i < hdr.font_count; i++) { + if (s.readUI8(text_addresses.get(i)) == 22) { //TEXT + long pomoff; + long pomsize; + pomoff = text_addresses.get(i); + pomsize = text_data_sizes.get(i); + text_addresses.set(i, font_add_off.get(0)); + text_data_sizes.set(i, font_add_size.get(0)); + font_add_off.set(0, pomoff); + font_add_size.set(0, pomsize); + } + } + } + } + + //long skipBytes = 840 - s.position(); + fonts = new HashMap<>(); + for (int i = 0; i < hdr.font_count; i++) { + s.seek(font_data_addresses[i], SeekMode.SET); + //byte font_data[] = s.readBytes((int) font_data_sizes[i]); + IggyFont font = new IggyFont(s); + tags.add(font); + fonts.put(i/*??*/, font); + } + + for (int i = 0; i < text_addresses.size(); i++) { + byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i)); + } + + if (hdr.isImported()) { + s.seek(font_add_off.get(0), SeekMode.SET); + byte font_add_data[] = s.readBytes((int) (long) font_add_size.get(0)); + } + + s.seek(hdr.getFontEndAddress(), SeekMode.SET); + } public String getName() { 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 b11de5655..fd22b1c73 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 @@ -142,4 +142,13 @@ public abstract class AbstractDataStream implements DataStreamInterface { //nothing } + @Override + public int readUI8(long addr) throws IOException { + long curPos = position(); + seek(addr, SeekMode.SET); + int val = readUI8(); + seek(curPos, SeekMode.SET); + return val; + } + } 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 1b22ba523..7bd57a76c 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 @@ -27,6 +27,8 @@ public interface ReadDataStreamInterface extends AutoCloseable { public int readUI8() throws IOException; + public int readUI8(long addr) throws IOException; + public int read() throws IOException; public byte[] readBytes(int numBytes) throws IOException; From f48a5ff08add58f31dd861a8cf1dfd8fc0d26752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 28 Nov 2016 19:16:13 +0100 Subject: [PATCH 12/27] read/write fixes, refactorings --- .../jpexs/decompiler/flash/iggy/IggyFile.java | 74 +++++-------- .../flash/iggy/IggyFlashHeader64.java | 52 +++++++-- .../jpexs/decompiler/flash/iggy/IggySwf.java | 101 ++++++++++-------- .../streams/WriteDataStreamInterface.java | 2 + 4 files changed, 131 insertions(+), 98 deletions(-) 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 19ee321a6..30b7791f2 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 @@ -43,30 +43,29 @@ public class IggyFile implements StructureInterface { public static final int FIRST_TAG_POSITION = 3; - public void replaceTag(int swfIndex, int tagIndex, IggyTag newTag) throws IOException { - WriteDataStreamInterface stream = new TemporaryDataStream(); - newTag.writeToDataStream(stream); + public void replaceFontTag(int targetSwfIndex, int fontIndex, IggyFont newFont) throws IOException { + IggySwf iggySwf = iggySwfs.get(targetSwfIndex); + iggySwf.replaceFontTag(fontIndex, newFont); - setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize()); - } - - public void saveTag(int swfIndex, IggyTag newTag) throws IOException { - WriteDataStreamInterface stream = new TemporaryDataStream(); - newTag.writeToDataStream(stream); - - int tagIndex = 0; - List taglist = iggySwfs.get(swfIndex).getTags(); - for (IggyTag t : taglist) { - if (t == newTag) { - break; + DataStreamInterface flashStream = new TemporaryDataStream(); + iggySwf.writeToDataStream(flashStream); + byte flashData[] = flashStream.getAllBytes(); + int swfIndex = 0; + int offsetChange = 0; + for (int i = 0; i < subFileEntries.size(); i++) { + IggySubFileEntry entry = subFileEntries.get(i); + entry.offset += offsetChange; + if (entry.type == IggySubFileEntry.TYPE_FLASH) { + if (swfIndex == targetSwfIndex) { + long newLen = flashData.length; + long oldLen = entry.size; + offsetChange += (newLen - oldLen); + } + swfIndex++; } - tagIndex++; - } - if (tagIndex < taglist.size()) { - setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize()); - } else { - throw new IllegalArgumentException("Tag does not exists in this iggy file"); } + subFileEntriesData.set(targetSwfIndex, flashData); + //TODO: Update index } private boolean setSwfItemLength(int swfIndex, int itemindex, long newLength) { @@ -103,14 +102,6 @@ public class IggyFile implements StructureInterface { return iggySwfs.get(swfIndex).fonts.get(fontId); } - public IggyText getText(int swfIndex, int textId) { - return iggySwfs.get(swfIndex).texts.get(textId); - } - - public Set getTextIds(int swfIndex) { - return iggySwfs.get(swfIndex).texts.keySet(); - } - public IggyFile(String filePath) throws IOException { this(new File(filePath)); } @@ -202,7 +193,8 @@ public class IggyFile implements StructureInterface { File outFile = new File(outFileName); IggyFile iggyFile = new IggyFile(inFile); IggySwf iswf = iggyFile.getSwf(0); - iggyFile.replaceSwf(0, iswf); + IggyFont ifont = iswf.fonts.get(0); + iggyFile.replaceFontTag(0, 0, ifont); outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); @@ -649,7 +641,9 @@ public class IggyFile implements StructureInterface { //WIP public boolean replaceSwf(int targetSwfIndex, IggySwf iggySwf) { - if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) { + return false; //Not working yet - need to make IggySWF.writeToDataStream work + + /*if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) { throw new ArrayIndexOutOfBoundsException("No such SWF file index"); } byte replacementData[]; @@ -680,7 +674,7 @@ public class IggyFile implements StructureInterface { } } subFileEntriesData.set(targetSwfIndex, replacementData); - return true; + return true;*/ } private void parseEntries() throws IOException { @@ -697,23 +691,9 @@ public class IggyFile implements StructureInterface { indexTables.add(indexTable); offsetTables.add(offsets); } else if (entry.type == IggySubFileEntry.TYPE_FLASH) { - IggyFlashHeaderInterface hdr; - if (header.is64()) { - hdr = new IggyFlashHeader64(dataStream); - } else { - hdr = new IggyFlashHeader32(dataStream); - throw new UnsupportedOperationException("Iggy 32bit files are not supported"); //TODO - } - headers.add(hdr); - flashDataStreams.add(dataStream); + iggySwfs.add(new IggySwf(dataStream)); } } - - for (int swfIndex = 0; swfIndex < headers.size(); swfIndex++) { - IggyFlashHeaderInterface hdr = headers.get(swfIndex); - IggySwf dataReader = new IggySwf((IggyFlashHeader64) hdr, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex)); - iggySwfs.add(dataReader); - } } @Override 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 aa8cf2e96..71de61c57 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 @@ -64,7 +64,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @IggyFieldType(DataType.uint64_t) long off_names; // 0x70 relative offset to the names/import section of the file - end of fonts @IggyFieldType(DataType.uint64_t) - long off_unk8C; // 0x78 relative offset to something + long off_unk78; // 0x78 relative offset to something @IggyFieldType(DataType.uint64_t) long off_unk80; @IggyFieldType(DataType.uint64_t) @@ -97,13 +97,35 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { private long font_end_address; private long sequence_start_address; private long names_address; - private long unk8C_address; + private long unk78_address; private long unk80_address; private long last_section_address; private long flash_filename_address; private long decl_strings_address; private long type_fonts_address; + /** + * Updates all addresses by inserting gap + * + * @param pos Position to insert bytes + * @param size Number of bytes + */ + public void insertGapAfter(long pos, long size) { + for (Field f : IggyFlashHeader64.class.getDeclaredFields()) { + if (f.getName().endsWith("_address")) { + try { + long val = f.getLong(this); + if (val > pos) { + long newval = val + size; + f.setLong(this, newval); + } + } catch (IllegalAccessException iex) { + //should not happen + } + } + } + } + public boolean isImported() { return imported == 1; } @@ -120,6 +142,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { return font_end_address; } + public void setFontEndAddress(long val) { + this.font_end_address = val; + } + public long getSequenceStartAddress() { return sequence_start_address; } @@ -128,8 +154,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { return names_address; } - public long getUnk8CAddress() { - return unk8C_address; + public long getUnk78Address() { + return unk78_address; } public long getUnk80Address() { @@ -191,8 +217,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { off_names = stream.readUI64(); names_address = off_names + stream.position() - 8; - off_unk8C = stream.readUI64(); - unk8C_address = off_unk8C + stream.position() - 8; + off_unk78 = stream.readUI64(); + unk78_address = off_unk78 + stream.position() - 8; off_unk80 = stream.readUI64(); unk80_address = off_unk80 + stream.position() - 8; off_last_section = stream.readUI64(); @@ -211,11 +237,16 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { + off_start = base_address - stream.position(); stream.writeUI64(off_start); + off_seq_end = sequence_end_address - stream.position(); stream.writeUI64(off_seq_end); + off_font_end = font_end_address - stream.position(); stream.writeUI64(off_font_end); + off_seq_start1 = sequence_start_address - stream.position(); stream.writeUI64(off_seq_start1); stream.writeUI64(pad_to_match); + off_seq_start2 = sequence_start_address - stream.position(); stream.writeUI64(off_seq_start2); stream.writeUI32(xmin); stream.writeUI32(ymin); @@ -232,12 +263,19 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { stream.writeUI32(additional_import1); stream.writeUI32(zero1); stream.writeUI64(unk_guid); + off_names = names_address - stream.position(); stream.writeUI64(off_names); - stream.writeUI64(off_unk8C); + off_unk78 = unk78_address - stream.position(); + stream.writeUI64(off_unk78); + off_unk80 = unk80_address - stream.position(); stream.writeUI64(off_unk80); + off_last_section = last_section_address - stream.position(); stream.writeUI64(off_last_section); + off_flash_filename = flash_filename_address - stream.position(); stream.writeUI64(off_flash_filename); + off_decl_strings = decl_strings_address - stream.position(); stream.writeUI64(off_decl_strings); + off_type_of_fonts = type_fonts_address - stream.position(); stream.writeUI64(off_type_of_fonts); stream.writeUI64(flags); stream.writeUI32(font_count); 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 c9b969e83..0eed741c1 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 @@ -25,35 +25,57 @@ public class IggySwf implements StructureInterface { String name; Map fonts; - Map texts; - Map text2Font; private IggyFlashHeader64 hdr; - private Map sizesOfOffsets; - private List offsets; - private List tags = new ArrayList<>(); - public List getTags() { - return tags; - } + private byte[] allFontBytes; - public IggySwf(IggyFlashHeader64 header, ReadDataStreamInterface stream, List offsets) throws IOException { - this.hdr = header; - this.offsets = offsets; - calcSizesFromOffsets(); + public IggySwf(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } - private void calcSizesFromOffsets() { - sizesOfOffsets = new HashMap<>(); - for (int i = 0; i < offsets.size() - 1; i++) { - sizesOfOffsets.put(offsets.get(i), offsets.get(i + 1) - offsets.get(i)); + private long font_data_addresses[]; + private long font_data_sizes[]; + private List text_addresses = new ArrayList<>(); + private List text_data_sizes = new ArrayList<>(); + private List font_add_off = new ArrayList<>(); + private List font_add_size = new ArrayList<>(); + + public void replaceFontTag(int fontIndex, IggyFont newFont) throws IOException { + long newLen; + byte newData[]; + try (WriteDataStreamInterface stream = new TemporaryDataStream()) { + newFont.writeToDataStream(stream); + newData = stream.getAllBytes(); + newLen = newData.length; } - sizesOfOffsets.put(offsets.get(offsets.size() - 1), 0L); //Last offset has 0L length? + long oldLen = font_data_sizes[fontIndex]; + long diff = newLen - oldLen; + if (diff != 0) { + font_data_sizes[fontIndex] = newLen; + for (int i = fontIndex; i < hdr.font_count; i++) { + font_data_addresses[i] += diff; + } + for (int i = 0; i < text_addresses.size(); i++) { + text_addresses.set(i, text_addresses.get(i) + diff); + } + for (int i = 0; i < font_add_off.size(); i++) { + font_add_off.set(i, font_add_off.get(i) + diff); + } + } + hdr.insertGapAfter(font_data_addresses[fontIndex], diff); + } @Override public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + this.hdr = new IggyFlashHeader64(s); + //Save all font bytes to buffer for later easy modification + long curPos = s.position(); + long maxPos = hdr.getFontEndAddress(); + allFontBytes = s.readBytes((int) (maxPos - curPos)); + s.seek(curPos, SeekMode.SET); + //here is offset[0] StringBuilder nameBuilder = new StringBuilder(); do { @@ -71,8 +93,8 @@ public class IggySwf implements StructureInterface { s.seek(hdr.getBaseAddress(), SeekMode.SET); s.readUI64(); //one pad - long font_data_addresses[] = new long[(int) hdr.font_count]; - long font_data_sizes[] = new long[(int) hdr.font_count]; + font_data_addresses = new long[(int) hdr.font_count]; + font_data_sizes = new long[(int) hdr.font_count]; for (int i = 0; i < hdr.font_count; i++) { long offset = s.readUI64(); @@ -85,8 +107,6 @@ public class IggySwf implements StructureInterface { font_data_sizes[i] = next_offset - offset; } } - List text_addresses = new ArrayList<>(); - List text_data_sizes = new ArrayList<>(); while (true) { long offset = s.readUI64(); long text_addr = offset + s.position() - 8; @@ -101,8 +121,6 @@ public class IggySwf implements StructureInterface { } } - List font_add_off = new ArrayList<>(); - List font_add_size = new ArrayList<>(); if (hdr.isImported()) { // tohle muze narusit iggy order, ale oni to pak stejne pocitaji dle infa long additionalOffset = s.readUI64(); font_add_off.add(additionalOffset + s.position() - 8); @@ -129,7 +147,6 @@ public class IggySwf implements StructureInterface { s.seek(font_data_addresses[i], SeekMode.SET); //byte font_data[] = s.readBytes((int) font_data_sizes[i]); IggyFont font = new IggyFont(s); - tags.add(font); fonts.put(i/*??*/, font); } @@ -151,30 +168,26 @@ public class IggySwf implements StructureInterface { } @Override - public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { - List newOffsets = new ArrayList<>(); - - try { - newOffsets.add(stream.position()); - for (int i = 0; i < name.length(); i++) { - stream.writeUI16(name.charAt(i)); + public void writeToDataStream(WriteDataStreamInterface st) throws IOException { + try (DataStreamInterface s = new TemporaryDataStream(allFontBytes)) { + hdr.writeToDataStream(s); + s.writeUI64(1); + for (int i = 0; i < font_data_addresses.length; i++) { + long offset = font_data_addresses[i] - s.position() + 8; + s.writeUI64(offset); } - stream.writeUI16(0); - newOffsets.add(stream.position()); - long pad8 = 8 - (stream.position() % 8); - for (int i = 0; i < pad8; i++) { - stream.write(0); + s.writeUI64(1); + for (int i = 0; i < text_addresses.size(); i++) { + long offset = text_addresses.get(i) - s.position() + 8; + s.writeUI64(offset); } - newOffsets.add(stream.position()); - for (IggyTag tag : tags) { - tag.writeToDataStream(stream); - newOffsets.add(stream.position()); + s.writeUI64(1); + s.seek(840, SeekMode.SET); + for (int i = 0; i < hdr.font_count; i++) { + fonts.get(i).writeToDataStream(s); } - } catch (IOException ex) { - //ignore + st.writeBytes(s.getAllBytes()); } - this.offsets = newOffsets; - calcSizesFromOffsets(); } @Override 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 1b3e47e61..1e087fd1b 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 @@ -35,6 +35,8 @@ public interface WriteDataStreamInterface extends AutoCloseable { public void seek(long pos, SeekMode mode) throws IOException; + public byte[] getAllBytes() throws IOException; + @Override public void close(); } From 1fa6a699884d6d873aed7bafb1e2a264030febc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 28 Nov 2016 19:19:46 +0100 Subject: [PATCH 13/27] read fix - hdr problems --- .../src/com/jpexs/decompiler/flash/iggy/IggyFile.java | 10 +++++----- .../src/com/jpexs/decompiler/flash/iggy/IggySwf.java | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) 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 30b7791f2..3e151a226 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 @@ -620,23 +620,23 @@ public class IggyFile implements StructureInterface { } public long getSwfXMin(int swfIndex) { - return headers.get(swfIndex).getXMin(); + return iggySwfs.get(swfIndex).getHdr().getXMin(); } public long getSwfYMin(int swfIndex) { - return headers.get(swfIndex).getYMin(); + return iggySwfs.get(swfIndex).getHdr().getYMin(); } public long getSwfXMax(int swfIndex) { - return headers.get(swfIndex).getXMax(); + return iggySwfs.get(swfIndex).getHdr().getXMax(); } public long getSwfYMax(int swfIndex) { - return headers.get(swfIndex).getYMax(); + return iggySwfs.get(swfIndex).getHdr().getYMax(); } public float getSwfFrameRate(int swfIndex) { - return headers.get(swfIndex).getFrameRate(); + return iggySwfs.get(swfIndex).getHdr().getFrameRate(); } //WIP 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 0eed741c1..8d9739e14 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 @@ -41,6 +41,10 @@ public class IggySwf implements StructureInterface { private List font_add_off = new ArrayList<>(); private List font_add_size = new ArrayList<>(); + public IggyFlashHeader64 getHdr() { + return hdr; + } + public void replaceFontTag(int fontIndex, IggyFont newFont) throws IOException { long newLen; byte newData[]; From 48177bb534484eeb47f880a3b9a85613edc97e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 30 Nov 2016 10:55:17 +0100 Subject: [PATCH 14/27] read and write of fonts matched --- .../flash/iggy/IggyCharKerning.java | 3 - .../decompiler/flash/iggy/IggyCharOffset.java | 19 ++--- .../jpexs/decompiler/flash/iggy/IggyFile.java | 6 +- .../flash/iggy/IggyFlashHeader64.java | 26 +++--- .../jpexs/decompiler/flash/iggy/IggyFont.java | 68 ++++++++++++---- .../decompiler/flash/iggy/IggyShape.java | 8 +- .../jpexs/decompiler/flash/iggy/IggySwf.java | 81 +++++++++++++------ 7 files changed, 141 insertions(+), 70 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index d1987d2b1..997999b76 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -17,7 +17,6 @@ public class IggyCharKerning implements StructureInterface { List charsA; List charsB; List kerningOffsets; - long pad; public long getKernCount() { return kernCount; @@ -50,7 +49,6 @@ public class IggyCharKerning implements StructureInterface { charsB.add((char) stream.readUI16()); kerningOffsets.add((short) stream.readUI16()); } - pad = stream.readUI32(); } @Override @@ -60,7 +58,6 @@ public class IggyCharKerning implements StructureInterface { stream.writeUI16(charsB.get(i)); stream.writeUI16(kerningOffsets.get(i)); } - stream.writeUI32(pad); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 564531c85..74b197582 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -30,8 +30,14 @@ public class IggyCharOffset implements StructureInterface { @IggyFieldType(DataType.uint32_t) long zero3; @IggyFieldType(DataType.uint64_t) + private long address; + long offset; + public long getAddress() { + return address; + } + public IggyCharOffset(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -56,12 +62,11 @@ public class IggyCharOffset implements StructureInterface { xscale = stream.readUI16(); yscale = stream.readUI16(); zero3 = stream.readUI32(); - long cur_position = stream.position(); - long relative_offset = stream.readUI64(); + offset = stream.readUI64(); if (ischar1 > 0) { - offset = cur_position + relative_offset; + address = offset + stream.position() - 8; } else { - offset = 0; + address = 0; LOGGER.finer(String.format("Empty char")); } } @@ -75,11 +80,7 @@ public class IggyCharOffset implements StructureInterface { stream.writeUI16(xscale); stream.writeUI16(yscale); stream.writeUI32(zero3); - if (ischar1 > 0) { - stream.writeUI64(offset - stream.position()); - } else { - stream.writeUI64(1); - } + stream.writeUI64(offset); } public boolean hasGlyph() { 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 3e151a226..03860a1ae 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 @@ -7,6 +7,7 @@ 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.TemporaryDataStream; +import com.jpexs.helpers.Helper; import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; @@ -186,7 +187,7 @@ 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 inFile = new File(inFileName); @@ -198,7 +199,7 @@ public class IggyFile implements StructureInterface { outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); - } + }*/ } private static void copyStream(InputStream is, OutputStream os) { @@ -719,7 +720,6 @@ public class IggyFile implements StructureInterface { for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); byte[] entryData = subFileEntriesData.get(i); - stream.seek(entry.offset, SeekMode.SET); stream.writeBytes(entryData); } 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 71de61c57..4c296d361 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 @@ -95,7 +95,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { private long base_address; private long sequence_end_address; private long font_end_address; - private long sequence_start_address; + private long sequence_start_address1; + private long sequence_start_address2; private long names_address; private long unk78_address; private long unk80_address; @@ -146,8 +147,12 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { this.font_end_address = val; } - public long getSequenceStartAddress() { - return sequence_start_address; + public long getSequenceStartAddress1() { + return sequence_start_address1; + } + + public long getSequenceStartAddress2() { + return sequence_start_address2; } public long getNamesAddress() { @@ -180,13 +185,14 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { - off_start = stream.readUI64(); + /* 0:*/ off_start = stream.readUI64(); base_address = off_start + stream.position() - 8; - off_seq_end = stream.readUI64(); + /* 8:*/ off_seq_end = stream.readUI64(); sequence_end_address = off_seq_end + stream.position() - 8; - off_font_end = stream.readUI64(); + /* 10:*/ off_font_end = stream.readUI64(); font_end_address = off_font_end + stream.position() - 8; - off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times) + /* 18:*/ off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times) + sequence_start_address1 = off_seq_start1 + stream.position() - 8; pad_to_match = stream.readUI64(); if (pad_to_match != 1) { throw new IOException("Wrong iggy file - no pad to match 1"); @@ -195,7 +201,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { if (off_seq_start1 != off_seq_start2) { throw new IOException("Wrong iggy font format (sequence_start)!\n"); } - sequence_start_address = off_seq_start2 + stream.position() - 8; + sequence_start_address2 = off_seq_start2 + stream.position() - 8; xmin = stream.readUI32(); ymin = stream.readUI32(); xmax = stream.readUI32(); @@ -243,10 +249,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { stream.writeUI64(off_seq_end); off_font_end = font_end_address - stream.position(); stream.writeUI64(off_font_end); - off_seq_start1 = sequence_start_address - stream.position(); + off_seq_start1 = sequence_start_address1 - stream.position(); stream.writeUI64(off_seq_start1); stream.writeUI64(pad_to_match); - off_seq_start2 = sequence_start_address - stream.position(); + off_seq_start2 = sequence_start_address2 - stream.position(); stream.writeUI64(off_seq_start2); stream.writeUI32(xmin); stream.writeUI32(ymin); 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 dfedbd954..4e7b8cefd 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 @@ -73,8 +73,14 @@ public class IggyFont extends IggyTag { long zero_padd_4; @IggyFieldType(DataType.uint64_t) long what_3; - @IggyFieldType(value = DataType.uint8_t, count = 272) - byte[] zeroes; + @IggyFieldType(value = DataType.widechar_t, count = 40) + String subName = ""; + @IggyFieldType(value = DataType.uint8_t, count = 48) + byte[] zeroes48a; + + @IggyFieldType(value = DataType.uint8_t, count = 48) + byte[] zeroes48b; + @IggyFieldType(DataType.float_t) float sss1; @IggyFieldType(DataType.uint32_t) @@ -103,7 +109,7 @@ public class IggyFont extends IggyTag { byte[] padTo4byteBoundary; - public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { + public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { this.type = type; this.fontId = order_in_iggy_file; this.zeroone = zeroone; @@ -131,7 +137,7 @@ public class IggyFont extends IggyTag { this.char_count = char_count; this.zero_padd_4 = zero_padd_4; this.what_3 = what_3; - this.zeroes = zeroes; + this.zeroes48a = zeroes48; this.sss1 = sss1; this.one_padd2 = one_padd2; this.sss2 = sss2; @@ -178,11 +184,11 @@ public class IggyFont extends IggyTag { } private long makeAbsOffset(ReadDataStreamInterface s, long offset) { - return offset == 1 ? 0 : s.position() - 8 + offset; + return offset == 1 ? 0 : offset + s.position() - 8; } private long makeAbsOffset(WriteDataStreamInterface s, long offset) { - return offset == 1 ? 0 : s.position() - 8 + offset; + return offset == 1 ? 0 : offset + s.position() - 8; } @Override @@ -224,7 +230,20 @@ public class IggyFont extends IggyTag { char_count = s.readUI32(); zero_padd_4 = s.readUI64(); what_3 = s.readUI64(); - s.seek(basePos + 272, SeekMode.SET); + StringBuilder subNameBuilder = new StringBuilder(); + + boolean snFinish = false; + for (int i = 0; i < 20; i++) { + char c = (char) s.readUI16(); + if (c == '\0') { + snFinish = true; + } + if (!snFinish) { + subNameBuilder.append(c); + } + } + subName = subNameBuilder.toString(); + zeroes48a = s.readBytes(48); sss1 = s.readFloat(); one_padd2 = s.readUI32(); sss2 = s.readFloat(); @@ -233,6 +252,8 @@ public class IggyFont extends IggyTag { one_padd4 = s.readUI32(); sss4 = s.readFloat(); one_padd5 = s.readUI32(); + zeroes48b = s.readBytes(48); + if (abs_start_of_name != 0) { s.seek(abs_start_of_name, SeekMode.SET); StringBuilder nameBuilder = new StringBuilder(); @@ -257,9 +278,10 @@ public class IggyFont extends IggyTag { } glyphs = new ArrayList<>(); for (int i = 0; i < char_count; i++) { - long offset = charOffsets.get(i).offset; - if (offset != 0) { - glyphs.add(new IggyShape(s, offset)); + long addr = charOffsets.get(i).getAddress(); + if (addr != 0) { + s.seek(addr, SeekMode.SET); + glyphs.add(new IggyShape(s)); } else { glyphs.add(null); } @@ -315,7 +337,14 @@ public class IggyFont extends IggyTag { s.writeUI32(char_count); s.writeUI64(zero_padd_4); s.writeUI64(what_3); - s.seek(272, SeekMode.SET); + for (int i = 0; i < 20; i++) { + if (i < subName.length()) { + s.writeUI16((char) subName.charAt(i)); + } else { + s.writeUI16(0); + } + } + s.writeBytes(zeroes48a); s.writeFloat(sss1); s.writeUI32(one_padd2); s.writeFloat(sss2); @@ -324,6 +353,7 @@ public class IggyFont extends IggyTag { s.writeUI32(one_padd4); s.writeFloat(sss4); s.writeUI32(one_padd5); + s.writeBytes(zeroes48b); if (abs_start_of_name != 0) { s.seek(abs_start_of_name, SeekMode.SET); for (char c : name.toCharArray()) { @@ -333,11 +363,14 @@ public class IggyFont extends IggyTag { //align to 8 bytes boundary int len = name.length() * 2 + 2; - int rem = 8 - (len % 8); - for (int i = 0; i < rem; i++) { - s.write(0); + int pad8 = 8 - (len % 8); + if (pad8 < 8) { + for (int i = 0; i < pad8; i++) { + s.write(0); + } } } + s.writeUI64(0); //pad zero if (abs_start_of_char_struct != 0) { s.seek(abs_start_of_char_struct, SeekMode.SET); @@ -348,7 +381,7 @@ public class IggyFont extends IggyTag { for (int i = 0; i < glyphs.size(); i++) { IggyShape shp = glyphs.get(i); if (shp != null) { - s.seek(charOffsets.get(i).offset, SeekMode.SET); + s.seek(charOffsets.get(i).getAddress(), SeekMode.SET); shp.writeToDataStream(s); } } @@ -368,6 +401,11 @@ public class IggyFont extends IggyTag { s.seek(abs_start_of_kern, SeekMode.SET); charKernings.writeToDataStream(s); } + + if ((s.position() - abs_start_of_char_index) % 8 != 0) { + byte padd[] = new byte[(int) (((s.position() - abs_start_of_char_index) / 8 + 1) * 8 - (s.position() - abs_start_of_char_index))]; + s.writeBytes(padd); + } } public int getType() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index 7fa2aa585..33c0ccfa3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -60,10 +60,7 @@ public class IggyShape implements StructureInterface { List nodes; - private long offset; - - public IggyShape(ReadDataStreamInterface stream, long offset) throws IOException { - this.offset = offset; + public IggyShape(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -84,7 +81,6 @@ public class IggyShape implements StructureInterface { @Override public void readFromDataStream(ReadDataStreamInterface s) throws IOException { - s.seek(offset, SeekMode.SET); minx = s.readFloat(); miny = s.readFloat(); maxx = s.readFloat(); @@ -98,7 +94,7 @@ public class IggyShape implements StructureInterface { two1 = s.readUI32(); if ((one != 1) || (one2 != 1) || (one3 != 1) || (one4 != 1) || (two1 != 2)) { - LOGGER.fine(String.format("Unique header at pos %d, one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", offset, one, one2, one3, one4, two1)); + LOGGER.fine(String.format("Unique header at one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", one, one2, one3, one4, two1)); } nodes = new ArrayList<>(); 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 8d9739e14..a8596d460 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 @@ -7,6 +7,8 @@ import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; +import com.jpexs.helpers.Helper; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -38,6 +40,8 @@ public class IggySwf implements StructureInterface { private long font_data_sizes[]; private List text_addresses = new ArrayList<>(); private List text_data_sizes = new ArrayList<>(); + private List text_data_bytes = new ArrayList<>(); + private byte font_add_data[]; private List font_add_off = new ArrayList<>(); private List font_add_size = new ArrayList<>(); @@ -95,7 +99,7 @@ public class IggySwf implements StructureInterface { s.seek(pad8, SeekMode.CUR); //here is offset [2] s.seek(hdr.getBaseAddress(), SeekMode.SET); - s.readUI64(); //one pad + s.readUI64(); //pad 1 font_data_addresses = new long[(int) hdr.font_count]; font_data_sizes = new long[(int) hdr.font_count]; @@ -113,6 +117,9 @@ public class IggySwf implements StructureInterface { } while (true) { long offset = s.readUI64(); + if (offset == 1) { + break; + } long text_addr = offset + s.position() - 8; text_addresses.add(text_addr); long next_offset = s.readUI64(); @@ -124,13 +131,14 @@ public class IggySwf implements StructureInterface { text_data_sizes.add(next_offset - offset); } } + s.readUI64(); //1 if (hdr.isImported()) { // tohle muze narusit iggy order, ale oni to pak stejne pocitaji dle infa long additionalOffset = s.readUI64(); font_add_off.add(additionalOffset + s.position() - 8); font_add_size.add(hdr.getFontEndAddress() - font_add_off.get(0)); if (s.readUI8(font_add_off.get(0)) != 22) { //22 = Text - for (int i = 0; i < hdr.font_count; i++) { + for (int i = 0; i < text_addresses.size(); i++) { if (s.readUI8(text_addresses.get(i)) == 22) { //TEXT long pomoff; long pomsize; @@ -144,27 +152,30 @@ public class IggySwf implements StructureInterface { } } } - - //long skipBytes = 840 - s.position(); fonts = new HashMap<>(); for (int i = 0; i < hdr.font_count; i++) { s.seek(font_data_addresses[i], SeekMode.SET); //byte font_data[] = s.readBytes((int) font_data_sizes[i]); IggyFont font = new IggyFont(s); - fonts.put(i/*??*/, font); + fonts.put(i, font); } for (int i = 0; i < text_addresses.size(); i++) { + s.seek(text_addresses.get(i), SeekMode.SET); byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i)); + text_data_bytes.add(text_data); } if (hdr.isImported()) { s.seek(font_add_off.get(0), SeekMode.SET); - byte font_add_data[] = s.readBytes((int) (long) font_add_size.get(0)); + font_add_data = s.readBytes((int) (long) font_add_size.get(0)); } - s.seek(hdr.getFontEndAddress(), SeekMode.SET); + WriteDataStreamInterface outs = new TemporaryDataStream(); + writeToDataStream(outs); + Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes()); + } public String getName() { @@ -172,25 +183,47 @@ public class IggySwf implements StructureInterface { } @Override - public void writeToDataStream(WriteDataStreamInterface st) throws IOException { - try (DataStreamInterface s = new TemporaryDataStream(allFontBytes)) { - hdr.writeToDataStream(s); - s.writeUI64(1); - for (int i = 0; i < font_data_addresses.length; i++) { - long offset = font_data_addresses[i] - s.position() + 8; - s.writeUI64(offset); + 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.writeUI64(1); - for (int i = 0; i < text_addresses.size(); i++) { - long offset = text_addresses.get(i) - s.position() + 8; - s.writeUI64(offset); + } + s.writeUI64(1); + for (int i = 0; i < font_data_addresses.length; i++) { + long offset = font_data_addresses[i] - s.position(); + s.writeUI64(offset); + } + for (int i = 0; i < text_addresses.size(); i++) { + 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); } - s.writeUI64(1); - s.seek(840, SeekMode.SET); - for (int i = 0; i < hdr.font_count; i++) { - fonts.get(i).writeToDataStream(s); - } - st.writeBytes(s.getAllBytes()); + } + for (int i = 0; i < hdr.font_count; i++) { + s.seek(font_data_addresses[i], SeekMode.SET); + fonts.get(i).writeToDataStream(s); + } + for (int i = 0; i < text_data_bytes.size(); i++) { + s.seek(text_addresses.get(i), SeekMode.SET); + s.writeBytes(text_data_bytes.get(i)); + } + + if (hdr.isImported()) { + s.seek(font_add_off.get(0), SeekMode.SET); + s.writeBytes(font_add_data); } } From 94d12bfe4c58803db446a882dee193d0c272702e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 30 Nov 2016 18:49:32 +0100 Subject: [PATCH 15/27] signed 64 bit read/write, font bin info read/save --- .../jpexs/decompiler/flash/iggy/DataType.java | 18 +-- .../decompiler/flash/iggy/FontBinInfo.java | 81 ++++++++++++ .../flash/iggy/IggyFlashHeader64.java | 119 +++++++++--------- .../jpexs/decompiler/flash/iggy/IggySwf.java | 17 ++- .../iggy/streams/AbstractDataStream.java | 34 +++-- .../iggy/streams/ReadDataStreamInterface.java | 2 + .../streams/WriteDataStreamInterface.java | 2 + 7 files changed, 196 insertions(+), 77 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/FontBinInfo.java 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 e3fd968cd..245b64957 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 @@ -1,9 +1,9 @@ -package com.jpexs.decompiler.flash.iggy; - -/** - * @author JPEXS - */ -public enum DataType { - ubits, uint8_t, uint16_t, uint32_t, uint64_t, float_t, unknown, - widechar_t //or maybe just "string"? It has two bytes per character and is null terminated -} +package com.jpexs.decompiler.flash.iggy; + +/** + * @author JPEXS + */ +public enum DataType { + ubits, uint8_t, uint16_t, uint32_t, uint64_t, float_t, unknown, int64_t, + 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/FontBinInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/FontBinInfo.java new file mode 100644 index 000000000..cd0da4d55 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/FontBinInfo.java @@ -0,0 +1,81 @@ +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +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 FontBinInfo implements StructureInterface { + + @IggyFieldType(DataType.uint64_t) + long size_of_this_info = 96; + @IggyFieldType(value = DataType.uint16_t, count = 4) + int font_specific[]; + @IggyFieldType(DataType.float_t) + float normX; + @IggyFieldType(DataType.float_t) + float zero; + @IggyFieldType(DataType.float_t) + float zero2; + @IggyFieldType(DataType.float_t) + float normY; + @IggyFieldType(DataType.float_t) + float minSize; + @IggyFieldType(DataType.float_t) + float maxSize; + @IggyFieldType(DataType.uint64_t) + long order_in_iggy_file; + @IggyFieldType(DataType.int64_t) + long address_back; //relative + @IggyFieldType(value = DataType.uint8_t, count = 40) + byte pad[]; + + public FontBinInfo(ReadDataStreamInterface s) throws IOException { + readFromDataStream(s); + } + + @Override + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + size_of_this_info = s.readUI64(); + if (size_of_this_info != 96) { + throw new IOException(String.format("Wrong iggy font format (bininfo)!")); + } + font_specific = new int[4]; + for (int i = 0; i < font_specific.length; i++) { + font_specific[i] = s.readUI16(); + } + normX = s.readFloat(); + zero = s.readFloat(); + zero2 = s.readFloat(); + normY = s.readFloat(); + minSize = s.readFloat(); + maxSize = s.readFloat(); + order_in_iggy_file = s.readUI64(); + address_back = s.readSI64(); +//if(address_back + s.position() - 8 != text_offsets[i]) Printf("Wrong iggy font format (bininfo-offsetback) (%u)!\n",i); + pad = s.readBytes(40); + } + + @Override + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + s.writeUI64(size_of_this_info); + for (int i = 0; i < font_specific.length; i++) { + s.writeUI16(font_specific[i]); + } + s.writeFloat(normX); + s.writeFloat(zero); + s.writeFloat(zero2); + s.writeFloat(normY); + s.writeFloat(minSize); + s.writeFloat(maxSize); + s.writeUI64(order_in_iggy_file); + s.writeSI64(address_back); + s.writeBytes(pad); + } + +} 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 4c296d361..0da2c4e5a 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 @@ -16,17 +16,17 @@ import java.lang.reflect.Field; public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @IggyFieldType(DataType.uint64_t) - long off_start; // 0 Relative offset to first section (matches sizeof header); + long off_base; // 0 Relative offset to first section (matches sizeof header); @IggyFieldType(DataType.uint64_t) - long off_seq_end; // 8 Relative offset to as3 file names table... + long off_sequence_end; // 8 Relative offset to as3 file names table... @IggyFieldType(DataType.uint64_t) long off_font_end; // 0x10 relative offset to something @IggyFieldType(DataType.uint64_t) - long off_seq_start1; // 0x18 relative offset to something + long off_sequence_start1; // 0x18 relative offset to something @IggyFieldType(DataType.uint64_t) - long pad_to_match; // 0x20 relative offset to something + long off_sequence_start2; // 0x20 relative offset to something @IggyFieldType(DataType.uint64_t) - long off_seq_start2; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file + long off_sequence_start3; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file @IggyFieldType(DataType.uint32_t) long xmin; // 0x30 in pixels @IggyFieldType(DataType.uint32_t) @@ -66,7 +66,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @IggyFieldType(DataType.uint64_t) long off_unk78; // 0x78 relative offset to something @IggyFieldType(DataType.uint64_t) - long off_unk80; + long unk80; @IggyFieldType(DataType.uint64_t) long off_last_section; @IggyFieldType(DataType.uint64_t) @@ -97,9 +97,9 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { private long font_end_address; private long sequence_start_address1; private long sequence_start_address2; + private long sequence_start_address3; private long names_address; private long unk78_address; - private long unk80_address; private long last_section_address; private long flash_filename_address; private long decl_strings_address; @@ -152,7 +152,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { } public long getSequenceStartAddress2() { - return sequence_start_address2; + return sequence_start_address3; } public long getNamesAddress() { @@ -163,10 +163,6 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { return unk78_address; } - public long getUnk80Address() { - return unk80_address; - } - public long getLastSectionAddress() { return last_section_address; } @@ -185,28 +181,30 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { - /* 0:*/ off_start = stream.readUI64(); - base_address = off_start + stream.position() - 8; - /* 8:*/ off_seq_end = stream.readUI64(); - sequence_end_address = off_seq_end + stream.position() - 8; - /* 10:*/ off_font_end = stream.readUI64(); - font_end_address = off_font_end + stream.position() - 8; - /* 18:*/ off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times) - sequence_start_address1 = off_seq_start1 + stream.position() - 8; - pad_to_match = stream.readUI64(); - if (pad_to_match != 1) { - throw new IOException("Wrong iggy file - no pad to match 1"); - } - off_seq_start2 = stream.readUI64(); - if (off_seq_start1 != off_seq_start2) { - throw new IOException("Wrong iggy font format (sequence_start)!\n"); - } - sequence_start_address2 = off_seq_start2 + stream.position() - 8; + off_base = stream.readUI64(); + base_address = off_base == 1 ? 0 : off_base + stream.position() - 8; + + off_sequence_end = stream.readUI64(); + sequence_end_address = off_sequence_end == 1 ? 0 : off_sequence_end + stream.position() - 8; + + off_font_end = stream.readUI64(); + font_end_address = off_font_end == 1 ? 0 : off_font_end + stream.position() - 8; + + off_sequence_start1 = stream.readUI64(); + sequence_start_address1 = off_sequence_start1 == 1 ? 0 : off_sequence_start1 + stream.position() - 8; + + off_sequence_start2 = stream.readUI64(); + sequence_start_address2 = off_sequence_start2 == 1 ? 0 : off_sequence_start2 + stream.position() - 8; + + off_sequence_start3 = stream.readUI64(); + sequence_start_address3 = off_sequence_start3 == 1 ? 0 : off_sequence_start3 + stream.position() - 8; + xmin = stream.readUI32(); ymin = stream.readUI32(); xmax = stream.readUI32(); ymax = stream.readUI32(); - unk_40 = stream.readUI32(); + + unk_40 = stream.readUI32(); // probably number of blocks/objects after header unk_44 = stream.readUI32(); unk_48 = stream.readUI32(); unk_4C = stream.readUI32(); @@ -222,19 +220,24 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { unk_guid = stream.readUI64(); off_names = stream.readUI64(); - names_address = off_names + stream.position() - 8; + names_address = off_names == 1 ? 0 : off_names + stream.position() - 8; + off_unk78 = stream.readUI64(); - unk78_address = off_unk78 + stream.position() - 8; - off_unk80 = stream.readUI64(); - unk80_address = off_unk80 + stream.position() - 8; + unk78_address = off_unk78 == 1 ? 0 : off_unk78 + stream.position() - 8; + + unk80 = stream.readUI64(); //Maybe number of imports/names pointed by names_offset + off_last_section = stream.readUI64(); - last_section_address = off_last_section + stream.position() - 8; + last_section_address = off_last_section == 1 ? 0 : off_last_section + stream.position() - 8; + off_flash_filename = stream.readUI64(); - flash_filename_address = off_flash_filename + stream.position() - 8; - off_decl_strings = stream.readUI64(); - decl_strings_address = off_decl_strings + stream.position() - 8; - off_type_of_fonts = stream.readUI64(); - type_fonts_address = off_type_of_fonts + stream.position() - 8; + flash_filename_address = off_flash_filename == 1 ? 0 : off_flash_filename + stream.position() - 8; + + off_decl_strings = stream.readUI64(); //relative offset to as3 code (16 bytes header + abc blob) + decl_strings_address = off_decl_strings == 1 ? 0 : off_decl_strings + stream.position() - 8; + + off_type_of_fonts = stream.readUI64(); //relative offset to as3 file names table (or classes names or whatever) + type_fonts_address = off_type_of_fonts == 1 ? 0 : off_type_of_fonts + stream.position() - 8; flags = stream.readUI64(); font_count = stream.readUI32(); @@ -243,17 +246,18 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { - off_start = base_address - stream.position(); - stream.writeUI64(off_start); - off_seq_end = sequence_end_address - stream.position(); - stream.writeUI64(off_seq_end); - off_font_end = font_end_address - stream.position(); + off_base = base_address == 0 ? 1 : base_address - stream.position(); + stream.writeUI64(off_base); + off_sequence_end = sequence_end_address == 0 ? 1 : sequence_end_address - stream.position(); + stream.writeUI64(off_sequence_end); + off_font_end = font_end_address == 0 ? 1 : font_end_address - stream.position(); stream.writeUI64(off_font_end); - off_seq_start1 = sequence_start_address1 - stream.position(); - stream.writeUI64(off_seq_start1); - stream.writeUI64(pad_to_match); - off_seq_start2 = sequence_start_address2 - stream.position(); - stream.writeUI64(off_seq_start2); + off_sequence_start1 = sequence_start_address1 == 0 ? 1 : sequence_start_address1 - stream.position(); + stream.writeUI64(off_sequence_start1); + off_sequence_start2 = sequence_start_address2 == 0 ? 1 : sequence_start_address2 - stream.position(); + stream.writeUI64(off_sequence_start2); + off_sequence_start3 = sequence_start_address3 == 0 ? 1 : sequence_start_address3 - stream.position(); + stream.writeUI64(off_sequence_start3); stream.writeUI32(xmin); stream.writeUI32(ymin); stream.writeUI32(xmax); @@ -269,19 +273,18 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { stream.writeUI32(additional_import1); stream.writeUI32(zero1); stream.writeUI64(unk_guid); - off_names = names_address - stream.position(); + off_names = names_address == 0 ? 1 : names_address - stream.position(); stream.writeUI64(off_names); - off_unk78 = unk78_address - stream.position(); + off_unk78 = unk78_address == 0 ? 1 : unk78_address - stream.position(); stream.writeUI64(off_unk78); - off_unk80 = unk80_address - stream.position(); - stream.writeUI64(off_unk80); - off_last_section = last_section_address - stream.position(); + stream.writeUI64(unk80); + off_last_section = last_section_address == 0 ? 1 : last_section_address - stream.position(); stream.writeUI64(off_last_section); - off_flash_filename = flash_filename_address - stream.position(); + off_flash_filename = flash_filename_address == 0 ? 1 : flash_filename_address - stream.position(); stream.writeUI64(off_flash_filename); - off_decl_strings = decl_strings_address - stream.position(); + off_decl_strings = decl_strings_address == 0 ? 1 : decl_strings_address - stream.position(); stream.writeUI64(off_decl_strings); - off_type_of_fonts = type_fonts_address - stream.position(); + off_type_of_fonts = type_fonts_address == 0 ? 1 : type_fonts_address - stream.position(); stream.writeUI64(off_type_of_fonts); stream.writeUI64(flags); stream.writeUI32(font_count); 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 a8596d460..920f578d6 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 @@ -44,6 +44,7 @@ public class IggySwf implements StructureInterface { private byte font_add_data[]; private List font_add_off = new ArrayList<>(); private List font_add_size = new ArrayList<>(); + private FontBinInfo font_bin_info[]; public IggyFlashHeader64 getHdr() { return hdr; @@ -171,11 +172,16 @@ public class IggySwf implements StructureInterface { font_add_data = s.readBytes((int) (long) font_add_size.get(0)); } s.seek(hdr.getFontEndAddress(), SeekMode.SET); + 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); - WriteDataStreamInterface outs = new TemporaryDataStream(); + //TODO: sequence,typeoffonts,declstrings,binarydata + /*WriteDataStreamInterface outs = new TemporaryDataStream(); writeToDataStream(outs); - Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes()); - + Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());*/ } public String getName() { @@ -225,6 +231,11 @@ public class IggySwf implements StructureInterface { s.seek(font_add_off.get(0), SeekMode.SET); s.writeBytes(font_add_data); } + s.seek(hdr.getFontEndAddress(), SeekMode.SET); + for (int i = 0; i < hdr.font_count; i++) { + font_bin_info[i].writeToDataStream(s); + } + //TODO: sequence,typeoffonts,declstrings,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 fd22b1c73..88f057208 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 @@ -22,11 +22,17 @@ public abstract class AbstractDataStream implements DataStreamInterface { @Override public long readUI64() throws IOException { - try { - return (readUI32() + (readUI32() << 32)) & 0xffffffffffffffffL; - } catch (EOFException ex) { - return -1; - } + long lsb = readUI32(); + long msb = readUI32(); + long result = msb << 32 | lsb; + return result & 0xffffffffffffffffL; + } + + @Override + public long readSI64() throws IOException { + long lsb = readUI32(); + long msb = readUI32(); + return msb << 32 | lsb; } @Override @@ -43,10 +49,24 @@ public abstract class AbstractDataStream implements DataStreamInterface { return true; } + @Override + public boolean writeSI64(long val) throws IOException { + write((int) (val & 0xff)); + write((int) ((val >> 8) & 0xff)); + write((int) ((val >> 16) & 0xff)); + write((int) ((val >> 24) & 0xff)); + + write((int) ((val >> 32) & 0xff)); + write((int) ((val >> 40) & 0xff)); + write((int) ((val >> 48) & 0xff)); + write((int) ((val >> 56) & 0xff)); + return true; + } + @Override public long readUI32() throws IOException { try { - return (readUI8() + (readUI8() << 8) + (readUI8() << 16) + (readUI8() << 24)); + return (readUI8() | (readUI8() << 8) | (readUI8() << 16) | (readUI8() << 24)); } catch (EOFException ex) { return -1; } @@ -64,7 +84,7 @@ public abstract class AbstractDataStream implements DataStreamInterface { @Override public int readUI16() throws IOException { try { - return (readUI8() + (readUI8() << 8)) & 0xffff; + return (readUI8() | (readUI8() << 8)) & 0xffff; } catch (EOFException ex) { return -1; } 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 7bd57a76c..1364ce5da 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 @@ -21,6 +21,8 @@ public interface ReadDataStreamInterface extends AutoCloseable { public long readUI64() throws IOException; + public long readSI64() throws IOException; + public long readUI32() throws IOException; public int readUI16() throws IOException; 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 1e087fd1b..01d48d282 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 @@ -21,6 +21,8 @@ public interface WriteDataStreamInterface extends AutoCloseable { public boolean writeUI64(long val) throws IOException; + public boolean writeSI64(long val) throws IOException; + public boolean writeUI32(long val) throws IOException; public boolean writeUI16(int val) throws IOException; From c498ebfaf405b7fb0ce3bce20821cfeb2e06958d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 1 Dec 2016 22:05:39 +0100 Subject: [PATCH 16/27] Decl strings, sequence, fonttypeinfo. Read/Write IggySWF is complete. TODO: Apply in GUI. Make index. --- .../jpexs/decompiler/flash/iggy/DataType.java | 2 +- .../flash/iggy/IggyCharIndices.java | 2 +- .../flash/iggy/IggyDeclStrings.java | 63 ++++++++++++++++ .../jpexs/decompiler/flash/iggy/IggyFont.java | 4 +- .../flash/iggy/IggyFontTypeInfo.java | 73 ++++++++++++++++++ .../decompiler/flash/iggy/IggySequence.java | 75 +++++++++++++++++++ .../jpexs/decompiler/flash/iggy/IggySwf.java | 36 ++++++++- .../jpexs/decompiler/flash/iggy/IggyText.java | 2 +- .../flash/iggy/annotations/FieldPrinter.java | 4 +- 9 files changed, 251 insertions(+), 10 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java 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 245b64957..b5f1fc8cc 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 @@ -5,5 +5,5 @@ package com.jpexs.decompiler.flash.iggy; */ public enum DataType { ubits, uint8_t, uint16_t, uint32_t, uint64_t, float_t, unknown, int64_t, - widechar_t //or maybe just "string"? It has two bytes per character and is null terminated + wchar_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/IggyCharIndices.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java index f4cfd4e3c..424ce93b0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java @@ -14,7 +14,7 @@ import java.util.List; */ public class IggyCharIndices implements StructureInterface { - @IggyFieldType(value = DataType.widechar_t) + @IggyFieldType(value = DataType.wchar_t) List chars; @IggyFieldType(DataType.uint32_t) long padd; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java new file mode 100644 index 000000000..a948e7b87 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java @@ -0,0 +1,63 @@ +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.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 IggyDeclStrings(ReadDataStreamInterface stream) throws IOException { + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + one = s.readUI64(); + 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 { + s.writeUI64(one); + s.writeUI32(size); + s.writeBytes(xxx); + s.writeBytes(data); + s.writeBytes(padd); + s.writeUI64(one); + s.writeUI64(zero); + } + +} 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 4e7b8cefd..dc0125746 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 @@ -73,7 +73,7 @@ public class IggyFont extends IggyTag { long zero_padd_4; @IggyFieldType(DataType.uint64_t) long what_3; - @IggyFieldType(value = DataType.widechar_t, count = 40) + @IggyFieldType(value = DataType.wchar_t, count = 40) String subName = ""; @IggyFieldType(value = DataType.uint8_t, count = 48) byte[] zeroes48a; @@ -98,7 +98,7 @@ public class IggyFont extends IggyTag { @IggyFieldType(DataType.uint32_t) long one_padd5; - @IggyFieldType(value = DataType.widechar_t, count = 16) + @IggyFieldType(value = DataType.wchar_t, count = 16) String name; List charOffsets; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java new file mode 100644 index 000000000..38958d521 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java @@ -0,0 +1,73 @@ +package com.jpexs.decompiler.flash.iggy; + +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +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 IggyFontTypeInfo implements StructureInterface { + + @IggyFieldType(DataType.uint64_t) + long zero; + @IggyFieldType(DataType.uint64_t) + long ofs_local_name; + @IggyFieldType(DataType.uint64_t) + long font_info_num; + + private long local_name_address; + + public long getLocal_name_address() { + return local_name_address; + } + + public IggyFontTypeInfo(ReadDataStreamInterface s) throws IOException { + readFromDataStream(s); + } + + @Override + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + zero = s.readUI64(); + ofs_local_name = s.readUI64(); + local_name_address = ofs_local_name + s.position() - 8; + font_info_num = s.readUI64(); + } + + public String readFontInfo(ReadDataStreamInterface s) throws IOException { + long pos = s.position(); + s.seek(local_name_address, SeekMode.SET); + StringBuilder inf_font_builder = new StringBuilder(); + while (true) { + char c = (char) s.readUI16(); + if (c == '\0') { + break; + } + inf_font_builder.append(c); + } + s.seek(pos, SeekMode.SET); + return inf_font_builder.toString(); + } + + public void writeFontInfo(String info_name, WriteDataStreamInterface s) throws IOException { + long pos = s.position(); + s.seek(local_name_address, SeekMode.SET); + for (int i = 0; i < info_name.length(); i++) { + s.writeUI16(info_name.charAt(i)); + } + s.writeUI16(0); + s.seek(pos, SeekMode.SET); + } + + @Override + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + s.writeUI64(zero); + s.writeUI64(ofs_local_name); + s.writeUI64(font_info_num); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java new file mode 100644 index 000000000..1ef7e26f0 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java @@ -0,0 +1,75 @@ +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.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 IggySequence implements StructureInterface { + + @IggyArrayFieldType(value = DataType.uint64_t, count = 2) + public long onepadd[]; + + @IggyFieldType(DataType.uint64_t) + public long local_seq_offset; + + @IggyFieldType(DataType.uint64_t) + public long zero; + + @IggyFieldType(DataType.wchar_t) + public String sequence_name; + + @IggyArrayFieldType(DataType.uint8_t) + byte pad[]; + + @IggyFieldType(DataType.uint64_t) + public long zero2; + + // wchar_t sequencname[(sequenceendaddress-sequencestartaddress-localseqoffset)/2]; +// if((sequenceendaddress-sequencestartaddress)%8!=0) byte padd[((sequenceendaddress-sequencestartaddress)/8+1)*8-(sequenceendaddress-sequencestartaddress)]; + public IggySequence(ReadDataStreamInterface stream) throws IOException { + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + onepadd = new long[2]; + for (int i = 0; i < onepadd.length; i++) { + onepadd[i] = s.readUI64(); + } + local_seq_offset = s.readUI64(); + zero = s.readUI64(); + StringBuilder sequence_name_builder = new StringBuilder(); + for (int i = 0; i < local_seq_offset; i++) { + sequence_name_builder.append((char) s.readUI16()); + } + sequence_name = sequence_name_builder.toString(); + int pad8 = 8 - (int) (s.position() % 8); + if (pad8 < 8) { + pad = s.readBytes(pad8); + } else { + pad = new byte[0]; + } + zero2 = s.readUI64(); //zero2 + } + + @Override + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + for (int i = 0; i < onepadd.length; i++) { + s.writeUI64(onepadd[i]); + } + s.writeUI64(local_seq_offset); + s.writeUI64(zero); + for (int i = 0; i < sequence_name.length(); i++) { + s.writeUI16(sequence_name.charAt(i)); + } + s.writeBytes(pad); + s.writeUI64(zero2); + } +} 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 920f578d6..c943bf098 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 @@ -23,7 +23,7 @@ public class IggySwf implements StructureInterface { final static int NO_OFFSET = 1; - @IggyFieldType(value = DataType.widechar_t, count = 48) + @IggyFieldType(value = DataType.wchar_t, count = 48) String name; Map fonts; @@ -45,6 +45,10 @@ public class IggySwf implements StructureInterface { private List font_add_off = new ArrayList<>(); private List font_add_size = new ArrayList<>(); private FontBinInfo font_bin_info[]; + private IggySequence sequence; + private IggyFontTypeInfo type_info[]; + private String type_info_name[]; + private IggyDeclStrings decl_strings; public IggyFlashHeader64 getHdr() { return hdr; @@ -177,8 +181,20 @@ public class IggySwf implements StructureInterface { font_bin_info[i] = new FontBinInfo(s); } s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET); + 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++) { + type_info_name[i] = type_info[i].readFontInfo(s); + } - //TODO: sequence,typeoffonts,declstrings,binarydata + 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());*/ @@ -235,7 +251,21 @@ public class IggySwf implements StructureInterface { for (int i = 0; i < hdr.font_count; i++) { font_bin_info[i].writeToDataStream(s); } - //TODO: sequence,typeoffonts,declstrings,binarydata + s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET); + sequence.writeToDataStream(s); + + 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++) { + type_info[i].writeFontInfo(type_info_name[i], s); + } + 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/IggyText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java index 746919b1d..1ddd359a9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java @@ -58,7 +58,7 @@ public class IggyText implements StructureInterface { long one; @IggyArrayFieldType(value = DataType.uint8_t, count = 32) byte[] some; // same for different fonts - @IggyArrayFieldType(value = DataType.widechar_t) + @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) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java index ada8192b9..9d3325283 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/FieldPrinter.java @@ -29,7 +29,7 @@ public class FieldPrinter { case uint64_t: sb.append(f.getLong(val)); break; - case widechar_t: + case wchar_t: sb.append("\"").append(f.get(val)).append("\""); break; } @@ -65,7 +65,7 @@ public class FieldPrinter { case uint64_t: sb.append("UI64"); break; - case widechar_t: + case wchar_t: sb.append("//FIXME"); break; } From d6d350bee805d4c664dc06791b790c7bb43133a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 3 Dec 2016 07:54:35 +0100 Subject: [PATCH 17/27] index stub --- .../jpexs/decompiler/flash/iggy/IggyFile.java | 38 ++- .../jpexs/decompiler/flash/iggy/IggyFont.java | 18 +- .../flash/iggy/IggyIndexBuilder.java | 12 + .../flash/iggy/IggyIndexParser.java | 85 ++++-- .../jpexs/decompiler/flash/iggy/IggySwf.java | 43 +-- .../iggy/streams/AbstractDataStream.java | 36 +++ .../flash/iggy/streams/EmptyIndexing.java | 84 ++++++ .../iggy/streams/IndexingDataStream.java | 272 ++++++++++++++++++ .../streams/IndexingDataStreamInterface.java | 38 +++ .../streams/RandomAccessFileDataStream.java | 31 ++ .../iggy/streams/ReadDataStreamInterface.java | 4 + .../streams/WriteDataStreamInterface.java | 8 + 12 files changed, 600 insertions(+), 69 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexBuilder.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/EmptyIndexing.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStream.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStreamInterface.java 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(); } From 91dabac158cda89e260ce1af49b9dc48c81343b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 3 Dec 2016 09:22:03 +0100 Subject: [PATCH 18/27] advances fix --- .../flash/iggy/IggyCharAdvances.java | 18 ++++++++++++------ .../jpexs/decompiler/flash/iggy/IggyFont.java | 5 +++-- .../jpexs/decompiler/flash/iggy/IggySwf.java | 13 ++++++++++--- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java index 537e6be3b..628c4dd1f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java @@ -14,29 +14,35 @@ import java.util.List; public class IggyCharAdvances implements StructureInterface { List advances; - private long charCount; + private List glyphs; public List getScales() { return advances; } - public IggyCharAdvances(ReadDataStreamInterface stream, long charCount) throws IOException { - this.charCount = charCount; + public IggyCharAdvances(ReadDataStreamInterface stream, List glyphs) throws IOException { + this.glyphs = glyphs; readFromDataStream(stream); } @Override public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { advances = new ArrayList<>(); - for (int i = 0; i < charCount; i++) { - advances.add(stream.readFloat()); + for (int i = 0; i < glyphs.size(); i++) { + if (glyphs.get(i) != null) { + advances.add(stream.readFloat()); + } else { + advances.add(null); + } } } @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { for (int i = 0; i < advances.size(); i++) { - stream.writeFloat(advances.get(i)); + if (advances.get(i) != null) { + stream.writeFloat(advances.get(i)); + } } } } 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 d1b39c06d..0f175d5d2 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 @@ -285,7 +285,7 @@ public class IggyFont extends IggyTag { } if (abs_start_of_scale != 0) { s.seek(abs_start_of_scale, SeekMode.SET); - charScales = new IggyCharAdvances(s, char_count); + charScales = new IggyCharAdvances(s, glyphs); } if (abs_start_of_kern != 0) { s.seek(abs_start_of_kern, SeekMode.SET); @@ -366,14 +366,15 @@ public class IggyFont extends IggyTag { s.writeUI64(0); //pad zero if (abs_start_of_char_struct != 0) { s.seek(abs_start_of_char_struct, SeekMode.SET); + long baseOfsAddr = s.position(); //offsets of shapes for (IggyCharOffset ofs : charOffsets) { ofs.writeToDataStream(s); } + //long afterOfsAddr = s.position(); for (int i = 0; i < glyphs.size(); i++) { IggyShape shp = glyphs.get(i); if (shp != null) { - s.seek(charOffsets.get(i).getAddress(), SeekMode.SET); shp.writeToDataStream(s); } } 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 279145d34..1905eebad 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 @@ -62,7 +62,11 @@ public class IggySwf implements StructureInterface { newData = stream.getAllBytes(); newLen = newData.length; } - long oldLen = font_data_sizes[fontIndex]; + + //FIXME + Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\font" + fontIndex + ".bin", newData); + + /* long oldLen = font_data_sizes[fontIndex]; long diff = newLen - oldLen; if (diff != 0) { font_data_sizes[fontIndex] = newLen; @@ -77,7 +81,7 @@ public class IggySwf implements StructureInterface { } } hdr.insertGapAfter(font_data_addresses[fontIndex], diff); - + */ } @Override @@ -154,7 +158,10 @@ public class IggySwf implements StructureInterface { fonts = new HashMap<>(); for (int i = 0; i < hdr.font_count; i++) { s.seek(font_data_addresses[i], SeekMode.SET); - //byte font_data[] = s.readBytes((int) font_data_sizes[i]); + byte font_data[] = s.readBytes((int) font_data_sizes[i]); + //FIXME + Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\font" + i + ".bin", font_data); + s.seek(-font_data_sizes[i], SeekMode.CUR); IggyFont font = new IggyFont(s); fonts.put(i, font); } From 72af4e6e93f284c736636b8e4bfc7a0506dae67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 3 Dec 2016 09:32:43 +0100 Subject: [PATCH 19/27] put advances back as were, fix font data size --- .../flash/iggy/IggyCharAdvances.java | 18 ++++++------------ .../jpexs/decompiler/flash/iggy/IggyFont.java | 2 +- .../jpexs/decompiler/flash/iggy/IggySwf.java | 4 ++-- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java index 628c4dd1f..537e6be3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java @@ -14,35 +14,29 @@ import java.util.List; public class IggyCharAdvances implements StructureInterface { List advances; - private List glyphs; + private long charCount; public List getScales() { return advances; } - public IggyCharAdvances(ReadDataStreamInterface stream, List glyphs) throws IOException { - this.glyphs = glyphs; + public IggyCharAdvances(ReadDataStreamInterface stream, long charCount) throws IOException { + this.charCount = charCount; readFromDataStream(stream); } @Override public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { advances = new ArrayList<>(); - for (int i = 0; i < glyphs.size(); i++) { - if (glyphs.get(i) != null) { - advances.add(stream.readFloat()); - } else { - advances.add(null); - } + for (int i = 0; i < charCount; i++) { + advances.add(stream.readFloat()); } } @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { for (int i = 0; i < advances.size(); i++) { - if (advances.get(i) != null) { - stream.writeFloat(advances.get(i)); - } + stream.writeFloat(advances.get(i)); } } } 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 0f175d5d2..c70b17c98 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 @@ -285,7 +285,7 @@ public class IggyFont extends IggyTag { } if (abs_start_of_scale != 0) { s.seek(abs_start_of_scale, SeekMode.SET); - charScales = new IggyCharAdvances(s, glyphs); + charScales = new IggyCharAdvances(s, char_count); } if (abs_start_of_kern != 0) { s.seek(abs_start_of_kern, SeekMode.SET); 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 1905eebad..eedd9101f 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 @@ -114,7 +114,7 @@ public class IggySwf implements StructureInterface { if (next_offset == 1) { font_data_sizes[i] = hdr.getFontEndAddress() - font_data_addresses[i]; } else { - font_data_sizes[i] = next_offset - offset; + font_data_sizes[i] = next_offset - offset + 8; } } while (true) { @@ -130,7 +130,7 @@ public class IggySwf implements StructureInterface { text_data_sizes.add(hdr.getFontEndAddress() - text_addr); break; } else { - text_data_sizes.add(next_offset - offset); + text_data_sizes.add(next_offset - offset + 8); } } s.readUI64(); //1 From 5bb0d8ac83e5a8eca4c7f79174b91f47d5d44c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 3 Dec 2016 21:59:42 +0100 Subject: [PATCH 20/27] Iggy - generating Index finished Other various Iggy fixes --- .../flash/iggy/IggyCharKerning.java | 2 + .../decompiler/flash/iggy/IggyCharOffset.java | 2 + .../flash/iggy/IggyDeclStrings.java | 5 + .../jpexs/decompiler/flash/iggy/IggyFile.java | 86 ++-- .../flash/iggy/IggyFlashHeader64.java | 29 +- .../jpexs/decompiler/flash/iggy/IggyFont.java | 26 +- ...{FontBinInfo.java => IggyFontBinInfo.java} | 6 +- .../flash/iggy/IggyFontTypeInfo.java | 1 + .../flash/iggy/IggyIndexBuilder.java | 12 - .../decompiler/flash/iggy/IggySequence.java | 32 +- .../decompiler/flash/iggy/IggyShape.java | 8 + .../decompiler/flash/iggy/IggyShapeNode.java | 3 + .../jpexs/decompiler/flash/iggy/IggySwf.java | 214 ++++++--- .../jpexs/decompiler/flash/iggy/IggyText.java | 71 ++- .../iggy/conversion/IggyToSwfConvertor.java | 5 +- .../iggy/streams/AbstractDataStream.java | 19 +- .../flash/iggy/streams/EmptyIndexing.java | 84 ---- .../flash/iggy/streams/IggyIndexBuilder.java | 430 ++++++++++++++++++ .../iggy/{ => streams}/IggyIndexParser.java | 68 ++- .../iggy/streams/IndexingDataStream.java | 272 ----------- .../streams/IndexingDataStreamInterface.java | 38 -- .../streams/RandomAccessFileDataStream.java | 16 +- .../streams/WriteDataStreamInterface.java | 4 +- 23 files changed, 792 insertions(+), 641 deletions(-) rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{FontBinInfo.java => IggyFontBinInfo.java} (90%) delete mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexBuilder.java delete mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/EmptyIndexing.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/{ => streams}/IggyIndexParser.java (68%) delete mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStream.java delete mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStreamInterface.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index 997999b76..e838c0ad6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -13,6 +13,8 @@ import java.util.List; */ public class IggyCharKerning implements StructureInterface { + public static final int STRUCT_SIZE = 6; + private long kernCount; List charsA; List charsB; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 74b197582..687ecaad1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -13,6 +13,8 @@ import java.util.logging.Logger; */ public class IggyCharOffset implements StructureInterface { + public static final int STRUCT_SIZE = 32; + private static Logger LOGGER = Logger.getLogger(IggyCharOffset.class.getName()); @IggyFieldType(DataType.uint64_t) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java index a948e7b87..9d229b8a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java @@ -2,6 +2,7 @@ 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; @@ -51,10 +52,14 @@ public class IggyDeclStrings implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + IggyIndexBuilder ib = s.getIndexing(); s.writeUI64(one); s.writeUI32(size); s.writeBytes(xxx); + ib.writeLengthSkipTwice(8 + 4 + 3, 0); + ib.writeLengthUI32(size); s.writeBytes(data); + ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE); s.writeBytes(padd); s.writeUI64(one); s.writeUI64(zero); 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 de66dd8b0..f490db013 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 @@ -1,13 +1,13 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.streams.IggyIndexParser; +import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; import com.jpexs.decompiler.flash.iggy.streams.SeekMode; 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; @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -38,11 +39,7 @@ public class IggyFile implements StructureInterface { private List subFileEntries = new ArrayList<>(); private List subFileEntriesData = new ArrayList<>(); - private List headers = new ArrayList<>(); private List iggySwfs = new ArrayList<>(); - private List> indexTables = new ArrayList<>(); - private List> offsetTables = new ArrayList<>(); - private List indexDataStreams = new ArrayList<>(); public static final int FIRST_TAG_POSITION = 3; @@ -50,7 +47,7 @@ public class IggyFile implements StructureInterface { IggySwf iggySwf = iggySwfs.get(targetSwfIndex); iggySwf.replaceFontTag(fontIndex, newFont); - IndexingDataStreamInterface indexStream = new IndexingDataStream(); + IggyIndexBuilder indexStream = new IggyIndexBuilder(); DataStreamInterface flashStream = new TemporaryDataStream(); flashStream.setIndexing(indexStream); iggySwf.writeToDataStream(flashStream); @@ -85,34 +82,12 @@ public class IggyFile implements StructureInterface { } } - private boolean setSwfItemLength(int swfIndex, int itemindex, long newLength) { - DataStreamInterface stream = indexDataStreams.get(swfIndex); - - List offsetTable = offsetTables.get(swfIndex); - - long offset = offsetTable.get(itemindex); - long nextOffset = itemindex == offsetTable.size() - 1 ? stream.totalSize() : offsetTable.get(itemindex + 1); - long currentSize = nextOffset - offset; - try { - byte indexData[] = stream.getAllBytes(); - setItemLength(offset, header.is64(), indexData, newLength); - indexDataStreams.set(swfIndex, new TemporaryDataStream(indexData)); //TODO: optimize! - long lengthDelta = newLength - currentSize; - for (int i = itemindex + 1; i < offsetTable.size(); i++) { - offsetTable.set(i, offsetTable.get(i) + lengthDelta); - } - return true; - } catch (IOException ex) { - return false; - } - } - public IggySwf getSwf(int swfIndex) { return iggySwfs.get(swfIndex); } - public Set getFontIds(int swfIndex) { - return iggySwfs.get(swfIndex).fonts.keySet(); + public int getFontCount(int swfIndex) { + return iggySwfs.get(swfIndex).fonts.size(); } public IggyFont getFont(int swfIndex, int fontId) { @@ -221,13 +196,15 @@ public class IggyFile implements StructureInterface { IggyFile iggyFile = new IggyFile(inFile); extractIggyFile(inFile, extractDirOrig); IggySwf iswf = iggyFile.getSwf(0); - IggyFont ifont = iswf.fonts.get(0); - iggyFile.replaceFontTag(0, 0, ifont); + iggyFile.replaceSwf(0, iswf); + //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); + System.exit(0); } private static void copyStream(InputStream is, OutputStream os) { @@ -669,27 +646,42 @@ public class IggyFile implements StructureInterface { } //WIP - public boolean replaceSwf(int targetSwfIndex, IggySwf iggySwf) { - return false; //Not working yet - need to make IggySWF.writeToDataStream work + public boolean replaceSwf(int targetSwfIndex, IggySwf iggySwf) throws IOException { - /*if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) { + if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) { throw new ArrayIndexOutOfBoundsException("No such SWF file index"); } byte replacementData[]; + byte replacementIndexData[]; + IggyIndexBuilder ib = new IggyIndexBuilder(); try (DataStreamInterface stream = new TemporaryDataStream()) { - headers.get(targetSwfIndex).writeToDataStream(stream); + 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; } + IggyIndexParser.parseIndex(true, new TemporaryDataStream(replacementIndexData), new ArrayList<>(), new ArrayList<>()); + int swfIndex = 0; long offsetsChange = 0; for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); entry.offset += offsetsChange; + if (entry.type == IggySubFileEntry.TYPE_INDEX) { + if (swfIndex == targetSwfIndex) { + long oldSize = entry.size; + long newSize = replacementIndexData.length; + offsetsChange = offsetsChange + (newSize - oldSize); + entry.size = newSize; + entry.size2 = newSize; + subFileEntriesData.set(i, replacementIndexData); + } + swfIndex++; + } if (entry.type == IggySubFileEntry.TYPE_FLASH) { if (swfIndex == targetSwfIndex) { long oldSize = entry.size; @@ -698,29 +690,19 @@ public class IggyFile implements StructureInterface { entry.size = newSize; entry.size2 = newSize; //entries after this one will have modified offsets + subFileEntriesData.set(i, replacementData); } - swfIndex++; } } - subFileEntriesData.set(targetSwfIndex, replacementData); - return true;*/ + + return true; } private void parseEntries() throws IOException { - List flashDataStreams = new ArrayList<>(); - for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); - DataStreamInterface dataStream = new TemporaryDataStream(getEntryData(i)); - if (entry.type == IggySubFileEntry.TYPE_INDEX) { - List indexTable = new ArrayList<>(); - List offsets = new ArrayList<>(); - IggyIndexParser.parseIndex(header.is64(), dataStream, indexTable, offsets); - indexDataStreams.add(dataStream); - indexTables.add(indexTable); - offsetTables.add(offsets); - } else if (entry.type == IggySubFileEntry.TYPE_FLASH) { - iggySwfs.add(new IggySwf(dataStream)); + if (entry.type == IggySubFileEntry.TYPE_FLASH) { + iggySwfs.add(new IggySwf(new TemporaryDataStream(getEntryData(i)))); } } } 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 0da2c4e5a..a2d35c3ee 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 @@ -51,16 +51,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { float frame_rate; @IggyFieldType(DataType.uint32_t) long unk_5C; - @IggyFieldType(DataType.uint32_t) - long additional_import1; - @IggyFieldType(DataType.uint32_t) - long zero1; - - //local - private int imported = 0; - @IggyFieldType(DataType.uint64_t) - long unk_guid; // same for some fonts (eng + chinese) + long imported_guid; + @IggyFieldType(DataType.uint64_t) + long my_guid; // same for some fonts (eng + chinese) @IggyFieldType(DataType.uint64_t) long off_names; // 0x70 relative offset to the names/import section of the file - end of fonts @IggyFieldType(DataType.uint64_t) @@ -127,8 +121,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { } } - public boolean isImported() { - return imported == 1; + public long getImported_guid() { + return imported_guid; } public long getBaseAddress() { @@ -212,12 +206,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { unk_54 = stream.readUI32(); frame_rate = stream.readFloat(); unk_5C = stream.readUI32(); - additional_import1 = stream.readUI32(); - if (additional_import1 > 0) { - imported = 1; - } - zero1 = stream.readUI32(); - unk_guid = stream.readUI64(); + imported_guid = stream.readUI64(); + my_guid = stream.readUI64(); off_names = stream.readUI64(); names_address = off_names == 1 ? 0 : off_names + stream.position() - 8; @@ -270,9 +260,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { stream.writeUI32(unk_54); stream.writeFloat(frame_rate); stream.writeUI32(unk_5C); - stream.writeUI32(additional_import1); - stream.writeUI32(zero1); - stream.writeUI64(unk_guid); + stream.writeUI64(imported_guid); + stream.writeUI64(my_guid); off_names = names_address == 0 ? 1 : names_address - stream.position(); stream.writeUI64(off_names); off_unk78 = unk78_address == 0 ? 1 : unk78_address - stream.position(); 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 c70b17c98..a75ef98e9 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 @@ -7,6 +7,7 @@ import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -217,6 +218,8 @@ public class IggyFont extends IggyTag { start_of_kern = s.readUI64(); long abs_start_of_kern = makeAbsOffset(s, start_of_kern); zero_padd = s.readUI64(); + + //-------------------------------------- what_2 = s.readUI64(); zero_padd_2 = s.readUI64(); start_of_name = s.readUI64(); @@ -244,6 +247,7 @@ public class IggyFont extends IggyTag { } subName = subNameBuilder.toString(); zeroes48a = s.readBytes(48); + sss1 = s.readFloat(); one_padd2 = s.readUI32(); sss2 = s.readFloat(); @@ -295,6 +299,8 @@ public class IggyFont extends IggyTag { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + IggyIndexBuilder ib = s.getIndexing(); + ib.writeConstLength(IggyIndexBuilder.CONST_GENERAL_FONT_INFO_SIZE); s.writeUI16(type); s.writeUI16(fontId); s.writeBytes(zeroone); @@ -316,6 +322,7 @@ public class IggyFont extends IggyTag { s.writeUI64(start_of_kern); long abs_start_of_kern = makeAbsOffset(s, start_of_kern); s.writeUI64(zero_padd); + ib.writeConstLength(IggyIndexBuilder.CONST_GENERAL_FONT_INFO2_SIZE); s.writeUI64(what_2); s.writeUI64(zero_padd_2); s.writeUI64(start_of_name); @@ -355,6 +362,9 @@ public class IggyFont extends IggyTag { //align to 8 bytes boundary int len = name.length() * 2 + 2; + + ib.write16bitArray(name.length() + 1); + ib.pad8bytes(); int pad8 = 8 - (len % 8); if (pad8 < 8) { for (int i = 0; i < pad8; i++) { @@ -366,7 +376,8 @@ public class IggyFont extends IggyTag { s.writeUI64(0); //pad zero if (abs_start_of_char_struct != 0) { s.seek(abs_start_of_char_struct, SeekMode.SET); - long baseOfsAddr = s.position(); + + ib.writeConstLengthArray(IggyIndexBuilder.CONST_CHAR_OFFSET_SIZE, charOffsets.size()); //offsets of shapes for (IggyCharOffset ofs : charOffsets) { ofs.writeToDataStream(s); @@ -384,21 +395,30 @@ public class IggyFont extends IggyTag { for (char c : codePoints.chars) { s.writeUI16(c); } - s.writeUI32(0); + ib.write16bitArray(codePoints.chars.size()); + ib.pad8bytes(); + s.pad8bytes(); } if (abs_start_of_scale != 0) { s.seek(abs_start_of_scale, SeekMode.SET); charScales.writeToDataStream(s); + ib.write32bitArray(charScales.advances.size()); + ib.pad8bytes(); + s.pad8bytes(); } if (abs_start_of_kern != 0) { s.seek(abs_start_of_kern, SeekMode.SET); + ib.writeConstLengthArray(IggyIndexBuilder.CONST_KERNING_RECORD_SIZE, kern_count); charKernings.writeToDataStream(s); + ib.pad8bytes(); + s.pad8bytes(); } - if ((s.position() - abs_start_of_char_index) % 8 != 0) { + /*if ((s.position() - abs_start_of_char_index) % 8 != 0) { byte padd[] = new byte[(int) (((s.position() - abs_start_of_char_index) / 8 + 1) * 8 - (s.position() - abs_start_of_char_index))]; s.writeBytes(padd); } + ib.writePaddingTo8(s.position());*/ } public int getType() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/FontBinInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontBinInfo.java similarity index 90% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/FontBinInfo.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontBinInfo.java index cd0da4d55..d11cde5fb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/FontBinInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontBinInfo.java @@ -10,7 +10,9 @@ import java.io.IOException; * * @author JPEXS */ -public class FontBinInfo implements StructureInterface { +public class IggyFontBinInfo implements StructureInterface { + + public static final int STRUCT_SIZE = 96; @IggyFieldType(DataType.uint64_t) long size_of_this_info = 96; @@ -35,7 +37,7 @@ public class FontBinInfo implements StructureInterface { @IggyFieldType(value = DataType.uint8_t, count = 40) byte pad[]; - public FontBinInfo(ReadDataStreamInterface s) throws IOException { + public IggyFontBinInfo(ReadDataStreamInterface s) throws IOException { readFromDataStream(s); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java index 38958d521..33ec71665 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java @@ -13,6 +13,7 @@ import java.io.IOException; */ public class IggyFontTypeInfo implements StructureInterface { + public static final int STRUCT_SIZE = 24; @IggyFieldType(DataType.uint64_t) long zero; @IggyFieldType(DataType.uint64_t) 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 deleted file mode 100644 index dace78461..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexBuilder.java +++ /dev/null @@ -1,12 +0,0 @@ -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/IggySequence.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java index 1ef7e26f0..026af5b43 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java @@ -1,7 +1,9 @@ package com.jpexs.decompiler.flash.iggy; +import static com.jpexs.decompiler.flash.iggy.IggyFontBinInfo.STRUCT_SIZE; 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; @@ -13,6 +15,8 @@ import java.io.IOException; */ public class IggySequence implements StructureInterface { + public static final int STRUCT_SIZE = 16; + @IggyArrayFieldType(value = DataType.uint64_t, count = 2) public long onepadd[]; @@ -25,9 +29,6 @@ public class IggySequence implements StructureInterface { @IggyFieldType(DataType.wchar_t) public String sequence_name; - @IggyArrayFieldType(DataType.uint8_t) - byte pad[]; - @IggyFieldType(DataType.uint64_t) public long zero2; @@ -43,33 +44,28 @@ public class IggySequence implements StructureInterface { for (int i = 0; i < onepadd.length; i++) { onepadd[i] = s.readUI64(); } + //sequence start local_seq_offset = s.readUI64(); zero = s.readUI64(); - StringBuilder sequence_name_builder = new StringBuilder(); - for (int i = 0; i < local_seq_offset; i++) { - sequence_name_builder.append((char) s.readUI16()); - } - sequence_name = sequence_name_builder.toString(); - int pad8 = 8 - (int) (s.position() % 8); - if (pad8 < 8) { - pad = s.readBytes(pad8); - } else { - pad = new byte[0]; - } + sequence_name = s.readWChar(); + s.pad8bytes(); zero2 = s.readUI64(); //zero2 } @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + IggyIndexBuilder ib = s.getIndexing(); + ib.writeLengthSkipTwice(16, 0); for (int i = 0; i < onepadd.length; i++) { s.writeUI64(onepadd[i]); } + ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE); s.writeUI64(local_seq_offset); s.writeUI64(zero); - for (int i = 0; i < sequence_name.length(); i++) { - s.writeUI16(sequence_name.charAt(i)); - } - s.writeBytes(pad); + ib.write16bitArray(sequence_name.length() + 1); + s.writeWChar(sequence_name); + s.pad8bytes(); + ib.pad8bytes(); s.writeUI64(zero2); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index 33c0ccfa3..ec0eb6ed1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -1,9 +1,12 @@ package com.jpexs.decompiler.flash.iggy; +import static com.jpexs.decompiler.flash.iggy.IggyCharOffset.STRUCT_SIZE; +import static com.jpexs.decompiler.flash.iggy.IggyShapeNode.STRUCT_SIZE; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; import com.jpexs.decompiler.flash.iggy.streams.SeekMode; import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; 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.WriteDataStreamInterface; import java.io.IOException; @@ -17,6 +20,8 @@ import java.util.logging.Logger; */ public class IggyShape implements StructureInterface { + public static final int STRUCT_SIZE = 64; + private static Logger LOGGER = Logger.getLogger(IggyShape.class.getName()); @IggyFieldType(DataType.float_t) @@ -106,6 +111,7 @@ public class IggyShape implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_SHAPE_SIZE); s.writeFloat(minx); s.writeFloat(miny); s.writeFloat(maxx); @@ -118,6 +124,8 @@ public class IggyShape implements StructureInterface { s.writeUI32(one4); s.writeUI32(two1); + s.getIndexing().writeConstLengthArray(IggyIndexBuilder.CONST_SHAPE_NODE_SIZE, nodes.size()); + for (IggyShapeNode node : nodes) { node.writeToDataStream(s); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java index 9507acd9e..04d9d4132 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java @@ -1,5 +1,6 @@ package com.jpexs.decompiler.flash.iggy; +import static com.jpexs.decompiler.flash.iggy.IggyShape.STRUCT_SIZE; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; @@ -15,6 +16,8 @@ import java.util.logging.Logger; */ public class IggyShapeNode implements StructureInterface { + public static final int STRUCT_SIZE = 24; + private static Logger LOGGER = Logger.getLogger(IggyShapeNode.class.getName()); public static int NODE_TYPE_MOVE = 1; 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 eedd9101f..8e63e8be9 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 @@ -6,6 +6,7 @@ import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder; import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import com.jpexs.helpers.Helper; import java.io.FileOutputStream; @@ -26,7 +27,10 @@ public class IggySwf implements StructureInterface { @IggyFieldType(value = DataType.wchar_t, count = 48) String name; - Map fonts; + List fonts = new ArrayList<>(); + private List font_data_addresses = new ArrayList<>(); + List add_fonts = new ArrayList<>(); + private List add_font_data_addresses = new ArrayList<>(); private IggyFlashHeader64 hdr; @@ -35,27 +39,27 @@ public class IggySwf implements StructureInterface { public IggySwf(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } + private List texts = new ArrayList<>(); + private List text_data_addresses = new ArrayList<>(); + private List add_texts = new ArrayList<>(); + private List add_text_data_addresses = new ArrayList<>(); - private long font_data_addresses[]; - private long font_data_sizes[]; - private List text_addresses = new ArrayList<>(); - private List text_data_sizes = new ArrayList<>(); - private List text_data_bytes = new ArrayList<>(); private byte font_add_data[]; - private List font_add_off = new ArrayList<>(); - private List font_add_size = new ArrayList<>(); - private FontBinInfo font_bin_info[]; + private List font_additional_size = new ArrayList<>(); + private IggyFontBinInfo font_bin_info[]; private IggySequence sequence; 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 void replaceFontTag(int fontIndex, IggyFont newFont) throws IOException { - long newLen; + /*long newLen; byte newData[]; try (WriteDataStreamInterface stream = new TemporaryDataStream()) { newFont.writeToDataStream(stream); @@ -66,7 +70,7 @@ public class IggySwf implements StructureInterface { //FIXME Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\font" + fontIndex + ".bin", newData); - /* long oldLen = font_data_sizes[fontIndex]; + long oldLen = font_data_sizes[fontIndex]; long diff = newLen - oldLen; if (diff != 0) { font_data_sizes[fontIndex] = newLen; @@ -103,9 +107,71 @@ public class IggySwf implements StructureInterface { s.seek(hdr.getBaseAddress(), SeekMode.SET); s.readUI64(); //pad 1 - font_data_addresses = new long[(int) hdr.font_count]; - font_data_sizes = new long[(int) hdr.font_count]; + List 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 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); + } + } + } + + /* for (int i = 0; i < hdr.font_count; i++) { long offset = s.readUI64(); font_data_addresses[i] = offset + s.position() - 8; @@ -135,56 +201,70 @@ public class IggySwf implements StructureInterface { } s.readUI64(); //1 - if (hdr.isImported()) { // tohle muze narusit iggy order, ale oni to pak stejne pocitaji dle infa - long additionalOffset = s.readUI64(); - font_add_off.add(additionalOffset + s.position() - 8); - font_add_size.add(hdr.getFontEndAddress() - font_add_off.get(0)); - if (s.readUI8(font_add_off.get(0)) != 22) { //22 = Text - for (int i = 0; i < text_addresses.size(); i++) { - if (s.readUI8(text_addresses.get(i)) == 22) { //TEXT + if (hdr.getImported_guid() != 0) { + ofs_additional = s.readUI64(); + additional_address = ofs_additional + s.position() - 8; + font_additional_addresses.add(additional_address); + font_additional_size.add(hdr.getFontEndAddress() - font_additional_addresses.get(0)); + + if (s.readUI8(font_additional_addresses.get(0)) != 22) { //additional is not text + // font je hozen mezi infa... + for (int i = 0; i < text_addresses.size(); i++) { //walk all already read texts + if (s.readUI8(text_addresses.get(i)) == 22) { //check if it's text long pomoff; long pomsize; pomoff = text_addresses.get(i); pomsize = text_data_sizes.get(i); - text_addresses.set(i, font_add_off.get(0)); - text_data_sizes.set(i, font_add_size.get(0)); - font_add_off.set(0, pomoff); - font_add_size.set(0, pomsize); + text_addresses.set(i, font_additional_addresses.get(0)); + text_data_sizes.set(i, font_additional_size.get(0)); + font_additional_addresses.set(0, pomoff); + font_additional_size.set(0, pomsize); } } } - } + }*/ + + /* if (s.readUI8(s.position()) == 22) { //22 = Text + byte[] textHdr = s.readBytes(IggyText.STRUCT_SIZE); + String textStr = s.readWChar(); + s.pad8bytes(); + }*/ //here is offset [3] - 744 - fonts = new HashMap<>(); + /* fonts = new ArrayList<>(); for (int i = 0; i < hdr.font_count; i++) { s.seek(font_data_addresses[i], SeekMode.SET); byte font_data[] = s.readBytes((int) font_data_sizes[i]); //FIXME - Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\font" + i + ".bin", font_data); + //Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\font" + i + ".bin", font_data); s.seek(-font_data_sizes[i], SeekMode.CUR); IggyFont font = new IggyFont(s); - fonts.put(i, font); + fonts.add(font); } - for (int i = 0; i < text_addresses.size(); i++) { + for (int i = 0; + i < text_addresses.size(); + i++) { s.seek(text_addresses.get(i), SeekMode.SET); - byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i)); - text_data_bytes.add(text_data); + texts.add(new IggyText(s)); + //byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i)); + //text_data_bytes.add(text_data); } - if (hdr.isImported()) { - s.seek(font_add_off.get(0), SeekMode.SET); - font_add_data = s.readBytes((int) (long) font_add_size.get(0)); - } + if (hdr.getImported_guid() + != 0) { + s.seek(font_additional_addresses.get(0), SeekMode.SET); + font_add_data = s.readBytes((int) (long) font_additional_size.get(0)); + }*/ s.seek(hdr.getFontEndAddress(), SeekMode.SET); //here is offset [4] - 856 ? - font_bin_info = new FontBinInfo[(int) hdr.font_count]; + font_bin_info = new IggyFontBinInfo[(int) hdr.font_count]; for (int i = 0; i < hdr.font_count; i++) { - font_bin_info[i] = new FontBinInfo(s); + font_bin_info[i] = new IggyFontBinInfo(s); } s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET); 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]; @@ -208,52 +288,72 @@ public class IggySwf implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + IggyIndexBuilder ib = s.getIndexing(); hdr.writeToDataStream(s); - s.getIndexing().writeIndexUI8SkipTwice8(184, 25); + ib.writeLengthSkipTwice(184, 0); 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(); + ib.write16bitArray(name.length() + 1); + ib.writeTwoPaddingBytes(); + ib.write64bitPointerArray(64); + for (int i = 0; i < font_data_addresses.size(); i++) { + long offset = font_data_addresses.get(i) - s.position(); s.writeUI64(offset); } - for (int i = 0; i < text_addresses.size(); i++) { - long offset = text_addresses.get(i) - s.position(); + for (int i = 0; i < text_data_addresses.size(); i++) { + long offset = text_data_addresses.get(i) - s.position(); s.writeUI64(offset); } - if (hdr.font_count > 0) { - while (s.position() < font_data_addresses[0]) { - s.writeUI64(1); - } - } - for (int i = 0; i < hdr.font_count; i++) { - s.seek(font_data_addresses[i], SeekMode.SET); - fonts.get(i).writeToDataStream(s); - } - for (int i = 0; i < text_data_bytes.size(); i++) { - s.seek(text_addresses.get(i), SeekMode.SET); - s.writeBytes(text_data_bytes.get(i)); + s.writeUI64(1); + if (additional_address != 0) { + long ofs_additional = additional_address - s.position(); + s.writeUI64(ofs_additional); } - if (hdr.isImported()) { - s.seek(font_add_off.get(0), SeekMode.SET); - s.writeBytes(font_add_data); + while (s.position() < font_data_addresses.get(0)) { + s.writeUI64(1); + } + for (int i = 0; i < fonts.size(); i++) { + s.seek(font_data_addresses.get(i), SeekMode.SET); + fonts.get(i).writeToDataStream(s); + } + for (int i = 0; i < texts.size(); i++) { + s.seek(text_data_addresses.get(i), SeekMode.SET); + texts.get(i).writeToDataStream(s); + } + + if (hdr.getImported_guid() != 0) { + for (int i = 0; i < add_fonts.size(); i++) { + s.seek(add_font_data_addresses.get(i), SeekMode.SET); + fonts.get(i).writeToDataStream(s); + } + for (int i = 0; i < add_texts.size(); i++) { + s.seek(add_text_data_addresses.get(i), SeekMode.SET); + texts.get(i).writeToDataStream(s); + } } s.seek(hdr.getFontEndAddress(), SeekMode.SET); + 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); } + s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET); sequence.writeToDataStream(s); + ib.writeConstLengthArray(IggyIndexBuilder.CONST_TYPE_INFO_SIZE, hdr.font_count); 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); type_info[i].writeFontInfo(type_info_name[i], s); } + s.pad8bytes(); + ib.pad8bytes(); s.seek(hdr.getDeclStringsAddress(), SeekMode.SET); decl_strings.writeToDataStream(s); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java index 1ddd359a9..0896d379b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java @@ -3,7 +3,9 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; 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.WriteDataStreamInterface; import java.io.IOException; @@ -13,6 +15,8 @@ import java.io.IOException; */ public class IggyText implements StructureInterface { + public static final int STRUCT_SIZE = 104; + public static final int ID = 0xFF06; @IggyFieldType(DataType.uint16_t) @@ -58,6 +62,8 @@ public class IggyText implements StructureInterface { 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? @@ -95,51 +101,42 @@ public class IggyText implements StructureInterface { par3 = s.readFloat(); par4 = s.readFloat(); - //flags enum_hex = s.readUI16(); - - int en = enum_hex; - - //guessing - it could be like DefineEditText?... - hasText = ((en >> 0) & 1) == 1; - wordWrap = ((en >> 1) & 1) == 1; - multiline = ((en >> 2) & 1) == 1; - password = ((en >> 3) & 1) == 1; - readOnly = ((en >> 4) & 1) == 1; - hasTextColor = ((en >> 5) & 1) == 1; - hasMaxLength = ((en >> 6) & 1) == 1; - hasFont = ((en >> 7) & 1) == 1; - hasFontClass = ((en >> 8) & 1) == 1; - autosize = ((en >> 9) & 1) == 1; - hasLayout = ((en >> 10) & 1) == 1; - noSelect = ((en >> 11) & 1) == 1; - border = ((en >> 12) & 1) == 1; - wasStatic = ((en >> 13) & 1) == 1; - html = ((en >> 14) & 1) == 1; - useOutlines = ((en >> 15) & 1) == 1; - - //if hasFont? fontIndex = s.readUI16(); //fontId - //if hasFontClass - readString? - //if hasFont || hasFontClass - readFontHeight? - //if hasTextColor....? zero = s.readUI32(); one = s.readUI64(); //01CB FF33 3333 some = s.readBytes(32); // [6] => 40, [24] => 8 - StringBuilder textBuilder = new StringBuilder(); - do { - char c = (char) s.readUI16(); - if (c == '\0') { - break; - } - textBuilder.append(c); - } while (true); - initialText = textBuilder.toString(); + 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 stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_IMPORTED_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() { 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 7acf46afb..18947a11d 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 @@ -102,12 +102,13 @@ public class IggyToSwfConvertor { fat.useNetwork = false; swf.addTag(fat); - Set fontIndices = file.getFontIds(swfIndex); + //Set fontIndices = file.getFontIds(swfIndex); + int fontCount = file.getFontCount(swfIndex); int currentCharId = 0; Map fontIndex2CharId = new HashMap<>(); - for (int fontIndex : fontIndices) { + for (int fontIndex = 0; fontIndex < fontCount; fontIndex++) { IggyFont iggyFont = file.getFont(swfIndex, fontIndex); DefineFont2Tag fontTag = new DefineFont2Tag(swf); currentCharId++; 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 f99fc86a4..3f9367f09 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 @@ -199,11 +199,22 @@ public abstract class AbstractDataStream implements DataStreamInterface { @Override public void pad8bytes() throws IOException { - int pad8 = 8 - (int) (position() % 8); - if (pad8 < 8) { - for (int i = 0; i < pad8; i++) { + int pad8 = (int) (position() % 8); + switch (pad8) { + case 1: + write(0); + case 2: + write(0); + case 3: + write(0); + case 4: + write(0); + case 5: + write(0); + case 6: + write(0); + case 7: 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 deleted file mode 100644 index 6e868625e..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/EmptyIndexing.java +++ /dev/null @@ -1,84 +0,0 @@ -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/IggyIndexBuilder.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java new file mode 100644 index 000000000..c8e077f0e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java @@ -0,0 +1,430 @@ +package com.jpexs.decompiler.flash.iggy.streams; + +import com.jpexs.decompiler.flash.iggy.IggyCharKerning; +import com.jpexs.decompiler.flash.iggy.IggyCharOffset; +import com.jpexs.decompiler.flash.iggy.IggyFontBinInfo; +import com.jpexs.decompiler.flash.iggy.IggyFontTypeInfo; +import com.jpexs.decompiler.flash.iggy.IggySequence; +import com.jpexs.decompiler.flash.iggy.IggyShape; +import com.jpexs.decompiler.flash.iggy.IggyShapeNode; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class IggyIndexBuilder { + + private static Logger LOGGER = Logger.getLogger(IggyIndexBuilder.class.getName()); + + /*static PrintWriter pw; + + static { + try { + pw = new PrintWriter("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\index.txt"); + } catch (FileNotFoundException ex) { + Logger.getLogger(IggyIndexParser.class.getName()).log(Level.SEVERE, null, ex); + } + LOGGER.setLevel(Level.ALL); + LOGGER.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + pw.println("" + record.getMessage()); + } + + @Override + public void flush() { + pw.flush(); + } + + @Override + public void close() throws SecurityException { + pw.close(); + } + }); + }*/ + private static final int CODE_FC_SKIP1 = 0xFC; + private static final int CODE_FD_OFS8_SKIP_TWICE8 = 0xFD; + private static final int CODE_FE_OFS8_POSITIVE = 0xFE; + private static final int CODE_FF_OFS32 = 0xFF; + + private List constTable = new ArrayList<>(); + private WriteDataStreamInterface indexStream; + + private static final int CONST_VAL_SHAPE_NODE_SIZE = IggyShapeNode.STRUCT_SIZE; + private static final int CONST_VAL_KERNING_RECORD_SIZE = IggyCharKerning.STRUCT_SIZE; + private static final int CONST_VAL_CHAR_OFFSET_SIZE = IggyCharOffset.STRUCT_SIZE; + private static final int CONST_VAL_BIN_INFO_SIZE = IggyFontBinInfo.STRUCT_SIZE; + private static final int CONST_VAL_TYPE_INFO_SIZE = IggyFontTypeInfo.STRUCT_SIZE; + private static final int CONST_VAL_SHAPE_SIZE = IggyShape.STRUCT_SIZE; + private static final int CONST_VAL_GENERAL_FONT_INFO_SIZE = 112; + private static final int CONST_VAL_GENERAL_FONT_INFO2_SIZE = 240; + private static final int CONST_VAL_IMPORTED_DATA_SIZE = 104; + private static final int CONST_VAL_SEQUENCE_SIZE = IggySequence.STRUCT_SIZE; + + public static final int[] DEFAULT_CONST_TABLE = new int[]{ + CONST_VAL_SHAPE_NODE_SIZE, + CONST_VAL_KERNING_RECORD_SIZE, + CONST_VAL_CHAR_OFFSET_SIZE, + CONST_VAL_BIN_INFO_SIZE, + CONST_VAL_TYPE_INFO_SIZE, + CONST_VAL_SHAPE_SIZE, + CONST_VAL_GENERAL_FONT_INFO_SIZE, + CONST_VAL_GENERAL_FONT_INFO2_SIZE, + CONST_VAL_IMPORTED_DATA_SIZE, + CONST_VAL_SEQUENCE_SIZE + }; + + public static final int CONST_SHAPE_NODE_SIZE = 0; + public static final int CONST_KERNING_RECORD_SIZE = 1; + public static final int CONST_CHAR_OFFSET_SIZE = 2; + public static final int CONST_BIN_INFO_SIZE = 3; + public static final int CONST_TYPE_INFO_SIZE = 4; + public static final int CONST_SHAPE_SIZE = 5; + public static final int CONST_GENERAL_FONT_INFO_SIZE = 6; + public static final int CONST_GENERAL_FONT_INFO2_SIZE = 7; + public static final int CONST_IMPORTED_DATA_SIZE = 8; + public static final int CONST_SEQUENCE_SIZE = 9; + + //If these skipped numbers matter, this is sample + final byte[] STATIC_HDR = new byte[]{(byte) 0x0A, (byte) 0x18, (byte) 0x07, (byte) 0x00, (byte) 0x05, (byte) 0x04, (byte) 0x05, (byte) 0x08, (byte) 0x05, (byte) 0x0C, (byte) 0x05, (byte) 0x12, (byte) 0x04, (byte) 0x14, (byte) 0x04, (byte) 0x16, + (byte) 0x04, (byte) 0x06, (byte) 0x03, (byte) 0x00, (byte) 0x04, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x04, (byte) 0x20, (byte) 0x03, (byte) 0x08, (byte) 0x04, (byte) 0x10, (byte) 0x08, (byte) 0x18, + (byte) 0x02, (byte) 0x60, (byte) 0x0D, (byte) 0x00, (byte) 0x02, (byte) 0x09, (byte) 0x03, (byte) 0x0C, (byte) 0x05, (byte) 0x10, (byte) 0x05, (byte) 0x14, (byte) 0x05, (byte) 0x18, (byte) 0x05, (byte) 0x1C, + (byte) 0x05, (byte) 0x20, (byte) 0x05, (byte) 0x24, (byte) 0x05, (byte) 0x28, (byte) 0x04, (byte) 0x30, (byte) 0x02, (byte) 0x38, (byte) 0x04, (byte) 0x3A, (byte) 0x04, (byte) 0x18, (byte) 0x02, (byte) 0x08, + (byte) 0x02, (byte) 0x10, (byte) 0x05, (byte) 0x40, (byte) 0x09, (byte) 0x00, (byte) 0x05, (byte) 0x04, (byte) 0x05, (byte) 0x08, (byte) 0x05, (byte) 0x0C, (byte) 0x05, (byte) 0x10, (byte) 0x02, (byte) 0x18, + (byte) 0x05, (byte) 0x20, (byte) 0x02, (byte) 0x28, (byte) 0x02, (byte) 0x30, (byte) 0x02, (byte) 0x70, (byte) 0x12, (byte) 0x01, (byte) 0x0C, (byte) 0x02, (byte) 0x04, (byte) 0x08, (byte) 0x05, (byte) 0x10, + (byte) 0x02, (byte) 0x20, (byte) 0x04, (byte) 0x22, (byte) 0x04, (byte) 0x24, (byte) 0x04, (byte) 0x26, (byte) 0x04, (byte) 0x2B, (byte) 0x03, (byte) 0x30, (byte) 0x02, (byte) 0x38, (byte) 0x02, (byte) 0x40, + (byte) 0x02, (byte) 0x48, (byte) 0x05, (byte) 0x4C, (byte) 0x05, (byte) 0x50, (byte) 0x05, (byte) 0x54, (byte) 0x05, (byte) 0x58, (byte) 0x05, (byte) 0x60, (byte) 0x02, (byte) 0xF0, (byte) 0x01, (byte) 0x10, + (byte) 0x02, (byte) 0x68, (byte) 0x12, (byte) 0x01, (byte) 0x0C, (byte) 0x02, (byte) 0x04, (byte) 0x08, (byte) 0x05, (byte) 0x10, (byte) 0x02, (byte) 0x20, (byte) 0x05, (byte) 0x24, (byte) 0x05, (byte) 0x28, + (byte) 0x05, (byte) 0x2C, (byte) 0x05, (byte) 0x30, (byte) 0x04, (byte) 0x32, (byte) 0x04, (byte) 0x38, (byte) 0x02, (byte) 0x44, (byte) 0x04, (byte) 0x46, (byte) 0x04, (byte) 0x48, (byte) 0x04, (byte) 0x4A, + (byte) 0x04, (byte) 0x4C, (byte) 0x04, (byte) 0x4E, (byte) 0x04, (byte) 0x60, (byte) 0x02, (byte) 0x10, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x08, (byte) 0x05}; + + private long position = 0; + + public IggyIndexBuilder() throws IOException { + indexStream = new TemporaryDataStream(); + for (int i = 0; i < DEFAULT_CONST_TABLE.length; i++) { + constTable.add(DEFAULT_CONST_TABLE[i]); + } + } + + private byte[] getIndexTableBytes() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write(constTable.size()); + for (int i = 0; i < constTable.size(); i++) { + baos.write(constTable.get(i)); + baos.write(0); + } + 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(); + } + + public long writeConstLength(int constIndex) { + return writeIndex(constIndex, false, 0, 0); + } + + private long writeConstLengthArrayUpTo64(int constIndex, int cntUpTo64) { + if (cntUpTo64 == 1) { + return writeIndex(constIndex, false, 0, 0); + } + return writeIndex(0x80 + cntUpTo64 - 1, false, constIndex, 0); + } + + /*private int indexOfConst(int val) { + int index = constTable.indexOf(val); + if (index > -1) { + return index; + } + constTable.add(val); + return constTable.size() - 1; + }*/ + public long writeConstLengthArray(int constIndex, long cnt) { + long ret = 0; + long rem = cnt; + while (true) { + if (rem <= 64) { + ret += writeConstLengthArrayUpTo64(constIndex, (int) rem); + break; + } else { + rem -= 64; + ret += writeConstLengthArrayUpTo64(constIndex, 64); + + } + } + return ret; + + } + + public long pad8bytes() { + int pad8 = (int) (position % 8); + switch (pad8) { + case 2: + writePaddingBytes(2); //+6 + break; + case 4: + writePaddingBytes(1); //+4 + break; + case 6: + writePaddingBytes(0); // +2 + break; + + } + return 0; + } + + public long writeTwoPaddingBytes() { + return writePaddingBytes(0); + } + + public long writePadding16bit() { + return writePaddingBytes(0); + } + + public long writePadding32bit() { + return writePaddingBytes(1); + } + + public long writePadding64bit() { + return writePaddingBytes(2); + } + + public long writePaddingBytes(int twoPlusHowManyTwoBytes) { + return writeIndex(0xC0 + twoPlusHowManyTwoBytes, false, 0, 0); + } + + public long writePointerArray(boolean is64, long cnt) { + return writeIndex(0xD0 + 0x2, is64, cnt - 1, 0); + } + + public long write64bitPointerArray(long cnt) { + return writeIndex(0xD0 + 0x2, true, cnt - 1, 0); + } + + public long write32bitPointerArray(long cnt) { + return writeIndex(0xD0 + 0x2, false, cnt - 1, 0); + } + + public long write16bitArray(long cnt) { + return writeIndex(0xD0 + 0x4, false, cnt - 1, 0); + } + + public long write32bitArray(long cnt) { + return writeIndex(0xD0 + 0x5, false, cnt - 1, 0); + } + + public long write64bitArray(long cnt) { + return writeIndex(0xD0 + 0x6, false, cnt - 1, 0); + } + + public long skipOneInIndex() { + return writeIndex(CODE_FC_SKIP1, false, 0, 0); + } + + public long writeLengthSkipTwice(int lenUI8, int skipTwice) { + return writeIndex(CODE_FD_OFS8_SKIP_TWICE8, false, lenUI8, skipTwice); + } + + public long writeLengthBytePositive(int valUI8) { + return writeIndex(CODE_FE_OFS8_POSITIVE, false, valUI8, 0); + } + + public long writeLengthUI32(long offset) { + return writeIndex(CODE_FF_OFS32, false, offset, 0); + } + + private long writeIndex(int code, boolean is64, long val, long skipNum) { + try { + LOGGER.finest(String.format("index offset: %d, %04X", STATIC_HDR.length + indexStream.position(), STATIC_HDR.length + indexStream.position())); + LOGGER.finer(String.format("Code = 0x%02X", code)); + 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 >= constTable.size()) { + LOGGER.severe(String.format("< 0x80: index is greater than index_table_size. %x > %x", code, constTable.size())); + return 0; + } + + LOGGER.finest(String.format("LENGTH = indexTable[%d] = %d", code, constTable.get(code))); + long ret = constTable.get(code); + position += ret; + return ret; + } 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 >= constTable.size()) { + LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, constTable.size())); + return 0; + } + + int n = code - 0x7F; + LOGGER.finest(String.format("index = %d, n = code - 0x7F = %d", index, n)); + LOGGER.finest(String.format("LENGTH = indexTable[index] * n = indexTable[%d] * %d = %d", index, n, constTable.get(index) * n)); + long ret = constTable.get(index) * n; + position += ret; + return ret; + } else if (code < 0xD0) // 0xC0-0xCF + { + LOGGER.finest("0xC0-CF: code*2-0x17E"); + long ret = ((code * 2) - 0x17E); + position += ret; + return ret; + } 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)); + position += 8 * n; + return 8 * n; // Ptr type + } else if (i <= 4) { + LOGGER.finest(String.format("offset += %d", 2 * n)); + position += 2 * n; + return 2 * n; + } else if (i == 5) { + LOGGER.finest(String.format("offset += %d", 4 * n)); + position += 4 * n; + return 4 * n; + } else if (i == 6) { + LOGGER.finest(String.format("offset += %d", 8 * n)); + position += 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)); + position += 4 * n; + return 4 * n; // Ptr type; + case 4: + LOGGER.finest(String.format("offset += %d", 2 * n)); + position += 2 * n; + return 2 * n; + case 5: + LOGGER.finest(String.format("offset += %d", 4 * n)); + position += 4 * n; + return 4 * n; // 32 bits type + case 6: + LOGGER.finest(String.format("offset += %d", 8 * n)); + position += 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; + position += 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; + position += n; + 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)); + position += 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/IggyIndexParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java similarity index 68% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java index b8277a0a1..0de06a2c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyIndexParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java @@ -1,10 +1,8 @@ -package com.jpexs.decompiler.flash.iggy; +package com.jpexs.decompiler.flash.iggy.streams; -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.FileNotFoundException; import java.io.IOException; +import java.io.PrintWriter; import java.util.List; import java.util.logging.ConsoleHandler; import java.util.logging.Handler; @@ -14,30 +12,40 @@ import java.util.logging.Logger; /** * - * @author Jindra + * @author JPEXS */ public class IggyIndexParser { private static Logger LOGGER = Logger.getLogger(IggyIndexParser.class.getName()); + /* + static PrintWriter pw; + static { + try { + pw = new PrintWriter("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\index.txt"); + } catch (FileNotFoundException ex) { + Logger.getLogger(IggyIndexParser.class.getName()).log(Level.SEVERE, null, ex); + } LOGGER.setLevel(Level.ALL); LOGGER.addHandler(new Handler() { @Override public void publish(LogRecord record) { - System.out.println("" + record.getMessage()); + pw.println("" + record.getMessage()); } @Override public void flush() { + pw.flush(); } @Override public void close() throws SecurityException { + pw.close(); } }); } - + */ /** * Parser for index data. It creates table of indices and table of offsets * @@ -51,7 +59,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", offset)); + LOGGER.fine(String.format("index_table_entry: %d", offset)); indexTable[i] = offset; indexTableEntry.add(offset); int num = indexStream.readUI8(); @@ -61,8 +69,12 @@ public class IggyIndexParser { long offset = 0; int code; + String tabs = "\t\t\t\t"; + + LOGGER.finer(String.format("-- OFFSET: 0" + tabs)); + while ((code = indexStream.readUI8()) > -1) { - LOGGER.finer(String.format("Code = %x", code)); + LOGGER.finer(String.format("Code = 0x%02X", code)); if (code < 0x80) // 0-0x7F { @@ -74,7 +86,7 @@ public class IggyIndexParser { } offset += indexTable[code]; - LOGGER.finest(String.format("ofset += %d", indexTable[code])); + LOGGER.finest(String.format("LENGTH = indexTable[%d] = %d", code, indexTable[code])); } else if (code < 0xC0) // 0x80-BF { @@ -92,11 +104,14 @@ public class IggyIndexParser { } int n = code - 0x7F; + LOGGER.finest(String.format("index = %d, n = code - 0x7F = %d", index, n)); + LOGGER.finest(String.format("LENGTH = indexTable[index] * n = indexTable[%d] * %d = %d", index, n, indexTable[index] * n)); offset += indexTable[index] * n; } else if (code < 0xD0) // 0xC0-0xCF { LOGGER.finest("0xC0-CF: code*2-0x17E"); offset += ((code * 2) - 0x17E); + LOGGER.finest(String.format("LENGTH = (code * 2) - 0x17E = (0x%02X * 2) - 0x17E = %d", code, ((code * 2) - 0x17E))); } else if (code < 0xE0) // 0xD0-0xDF { LOGGER.finest("0xD0-0xDF: platform based"); @@ -119,16 +134,16 @@ public class IggyIndexParser { if (is64) { if (i <= 2) { offset += 8 * n; // Ptr type - LOGGER.finest(String.format("offset += %d", 8 * n)); + LOGGER.finest(String.format("LENGTH = 8 * n = 8 * %d = %d", n, 8 * n)); } else if (i <= 4) { offset += 2 * n; - LOGGER.finest(String.format("offset += %d", 2 * n)); + LOGGER.finest(String.format("LENGTH = 2 * n = 2 * %d = %d", n, 2 * n)); } else if (i == 5) { offset += 4 * n; - LOGGER.finest(String.format("offset += %d", 4 * n)); + LOGGER.finest(String.format("LENGTH = 4 * n = 4 * %d = %d", n, 4 * n)); } else if (i == 6) { offset += 8 * n; // 64 bits type - LOGGER.finest(String.format("offset += %d", 8 * n)); + LOGGER.finest(String.format("LENGTH = 8 * n = 8 * %d = %d", n, 8 * n)); } else { LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)", i, code)); } @@ -136,26 +151,26 @@ public class IggyIndexParser { switch (i) { case 2: offset += 4 * n; // Ptr type - LOGGER.finest(String.format("offset += %d", 4 * n)); + LOGGER.finest(String.format("LENGTH = 4 * n = 4 * %d = %d", n, 4 * n)); break; case 4: offset += 2 * n; - LOGGER.finest(String.format("offset += %d", 2 * n)); + LOGGER.finest(String.format("LENGTH = 2 * n = 2 * %d = %d", n, 2 * n)); break; case 5: offset += 4 * n; // 32 bits type - LOGGER.finest(String.format("offset += %d", 4 * n)); + LOGGER.finest(String.format("LENGTH = 4 * n = 4 * %d = %d", n, 4 * n)); break; case 6: offset += 8 * n; - LOGGER.finest(String.format("offset += %d", 8 * n)); + LOGGER.finest(String.format("LENGTH = 8 * n = 8 * %d = %d", n, 8 * n)); break; default: LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)", i, code)); } } } else if (code == 0xFC) { - LOGGER.finest(String.format("0xFC: skip 1 ")); + 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 ")); @@ -165,16 +180,18 @@ public class IggyIndexParser { LOGGER.severe(String.format("0xFD: Cannot read n.")); return; } + LOGGER.finest(String.format("n = %d", n)); if ((m = indexStream.readUI8()) < 0) { LOGGER.severe(String.format("0xFD: Cannot read m.")); return; } + LOGGER.finest(String.format("m = %d", m)); offset += n; - LOGGER.finest(String.format("offset += %d", n)); + LOGGER.finest(String.format("LENGTH = n = %d", n)); indexStream.seek(m * 2, SeekMode.CUR); - LOGGER.finest(String.format("skip %d", m * 2)); + LOGGER.finest(String.format("SKIP m * 2 = skip %d * 2 = %d", m, m * 2)); } else if (code == 0xFE) { LOGGER.finest(String.format("0xFD: 0..255 + 1 ")); int n8; @@ -184,10 +201,11 @@ public class IggyIndexParser { LOGGER.severe(String.format("0xFE: Cannot read n.")); return; } + LOGGER.finest(String.format("n8 = %d", n8)); n = n8 + 1; offset += n; - LOGGER.finest(String.format("offset += %d", n)); + LOGGER.finest(String.format("LENGTH = n8 + 1 = %d + 1 = %d", n8, n)); } else if (code == 0xFF) { LOGGER.finest(String.format("0xFF: 32bit ")); long n; @@ -198,12 +216,12 @@ public class IggyIndexParser { } offset += n; - LOGGER.finest(String.format("offset += %d", n)); + LOGGER.finest(String.format("LENGTH = n = %d", n)); } else { LOGGER.warning(String.format("Unrecognized code: %x", code)); } - LOGGER.finer(String.format("OFFSET: %d", offset)); + LOGGER.finer(String.format("-- OFFSET: %d" + tabs, offset)); offsets.add(offset); } 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 deleted file mode 100644 index 610ab8344..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStream.java +++ /dev/null @@ -1,272 +0,0 @@ -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 deleted file mode 100644 index 0e6d250f3..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IndexingDataStreamInterface.java +++ /dev/null @@ -1,38 +0,0 @@ -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 eb6a15a4c..4b0f613bd 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,24 +16,19 @@ public class RandomAccessFileDataStream extends AbstractDataStream { private File file; private RandomAccessFile raf; - private IndexingDataStreamInterface indexing; + private IggyIndexBuilder indexing; protected File getFile() { return file; } @Override - public void setIndexing(IndexingDataStreamInterface indexing) { + public void setIndexing(IggyIndexBuilder 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"); } @@ -116,22 +111,17 @@ public class RandomAccessFileDataStream extends AbstractDataStream { } @Override - public IndexingDataStreamInterface getIndexing() { + public IggyIndexBuilder 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/WriteDataStreamInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java index f22ace170..ba48899a4 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 @@ -46,7 +46,7 @@ public interface WriteDataStreamInterface extends AutoCloseable { @Override public void close(); - public void setIndexing(IndexingDataStreamInterface indexing); + public void setIndexing(IggyIndexBuilder indexing); - public IndexingDataStreamInterface getIndexing(); + public IggyIndexBuilder getIndexing(); } From 460aad9dfceb26703e31b33c5fc903779b2e2315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 4 Dec 2016 08:21:45 +0100 Subject: [PATCH 21/27] Inluding offset and type info in index. Exact byte match of result file reached. --- .../flash/iggy/IggyDeclStrings.java | 2 +- .../jpexs/decompiler/flash/iggy/IggyFile.java | 8 +- .../flash/iggy/IggyFlashHeader64.java | 3 + .../decompiler/flash/iggy/IggySequence.java | 2 +- .../jpexs/decompiler/flash/iggy/IggySwf.java | 1 - .../jpexs/decompiler/flash/iggy/IggyText.java | 2 +- .../flash/iggy/streams/IggyIndexBuilder.java | 148 ++++++++++-------- .../flash/iggy/streams/IggyIndexParser.java | 32 +++- 8 files changed, 120 insertions(+), 78 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java index 9d229b8a4..c9c21b2c8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java @@ -56,7 +56,7 @@ public class IggyDeclStrings implements StructureInterface { s.writeUI64(one); s.writeUI32(size); s.writeBytes(xxx); - ib.writeLengthSkipTwice(8 + 4 + 3, 0); + ib.writeLengthCustom(15, new int[]{0x00, 0x08}, new int[]{2, 5}); ib.writeLengthUI32(size); s.writeBytes(data); ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE); 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 f490db013..26e5db0ac 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 @@ -197,8 +197,6 @@ public class IggyFile implements StructureInterface { extractIggyFile(inFile, extractDirOrig); IggySwf iswf = iggyFile.getSwf(0); iggyFile.replaceSwf(0, iswf); - //IggyFont ifont = iswf.fonts.get(0); - //iggyFile.replaceFontTag(0, 0, ifont); outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); @@ -664,8 +662,7 @@ public class IggyFile implements StructureInterface { return false; } - IggyIndexParser.parseIndex(true, new TemporaryDataStream(replacementIndexData), new ArrayList<>(), new ArrayList<>()); - + //IggyIndexParser.parseIndex(true, new TemporaryDataStream(replacementIndexData), new ArrayList<>(), new ArrayList<>()); int swfIndex = 0; long offsetsChange = 0; for (int i = 0; i < subFileEntries.size(); i++) { @@ -704,6 +701,9 @@ public class IggyFile implements StructureInterface { if (entry.type == IggySubFileEntry.TYPE_FLASH) { iggySwfs.add(new IggySwf(new TemporaryDataStream(getEntryData(i)))); } + /*if (entry.type == IggySubFileEntry.TYPE_INDEX) { + IggyIndexParser.parseIndex(true, new TemporaryDataStream(getEntryData(i)), new ArrayList<>(), new ArrayList<>()); + }*/ } } 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 a2d35c3ee..fa433e1ab 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 @@ -278,6 +278,9 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { stream.writeUI64(flags); stream.writeUI32(font_count); stream.writeUI32(zero2); + + stream.getIndexing().writeLengthCustom(184, new int[]{0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x34, 0x38, 0x3C, 0x40, 0x44, 0x48, 0x4C, 0x50, 0x58, 0x70, 0x78, 0x80, 0x84, 0x88, 0x90, 0x98, 0xA0, 0xB0}, new int[]{2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, 2, 2, 2, 5}); + } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java index 026af5b43..0c635183a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java @@ -55,7 +55,7 @@ public class IggySequence implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { IggyIndexBuilder ib = s.getIndexing(); - ib.writeLengthSkipTwice(16, 0); + ib.writeLengthCustom(16, new int[]{0x00}, new int[]{2}); for (int i = 0; i < onepadd.length; i++) { s.writeUI64(onepadd[i]); } 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 8e63e8be9..16ab15e0a 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 @@ -290,7 +290,6 @@ public class IggySwf implements StructureInterface { public void writeToDataStream(WriteDataStreamInterface s) throws IOException { IggyIndexBuilder ib = s.getIndexing(); hdr.writeToDataStream(s); - ib.writeLengthSkipTwice(184, 0); s.writeWChar(name); s.pad8bytes(); s.writeUI64(1); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java index 0896d379b..fdce6f318 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java @@ -115,7 +115,7 @@ public class IggyText implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { - s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_IMPORTED_DATA_SIZE); + s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_TEXT_DATA_SIZE); s.writeUI16(type); s.writeUI16(textIndex); s.writeBytes(zeroone); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java index c8e077f0e..7b4322c4a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java @@ -60,6 +60,8 @@ public class IggyIndexBuilder { private static final int CODE_FF_OFS32 = 0xFF; private List constTable = new ArrayList<>(); + private Map> constTableOffsets = new HashMap<>(); + private Map> constTableTypes = new HashMap<>(); private WriteDataStreamInterface indexStream; private static final int CONST_VAL_SHAPE_NODE_SIZE = IggyShapeNode.STRUCT_SIZE; @@ -70,22 +72,9 @@ public class IggyIndexBuilder { private static final int CONST_VAL_SHAPE_SIZE = IggyShape.STRUCT_SIZE; private static final int CONST_VAL_GENERAL_FONT_INFO_SIZE = 112; private static final int CONST_VAL_GENERAL_FONT_INFO2_SIZE = 240; - private static final int CONST_VAL_IMPORTED_DATA_SIZE = 104; + private static final int CONST_VAL_TEXT_DATA_SIZE = 104; private static final int CONST_VAL_SEQUENCE_SIZE = IggySequence.STRUCT_SIZE; - public static final int[] DEFAULT_CONST_TABLE = new int[]{ - CONST_VAL_SHAPE_NODE_SIZE, - CONST_VAL_KERNING_RECORD_SIZE, - CONST_VAL_CHAR_OFFSET_SIZE, - CONST_VAL_BIN_INFO_SIZE, - CONST_VAL_TYPE_INFO_SIZE, - CONST_VAL_SHAPE_SIZE, - CONST_VAL_GENERAL_FONT_INFO_SIZE, - CONST_VAL_GENERAL_FONT_INFO2_SIZE, - CONST_VAL_IMPORTED_DATA_SIZE, - CONST_VAL_SEQUENCE_SIZE - }; - public static final int CONST_SHAPE_NODE_SIZE = 0; public static final int CONST_KERNING_RECORD_SIZE = 1; public static final int CONST_CHAR_OFFSET_SIZE = 2; @@ -94,11 +83,11 @@ public class IggyIndexBuilder { public static final int CONST_SHAPE_SIZE = 5; public static final int CONST_GENERAL_FONT_INFO_SIZE = 6; public static final int CONST_GENERAL_FONT_INFO2_SIZE = 7; - public static final int CONST_IMPORTED_DATA_SIZE = 8; + public static final int CONST_TEXT_DATA_SIZE = 8; public static final int CONST_SEQUENCE_SIZE = 9; - //If these skipped numbers matter, this is sample - final byte[] STATIC_HDR = new byte[]{(byte) 0x0A, (byte) 0x18, (byte) 0x07, (byte) 0x00, (byte) 0x05, (byte) 0x04, (byte) 0x05, (byte) 0x08, (byte) 0x05, (byte) 0x0C, (byte) 0x05, (byte) 0x12, (byte) 0x04, (byte) 0x14, (byte) 0x04, (byte) 0x16, + /*final byte[] STATIC_HDR = new byte[]{ + (byte) 0x0A, (byte) 0x18, (byte) 0x07, (byte) 0x00, (byte) 0x05, (byte) 0x04, (byte) 0x05, (byte) 0x08, (byte) 0x05, (byte) 0x0C, (byte) 0x05, (byte) 0x12, (byte) 0x04, (byte) 0x14, (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x06, (byte) 0x03, (byte) 0x00, (byte) 0x04, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x04, (byte) 0x20, (byte) 0x03, (byte) 0x08, (byte) 0x04, (byte) 0x10, (byte) 0x08, (byte) 0x18, (byte) 0x02, (byte) 0x60, (byte) 0x0D, (byte) 0x00, (byte) 0x02, (byte) 0x09, (byte) 0x03, (byte) 0x0C, (byte) 0x05, (byte) 0x10, (byte) 0x05, (byte) 0x14, (byte) 0x05, (byte) 0x18, (byte) 0x05, (byte) 0x1C, (byte) 0x05, (byte) 0x20, (byte) 0x05, (byte) 0x24, (byte) 0x05, (byte) 0x28, (byte) 0x04, (byte) 0x30, (byte) 0x02, (byte) 0x38, (byte) 0x04, (byte) 0x3A, (byte) 0x04, (byte) 0x18, (byte) 0x02, (byte) 0x08, @@ -109,14 +98,40 @@ public class IggyIndexBuilder { (byte) 0x02, (byte) 0x68, (byte) 0x12, (byte) 0x01, (byte) 0x0C, (byte) 0x02, (byte) 0x04, (byte) 0x08, (byte) 0x05, (byte) 0x10, (byte) 0x02, (byte) 0x20, (byte) 0x05, (byte) 0x24, (byte) 0x05, (byte) 0x28, (byte) 0x05, (byte) 0x2C, (byte) 0x05, (byte) 0x30, (byte) 0x04, (byte) 0x32, (byte) 0x04, (byte) 0x38, (byte) 0x02, (byte) 0x44, (byte) 0x04, (byte) 0x46, (byte) 0x04, (byte) 0x48, (byte) 0x04, (byte) 0x4A, (byte) 0x04, (byte) 0x4C, (byte) 0x04, (byte) 0x4E, (byte) 0x04, (byte) 0x60, (byte) 0x02, (byte) 0x10, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x08, (byte) 0x05}; - + */ private long position = 0; public IggyIndexBuilder() throws IOException { indexStream = new TemporaryDataStream(); - for (int i = 0; i < DEFAULT_CONST_TABLE.length; i++) { - constTable.add(DEFAULT_CONST_TABLE[i]); + + addConst(CONST_VAL_SHAPE_NODE_SIZE, new int[]{0, 4, 8, 0xC, 0x12, 0x14, 0x16}, new int[]{5, 5, 5, 5, 4, 4, 4}); + addConst(CONST_VAL_KERNING_RECORD_SIZE, new int[]{0, 2, 4}, new int[]{4, 4, 4}); + addConst(CONST_VAL_CHAR_OFFSET_SIZE, new int[]{8, 0x10, 0x18}, new int[]{4, 8, 2}); + addConst(CONST_VAL_BIN_INFO_SIZE, new int[]{0, 9, 0xC, 0x10, 0x14, 0x18, 0x1C, 0x20, 0x24, 0x28, 0x30, 0x38, 0x3A}, new int[]{2, 3, 5, 5, 5, 5, 5, 5, 5, 4, 2, 4, 4}); + addConst(CONST_VAL_TYPE_INFO_SIZE, new int[]{8, 0x10}, new int[]{2, 5}); + addConst(CONST_VAL_SHAPE_SIZE, new int[]{0, 4, 8, 0xC, 0x10, 0x18, 0x20, 0x28, 0x30}, new int[]{5, 5, 5, 5, 2, 5, 2, 2, 2}); + addConst(CONST_VAL_GENERAL_FONT_INFO_SIZE, new int[]{0x1, 0x02, 0x08, 0x10, 0x20, 0x22, 0x24, 0x26, 0x2B, 0x30, 0x38, 0x40, 0x48, 0x4C, 0x50, 0x54, 0x58, 0x60}, new int[]{0xC, 4, 5, 2, 4, 4, 4, 4, 3, 2, 2, 2, 5, 5, 5, 5, 5, 2}); + addConst(CONST_VAL_GENERAL_FONT_INFO2_SIZE, new int[]{0x10}, new int[]{2}); + addConst(CONST_VAL_TEXT_DATA_SIZE, new int[]{0x01, 0x02, 0x08, 0x10, 0x20, 0x24, 0x28, 0x2C, 0x30, 0x32, 0x38, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x60}, new int[]{0x0C, 4, 5, 2, 5, 5, 5, 5, 4, 4, 2, 4, 4, 4, 4, 4, 4, 2}); + addConst(CONST_VAL_SEQUENCE_SIZE, new int[]{0, 8}, new int[]{2, 5}); + } + + private void addConst(int totalLength, int[] localOffsets, int[] types) { + if (localOffsets.length != types.length) { + throw new RuntimeException("Size of localOffsets does not match size of types on adding consts with total length " + totalLength); } + constTable.add(totalLength); + int newIndex = constTable.size() - 1; + List localOffsetsList = new ArrayList<>(); + for (int t : localOffsets) { + localOffsetsList.add(t); + } + List typesList = new ArrayList<>(); + for (int t : types) { + typesList.add(t); + } + constTableOffsets.put(newIndex, localOffsetsList); + constTableTypes.put(newIndex, typesList); } private byte[] getIndexTableBytes() { @@ -124,7 +139,11 @@ public class IggyIndexBuilder { baos.write(constTable.size()); for (int i = 0; i < constTable.size(); i++) { baos.write(constTable.get(i)); - baos.write(0); + baos.write(constTableOffsets.get(i).size()); + for (int j = 0; j < constTableOffsets.get(i).size(); j++) { + baos.write(constTableOffsets.get(i).get(j)); + baos.write(constTableTypes.get(i).get(j)); + } } return baos.toByteArray(); } @@ -141,14 +160,7 @@ public class IggyIndexBuilder { } public long writeConstLength(int constIndex) { - return writeIndex(constIndex, false, 0, 0); - } - - private long writeConstLengthArrayUpTo64(int constIndex, int cntUpTo64) { - if (cntUpTo64 == 1) { - return writeIndex(constIndex, false, 0, 0); - } - return writeIndex(0x80 + cntUpTo64 - 1, false, constIndex, 0); + return writeIndex(constIndex, false, 0); } /*private int indexOfConst(int val) { @@ -163,17 +175,18 @@ public class IggyIndexBuilder { long ret = 0; long rem = cnt; while (true) { + if (rem == 1) { + return writeIndex(constIndex, false, 0); + } if (rem <= 64) { - ret += writeConstLengthArrayUpTo64(constIndex, (int) rem); + ret += writeIndex(0x80 + (int) rem - 1, false, constIndex); break; } else { rem -= 64; - ret += writeConstLengthArrayUpTo64(constIndex, 64); - + ret += writeIndex(0x80 + 64 - 1, false, constIndex); } } return ret; - } public long pad8bytes() { @@ -210,52 +223,69 @@ public class IggyIndexBuilder { } public long writePaddingBytes(int twoPlusHowManyTwoBytes) { - return writeIndex(0xC0 + twoPlusHowManyTwoBytes, false, 0, 0); + return writeIndex(0xC0 + twoPlusHowManyTwoBytes, false, 0); } public long writePointerArray(boolean is64, long cnt) { - return writeIndex(0xD0 + 0x2, is64, cnt - 1, 0); + return writeIndex(0xD0 + 0x2, is64, cnt - 1); } public long write64bitPointerArray(long cnt) { - return writeIndex(0xD0 + 0x2, true, cnt - 1, 0); + return writeIndex(0xD0 + 0x2, true, cnt - 1); } public long write32bitPointerArray(long cnt) { - return writeIndex(0xD0 + 0x2, false, cnt - 1, 0); + return writeIndex(0xD0 + 0x2, false, cnt - 1); } public long write16bitArray(long cnt) { - return writeIndex(0xD0 + 0x4, false, cnt - 1, 0); + return writeIndex(0xD0 + 0x4, false, cnt - 1); } public long write32bitArray(long cnt) { - return writeIndex(0xD0 + 0x5, false, cnt - 1, 0); + return writeIndex(0xD0 + 0x5, false, cnt - 1); } public long write64bitArray(long cnt) { - return writeIndex(0xD0 + 0x6, false, cnt - 1, 0); + return writeIndex(0xD0 + 0x6, false, cnt - 1); } public long skipOneInIndex() { - return writeIndex(CODE_FC_SKIP1, false, 0, 0); + return writeIndex(CODE_FC_SKIP1, false, 0); } - public long writeLengthSkipTwice(int lenUI8, int skipTwice) { - return writeIndex(CODE_FD_OFS8_SKIP_TWICE8, false, lenUI8, skipTwice); + public long writeLengthCustom(int totalLen, int localOffsets[], int platformTypes[]) { + return writeIndex(CODE_FD_OFS8_SKIP_TWICE8, false, totalLen, localOffsets, platformTypes); } public long writeLengthBytePositive(int valUI8) { - return writeIndex(CODE_FE_OFS8_POSITIVE, false, valUI8, 0); + return writeIndex(CODE_FE_OFS8_POSITIVE, false, valUI8); } public long writeLengthUI32(long offset) { - return writeIndex(CODE_FF_OFS32, false, offset, 0); + return writeIndex(CODE_FF_OFS32, false, offset); } - private long writeIndex(int code, boolean is64, long val, long skipNum) { + public static int platformNumSize(boolean is64, int i) { + if (i <= 2) { + return is64 ? 8 : 4; + } else if (i <= 4) { + return 2; + } else if (i == 5) { + return 4; + } else if (i == 6) { + return 8; + } + throw new RuntimeException("Uknown platform num"); + } + + private long writeIndex(int code, boolean is64, long val) { + return writeIndex(code, is64, val, null, null); + } + + private long writeIndex(int code, boolean is64, long val, int localOffsets[], int platformTypes[]) { try { - LOGGER.finest(String.format("index offset: %d, %04X", STATIC_HDR.length + indexStream.position(), STATIC_HDR.length + indexStream.position())); + //LOGGER.finest(String.format("index offset: %d, %04X", STATIC_HDR.length + indexStream.position(), STATIC_HDR.length + indexStream.position())); LOGGER.finer(String.format("Code = 0x%02X", code)); indexStream.writeUI8(code); if (code < 0x80) // 0-0x7F @@ -366,31 +396,25 @@ public class IggyIndexBuilder { } else if (code == CODE_FC_SKIP1) { LOGGER.finest(String.format("0xFC: skip 1 ")); //indexStream.seek(1, SeekMode.CUR); + indexStream.write(0); //?? 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; + n = (int) val; 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; - } + m = localOffsets.length; + indexStream.writeUI8(localOffsets.length); long offset = n; position += n; LOGGER.finest(String.format("offset += %d", n)); - long skip = m * 2; - LOGGER.finest(String.format("skip %d", m * 2)); - return offset + skip; + for (int i = 0; i < localOffsets.length; i++) { + indexStream.writeUI8(localOffsets[i]); + indexStream.writeUI8(platformTypes[i]); + } + return offset; } else if (code == CODE_FE_OFS8_POSITIVE) { LOGGER.finest(String.format("0xFD: 0..255 + 1 ")); int n8; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java index 0de06a2c7..4a6a13c9f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java @@ -18,12 +18,11 @@ public class IggyIndexParser { private static Logger LOGGER = Logger.getLogger(IggyIndexParser.class.getName()); - /* - static PrintWriter pw; + /*static PrintWriter pw; static { try { - pw = new PrintWriter("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\index.txt"); + pw = new PrintWriter("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\index2.txt"); } catch (FileNotFoundException ex) { Logger.getLogger(IggyIndexParser.class.getName()).log(Level.SEVERE, null, ex); } @@ -44,8 +43,7 @@ public class IggyIndexParser { pw.close(); } }); - } - */ + }*/ /** * Parser for index data. It creates table of indices and table of offsets * @@ -63,7 +61,11 @@ public class IggyIndexParser { indexTable[i] = offset; indexTableEntry.add(offset); int num = indexStream.readUI8(); - indexStream.seek(num * 2, SeekMode.CUR); + for (int j = 0; j < num; j++) { + int locOffset = indexStream.readUI8(); + int type = indexStream.readUI8(); + LOGGER.finer(String.format("- local offset: %d, type: %d", locOffset, type)); + } } long offset = 0; @@ -190,8 +192,22 @@ public class IggyIndexParser { offset += n; LOGGER.finest(String.format("LENGTH = n = %d", n)); - indexStream.seek(m * 2, SeekMode.CUR); - LOGGER.finest(String.format("SKIP m * 2 = skip %d * 2 = %d", m, m * 2)); + StringBuilder locOffStr = new StringBuilder(); + StringBuilder platStr = new StringBuilder(); + for (int i = 0; i < m; i++) { + int localOffset = indexStream.readUI8(); + int platformType = indexStream.readUI8(); + if (i > 0) { + locOffStr.append(", "); + platStr.append(", "); + } + locOffStr.append(String.format("0x%02X", localOffset)); + platStr.append(platformType); + LOGGER.finest(String.format("- localOffset 0x%02X, platformType %d", localOffset, platformType)); + } + LOGGER.finer(String.format("stream.writeLengthCustom(%s,new int[]{%s},new int[]{%s}", n, locOffStr, platStr)); + //indexStream.seek(m * 2, SeekMode.CUR); + //LOGGER.finest(String.format("SKIP m * 2 = skip %d * 2 = %d", m, m * 2)); } else if (code == 0xFE) { LOGGER.finest(String.format("0xFD: 0..255 + 1 ")); int n8; From 0d21e9b96a981bdf944f088f0f3a4bb1812db19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 4 Dec 2016 09:31:52 +0100 Subject: [PATCH 22/27] grouping index, more universal saving entries --- .../jpexs/decompiler/flash/iggy/IggyFile.java | 58 +++++++++++++------ .../decompiler/flash/iggy/IggyHeader.java | 2 + .../flash/iggy/IggySubFileEntry.java | 2 + .../jpexs/decompiler/flash/iggy/IggySwf.java | 6 -- .../flash/iggy/streams/IggyIndexParser.java | 5 +- 5 files changed, 47 insertions(+), 26 deletions(-) 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 26e5db0ac..3f6c06395 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 @@ -178,6 +178,11 @@ public class IggyFile implements StructureInterface { } public static void main(String[] args) throws IOException { + /* + String indexFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\index4_type0.bin"; + IggyIndexParser.parseIndex(true, new TemporaryDataStream(Helper.readFile(indexFileName)), new ArrayList<>(), new ArrayList<>()); + + System.exit(0);*/ String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy"; String outFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font2.iggy"; @@ -643,7 +648,25 @@ public class IggyFile implements StructureInterface { return iggySwfs.get(swfIndex).getHdr().getFrameRate(); } - //WIP + /** + * 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 replaceSwf(int targetSwfIndex, IggySwf iggySwf) throws IOException { if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) { @@ -668,30 +691,22 @@ public class IggyFile implements StructureInterface { for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); entry.offset += offsetsChange; - if (entry.type == IggySubFileEntry.TYPE_INDEX) { - if (swfIndex == targetSwfIndex) { - long oldSize = entry.size; - long newSize = replacementIndexData.length; - offsetsChange = offsetsChange + (newSize - oldSize); - entry.size = newSize; - entry.size2 = newSize; - subFileEntriesData.set(i, replacementIndexData); - } - swfIndex++; - } if (entry.type == IggySubFileEntry.TYPE_FLASH) { if (swfIndex == targetSwfIndex) { long oldSize = entry.size; long newSize = replacementData.length; - offsetsChange = offsetsChange + (newSize - oldSize); entry.size = newSize; entry.size2 = newSize; - //entries after this one will have modified offsets + 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; } @@ -724,15 +739,22 @@ public class IggyFile implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { header.writeToDataStream(stream); - for (IggySubFileEntry entry : subFileEntries) { - entry.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.seek(entry.offset, SeekMode.SET); stream.writeBytes(entryData); } + } } 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 f6dff51f6..e01a160f0 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 @@ -17,6 +17,8 @@ import java.io.IOException; */ public class IggyHeader implements StructureInterface { + public static int STRUCT_SIZE = 32; + public static long MAGIC = 0xED0A6749; //Must be 0xED0A6749 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 c87b3598b..05975e37c 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 @@ -17,6 +17,8 @@ import java.util.List; */ public class IggySubFileEntry implements StructureInterface { + public static final int STRUCTURE_SIZE = 16; + public static final int TYPE_INDEX = 0; public static final int TYPE_FLASH = 1; 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 16ab15e0a..6b95d8b1c 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 @@ -34,8 +34,6 @@ public class IggySwf implements StructureInterface { private IggyFlashHeader64 hdr; - private byte[] allFontBytes; - public IggySwf(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -92,10 +90,6 @@ public class IggySwf implements StructureInterface { public void readFromDataStream(ReadDataStreamInterface s) throws IOException { this.hdr = new IggyFlashHeader64(s); //Save all font bytes to buffer for later easy modification - long curPos = s.position(); - long maxPos = hdr.getFontEndAddress(); - allFontBytes = s.readBytes((int) (maxPos - curPos)); - s.seek(curPos, SeekMode.SET); //here is offset[0] - 184 name = s.readWChar(); //here is offset[1] - 230 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java index 4a6a13c9f..87e7f02c8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexParser.java @@ -22,7 +22,7 @@ public class IggyIndexParser { static { try { - pw = new PrintWriter("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\index2.txt"); + pw = new PrintWriter("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\index2b.txt"); } catch (FileNotFoundException ex) { Logger.getLogger(IggyIndexParser.class.getName()).log(Level.SEVERE, null, ex); } @@ -43,7 +43,8 @@ public class IggyIndexParser { pw.close(); } }); - }*/ + } + */ /** * Parser for index data. It creates table of indices and table of offsets * From b889c5cb37773d629f45c7a1830f110b9f82cc9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 4 Dec 2016 10:14:31 +0100 Subject: [PATCH 23/27] no magic offsets in IggyFont --- .../jpexs/decompiler/flash/iggy/IggyFont.java | 90 +++++++++---------- .../iggy/streams/AbstractDataStream.java | 9 ++ .../streams/WriteDataStreamInterface.java | 2 + 3 files changed, 54 insertions(+), 47 deletions(-) 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 a75ef98e9..f2a9136e6 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 @@ -36,26 +36,26 @@ public class IggyFont extends IggyTag { int leading; @IggyFieldType(DataType.uint64_t) long flags; - @IggyFieldType(DataType.uint64_t) - long start_of_char_struct; - @IggyFieldType(DataType.uint64_t) - long start_of_char_index; - @IggyFieldType(DataType.uint64_t) - long start_of_scale; + //@IggyFieldType(DataType.uint64_t) + //long start_of_char_struct; + //@IggyFieldType(DataType.uint64_t) + //long start_of_char_index; + //@IggyFieldType(DataType.uint64_t) + //long start_of_scale; @IggyFieldType(DataType.uint32_t) long kern_count; @IggyArrayFieldType(value = DataType.float_t, count = 5) float[] unk_float; - @IggyFieldType(DataType.uint64_t) - long start_of_kern; + //@IggyFieldType(DataType.uint64_t) + //long start_of_kern; @IggyFieldType(DataType.uint64_t) long zero_padd; @IggyFieldType(DataType.uint64_t) long what_2; @IggyFieldType(DataType.uint64_t) long zero_padd_2; - @IggyFieldType(DataType.uint64_t) - long start_of_name; + //@IggyFieldType(DataType.uint64_t) + //long start_of_name; @IggyFieldType(DataType.uint64_t) long one_padd; @IggyFieldType(DataType.uint16_t) @@ -110,25 +110,20 @@ public class IggyFont extends IggyTag { byte[] padTo4byteBoundary; - public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { + public IggyFont(int type, int fontId, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long kern_count, float[] unk_float, long zero_padd, long what_2, long zero_padd_2, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48a, byte[] zeroes48b, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List glyphs, IggyCharIndices codePoints, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { this.type = type; - this.fontId = order_in_iggy_file; + this.fontId = fontId; this.zeroone = zeroone; this.char_count2 = char_count2; this.ascent = ascent; this.descent = descent; this.leading = leading; this.flags = flags; - this.start_of_char_struct = start_of_char_struct; - this.start_of_char_index = start_of_char_index; - this.start_of_scale = start_of_scale; this.kern_count = kern_count; this.unk_float = unk_float; - this.start_of_kern = start_of_kern; this.zero_padd = zero_padd; this.what_2 = what_2; this.zero_padd_2 = zero_padd_2; - this.start_of_name = start_of_name; this.one_padd = one_padd; this.xscale = xscale; this.yscale = yscale; @@ -138,7 +133,8 @@ public class IggyFont extends IggyTag { this.char_count = char_count; this.zero_padd_4 = zero_padd_4; this.what_3 = what_3; - this.zeroes48a = zeroes48; + this.zeroes48a = zeroes48a; + this.zeroes48b = zeroes48b; this.sss1 = sss1; this.one_padd2 = one_padd2; this.sss2 = sss2; @@ -149,8 +145,8 @@ public class IggyFont extends IggyTag { this.one_padd5 = one_padd5; this.name = name; this.charOffsets = charOffsets; - this.glyphs = chars; - this.codePoints = charIndices; + this.glyphs = glyphs; + this.codePoints = codePoints; this.charScales = charScales; this.charKernings = charKernings; this.padTo4byteBoundary = padTo4byteBoundary; @@ -194,7 +190,6 @@ public class IggyFont extends IggyTag { @Override public void readFromDataStream(ReadDataStreamInterface s) throws IOException { - long basePos = s.position(); type = s.readUI16(); fontId = s.readUI16(); zeroone = s.readBytes(28); @@ -203,11 +198,11 @@ public class IggyFont extends IggyTag { descent = s.readUI16(); leading = s.readUI16(); flags = s.readUI64(); - start_of_char_struct = s.readUI64(); + long start_of_char_struct = s.readUI64(); long abs_start_of_char_struct = makeAbsOffset(s, start_of_char_struct); - start_of_char_index = s.readUI64(); + long start_of_char_index = s.readUI64(); long abs_start_of_char_index = makeAbsOffset(s, start_of_char_index); - start_of_scale = s.readUI64(); + long start_of_scale = s.readUI64(); long abs_start_of_scale = makeAbsOffset(s, start_of_scale); kern_count = s.readUI32(); @@ -215,14 +210,14 @@ public class IggyFont extends IggyTag { for (int i = 0; i < unk_float.length; i++) { unk_float[i] = s.readFloat(); } - start_of_kern = s.readUI64(); + long start_of_kern = s.readUI64(); long abs_start_of_kern = makeAbsOffset(s, start_of_kern); zero_padd = s.readUI64(); //-------------------------------------- what_2 = s.readUI64(); zero_padd_2 = s.readUI64(); - start_of_name = s.readUI64(); + long start_of_name = s.readUI64(); long abs_start_of_name = makeAbsOffset(s, start_of_name); one_padd = s.readUI64(); xscale = s.readUI16(); @@ -299,6 +294,7 @@ public class IggyFont extends IggyTag { @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + final int FILL_LATER_IF_AVAILABLE = 1; IggyIndexBuilder ib = s.getIndexing(); ib.writeConstLength(IggyIndexBuilder.CONST_GENERAL_FONT_INFO_SIZE); s.writeUI16(type); @@ -309,24 +305,24 @@ public class IggyFont extends IggyTag { s.writeUI16(descent); s.writeUI16(leading); s.writeUI64(flags); - s.writeUI64(start_of_char_struct); - long abs_start_of_char_struct = makeAbsOffset(s, start_of_char_struct); - s.writeUI64(start_of_char_index); - long abs_start_of_char_index = makeAbsOffset(s, start_of_char_index); - s.writeUI64(start_of_scale); - long abs_start_of_scale = makeAbsOffset(s, start_of_scale); + long start_of_char_struct_ofs_pos = s.position(); + s.writeUI64(FILL_LATER_IF_AVAILABLE); + long start_of_char_index_ofs_pos = s.position(); + s.writeUI64(FILL_LATER_IF_AVAILABLE); + long start_of_scale_ofs_pos = s.position(); + s.writeUI64(FILL_LATER_IF_AVAILABLE); s.writeUI32(kern_count); for (int i = 0; i < unk_float.length; i++) { s.writeFloat(unk_float[i]); } - s.writeUI64(start_of_kern); - long abs_start_of_kern = makeAbsOffset(s, start_of_kern); + long start_of_kern_ofs_pos = s.position(); + s.writeUI64(FILL_LATER_IF_AVAILABLE); s.writeUI64(zero_padd); ib.writeConstLength(IggyIndexBuilder.CONST_GENERAL_FONT_INFO2_SIZE); s.writeUI64(what_2); s.writeUI64(zero_padd_2); - s.writeUI64(start_of_name); - long abs_start_of_name = makeAbsOffset(s, start_of_name); + long start_of_name_ofs_pos = s.position(); + s.writeUI64(FILL_LATER_IF_AVAILABLE); s.writeUI64(one_padd); s.writeUI16(xscale); s.writeUI16(yscale); @@ -353,8 +349,8 @@ public class IggyFont extends IggyTag { s.writeFloat(sss4); s.writeUI32(one_padd5); s.writeBytes(zeroes48b); - if (abs_start_of_name != 0) { - s.seek(abs_start_of_name, SeekMode.SET); + if (name != null) { + s.setOlderOffsetToThisPos(start_of_name_ofs_pos); for (char c : name.toCharArray()) { s.writeUI16(c); } @@ -373,9 +369,9 @@ public class IggyFont extends IggyTag { } } - s.writeUI64(0); //pad zero - if (abs_start_of_char_struct != 0) { - s.seek(abs_start_of_char_struct, SeekMode.SET); + //s.writeUI64(0); //pad zero + if (charOffsets != null) { + s.setOlderOffsetToThisPos(start_of_char_struct_ofs_pos); ib.writeConstLengthArray(IggyIndexBuilder.CONST_CHAR_OFFSET_SIZE, charOffsets.size()); //offsets of shapes @@ -390,8 +386,8 @@ public class IggyFont extends IggyTag { } } } - if (abs_start_of_char_index != 0) { - s.seek(abs_start_of_char_index, SeekMode.SET); + if (codePoints != null) { + s.setOlderOffsetToThisPos(start_of_char_index_ofs_pos); for (char c : codePoints.chars) { s.writeUI16(c); } @@ -399,15 +395,15 @@ public class IggyFont extends IggyTag { ib.pad8bytes(); s.pad8bytes(); } - if (abs_start_of_scale != 0) { - s.seek(abs_start_of_scale, SeekMode.SET); + if (charScales != null) { + s.setOlderOffsetToThisPos(start_of_scale_ofs_pos); charScales.writeToDataStream(s); ib.write32bitArray(charScales.advances.size()); ib.pad8bytes(); s.pad8bytes(); } - if (abs_start_of_kern != 0) { - s.seek(abs_start_of_kern, SeekMode.SET); + if (charKernings != null) { + s.setOlderOffsetToThisPos(start_of_kern_ofs_pos); ib.writeConstLengthArray(IggyIndexBuilder.CONST_KERNING_RECORD_SIZE, kern_count); charKernings.writeToDataStream(s); ib.pad8bytes(); 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 3f9367f09..73876d1a8 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 @@ -218,4 +218,13 @@ public abstract class AbstractDataStream implements DataStreamInterface { } } + @Override + public void setOlderOffsetToThisPos(long savedPos) throws IOException { + long curPos = position(); + long actual = curPos - savedPos; + + seek(savedPos, SeekMode.SET); + writeUI64(actual); + seek(curPos, SeekMode.SET); + } } 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 ba48899a4..40f696376 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 @@ -19,6 +19,8 @@ public interface WriteDataStreamInterface extends AutoCloseable { public long position(); + public void setOlderOffsetToThisPos(long savedPos) throws IOException; + public boolean writeUI64(long val) throws IOException; public boolean writeSI64(long val) throws IOException; From 0403e847f50a6d2d1e45dca8346cc17d978667f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 4 Dec 2016 10:30:34 +0100 Subject: [PATCH 24/27] no magic shapes offsets --- .../decompiler/flash/iggy/IggyCharOffset.java | 12 ------------ .../jpexs/decompiler/flash/iggy/IggyFont.java | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 687ecaad1..2023a9841 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -32,14 +32,8 @@ public class IggyCharOffset implements StructureInterface { @IggyFieldType(DataType.uint32_t) long zero3; @IggyFieldType(DataType.uint64_t) - private long address; - long offset; - public long getAddress() { - return address; - } - public IggyCharOffset(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -65,12 +59,6 @@ public class IggyCharOffset implements StructureInterface { yscale = stream.readUI16(); zero3 = stream.readUI32(); offset = stream.readUI64(); - if (ischar1 > 0) { - address = offset + stream.position() - 8; - } else { - address = 0; - LOGGER.finer(String.format("Empty char")); - } } @Override 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 f2a9136e6..1e93ec19c 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 @@ -264,12 +264,19 @@ public class IggyFont extends IggyTag { //here is offset [7] - 1136 s.seek(abs_start_of_char_struct, SeekMode.SET); charOffsets = new ArrayList<>(); + List charAddresses = new ArrayList<>(); for (int i = 0; i < char_count; i++) { - charOffsets.add(new IggyCharOffset(s)); + IggyCharOffset iggyOffset = new IggyCharOffset(s); + charOffsets.add(iggyOffset); + if (iggyOffset.offset == 1) { + charAddresses.add(0L); + } else { + charAddresses.add(iggyOffset.offset + s.position() - 8); + } } glyphs = new ArrayList<>(); for (int i = 0; i < char_count; i++) { - long addr = charOffsets.get(i).getAddress(); + long addr = charAddresses.get(i); if (addr != 0) { s.seek(addr, SeekMode.SET); glyphs.add(new IggyShape(s)); @@ -374,14 +381,18 @@ public class IggyFont extends IggyTag { s.setOlderOffsetToThisPos(start_of_char_struct_ofs_pos); ib.writeConstLengthArray(IggyIndexBuilder.CONST_CHAR_OFFSET_SIZE, charOffsets.size()); + + List toFixOffsets = new ArrayList<>(); //offsets of shapes for (IggyCharOffset ofs : charOffsets) { + ofs.offset = FILL_LATER_IF_AVAILABLE; ofs.writeToDataStream(s); + toFixOffsets.add(s.position() - 8); } - //long afterOfsAddr = s.position(); for (int i = 0; i < glyphs.size(); i++) { IggyShape shp = glyphs.get(i); if (shp != null) { + s.setOlderOffsetToThisPos(toFixOffsets.get(i)); shp.writeToDataStream(s); } } From 189460655133eadeeb5137aa82bff28ef7667540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 4 Dec 2016 18:57:10 +0100 Subject: [PATCH 25/27] Saving correct font data offsets --- .../flash/iggy/IggyCharAdvances.java | 5 + .../flash/iggy/IggyCharIndices.java | 6 + .../flash/iggy/IggyCharKerning.java | 10 + .../decompiler/flash/iggy/IggyCharOffset.java | 10 +- .../jpexs/decompiler/flash/iggy/IggyFile.java | 121 +++----- .../flash/iggy/IggyFlashHeader64.java | 77 +++++ .../jpexs/decompiler/flash/iggy/IggyFont.java | 111 ++++++- .../flash/iggy/IggyFontBinInfo.java | 2 +- .../flash/iggy/IggyFontTypeInfo.java | 34 +-- .../decompiler/flash/iggy/IggySequence.java | 71 ----- .../decompiler/flash/iggy/IggyShape.java | 16 +- .../decompiler/flash/iggy/IggyShapeNode.java | 25 +- .../jpexs/decompiler/flash/iggy/IggySwf.java | 272 ++++++++---------- .../conversion/IggyShapeToSwfConvertor.java | 210 +++++++------- .../flash/iggy/conversion/IggySwfBundle.java | 238 ++++++++------- .../iggy/conversion/IggyToSwfConvertor.java | 52 ++-- .../conversion/SwfShapeToIggyConvertor.java | 59 ++++ .../iggy/conversion/SwfToIggyConvertor.java | 157 ++++++++++ .../iggy/streams/AbstractDataStream.java | 11 + .../flash/iggy/streams/IggyIndexBuilder.java | 19 +- .../streams/WriteDataStreamInterface.java | 2 + 21 files changed, 890 insertions(+), 618 deletions(-) delete mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfShapeToIggyConvertor.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java index 537e6be3b..61390c3d5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java @@ -20,6 +20,11 @@ public class IggyCharAdvances implements StructureInterface { return advances; } + public IggyCharAdvances(List advances) { + this.advances = advances; + this.charCount = advances.size(); + } + public IggyCharAdvances(ReadDataStreamInterface stream, long charCount) throws IOException { this.charCount = charCount; readFromDataStream(stream); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java index 424ce93b0..207dcf724 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java @@ -25,6 +25,12 @@ public class IggyCharIndices implements StructureInterface { private long charCount; + public IggyCharIndices(List chars) { + this.chars = chars; + this.charCount = chars.size(); + padd = 0; + } + public IggyCharIndices(ReadDataStreamInterface stream, long charCount) throws IOException { this.charCount = charCount; readFromDataStream(stream); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index e838c0ad6..1353ced5c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -36,6 +36,16 @@ public class IggyCharKerning implements StructureInterface { return kerningOffsets; } + public IggyCharKerning(List charsA, List charsB, List kerningOffsets) { + if ((charsA.size() != charsB.size()) || (charsB.size() != kerningOffsets.size())) { + throw new RuntimeException("sizes of charsA, charsB and offsets must match"); + } + this.kernCount = charsA.size(); + this.charsA = charsA; + this.charsB = charsB; + this.kerningOffsets = kerningOffsets; + } + public IggyCharKerning(ReadDataStreamInterface stream, long kernCount) throws IOException { this.kernCount = kernCount; readFromDataStream(stream); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 2023a9841..d753582db 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -38,15 +38,15 @@ public class IggyCharOffset implements StructureInterface { readFromDataStream(stream); } - public IggyCharOffset(long zero, int ischar1, int ischar2, long zero2, int xscale, int yscale, long zero3, long offset) { - this.zero = zero; + public IggyCharOffset(int ischar1, int ischar2, int xscale, int yscale) { + this.zero = 0; this.ischar1 = ischar1; this.ischar2 = ischar2; - this.zero2 = zero2; + this.zero2 = 0; this.xscale = xscale; this.yscale = yscale; - this.zero3 = zero3; - this.offset = offset; + this.zero3 = 0; + this.offset = 0; } @Override 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 3f6c06395..c49c6a683 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 @@ -35,63 +35,25 @@ public class IggyFile implements StructureInterface { final static Logger LOGGER = Logger.getLogger(IggyFile.class.getName()); + private File originalFile; private IggyHeader header; private List subFileEntries = new ArrayList<>(); private List subFileEntriesData = new ArrayList<>(); - private List iggySwfs = new ArrayList<>(); + private IggySwf iggySwf; public static final int FIRST_TAG_POSITION = 3; - public void replaceFontTag(int targetSwfIndex, int fontIndex, IggyFont newFont) throws IOException { - IggySwf iggySwf = iggySwfs.get(targetSwfIndex); - iggySwf.replaceFontTag(fontIndex, newFont); - - IggyIndexBuilder indexStream = new IggyIndexBuilder(); - DataStreamInterface flashStream = new TemporaryDataStream(); - flashStream.setIndexing(indexStream); - iggySwf.writeToDataStream(flashStream); - byte flashData[] = flashStream.getAllBytes(); - int swfIndex = 0; - int offsetChange = 0; - 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); - } - } - } + public IggySwf getSwf() { + return iggySwf; } - public IggySwf getSwf(int swfIndex) { - return iggySwfs.get(swfIndex); + public int getFontCount() { + return iggySwf.fonts.size(); } - public int getFontCount(int swfIndex) { - return iggySwfs.get(swfIndex).fonts.size(); - } - - public IggyFont getFont(int swfIndex, int fontId) { - return iggySwfs.get(swfIndex).fonts.get(fontId); + public IggyFont getFont(int fontId) { + return iggySwf.fonts.get(fontId); } public IggyFile(String filePath) throws IOException { @@ -99,11 +61,16 @@ public class IggyFile implements StructureInterface { } 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; } @@ -200,8 +167,7 @@ public class IggyFile implements StructureInterface { File outFile = new File(outFileName); IggyFile iggyFile = new IggyFile(inFile); extractIggyFile(inFile, extractDirOrig); - IggySwf iswf = iggyFile.getSwf(0); - iggyFile.replaceSwf(0, iswf); + iggyFile.updateFlashEntry(); outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); @@ -620,32 +586,28 @@ public class IggyFile implements StructureInterface { return null; } - public int getSwfCount() { - return iggySwfs.size(); + public String getSwfName() { + return iggySwf.getName(); } - public String getSwfName(int swfIndex) { - return iggySwfs.get(swfIndex).getName(); + public long getSwfXMin() { + return iggySwf.getHdr().getXMin(); } - public long getSwfXMin(int swfIndex) { - return iggySwfs.get(swfIndex).getHdr().getXMin(); + public long getSwfYMin() { + return iggySwf.getHdr().getYMin(); } - public long getSwfYMin(int swfIndex) { - return iggySwfs.get(swfIndex).getHdr().getYMin(); + public long getSwfXMax() { + return iggySwf.getHdr().getXMax(); } - public long getSwfXMax(int swfIndex) { - return iggySwfs.get(swfIndex).getHdr().getXMax(); + public long getSwfYMax() { + return iggySwf.getHdr().getYMax(); } - public long getSwfYMax(int swfIndex) { - return iggySwfs.get(swfIndex).getHdr().getYMax(); - } - - public float getSwfFrameRate(int swfIndex) { - return iggySwfs.get(swfIndex).getHdr().getFrameRate(); + public float getSwfFrameRate() { + return iggySwf.getHdr().getFrameRate(); } /** @@ -667,11 +629,8 @@ public class IggyFile implements StructureInterface { } } - public boolean replaceSwf(int targetSwfIndex, IggySwf iggySwf) throws IOException { + public boolean updateFlashEntry() throws IOException { - if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) { - throw new ArrayIndexOutOfBoundsException("No such SWF file index"); - } byte replacementData[]; byte replacementIndexData[]; IggyIndexBuilder ib = new IggyIndexBuilder(); @@ -685,21 +644,17 @@ public class IggyFile implements StructureInterface { return false; } - //IggyIndexParser.parseIndex(true, new TemporaryDataStream(replacementIndexData), new ArrayList<>(), new ArrayList<>()); - int swfIndex = 0; 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) { - if (swfIndex == targetSwfIndex) { - 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); - } + 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); } } @@ -714,7 +669,8 @@ public class IggyFile implements StructureInterface { for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); if (entry.type == IggySubFileEntry.TYPE_FLASH) { - iggySwfs.add(new IggySwf(new TemporaryDataStream(getEntryData(i)))); + 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<>()); @@ -736,6 +692,13 @@ public class IggyFile implements StructureInterface { 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); 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 fa433e1ab..f5a17c9eb 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 @@ -99,6 +99,67 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { private long decl_strings_address; private long type_fonts_address; + private long base_ofs_pos; + private long sequence_end_ofs_pos; + private long font_end_ofs_pos; + private long sequence_start1_ofs_pos; + private long sequence_start2_ofs_pos; + private long sequence_start3_ofs_pos; + private long names_ofs_pos; + private long unk78_ofs_pos; + private long last_section_ofs_pos; + private long flash_filename_ofs_pos; + private long decl_strings_ofs_pos; + private long type_fonts_ofs_pos; + + public long getBase_ofs_pos() { + return base_ofs_pos; + } + + public long getSequence_end_ofs_pos() { + return sequence_end_ofs_pos; + } + + public long getFont_end_ofs_pos() { + return font_end_ofs_pos; + } + + public long getSequence_start1_ofs_pos() { + return sequence_start1_ofs_pos; + } + + public long getSequence_start2_ofs_pos() { + return sequence_start2_ofs_pos; + } + + public long getSequence_start3_ofs_pos() { + return sequence_start3_ofs_pos; + } + + public long getNames_ofs_pos() { + return names_ofs_pos; + } + + public long getUnk78_ofs_pos() { + return unk78_ofs_pos; + } + + public long getLast_section_ofs_pos() { + return last_section_ofs_pos; + } + + public long getFlash_filename_ofs_pos() { + return flash_filename_ofs_pos; + } + + public long getDecl_strings_ofs_pos() { + return decl_strings_ofs_pos; + } + + public long getType_fonts_ofs_pos() { + return type_fonts_ofs_pos; + } + /** * Updates all addresses by inserting gap * @@ -146,6 +207,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { } public long getSequenceStartAddress2() { + return sequence_start_address2; + } + + public long getSequenceStartAddress3() { return sequence_start_address3; } @@ -175,21 +240,27 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { + base_ofs_pos = stream.position(); off_base = stream.readUI64(); base_address = off_base == 1 ? 0 : off_base + stream.position() - 8; + sequence_end_ofs_pos = stream.position(); off_sequence_end = stream.readUI64(); sequence_end_address = off_sequence_end == 1 ? 0 : off_sequence_end + stream.position() - 8; + font_end_ofs_pos = stream.position(); off_font_end = stream.readUI64(); font_end_address = off_font_end == 1 ? 0 : off_font_end + stream.position() - 8; + sequence_start1_ofs_pos = stream.position(); off_sequence_start1 = stream.readUI64(); sequence_start_address1 = off_sequence_start1 == 1 ? 0 : off_sequence_start1 + stream.position() - 8; + sequence_start2_ofs_pos = stream.position(); off_sequence_start2 = stream.readUI64(); sequence_start_address2 = off_sequence_start2 == 1 ? 0 : off_sequence_start2 + stream.position() - 8; + sequence_start3_ofs_pos = stream.position(); off_sequence_start3 = stream.readUI64(); sequence_start_address3 = off_sequence_start3 == 1 ? 0 : off_sequence_start3 + stream.position() - 8; @@ -209,23 +280,29 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { imported_guid = stream.readUI64(); my_guid = stream.readUI64(); + names_ofs_pos = stream.position(); off_names = stream.readUI64(); names_address = off_names == 1 ? 0 : off_names + stream.position() - 8; + unk78_ofs_pos = stream.position(); off_unk78 = stream.readUI64(); unk78_address = off_unk78 == 1 ? 0 : off_unk78 + stream.position() - 8; unk80 = stream.readUI64(); //Maybe number of imports/names pointed by names_offset + last_section_ofs_pos = stream.position(); off_last_section = stream.readUI64(); last_section_address = off_last_section == 1 ? 0 : off_last_section + stream.position() - 8; + flash_filename_ofs_pos = stream.position(); off_flash_filename = stream.readUI64(); flash_filename_address = off_flash_filename == 1 ? 0 : off_flash_filename + stream.position() - 8; + decl_strings_ofs_pos = stream.position(); off_decl_strings = stream.readUI64(); //relative offset to as3 code (16 bytes header + abc blob) decl_strings_address = off_decl_strings == 1 ? 0 : off_decl_strings + stream.position() - 8; + type_fonts_ofs_pos = stream.position(); off_type_of_fonts = stream.readUI64(); //relative offset to as3 file names table (or classes names or whatever) type_fonts_address = off_type_of_fonts == 1 ? 0 : off_type_of_fonts + stream.position() - 8; 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 1e93ec19c..9325c7b42 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 @@ -108,9 +108,7 @@ public class IggyFont extends IggyTag { IggyCharAdvances charScales; IggyCharKerning charKernings; - byte[] padTo4byteBoundary; - - public IggyFont(int type, int fontId, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long kern_count, float[] unk_float, long zero_padd, long what_2, long zero_padd_2, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48a, byte[] zeroes48b, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List glyphs, IggyCharIndices codePoints, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { + public IggyFont(int type, int fontId, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long kern_count, float[] unk_float, long zero_padd, long what_2, long zero_padd_2, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48a, byte[] zeroes48b, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List glyphs, IggyCharIndices codePoints, IggyCharAdvances charScales, IggyCharKerning charKernings) { this.type = type; this.fontId = fontId; this.zeroone = zeroone; @@ -149,7 +147,6 @@ public class IggyFont extends IggyTag { this.codePoints = codePoints; this.charScales = charScales; this.charKernings = charKernings; - this.padTo4byteBoundary = padTo4byteBoundary; } public IggyFont(ReadDataStreamInterface stream) throws IOException { @@ -276,8 +273,10 @@ public class IggyFont extends IggyTag { } glyphs = new ArrayList<>(); for (int i = 0; i < char_count; i++) { + //System.err.println("read char " + (i + 1) + "/" + char_count); long addr = charAddresses.get(i); if (addr != 0) { + //System.err.println("read chars at offset " + addr); s.seek(addr, SeekMode.SET); glyphs.add(new IggyShape(s)); } else { @@ -506,4 +505,108 @@ public class IggyFont extends IggyTag { return String.format("IggyFontTag (%04X)", ID); } + public void setType(int type) { + this.type = type; + } + + public void setFontId(int fontId) { + this.fontId = fontId; + } + + public void setCharCount2(int char_count2) { + this.char_count2 = char_count2; + } + + public void setAscent(int ascent) { + this.ascent = ascent; + } + + public void setDescent(int descent) { + this.descent = descent; + } + + public void setLeading(int leading) { + this.leading = leading; + } + + public void setFlags(long flags) { + this.flags = flags; + } + + public void setUnkFloat(float[] unk_float) { + this.unk_float = unk_float; + } + + public void setWhat2(long what_2) { + this.what_2 = what_2; + } + + public void setXScale(int xscale) { + this.xscale = xscale; + } + + public void setYScale(int yscale) { + this.yscale = yscale; + } + + public void setSsr1(float ssr1) { + this.ssr1 = ssr1; + } + + public void setSsr2(float ssr2) { + this.ssr2 = ssr2; + } + + public void setCharCount(long char_count) { + this.char_count = char_count; + } + + public void setWhat3(long what_3) { + this.what_3 = what_3; + } + + public void setSubName(String subName) { + this.subName = subName; + } + + public void setSss1(float sss1) { + this.sss1 = sss1; + } + + public void setSss2(float sss2) { + this.sss2 = sss2; + } + + public void setSss3(float sss3) { + this.sss3 = sss3; + } + + public void setSss4(float sss4) { + this.sss4 = sss4; + } + + public void setName(String name) { + this.name = name; + } + + public void setCharOffsets(List charOffsets) { + this.charOffsets = charOffsets; + } + + public void setGlyphs(List glyphs) { + this.glyphs = glyphs; + } + + public void setCodePoints(IggyCharIndices codePoints) { + this.codePoints = codePoints; + } + + public void setCharScales(IggyCharAdvances charScales) { + this.charScales = charScales; + } + + public void setCharKernings(IggyCharKerning charKernings) { + this.charKernings = charKernings; + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontBinInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontBinInfo.java index d11cde5fb..a76f2127b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontBinInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontBinInfo.java @@ -15,7 +15,7 @@ public class IggyFontBinInfo implements StructureInterface { public static final int STRUCT_SIZE = 96; @IggyFieldType(DataType.uint64_t) - long size_of_this_info = 96; + long size_of_this_info = STRUCT_SIZE; @IggyFieldType(value = DataType.uint16_t, count = 4) int font_specific[]; @IggyFieldType(DataType.float_t) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java index 33ec71665..7760816e2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java @@ -21,10 +21,10 @@ public class IggyFontTypeInfo implements StructureInterface { @IggyFieldType(DataType.uint64_t) long font_info_num; - private long local_name_address; + private long local_name_ofs_pos; - public long getLocal_name_address() { - return local_name_address; + public long getLocal_name_ofs_pos() { + return local_name_ofs_pos; } public IggyFontTypeInfo(ReadDataStreamInterface s) throws IOException { @@ -34,39 +34,15 @@ public class IggyFontTypeInfo implements StructureInterface { @Override public void readFromDataStream(ReadDataStreamInterface s) throws IOException { zero = s.readUI64(); + local_name_ofs_pos = s.position(); ofs_local_name = s.readUI64(); - local_name_address = ofs_local_name + s.position() - 8; font_info_num = s.readUI64(); } - public String readFontInfo(ReadDataStreamInterface s) throws IOException { - long pos = s.position(); - s.seek(local_name_address, SeekMode.SET); - StringBuilder inf_font_builder = new StringBuilder(); - while (true) { - char c = (char) s.readUI16(); - if (c == '\0') { - break; - } - inf_font_builder.append(c); - } - s.seek(pos, SeekMode.SET); - return inf_font_builder.toString(); - } - - public void writeFontInfo(String info_name, WriteDataStreamInterface s) throws IOException { - long pos = s.position(); - s.seek(local_name_address, SeekMode.SET); - for (int i = 0; i < info_name.length(); i++) { - s.writeUI16(info_name.charAt(i)); - } - s.writeUI16(0); - s.seek(pos, SeekMode.SET); - } - @Override public void writeToDataStream(WriteDataStreamInterface s) throws IOException { s.writeUI64(zero); + local_name_ofs_pos = s.position(); s.writeUI64(ofs_local_name); s.writeUI64(font_info_num); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java deleted file mode 100644 index 0c635183a..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySequence.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.jpexs.decompiler.flash.iggy; - -import static com.jpexs.decompiler.flash.iggy.IggyFontBinInfo.STRUCT_SIZE; -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 IggySequence implements StructureInterface { - - public static final int STRUCT_SIZE = 16; - - @IggyArrayFieldType(value = DataType.uint64_t, count = 2) - public long onepadd[]; - - @IggyFieldType(DataType.uint64_t) - public long local_seq_offset; - - @IggyFieldType(DataType.uint64_t) - public long zero; - - @IggyFieldType(DataType.wchar_t) - public String sequence_name; - - @IggyFieldType(DataType.uint64_t) - public long zero2; - - // wchar_t sequencname[(sequenceendaddress-sequencestartaddress-localseqoffset)/2]; -// if((sequenceendaddress-sequencestartaddress)%8!=0) byte padd[((sequenceendaddress-sequencestartaddress)/8+1)*8-(sequenceendaddress-sequencestartaddress)]; - public IggySequence(ReadDataStreamInterface stream) throws IOException { - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(ReadDataStreamInterface s) throws IOException { - onepadd = new long[2]; - for (int i = 0; i < onepadd.length; i++) { - onepadd[i] = s.readUI64(); - } - //sequence start - local_seq_offset = s.readUI64(); - zero = s.readUI64(); - sequence_name = s.readWChar(); - s.pad8bytes(); - zero2 = s.readUI64(); //zero2 - } - - @Override - public void writeToDataStream(WriteDataStreamInterface s) throws IOException { - IggyIndexBuilder ib = s.getIndexing(); - ib.writeLengthCustom(16, new int[]{0x00}, new int[]{2}); - for (int i = 0; i < onepadd.length; i++) { - s.writeUI64(onepadd[i]); - } - ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE); - s.writeUI64(local_seq_offset); - s.writeUI64(zero); - ib.write16bitArray(sequence_name.length() + 1); - s.writeWChar(sequence_name); - s.pad8bytes(); - ib.pad8bytes(); - s.writeUI64(zero2); - } -} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index ec0eb6ed1..b5812944d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -69,18 +69,18 @@ public class IggyShape implements StructureInterface { readFromDataStream(stream); } - public IggyShape(float minx, float miny, float maxx, float maxy, long advance, long count, long one, long one2, long one3, long one4, long two1, List nodes) { + public IggyShape(float minx, float miny, float maxx, float maxy, List nodes) { this.minx = minx; this.miny = miny; this.maxx = maxx; this.maxy = maxy; - this.unk = advance; - this.count = count; - this.one = one; - this.one2 = one2; - this.one3 = one3; - this.one4 = one4; - this.two1 = two1; + this.unk = 0; //?? + this.one = 1; + this.one2 = 1; + this.one3 = 1; + this.one4 = 1; + this.two1 = 2; + this.count = nodes.size(); this.nodes = nodes; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java index 04d9d4132..b99129289 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java @@ -45,16 +45,17 @@ public class IggyShapeNode implements StructureInterface { private boolean first; - public IggyShapeNode(float x1, float y1, float x2, float y2, int node_type, int node_subtype, int zer1, int zer2, long isstart) { - this.targetX = x1; - this.targetY = y1; - this.controlX = x2; - this.controlY = y2; + public IggyShapeNode(float targetX, float targetY, float controlX, float controlY, int node_type, int node_subtype, boolean first) { + this.targetX = targetX; + this.targetY = targetY; + this.controlX = controlX; + this.controlY = controlY; this.node_type = node_type; this.node_subtype = node_subtype; - this.zer1 = zer1; - this.zer2 = zer2; - this.isstart = isstart; + this.zer1 = 0; + this.zer2 = 0; + this.first = first; + this.isstart = first ? 0 : 1; } public IggyShapeNode(ReadDataStreamInterface s, boolean first) throws IOException { @@ -98,19 +99,19 @@ public class IggyShapeNode implements StructureInterface { s.writeUI32(isstart); } - public float getX1() { + public float getTargetX() { return targetX; } - public float getY1() { + public float getTargetY() { return targetY; } - public float getX2() { + public float getControlX() { return controlX; } - public float getY2() { + public float getControlY() { return controlY; } 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 6b95d8b1c..f3e3a8ef1 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 @@ -28,9 +28,9 @@ public class IggySwf implements StructureInterface { String name; List fonts = new ArrayList<>(); - private List font_data_addresses = new ArrayList<>(); + // private List font_data_addresses = new ArrayList<>(); List add_fonts = new ArrayList<>(); - private List add_font_data_addresses = new ArrayList<>(); +// private List add_font_data_addresses = new ArrayList<>(); private IggyFlashHeader64 hdr; @@ -38,14 +38,16 @@ public class IggySwf implements StructureInterface { readFromDataStream(stream); } private List texts = new ArrayList<>(); - private List text_data_addresses = new ArrayList<>(); + //private List text_data_addresses = new ArrayList<>(); private List add_texts = new ArrayList<>(); - private List add_text_data_addresses = new ArrayList<>(); + //private List add_text_data_addresses = new ArrayList<>(); - private byte font_add_data[]; - private List font_additional_size = new ArrayList<>(); + //private byte font_add_data[]; + //private List font_additional_size = new ArrayList<>(); private IggyFontBinInfo font_bin_info[]; - private IggySequence sequence; + private List sequenceNames = new ArrayList<>(); + //private List sequenceValues = new ArrayList<>(); + private IggyFontTypeInfo type_info[]; private String type_info_name[]; private IggyDeclStrings decl_strings; @@ -56,36 +58,6 @@ public class IggySwf implements StructureInterface { return hdr; } - public void replaceFontTag(int fontIndex, IggyFont newFont) throws IOException { - /*long newLen; - byte newData[]; - try (WriteDataStreamInterface stream = new TemporaryDataStream()) { - newFont.writeToDataStream(stream); - newData = stream.getAllBytes(); - newLen = newData.length; - } - - //FIXME - Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\font" + fontIndex + ".bin", newData); - - long oldLen = font_data_sizes[fontIndex]; - long diff = newLen - oldLen; - if (diff != 0) { - font_data_sizes[fontIndex] = newLen; - for (int i = fontIndex; i < hdr.font_count; i++) { - font_data_addresses[i] += diff; - } - for (int i = 0; i < text_addresses.size(); i++) { - text_addresses.set(i, text_addresses.get(i) + diff); - } - for (int i = 0; i < font_add_off.size(); i++) { - font_add_off.set(i, font_add_off.get(i) + diff); - } - } - hdr.insertGapAfter(font_data_addresses[fontIndex], diff); - */ - } - @Override public void readFromDataStream(ReadDataStreamInterface s) throws IOException { this.hdr = new IggyFlashHeader64(s); @@ -97,7 +69,7 @@ public class IggySwf implements StructureInterface { if (pad8 > 8) { s.seek(pad8, SeekMode.CUR); } - //here is offset [2] - 232 + //here is offset [2] - 232 s.seek(hdr.getBaseAddress(), SeekMode.SET); s.readUI64(); //pad 1 @@ -121,12 +93,12 @@ public class IggySwf implements StructureInterface { switch (kind) { case 22 /*FONT*/: IggyFont font = new IggyFont(s); - font_data_addresses.add(addr); + //font_data_addresses.add(addr); fonts.add(font); break; case 6 /*TEXT*/: IggyText text = new IggyText(s); - text_data_addresses.add(addr); + //text_data_addresses.add(addr); texts.add(text); break; default: @@ -151,12 +123,12 @@ public class IggySwf implements StructureInterface { switch (kind) { case 22 /*FONT*/: IggyFont font = new IggyFont(s); - add_font_data_addresses.add(addr); + //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_text_data_addresses.add(addr); add_texts.add(text); break; default: @@ -164,91 +136,6 @@ public class IggySwf implements StructureInterface { } } } - - /* - for (int i = 0; i < hdr.font_count; i++) { - long offset = s.readUI64(); - font_data_addresses[i] = offset + s.position() - 8; - long next_offset = s.readUI64(); - s.seek(-8, SeekMode.CUR); - if (next_offset == 1) { - font_data_sizes[i] = hdr.getFontEndAddress() - font_data_addresses[i]; - } else { - font_data_sizes[i] = next_offset - offset + 8; - } - } - while (true) { - long offset = s.readUI64(); - if (offset == 1) { - break; - } - long text_addr = offset + s.position() - 8; - text_addresses.add(text_addr); - long next_offset = s.readUI64(); - s.seek(-8, SeekMode.CUR); - if (next_offset == 1) { - text_data_sizes.add(hdr.getFontEndAddress() - text_addr); - break; - } else { - text_data_sizes.add(next_offset - offset + 8); - } - } - s.readUI64(); //1 - - if (hdr.getImported_guid() != 0) { - ofs_additional = s.readUI64(); - additional_address = ofs_additional + s.position() - 8; - font_additional_addresses.add(additional_address); - font_additional_size.add(hdr.getFontEndAddress() - font_additional_addresses.get(0)); - - if (s.readUI8(font_additional_addresses.get(0)) != 22) { //additional is not text - // font je hozen mezi infa... - for (int i = 0; i < text_addresses.size(); i++) { //walk all already read texts - if (s.readUI8(text_addresses.get(i)) == 22) { //check if it's text - long pomoff; - long pomsize; - pomoff = text_addresses.get(i); - pomsize = text_data_sizes.get(i); - text_addresses.set(i, font_additional_addresses.get(0)); - text_data_sizes.set(i, font_additional_size.get(0)); - font_additional_addresses.set(0, pomoff); - font_additional_size.set(0, pomsize); - } - } - } - }*/ - - /* if (s.readUI8(s.position()) == 22) { //22 = Text - byte[] textHdr = s.readBytes(IggyText.STRUCT_SIZE); - String textStr = s.readWChar(); - s.pad8bytes(); - }*/ - //here is offset [3] - 744 - /* fonts = new ArrayList<>(); - for (int i = 0; i < hdr.font_count; i++) { - s.seek(font_data_addresses[i], SeekMode.SET); - byte font_data[] = s.readBytes((int) font_data_sizes[i]); - //FIXME - //Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\font" + i + ".bin", font_data); - s.seek(-font_data_sizes[i], SeekMode.CUR); - IggyFont font = new IggyFont(s); - fonts.add(font); - } - - for (int i = 0; - i < text_addresses.size(); - i++) { - s.seek(text_addresses.get(i), SeekMode.SET); - texts.add(new IggyText(s)); - //byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i)); - //text_data_bytes.add(text_data); - } - - if (hdr.getImported_guid() - != 0) { - s.seek(font_additional_addresses.get(0), SeekMode.SET); - font_add_data = s.readBytes((int) (long) font_additional_size.get(0)); - }*/ s.seek(hdr.getFontEndAddress(), SeekMode.SET); //here is offset [4] - 856 ? font_bin_info = new IggyFontBinInfo[(int) hdr.font_count]; @@ -256,9 +143,33 @@ public class IggySwf implements StructureInterface { font_bin_info[i] = new IggyFontBinInfo(s); } - s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET); - sequence = new IggySequence(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]; @@ -266,7 +177,8 @@ public class IggySwf implements StructureInterface { type_info[i] = new IggyFontTypeInfo(s); } for (int i = 0; i < hdr.font_count; i++) { - type_info_name[i] = type_info[i].readFontInfo(s); + 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); @@ -290,64 +202,114 @@ public class IggySwf implements StructureInterface { ib.write16bitArray(name.length() + 1); ib.writeTwoPaddingBytes(); ib.write64bitPointerArray(64); - for (int i = 0; i < font_data_addresses.size(); i++) { - long offset = font_data_addresses.get(i) - s.position(); - s.writeUI64(offset); + long posBeforeOffsets = s.position(); + + final int FILL_LATER = 1; + + List fontPosFillLater = new ArrayList<>(); + + for (int i = 0; i < fonts.size(); i++) { + fontPosFillLater.add(s.position()); + s.writeUI64(FILL_LATER); } - for (int i = 0; i < text_data_addresses.size(); i++) { - long offset = text_data_addresses.get(i) - s.position(); - s.writeUI64(offset); + List textPosFillLater = new ArrayList<>(); + for (int i = 0; i < texts.size(); i++) { + textPosFillLater.add(s.position()); + s.writeUI64(FILL_LATER); } s.writeUI64(1); - if (additional_address != 0) { - long ofs_additional = additional_address - s.position(); - s.writeUI64(ofs_additional); + + 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); } - while (s.position() < font_data_addresses.get(0)) { - s.writeUI64(1); - } for (int i = 0; i < fonts.size(); i++) { - s.seek(font_data_addresses.get(i), SeekMode.SET); + s.setOlderOffsetToThisPos(fontPosFillLater.get(i)); fonts.get(i).writeToDataStream(s); } for (int i = 0; i < texts.size(); i++) { - s.seek(text_data_addresses.get(i), SeekMode.SET); + s.setOlderOffsetToThisPos(textPosFillLater.get(i)); texts.get(i).writeToDataStream(s); } - if (hdr.getImported_guid() != 0) { + if (!add_fonts.isEmpty() || !add_texts.isEmpty()) { + s.setOlderOffsetToThisPos(addPosFillLater); + + List addFontPosFillLater = new ArrayList<>(); + for (int i = 0; i < add_fonts.size(); i++) { - s.seek(add_font_data_addresses.get(i), SeekMode.SET); - fonts.get(i).writeToDataStream(s); + addFontPosFillLater.add(s.position()); + s.writeUI64(FILL_LATER); + } + List 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.seek(add_text_data_addresses.get(i), SeekMode.SET); - texts.get(i).writeToDataStream(s); + s.setOlderOffsetToThisPos(addTextPosFillLater.get(i)); + add_texts.get(i).writeToDataStream(s); } } - s.seek(hdr.getFontEndAddress(), SeekMode.SET); + 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); } - s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET); - sequence.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.pad8bytes(); + ib.pad8bytes(); ib.writeConstLengthArray(IggyIndexBuilder.CONST_TYPE_INFO_SIZE, hdr.font_count); - s.seek(hdr.getTypeFontsAddress(), SeekMode.SET); + 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); - type_info[i].writeFontInfo(type_info_name[i], s); + s.setOlderOffsetToThisPos(type_info[i].getLocal_name_ofs_pos()); + s.writeWChar(type_info_name[i]); } s.pad8bytes(); ib.pad8bytes(); - s.seek(hdr.getDeclStringsAddress(), SeekMode.SET); + + s.setOlderOffsetToThisPos(hdr.getDecl_strings_ofs_pos()); + //s.seek(hdr.getDeclStringsAddress(), SeekMode.SET); decl_strings.writeToDataStream(s); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyShapeToSwfConvertor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyShapeToSwfConvertor.java index 8644c6882..00ab98dce 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyShapeToSwfConvertor.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyShapeToSwfConvertor.java @@ -1,105 +1,105 @@ -package com.jpexs.decompiler.flash.iggy.conversion; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.iggy.IggyShape; -import com.jpexs.decompiler.flash.iggy.IggyShapeNode; -import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.LINESTYLE; -import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.RGB; -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 java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class IggyShapeToSwfConvertor { - - private static int makeLengthsEmX(double val) { - return (int) (val * 1024.0); - } - - private static int makeLengthsEmY(double val) { - return (int) (val * 1024.0); - } - - public static SHAPE convertCharToShape(IggyShape igchar) { - SHAPE shape = new SHAPE(); - List retList = new ArrayList<>(); - List ignodes = igchar.getNodes(); - - int prevX = 0; - int prevY = 0; - - for (IggyShapeNode ign : ignodes) { - if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_MOVE) { - StyleChangeRecord scr = new StyleChangeRecord(); - scr.stateMoveTo = true; - prevX = scr.moveDeltaX = makeLengthsEmX(ign.getX1()); - prevY = scr.moveDeltaY = makeLengthsEmY(ign.getY1()); - scr.fillStyles = new FILLSTYLEARRAY(); - scr.lineStyles = new LINESTYLEARRAY(); - scr.calculateBits(); - retList.add(scr); - } else { - - int curX1 = makeLengthsEmX(ign.getX1()); - int curY1 = makeLengthsEmY(ign.getY1()); - - int curX2 = makeLengthsEmX(ign.getX2()); - int curY2 = makeLengthsEmY(ign.getY2()); - - if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_LINE_TO) { - StraightEdgeRecord ser = new StraightEdgeRecord(); - ser.deltaX = curX1 - prevX; - ser.deltaY = curY1 - prevY; - ser.generalLineFlag = true; - ser.simplify(); - ser.calculateBits(); - prevX = curX1; - prevY = curY1; - retList.add(ser); - } else if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_CURVE_POINT) { - CurvedEdgeRecord cer = new CurvedEdgeRecord(); - cer.controlDeltaX = curX2 - prevX; - cer.controlDeltaY = curY2 - prevY; - cer.anchorDeltaX = curX1 - curX2; - cer.anchorDeltaY = curY1 - curY2; - prevX = curX1; - prevY = curY1; - cer.calculateBits(); - retList.add(cer); - } - } - } - if (!retList.isEmpty()) { - StyleChangeRecord init; - if (retList.get(0) instanceof StyleChangeRecord) { - init = (StyleChangeRecord) retList.get(0); - } else { - init = new StyleChangeRecord(); - retList.add(0, init); - } - init.stateFillStyle0 = true; - init.fillStyle0 = 1; - shape.numFillBits = 1; - - } else { - shape.numFillBits = 0; - - } - retList.add(new EndShapeRecord()); - shape.shapeRecords = retList; - shape.numLineBits = 0; - - return shape; - } -} +package com.jpexs.decompiler.flash.iggy.conversion; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.iggy.IggyShape; +import com.jpexs.decompiler.flash.iggy.IggyShapeNode; +import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.LINESTYLE; +import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.RGB; +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 java.awt.Color; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class IggyShapeToSwfConvertor { + + private static int makeLengthsEmX(double val) { + return (int) (val * 1024.0); + } + + private static int makeLengthsEmY(double val) { + return (int) (val * 1024.0); + } + + public static SHAPE convertCharToShape(IggyShape igchar) { + SHAPE shape = new SHAPE(); + List retList = new ArrayList<>(); + List ignodes = igchar.getNodes(); + + int prevX = 0; + int prevY = 0; + + for (IggyShapeNode ign : ignodes) { + if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_MOVE) { + StyleChangeRecord scr = new StyleChangeRecord(); + scr.stateMoveTo = true; + prevX = scr.moveDeltaX = makeLengthsEmX(ign.getTargetX()); + prevY = scr.moveDeltaY = makeLengthsEmY(ign.getTargetY()); + scr.fillStyles = new FILLSTYLEARRAY(); + scr.lineStyles = new LINESTYLEARRAY(); + scr.calculateBits(); + retList.add(scr); + } else { + + int curX1 = makeLengthsEmX(ign.getTargetX()); + int curY1 = makeLengthsEmY(ign.getTargetY()); + + int curX2 = makeLengthsEmX(ign.getControlX()); + int curY2 = makeLengthsEmY(ign.getControlY()); + + if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_LINE_TO) { + StraightEdgeRecord ser = new StraightEdgeRecord(); + ser.deltaX = curX1 - prevX; + ser.deltaY = curY1 - prevY; + ser.generalLineFlag = true; + ser.simplify(); + ser.calculateBits(); + prevX = curX1; + prevY = curY1; + retList.add(ser); + } else if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_CURVE_POINT) { + CurvedEdgeRecord cer = new CurvedEdgeRecord(); + cer.controlDeltaX = curX2 - prevX; + cer.controlDeltaY = curY2 - prevY; + cer.anchorDeltaX = curX1 - curX2; + cer.anchorDeltaY = curY1 - curY2; + prevX = curX1; + prevY = curY1; + cer.calculateBits(); + retList.add(cer); + } + } + } + if (!retList.isEmpty()) { + StyleChangeRecord init; + if (retList.get(0) instanceof StyleChangeRecord) { + init = (StyleChangeRecord) retList.get(0); + } else { + init = new StyleChangeRecord(); + retList.add(0, init); + } + init.stateFillStyle0 = true; + init.fillStyle0 = 1; + shape.numFillBits = 1; + + } else { + shape.numFillBits = 0; + + } + retList.add(new EndShapeRecord()); + shape.shapeRecords = retList; + shape.numLineBits = 0; + + return shape; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java index 330342129..058f010e1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java @@ -1,104 +1,134 @@ -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.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.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -/** - * - * @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 iggyFile.getSwfCount(); - } - - @Override - public Set getKeys() { - Set ret = new TreeSet<>(); - for (int i = 0; i < length(); i++) { - ret.add(iggyFile.getSwfName(i)); - } - return ret; - } - - private int keyToSwfIndex(String key) { - for (int i = 0; i < length(); i++) { - if (key.equals(iggyFile.getSwfName(i))) { - return i; - } - } - throw new IllegalArgumentException("Key " + key + " does not exist!"); - } - - @Override - public SeekableInputStream getSWF(String key) throws IOException { - SWF swf = IggyToSwfConvertor.getSwf(iggyFile, keyToSwfIndex(key)); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - swf.saveTo(baos); - MemoryInputStream mis = new MemoryInputStream(baos.toByteArray()); - return mis; - } - - @Override - public Map getAll() throws IOException { - Map 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 true; //TODO: make writable - } - - @Override - public boolean putSWF(String key, InputStream is) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - -} +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.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 getKeys() { + Set 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 getAll() throws IOException { + Map 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 { + int swfIndex = 0; + SWF swf = new SWF(is, false, false); + List fontTags = new ArrayList<>(); + for (CharacterTag ct : swf.getCharacters().values()) { + if (ct instanceof DefineFont2Tag) { + fontTags.add((DefineFont2Tag) ct); + } + } + int fontCount = iggyFile.getFontCount(); + if (fontCount != fontTags.size()) { + throw new IOException("Font count is different from original iggy file"); + } + for (int i = 0; i < fontCount; i++) { + IggyFont iggyFont = iggyFile.getFont(i); + DefineFont2Tag fontTag = fontTags.get(i); + SwfToIggyConvertor.updateIggyFont(iggyFont, fontTag); + } + iggyFile.saveChanges(); + return true; + } catch (InterruptedException ex) { + return false; + } + + } + +} 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 18947a11d..3fcaafad2 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 @@ -9,6 +9,7 @@ import com.jpexs.decompiler.flash.iggy.IggyCharOffset; import com.jpexs.decompiler.flash.iggy.IggyCharAdvances; 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; @@ -44,56 +45,42 @@ import java.util.Set; */ public class IggyToSwfConvertor { - public static SWF[] getAllSwfs(IggyFile file) { - SWF[] ret = new SWF[file.getSwfCount()]; - for (int i = 0; i < ret.length; i++) { - ret[i] = getSwf(file, i); - } - return ret; - } - public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException { - for (int swfIndex = 0; swfIndex < file.getSwfCount(); swfIndex++) { - exportSwfToDir(file, swfIndex, outputDir); + 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 exportSwfToDir(IggyFile file, int swfIndex, File outputDir) throws IOException { - try (FileOutputStream fos = new FileOutputStream(new File(outputDir, file.getSwfName(swfIndex)))) { - exportSwf(file, swfIndex, fos); - } - } - - public static void exportSwfToFile(IggyFile file, int swfIndex, File outputFile) throws IOException { + public static void exportSwfToFile(IggyFile file, File outputFile) throws IOException { try (FileOutputStream fos = new FileOutputStream(outputFile)) { - exportSwf(file, swfIndex, fos); + exportSwf(file, fos); } } - public static void exportSwf(IggyFile file, int swfIndex, OutputStream output) throws IOException { - SWF swf = getSwf(file, swfIndex); + public static void exportSwf(IggyFile file, OutputStream output) throws IOException { + SWF swf = getSwf(file); swf.saveTo(output); } - private static int makeLengthsTwip(double val) { - return (int) (val * SWF.unitDivisor); - } - private static int makeLengthsEm(double val) { return (int) (val * 1024.0); } - public static SWF getSwf(IggyFile file, int swfIndex) { + public static SWF getSwf(IggyFile file) { SWF swf = new SWF(); swf.compression = SWFCompression.NONE; swf.frameCount = 1; //FIXME!! - swf.frameRate = file.getSwfFrameRate(swfIndex); + swf.frameRate = file.getSwfFrameRate(); swf.gfx = false; swf.displayRect = new RECT( - (int) (file.getSwfXMin(swfIndex) * SWF.unitDivisor), - (int) (file.getSwfXMax(swfIndex) * SWF.unitDivisor), - (int) (file.getSwfYMin(swfIndex) * SWF.unitDivisor), - (int) (file.getSwfYMax(swfIndex) * SWF.unitDivisor)); + (int) (file.getSwfXMin() * SWF.unitDivisor), + (int) (file.getSwfXMax() * SWF.unitDivisor), + (int) (file.getSwfYMin() * SWF.unitDivisor), + (int) (file.getSwfYMax() * SWF.unitDivisor)); swf.version = 10; //FIXME FileAttributesTag fat = new FileAttributesTag(swf); @@ -101,15 +88,14 @@ public class IggyToSwfConvertor { fat.hasMetadata = false; fat.useNetwork = false; swf.addTag(fat); - //Set fontIndices = file.getFontIds(swfIndex); - int fontCount = file.getFontCount(swfIndex); + int fontCount = file.getFontCount(); int currentCharId = 0; Map fontIndex2CharId = new HashMap<>(); for (int fontIndex = 0; fontIndex < fontCount; fontIndex++) { - IggyFont iggyFont = file.getFont(swfIndex, fontIndex); + IggyFont iggyFont = file.getFont(fontIndex); DefineFont2Tag fontTag = new DefineFont2Tag(swf); currentCharId++; fontIndex2CharId.put(fontIndex, currentCharId); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfShapeToIggyConvertor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfShapeToIggyConvertor.java new file mode 100644 index 000000000..c23c6a009 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfShapeToIggyConvertor.java @@ -0,0 +1,59 @@ +package com.jpexs.decompiler.flash.iggy.conversion; + +import com.jpexs.decompiler.flash.iggy.IggyShape; +import com.jpexs.decompiler.flash.iggy.IggyShapeNode; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +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 java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class SwfShapeToIggyConvertor { + + private static float normalizeLengths(int val) { + return (val / 1024f); + } + + public static IggyShape convertShape(SHAPE swfShape) { + /*if (swfShape.shapeRecords.size() == 1) { //no glyphs, maybe space + return null; + }*/ + List nodes = new ArrayList<>(); + RECT bounds = swfShape.getBounds(); + boolean first = true; + float curX = 0f; + float curY = 0f; + for (SHAPERECORD rec : swfShape.shapeRecords) { + if (rec instanceof StraightEdgeRecord) { + StraightEdgeRecord ser = (StraightEdgeRecord) rec; + curX += normalizeLengths(ser.deltaX); + curY += normalizeLengths(ser.deltaY); + nodes.add(new IggyShapeNode(curX, curY, 0f, 0f, IggyShapeNode.NODE_TYPE_LINE_TO, 0, first)); + } else if (rec instanceof CurvedEdgeRecord) { + CurvedEdgeRecord cer = (CurvedEdgeRecord) rec; + float controlX = curX + normalizeLengths(cer.controlDeltaX); + float controlY = curY + normalizeLengths(cer.controlDeltaY); + curX = curX + normalizeLengths(cer.controlDeltaX + cer.anchorDeltaX); + curY = curY + normalizeLengths(cer.controlDeltaY + cer.anchorDeltaY); + nodes.add(new IggyShapeNode(curX, curY, controlX, controlY, IggyShapeNode.NODE_TYPE_CURVE_POINT, 0, first)); + } else if (rec instanceof StyleChangeRecord) { + StyleChangeRecord scr = (StyleChangeRecord) rec; + if (scr.stateMoveTo) { + curX = normalizeLengths(scr.moveDeltaX); + curY = normalizeLengths(scr.moveDeltaY); + nodes.add(new IggyShapeNode(curX, curY, 0f, 0f, IggyShapeNode.NODE_TYPE_MOVE, 0, first)); + } + } + first = false; + } + IggyShape ret = new IggyShape(normalizeLengths(bounds.Xmin), normalizeLengths(bounds.Ymin), normalizeLengths(bounds.Xmax), normalizeLengths(bounds.Ymax), nodes); + return ret; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java new file mode 100644 index 000000000..649135c3b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java @@ -0,0 +1,157 @@ +package com.jpexs.decompiler.flash.iggy.conversion; + +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.tags.DefineFont2Tag; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.SHAPE; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class SwfToIggyConvertor { + + private static float normalizeLengths(int val) { + return (val / 1024f); + } + + 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 charOffsets = new ArrayList<>(); + + List glyphs = new ArrayList<>(); + + for (SHAPE s : fontTag.glyphShapeTable) { + glyphs.add(SwfShapeToIggyConvertor.convertShape(s)); + } + + List chars = new ArrayList<>(); + for (int code : fontTag.codeTable) { + chars.add((char) code); + } + IggyCharIndices codePoints = new IggyCharIndices(chars); + List scales = new ArrayList<>(); + for (int adv : fontTag.fontAdvanceTable) { + scales.add(normalizeLengths(adv)); + } + IggyCharAdvances charScales = new IggyCharAdvances(scales); + List charA = new ArrayList<>(); + List charB = new ArrayList<>(); + List 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); + /* + 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); + */ + } + + 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 charOffsets = new ArrayList<>(); + List glyphs = new ArrayList<>(); + List chars = new ArrayList<>(); + for (int code : fontTag.codeTable) { + chars.add((char) code); + } + IggyCharIndices codePoints = new IggyCharIndices(chars); + List scales = new ArrayList<>(); + for (int adv : fontTag.fontAdvanceTable) { + scales.add((float) adv); + } + IggyCharAdvances charScales = new IggyCharAdvances(scales); + List charA = new ArrayList<>(); + List charB = new ArrayList<>(); + List 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; + } +} 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 73876d1a8..2cda5f443 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 @@ -227,4 +227,15 @@ public abstract class AbstractDataStream implements DataStreamInterface { writeUI64(actual); seek(curPos, SeekMode.SET); } + + public void setOlderOffsetToThisPosCheck(long savedPos, long expected) throws IOException { + if (expected == 1) { + return; + } + long curPos = position(); + long actual = curPos - savedPos; + if (actual != expected) { + throw new RuntimeException("Expected " + expected + " but found actual " + actual + ". Diff:" + ((actual - expected) > 0 ? "+" : "") + (actual - expected)); + } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java index 7b4322c4a..9d1356e63 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java @@ -4,20 +4,14 @@ import com.jpexs.decompiler.flash.iggy.IggyCharKerning; import com.jpexs.decompiler.flash.iggy.IggyCharOffset; import com.jpexs.decompiler.flash.iggy.IggyFontBinInfo; import com.jpexs.decompiler.flash.iggy.IggyFontTypeInfo; -import com.jpexs.decompiler.flash.iggy.IggySequence; import com.jpexs.decompiler.flash.iggy.IggyShape; import com.jpexs.decompiler.flash.iggy.IggyShapeNode; import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; import java.util.logging.Logger; /** @@ -73,7 +67,7 @@ public class IggyIndexBuilder { private static final int CONST_VAL_GENERAL_FONT_INFO_SIZE = 112; private static final int CONST_VAL_GENERAL_FONT_INFO2_SIZE = 240; private static final int CONST_VAL_TEXT_DATA_SIZE = 104; - private static final int CONST_VAL_SEQUENCE_SIZE = IggySequence.STRUCT_SIZE; + private static final int CONST_VAL_SEQUENCE_SIZE = 16; public static final int CONST_SHAPE_NODE_SIZE = 0; public static final int CONST_KERNING_RECORD_SIZE = 1; @@ -175,8 +169,12 @@ public class IggyIndexBuilder { long ret = 0; long rem = cnt; while (true) { + if (rem == 0) { + break; + } if (rem == 1) { - return writeIndex(constIndex, false, 0); + ret += writeIndex(constIndex, false, 0); + break; } if (rem <= 64) { ret += writeIndex(0x80 + (int) rem - 1, false, constIndex); @@ -307,10 +305,7 @@ public class IggyIndexBuilder { int index; indexStream.writeUI8((int) val); - if ((index = (int) val) < 0) { - LOGGER.severe(String.format("< 0xC0: Cannot read index.")); - return 0; - } + index = (int) val; if (index >= constTable.size()) { LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, constTable.size())); 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 40f696376..079d53136 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 @@ -21,6 +21,8 @@ public interface WriteDataStreamInterface extends AutoCloseable { public void setOlderOffsetToThisPos(long savedPos) throws IOException; + public void setOlderOffsetToThisPosCheck(long savedPos, long expected) throws IOException; + public boolean writeUI64(long val) throws IOException; public boolean writeSI64(long val) throws IOException; From 8fe30defde7c4625c9de74e4e0f57a9d82820223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 4 Dec 2016 19:06:00 +0100 Subject: [PATCH 26/27] remove garbage comments --- .../jpexs/decompiler/flash/iggy/IggyFont.java | 2 - .../flash/iggy/streams/IggyIndexBuilder.java | 48 ------------------- 2 files changed, 50 deletions(-) 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 9325c7b42..3dd59f192 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 @@ -273,10 +273,8 @@ public class IggyFont extends IggyTag { } glyphs = new ArrayList<>(); for (int i = 0; i < char_count; i++) { - //System.err.println("read char " + (i + 1) + "/" + char_count); long addr = charAddresses.get(i); if (addr != 0) { - //System.err.println("read chars at offset " + addr); s.seek(addr, SeekMode.SET); glyphs.add(new IggyShape(s)); } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java index 9d1356e63..49c6263be 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/IggyIndexBuilder.java @@ -21,33 +21,6 @@ import java.util.logging.Logger; public class IggyIndexBuilder { private static Logger LOGGER = Logger.getLogger(IggyIndexBuilder.class.getName()); - - /*static PrintWriter pw; - - static { - try { - pw = new PrintWriter("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\index.txt"); - } catch (FileNotFoundException ex) { - Logger.getLogger(IggyIndexParser.class.getName()).log(Level.SEVERE, null, ex); - } - LOGGER.setLevel(Level.ALL); - LOGGER.addHandler(new Handler() { - @Override - public void publish(LogRecord record) { - pw.println("" + record.getMessage()); - } - - @Override - public void flush() { - pw.flush(); - } - - @Override - public void close() throws SecurityException { - pw.close(); - } - }); - }*/ private static final int CODE_FC_SKIP1 = 0xFC; private static final int CODE_FD_OFS8_SKIP_TWICE8 = 0xFD; private static final int CODE_FE_OFS8_POSITIVE = 0xFE; @@ -80,19 +53,6 @@ public class IggyIndexBuilder { public static final int CONST_TEXT_DATA_SIZE = 8; public static final int CONST_SEQUENCE_SIZE = 9; - /*final byte[] STATIC_HDR = new byte[]{ - (byte) 0x0A, (byte) 0x18, (byte) 0x07, (byte) 0x00, (byte) 0x05, (byte) 0x04, (byte) 0x05, (byte) 0x08, (byte) 0x05, (byte) 0x0C, (byte) 0x05, (byte) 0x12, (byte) 0x04, (byte) 0x14, (byte) 0x04, (byte) 0x16, - (byte) 0x04, (byte) 0x06, (byte) 0x03, (byte) 0x00, (byte) 0x04, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x04, (byte) 0x20, (byte) 0x03, (byte) 0x08, (byte) 0x04, (byte) 0x10, (byte) 0x08, (byte) 0x18, - (byte) 0x02, (byte) 0x60, (byte) 0x0D, (byte) 0x00, (byte) 0x02, (byte) 0x09, (byte) 0x03, (byte) 0x0C, (byte) 0x05, (byte) 0x10, (byte) 0x05, (byte) 0x14, (byte) 0x05, (byte) 0x18, (byte) 0x05, (byte) 0x1C, - (byte) 0x05, (byte) 0x20, (byte) 0x05, (byte) 0x24, (byte) 0x05, (byte) 0x28, (byte) 0x04, (byte) 0x30, (byte) 0x02, (byte) 0x38, (byte) 0x04, (byte) 0x3A, (byte) 0x04, (byte) 0x18, (byte) 0x02, (byte) 0x08, - (byte) 0x02, (byte) 0x10, (byte) 0x05, (byte) 0x40, (byte) 0x09, (byte) 0x00, (byte) 0x05, (byte) 0x04, (byte) 0x05, (byte) 0x08, (byte) 0x05, (byte) 0x0C, (byte) 0x05, (byte) 0x10, (byte) 0x02, (byte) 0x18, - (byte) 0x05, (byte) 0x20, (byte) 0x02, (byte) 0x28, (byte) 0x02, (byte) 0x30, (byte) 0x02, (byte) 0x70, (byte) 0x12, (byte) 0x01, (byte) 0x0C, (byte) 0x02, (byte) 0x04, (byte) 0x08, (byte) 0x05, (byte) 0x10, - (byte) 0x02, (byte) 0x20, (byte) 0x04, (byte) 0x22, (byte) 0x04, (byte) 0x24, (byte) 0x04, (byte) 0x26, (byte) 0x04, (byte) 0x2B, (byte) 0x03, (byte) 0x30, (byte) 0x02, (byte) 0x38, (byte) 0x02, (byte) 0x40, - (byte) 0x02, (byte) 0x48, (byte) 0x05, (byte) 0x4C, (byte) 0x05, (byte) 0x50, (byte) 0x05, (byte) 0x54, (byte) 0x05, (byte) 0x58, (byte) 0x05, (byte) 0x60, (byte) 0x02, (byte) 0xF0, (byte) 0x01, (byte) 0x10, - (byte) 0x02, (byte) 0x68, (byte) 0x12, (byte) 0x01, (byte) 0x0C, (byte) 0x02, (byte) 0x04, (byte) 0x08, (byte) 0x05, (byte) 0x10, (byte) 0x02, (byte) 0x20, (byte) 0x05, (byte) 0x24, (byte) 0x05, (byte) 0x28, - (byte) 0x05, (byte) 0x2C, (byte) 0x05, (byte) 0x30, (byte) 0x04, (byte) 0x32, (byte) 0x04, (byte) 0x38, (byte) 0x02, (byte) 0x44, (byte) 0x04, (byte) 0x46, (byte) 0x04, (byte) 0x48, (byte) 0x04, (byte) 0x4A, - (byte) 0x04, (byte) 0x4C, (byte) 0x04, (byte) 0x4E, (byte) 0x04, (byte) 0x60, (byte) 0x02, (byte) 0x10, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x08, (byte) 0x05}; - */ private long position = 0; public IggyIndexBuilder() throws IOException { @@ -157,14 +117,6 @@ public class IggyIndexBuilder { return writeIndex(constIndex, false, 0); } - /*private int indexOfConst(int val) { - int index = constTable.indexOf(val); - if (index > -1) { - return index; - } - constTable.add(val); - return constTable.size() - 1; - }*/ public long writeConstLengthArray(int constIndex, long cnt) { long ret = 0; long rem = cnt; From 160444590a7b3a8559a3b88e57e9179615efb995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 4 Dec 2016 19:07:21 +0100 Subject: [PATCH 27/27] organize imports --- .../decompiler/flash/iggy/IggyCharAdvances.java | 2 +- .../decompiler/flash/iggy/IggyCharIndices.java | 6 +++--- .../decompiler/flash/iggy/IggyCharKerning.java | 2 +- .../decompiler/flash/iggy/IggyCharOffset.java | 6 +++--- .../com/jpexs/decompiler/flash/iggy/IggyFile.java | 13 ++++--------- .../decompiler/flash/iggy/IggyFlashHeader32.java | 2 +- .../decompiler/flash/iggy/IggyFlashHeader64.java | 2 +- .../com/jpexs/decompiler/flash/iggy/IggyFont.java | 8 +++----- .../decompiler/flash/iggy/IggyFontTypeInfo.java | 1 - .../jpexs/decompiler/flash/iggy/IggyHeader.java | 6 +++--- .../com/jpexs/decompiler/flash/iggy/IggyShape.java | 6 +----- .../jpexs/decompiler/flash/iggy/IggyShapeNode.java | 5 +---- .../decompiler/flash/iggy/IggySubFileEntry.java | 4 +--- .../com/jpexs/decompiler/flash/iggy/IggySwf.java | 14 ++++---------- .../com/jpexs/decompiler/flash/iggy/IggyText.java | 2 +- 15 files changed, 28 insertions(+), 51 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java index 61390c3d5..b7a5e7fce 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharAdvances.java @@ -1,7 +1,7 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; 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; import java.util.ArrayList; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java index 207dcf724..cf3d28e95 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharIndices.java @@ -1,9 +1,9 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +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; import java.util.ArrayList; import java.util.List; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index 1353ced5c..6b60bdd20 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -1,7 +1,7 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; 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; import java.util.ArrayList; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index d753582db..b3632d94e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -1,9 +1,9 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +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; import java.util.logging.Logger; 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 c49c6a683..4b248ef66 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 @@ -1,26 +1,21 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.IggyIndexParser; +import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.SeekMode; 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.SeekMode; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; -import com.jpexs.helpers.Helper; +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.io.RandomAccessFile; -import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; 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 0c913fd0d..55178b372 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 @@ -1,8 +1,8 @@ package com.jpexs.decompiler.flash.iggy; +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; /** 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 f5a17c9eb..ecf77100c 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,9 +1,9 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.annotations.FieldPrinter; +import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import java.io.IOException; import java.lang.reflect.Field; 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 3dd59f192..978d05c8e 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 @@ -1,13 +1,11 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.SeekMode; -import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; 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.WriteDataStreamInterface; import java.io.IOException; import java.util.ArrayList; import java.util.List; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java index 7760816e2..b326f6673 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFontTypeInfo.java @@ -2,7 +2,6 @@ package com.jpexs.decompiler.flash.iggy; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; 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; 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 e01a160f0..c6890e6a2 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 @@ -1,10 +1,10 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; +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; /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index b5812944d..1cecf0e49 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -1,13 +1,9 @@ package com.jpexs.decompiler.flash.iggy; -import static com.jpexs.decompiler.flash.iggy.IggyCharOffset.STRUCT_SIZE; -import static com.jpexs.decompiler.flash.iggy.IggyShapeNode.STRUCT_SIZE; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.SeekMode; -import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; 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; import java.util.ArrayList; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java index b99129289..0961f838e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShapeNode.java @@ -1,13 +1,10 @@ package com.jpexs.decompiler.flash.iggy; -import static com.jpexs.decompiler.flash.iggy.IggyShape.STRUCT_SIZE; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; 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; -import java.util.logging.Level; import java.util.logging.Logger; /** 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 05975e37c..485789a04 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 @@ -1,13 +1,11 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; 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 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/IggySwf.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java index f3e3a8ef1..34fafba0f 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 @@ -1,20 +1,14 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.SeekMode; -import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; -import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; -import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder; -import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; -import com.jpexs.helpers.Helper; -import java.io.FileOutputStream; +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.HashMap; import java.util.List; -import java.util.Map; /** * diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java index fdce6f318..8aee23b66 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java @@ -1,11 +1,11 @@ package com.jpexs.decompiler.flash.iggy; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; 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;