From 48177bb534484eeb47f880a3b9a85613edc97e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 30 Nov 2016 10:55:17 +0100 Subject: [PATCH] read and write of fonts matched --- .../flash/iggy/IggyCharKerning.java | 3 - .../decompiler/flash/iggy/IggyCharOffset.java | 19 ++--- .../jpexs/decompiler/flash/iggy/IggyFile.java | 6 +- .../flash/iggy/IggyFlashHeader64.java | 26 +++--- .../jpexs/decompiler/flash/iggy/IggyFont.java | 68 ++++++++++++---- .../decompiler/flash/iggy/IggyShape.java | 8 +- .../jpexs/decompiler/flash/iggy/IggySwf.java | 81 +++++++++++++------ 7 files changed, 141 insertions(+), 70 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java index d1987d2b1..997999b76 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharKerning.java @@ -17,7 +17,6 @@ public class IggyCharKerning implements StructureInterface { List charsA; List charsB; List kerningOffsets; - long pad; public long getKernCount() { return kernCount; @@ -50,7 +49,6 @@ public class IggyCharKerning implements StructureInterface { charsB.add((char) stream.readUI16()); kerningOffsets.add((short) stream.readUI16()); } - pad = stream.readUI32(); } @Override @@ -60,7 +58,6 @@ public class IggyCharKerning implements StructureInterface { stream.writeUI16(charsB.get(i)); stream.writeUI16(kerningOffsets.get(i)); } - stream.writeUI32(pad); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 564531c85..74b197582 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -30,8 +30,14 @@ public class IggyCharOffset implements StructureInterface { @IggyFieldType(DataType.uint32_t) long zero3; @IggyFieldType(DataType.uint64_t) + private long address; + long offset; + public long getAddress() { + return address; + } + public IggyCharOffset(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -56,12 +62,11 @@ public class IggyCharOffset implements StructureInterface { xscale = stream.readUI16(); yscale = stream.readUI16(); zero3 = stream.readUI32(); - long cur_position = stream.position(); - long relative_offset = stream.readUI64(); + offset = stream.readUI64(); if (ischar1 > 0) { - offset = cur_position + relative_offset; + address = offset + stream.position() - 8; } else { - offset = 0; + address = 0; LOGGER.finer(String.format("Empty char")); } } @@ -75,11 +80,7 @@ public class IggyCharOffset implements StructureInterface { stream.writeUI16(xscale); stream.writeUI16(yscale); stream.writeUI32(zero3); - if (ischar1 > 0) { - stream.writeUI64(offset - stream.position()); - } else { - stream.writeUI64(1); - } + stream.writeUI64(offset); } public boolean hasGlyph() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java index 3e151a226..03860a1ae 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java @@ -7,6 +7,7 @@ import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; +import com.jpexs.helpers.Helper; import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; @@ -186,7 +187,7 @@ public class IggyFile implements StructureInterface { } public static void main(String[] args) throws IOException { - String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy"; + /*String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy"; String outFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font2.iggy"; File inFile = new File(inFileName); @@ -198,7 +199,7 @@ public class IggyFile implements StructureInterface { outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); - } + }*/ } private static void copyStream(InputStream is, OutputStream os) { @@ -719,7 +720,6 @@ public class IggyFile implements StructureInterface { for (int i = 0; i < subFileEntries.size(); i++) { IggySubFileEntry entry = subFileEntries.get(i); byte[] entryData = subFileEntriesData.get(i); - stream.seek(entry.offset, SeekMode.SET); stream.writeBytes(entryData); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java index 71de61c57..4c296d361 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java @@ -95,7 +95,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { private long base_address; private long sequence_end_address; private long font_end_address; - private long sequence_start_address; + private long sequence_start_address1; + private long sequence_start_address2; private long names_address; private long unk78_address; private long unk80_address; @@ -146,8 +147,12 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { this.font_end_address = val; } - public long getSequenceStartAddress() { - return sequence_start_address; + public long getSequenceStartAddress1() { + return sequence_start_address1; + } + + public long getSequenceStartAddress2() { + return sequence_start_address2; } public long getNamesAddress() { @@ -180,13 +185,14 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { - off_start = stream.readUI64(); + /* 0:*/ off_start = stream.readUI64(); base_address = off_start + stream.position() - 8; - off_seq_end = stream.readUI64(); + /* 8:*/ off_seq_end = stream.readUI64(); sequence_end_address = off_seq_end + stream.position() - 8; - off_font_end = stream.readUI64(); + /* 10:*/ off_font_end = stream.readUI64(); font_end_address = off_font_end + stream.position() - 8; - off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times) + /* 18:*/ off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times) + sequence_start_address1 = off_seq_start1 + stream.position() - 8; pad_to_match = stream.readUI64(); if (pad_to_match != 1) { throw new IOException("Wrong iggy file - no pad to match 1"); @@ -195,7 +201,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { if (off_seq_start1 != off_seq_start2) { throw new IOException("Wrong iggy font format (sequence_start)!\n"); } - sequence_start_address = off_seq_start2 + stream.position() - 8; + sequence_start_address2 = off_seq_start2 + stream.position() - 8; xmin = stream.readUI32(); ymin = stream.readUI32(); xmax = stream.readUI32(); @@ -243,10 +249,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { stream.writeUI64(off_seq_end); off_font_end = font_end_address - stream.position(); stream.writeUI64(off_font_end); - off_seq_start1 = sequence_start_address - stream.position(); + off_seq_start1 = sequence_start_address1 - stream.position(); stream.writeUI64(off_seq_start1); stream.writeUI64(pad_to_match); - off_seq_start2 = sequence_start_address - stream.position(); + off_seq_start2 = sequence_start_address2 - stream.position(); stream.writeUI64(off_seq_start2); stream.writeUI32(xmin); stream.writeUI32(ymin); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java index dfedbd954..4e7b8cefd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java @@ -73,8 +73,14 @@ public class IggyFont extends IggyTag { long zero_padd_4; @IggyFieldType(DataType.uint64_t) long what_3; - @IggyFieldType(value = DataType.uint8_t, count = 272) - byte[] zeroes; + @IggyFieldType(value = DataType.widechar_t, count = 40) + String subName = ""; + @IggyFieldType(value = DataType.uint8_t, count = 48) + byte[] zeroes48a; + + @IggyFieldType(value = DataType.uint8_t, count = 48) + byte[] zeroes48b; + @IggyFieldType(DataType.float_t) float sss1; @IggyFieldType(DataType.uint32_t) @@ -103,7 +109,7 @@ public class IggyFont extends IggyTag { byte[] padTo4byteBoundary; - public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { + public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List charOffsets, List chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) { this.type = type; this.fontId = order_in_iggy_file; this.zeroone = zeroone; @@ -131,7 +137,7 @@ public class IggyFont extends IggyTag { this.char_count = char_count; this.zero_padd_4 = zero_padd_4; this.what_3 = what_3; - this.zeroes = zeroes; + this.zeroes48a = zeroes48; this.sss1 = sss1; this.one_padd2 = one_padd2; this.sss2 = sss2; @@ -178,11 +184,11 @@ public class IggyFont extends IggyTag { } private long makeAbsOffset(ReadDataStreamInterface s, long offset) { - return offset == 1 ? 0 : s.position() - 8 + offset; + return offset == 1 ? 0 : offset + s.position() - 8; } private long makeAbsOffset(WriteDataStreamInterface s, long offset) { - return offset == 1 ? 0 : s.position() - 8 + offset; + return offset == 1 ? 0 : offset + s.position() - 8; } @Override @@ -224,7 +230,20 @@ public class IggyFont extends IggyTag { char_count = s.readUI32(); zero_padd_4 = s.readUI64(); what_3 = s.readUI64(); - s.seek(basePos + 272, SeekMode.SET); + StringBuilder subNameBuilder = new StringBuilder(); + + boolean snFinish = false; + for (int i = 0; i < 20; i++) { + char c = (char) s.readUI16(); + if (c == '\0') { + snFinish = true; + } + if (!snFinish) { + subNameBuilder.append(c); + } + } + subName = subNameBuilder.toString(); + zeroes48a = s.readBytes(48); sss1 = s.readFloat(); one_padd2 = s.readUI32(); sss2 = s.readFloat(); @@ -233,6 +252,8 @@ public class IggyFont extends IggyTag { one_padd4 = s.readUI32(); sss4 = s.readFloat(); one_padd5 = s.readUI32(); + zeroes48b = s.readBytes(48); + if (abs_start_of_name != 0) { s.seek(abs_start_of_name, SeekMode.SET); StringBuilder nameBuilder = new StringBuilder(); @@ -257,9 +278,10 @@ public class IggyFont extends IggyTag { } glyphs = new ArrayList<>(); for (int i = 0; i < char_count; i++) { - long offset = charOffsets.get(i).offset; - if (offset != 0) { - glyphs.add(new IggyShape(s, offset)); + long addr = charOffsets.get(i).getAddress(); + if (addr != 0) { + s.seek(addr, SeekMode.SET); + glyphs.add(new IggyShape(s)); } else { glyphs.add(null); } @@ -315,7 +337,14 @@ public class IggyFont extends IggyTag { s.writeUI32(char_count); s.writeUI64(zero_padd_4); s.writeUI64(what_3); - s.seek(272, SeekMode.SET); + for (int i = 0; i < 20; i++) { + if (i < subName.length()) { + s.writeUI16((char) subName.charAt(i)); + } else { + s.writeUI16(0); + } + } + s.writeBytes(zeroes48a); s.writeFloat(sss1); s.writeUI32(one_padd2); s.writeFloat(sss2); @@ -324,6 +353,7 @@ public class IggyFont extends IggyTag { s.writeUI32(one_padd4); s.writeFloat(sss4); s.writeUI32(one_padd5); + s.writeBytes(zeroes48b); if (abs_start_of_name != 0) { s.seek(abs_start_of_name, SeekMode.SET); for (char c : name.toCharArray()) { @@ -333,11 +363,14 @@ public class IggyFont extends IggyTag { //align to 8 bytes boundary int len = name.length() * 2 + 2; - int rem = 8 - (len % 8); - for (int i = 0; i < rem; i++) { - s.write(0); + int pad8 = 8 - (len % 8); + if (pad8 < 8) { + for (int i = 0; i < pad8; i++) { + s.write(0); + } } } + s.writeUI64(0); //pad zero if (abs_start_of_char_struct != 0) { s.seek(abs_start_of_char_struct, SeekMode.SET); @@ -348,7 +381,7 @@ public class IggyFont extends IggyTag { for (int i = 0; i < glyphs.size(); i++) { IggyShape shp = glyphs.get(i); if (shp != null) { - s.seek(charOffsets.get(i).offset, SeekMode.SET); + s.seek(charOffsets.get(i).getAddress(), SeekMode.SET); shp.writeToDataStream(s); } } @@ -368,6 +401,11 @@ public class IggyFont extends IggyTag { s.seek(abs_start_of_kern, SeekMode.SET); charKernings.writeToDataStream(s); } + + if ((s.position() - abs_start_of_char_index) % 8 != 0) { + byte padd[] = new byte[(int) (((s.position() - abs_start_of_char_index) / 8 + 1) * 8 - (s.position() - abs_start_of_char_index))]; + s.writeBytes(padd); + } } public int getType() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index 7fa2aa585..33c0ccfa3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -60,10 +60,7 @@ public class IggyShape implements StructureInterface { List nodes; - private long offset; - - public IggyShape(ReadDataStreamInterface stream, long offset) throws IOException { - this.offset = offset; + public IggyShape(ReadDataStreamInterface stream) throws IOException { readFromDataStream(stream); } @@ -84,7 +81,6 @@ public class IggyShape implements StructureInterface { @Override public void readFromDataStream(ReadDataStreamInterface s) throws IOException { - s.seek(offset, SeekMode.SET); minx = s.readFloat(); miny = s.readFloat(); maxx = s.readFloat(); @@ -98,7 +94,7 @@ public class IggyShape implements StructureInterface { two1 = s.readUI32(); if ((one != 1) || (one2 != 1) || (one3 != 1) || (one4 != 1) || (two1 != 2)) { - LOGGER.fine(String.format("Unique header at pos %d, one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", offset, one, one2, one3, one4, two1)); + LOGGER.fine(String.format("Unique header at one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", one, one2, one3, one4, two1)); } nodes = new ArrayList<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java index 8d9739e14..a8596d460 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java @@ -7,6 +7,8 @@ import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; +import com.jpexs.helpers.Helper; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -38,6 +40,8 @@ public class IggySwf implements StructureInterface { private long font_data_sizes[]; private List text_addresses = new ArrayList<>(); private List text_data_sizes = new ArrayList<>(); + private List text_data_bytes = new ArrayList<>(); + private byte font_add_data[]; private List font_add_off = new ArrayList<>(); private List font_add_size = new ArrayList<>(); @@ -95,7 +99,7 @@ public class IggySwf implements StructureInterface { s.seek(pad8, SeekMode.CUR); //here is offset [2] s.seek(hdr.getBaseAddress(), SeekMode.SET); - s.readUI64(); //one pad + s.readUI64(); //pad 1 font_data_addresses = new long[(int) hdr.font_count]; font_data_sizes = new long[(int) hdr.font_count]; @@ -113,6 +117,9 @@ public class IggySwf implements StructureInterface { } while (true) { long offset = s.readUI64(); + if (offset == 1) { + break; + } long text_addr = offset + s.position() - 8; text_addresses.add(text_addr); long next_offset = s.readUI64(); @@ -124,13 +131,14 @@ public class IggySwf implements StructureInterface { text_data_sizes.add(next_offset - offset); } } + s.readUI64(); //1 if (hdr.isImported()) { // tohle muze narusit iggy order, ale oni to pak stejne pocitaji dle infa long additionalOffset = s.readUI64(); font_add_off.add(additionalOffset + s.position() - 8); font_add_size.add(hdr.getFontEndAddress() - font_add_off.get(0)); if (s.readUI8(font_add_off.get(0)) != 22) { //22 = Text - for (int i = 0; i < hdr.font_count; i++) { + for (int i = 0; i < text_addresses.size(); i++) { if (s.readUI8(text_addresses.get(i)) == 22) { //TEXT long pomoff; long pomsize; @@ -144,27 +152,30 @@ public class IggySwf implements StructureInterface { } } } - - //long skipBytes = 840 - s.position(); fonts = new HashMap<>(); for (int i = 0; i < hdr.font_count; i++) { s.seek(font_data_addresses[i], SeekMode.SET); //byte font_data[] = s.readBytes((int) font_data_sizes[i]); IggyFont font = new IggyFont(s); - fonts.put(i/*??*/, font); + fonts.put(i, font); } for (int i = 0; i < text_addresses.size(); i++) { + s.seek(text_addresses.get(i), SeekMode.SET); byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i)); + text_data_bytes.add(text_data); } if (hdr.isImported()) { s.seek(font_add_off.get(0), SeekMode.SET); - byte font_add_data[] = s.readBytes((int) (long) font_add_size.get(0)); + font_add_data = s.readBytes((int) (long) font_add_size.get(0)); } - s.seek(hdr.getFontEndAddress(), SeekMode.SET); + WriteDataStreamInterface outs = new TemporaryDataStream(); + writeToDataStream(outs); + Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes()); + } public String getName() { @@ -172,25 +183,47 @@ public class IggySwf implements StructureInterface { } @Override - public void writeToDataStream(WriteDataStreamInterface st) throws IOException { - try (DataStreamInterface s = new TemporaryDataStream(allFontBytes)) { - hdr.writeToDataStream(s); - s.writeUI64(1); - for (int i = 0; i < font_data_addresses.length; i++) { - long offset = font_data_addresses[i] - s.position() + 8; - s.writeUI64(offset); + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + hdr.writeToDataStream(s); + for (int i = 0; i < name.length(); i++) { + s.writeUI16(name.charAt(i)); + } + s.writeUI16(0); + + int pad8 = 8 - (int) (s.position() % 8); + if (pad8 < 8) { + for (int i = 0; i < pad8; i++) { + s.write(0); } - s.writeUI64(1); - for (int i = 0; i < text_addresses.size(); i++) { - long offset = text_addresses.get(i) - s.position() + 8; - s.writeUI64(offset); + } + s.writeUI64(1); + for (int i = 0; i < font_data_addresses.length; i++) { + long offset = font_data_addresses[i] - s.position(); + s.writeUI64(offset); + } + for (int i = 0; i < text_addresses.size(); i++) { + long offset = text_addresses.get(i) - s.position(); + s.writeUI64(offset); + } + s.writeUI64(1); + + if (hdr.font_count > 0) { + while (s.position() < font_data_addresses[0]) { + s.writeUI64(1); } - s.writeUI64(1); - s.seek(840, SeekMode.SET); - for (int i = 0; i < hdr.font_count; i++) { - fonts.get(i).writeToDataStream(s); - } - st.writeBytes(s.getAllBytes()); + } + for (int i = 0; i < hdr.font_count; i++) { + s.seek(font_data_addresses[i], SeekMode.SET); + fonts.get(i).writeToDataStream(s); + } + for (int i = 0; i < text_data_bytes.size(); i++) { + s.seek(text_addresses.get(i), SeekMode.SET); + s.writeBytes(text_data_bytes.get(i)); + } + + if (hdr.isImported()) { + s.seek(font_add_off.get(0), SeekMode.SET); + s.writeBytes(font_add_data); } }