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] 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(); +}