package com.jpexs.decompiler.flash.iggy;
import com.jpexs.decompiler.flash.iggy.annotations.FieldPrinter;
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
import java.io.IOException;
import java.lang.reflect.Field;
/**
*
* @author Jindra
*
* Based of works of somebody called eternity.
*/
public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
@IggyFieldType(DataType.uint64_t)
long off_base; // 0 Relative offset to first section (matches sizeof header);
@IggyFieldType(DataType.uint64_t)
long off_sequence_end; // 8 Relative offset to as3 file names table...
@IggyFieldType(DataType.uint64_t)
long off_font_end; // 0x10 relative offset to something
@IggyFieldType(DataType.uint64_t)
long off_sequence_start1; // 0x18 relative offset to something
@IggyFieldType(DataType.uint64_t)
long off_sequence_start2; // 0x20 relative offset to something
@IggyFieldType(DataType.uint64_t)
long off_sequence_start3; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file
@IggyFieldType(DataType.uint32_t)
long xmin; // 0x30 in pixels
@IggyFieldType(DataType.uint32_t)
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 imported_guid;
@IggyFieldType(DataType.uint64_t)
long my_guid; // same for some fonts (eng + chinese)
@IggyFieldType(DataType.uint64_t)
long off_names; // 0x70 relative offset to the names/import section of the file - end of fonts
@IggyFieldType(DataType.uint64_t)
long off_unk78; // 0x78 relative offset to something
@IggyFieldType(DataType.uint64_t)
long unk80;
@IggyFieldType(DataType.uint64_t)
long off_last_section;
@IggyFieldType(DataType.uint64_t)
long off_flash_filename;
@IggyFieldType(DataType.uint64_t)
long off_decl_strings;
@IggyFieldType(DataType.uint64_t)
long off_type_of_fonts;
@IggyFieldType(DataType.uint64_t)
long flags;
@IggyFieldType(DataType.uint32_t)
long font_count;
@IggyFieldType(DataType.uint32_t)
long zero2;
// Offset 0xB8 (outside header): there are *unk_40* relative offsets that point to flash objects.
// The flash objects are in a format different to swf but there is probably a way to convert between them.
// 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(ReadDataStreamInterface stream) throws IOException {
readFromDataStream(stream);
}
private long base_address;
private long sequence_end_address;
private long font_end_address;
private long sequence_start_address1;
private long sequence_start_address2;
private long sequence_start_address3;
private long names_address;
private long unk78_address;
private long last_section_address;
private long flash_filename_address;
private long decl_strings_address;
private long type_fonts_address;
private long base_ofs_pos;
private long sequence_end_ofs_pos;
private long font_end_ofs_pos;
private long sequence_start1_ofs_pos;
private long sequence_start2_ofs_pos;
private long sequence_start3_ofs_pos;
private long names_ofs_pos;
private long unk78_ofs_pos;
private long last_section_ofs_pos;
private long flash_filename_ofs_pos;
private long decl_strings_ofs_pos;
private long type_fonts_ofs_pos;
public long getBase_ofs_pos() {
return base_ofs_pos;
}
public long getSequence_end_ofs_pos() {
return sequence_end_ofs_pos;
}
public long getFont_end_ofs_pos() {
return font_end_ofs_pos;
}
public long getSequence_start1_ofs_pos() {
return sequence_start1_ofs_pos;
}
public long getSequence_start2_ofs_pos() {
return sequence_start2_ofs_pos;
}
public long getSequence_start3_ofs_pos() {
return sequence_start3_ofs_pos;
}
public long getNames_ofs_pos() {
return names_ofs_pos;
}
public long getUnk78_ofs_pos() {
return unk78_ofs_pos;
}
public long getLast_section_ofs_pos() {
return last_section_ofs_pos;
}
public long getFlash_filename_ofs_pos() {
return flash_filename_ofs_pos;
}
public long getDecl_strings_ofs_pos() {
return decl_strings_ofs_pos;
}
public long getType_fonts_ofs_pos() {
return type_fonts_ofs_pos;
}
/**
* Updates all addresses by inserting gap
*
* @param pos Position to insert bytes
* @param size Number of bytes
*/
public void insertGapAfter(long pos, long size) {
for (Field f : IggyFlashHeader64.class.getDeclaredFields()) {
if (f.getName().endsWith("_address")) {
try {
long val = f.getLong(this);
if (val > pos) {
long newval = val + size;
f.setLong(this, newval);
}
} catch (IllegalAccessException iex) {
//should not happen
}
}
}
}
public long getImported_guid() {
return imported_guid;
}
public long getBaseAddress() {
return base_address;
}
public long getSequenceEndAddress() {
return sequence_end_address;
}
public long getFontEndAddress() {
return font_end_address;
}
public void setFontEndAddress(long val) {
this.font_end_address = val;
}
public long getSequenceStartAddress1() {
return sequence_start_address1;
}
public long getSequenceStartAddress2() {
return sequence_start_address2;
}
public long getSequenceStartAddress3() {
return sequence_start_address3;
}
public long getNamesAddress() {
return names_address;
}
public long getUnk78Address() {
return unk78_address;
}
public long getLastSectionAddress() {
return last_section_address;
}
public long getFlashFilenameAddress() {
return flash_filename_address;
}
public long getDeclStringsAddress() {
return decl_strings_address;
}
public long getTypeFontsAddress() {
return type_fonts_address;
}
@Override
public void readFromDataStream(ReadDataStreamInterface stream) throws IOException {
base_ofs_pos = stream.position();
off_base = stream.readUI64();
base_address = off_base == 1 ? 0 : off_base + stream.position() - 8;
sequence_end_ofs_pos = stream.position();
off_sequence_end = stream.readUI64();
sequence_end_address = off_sequence_end == 1 ? 0 : off_sequence_end + stream.position() - 8;
font_end_ofs_pos = stream.position();
off_font_end = stream.readUI64();
font_end_address = off_font_end == 1 ? 0 : off_font_end + stream.position() - 8;
sequence_start1_ofs_pos = stream.position();
off_sequence_start1 = stream.readUI64();
sequence_start_address1 = off_sequence_start1 == 1 ? 0 : off_sequence_start1 + stream.position() - 8;
sequence_start2_ofs_pos = stream.position();
off_sequence_start2 = stream.readUI64();
sequence_start_address2 = off_sequence_start2 == 1 ? 0 : off_sequence_start2 + stream.position() - 8;
sequence_start3_ofs_pos = stream.position();
off_sequence_start3 = stream.readUI64();
sequence_start_address3 = off_sequence_start3 == 1 ? 0 : off_sequence_start3 + stream.position() - 8;
xmin = stream.readUI32();
ymin = stream.readUI32();
xmax = stream.readUI32();
ymax = stream.readUI32();
unk_40 = stream.readUI32(); // probably number of blocks/objects after header
unk_44 = stream.readUI32();
unk_48 = stream.readUI32();
unk_4C = stream.readUI32();
unk_50 = stream.readUI32();
unk_54 = stream.readUI32();
frame_rate = stream.readFloat();
unk_5C = stream.readUI32();
imported_guid = stream.readUI64();
my_guid = stream.readUI64();
names_ofs_pos = stream.position();
off_names = stream.readUI64();
names_address = off_names == 1 ? 0 : off_names + stream.position() - 8;
unk78_ofs_pos = stream.position();
off_unk78 = stream.readUI64();
unk78_address = off_unk78 == 1 ? 0 : off_unk78 + stream.position() - 8;
unk80 = stream.readUI64(); //Maybe number of imports/names pointed by names_offset
last_section_ofs_pos = stream.position();
off_last_section = stream.readUI64();
last_section_address = off_last_section == 1 ? 0 : off_last_section + stream.position() - 8;
flash_filename_ofs_pos = stream.position();
off_flash_filename = stream.readUI64();
flash_filename_address = off_flash_filename == 1 ? 0 : off_flash_filename + stream.position() - 8;
decl_strings_ofs_pos = stream.position();
off_decl_strings = stream.readUI64(); //relative offset to as3 code (16 bytes header + abc blob)
decl_strings_address = off_decl_strings == 1 ? 0 : off_decl_strings + stream.position() - 8;
type_fonts_ofs_pos = stream.position();
off_type_of_fonts = stream.readUI64(); //relative offset to as3 file names table (or classes names or whatever)
type_fonts_address = off_type_of_fonts == 1 ? 0 : off_type_of_fonts + stream.position() - 8;
flags = stream.readUI64();
font_count = stream.readUI32();
zero2 = stream.readUI32();
}
@Override
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
off_base = base_address == 0 ? 1 : base_address - stream.position();
stream.writeUI64(off_base);
off_sequence_end = sequence_end_address == 0 ? 1 : sequence_end_address - stream.position();
stream.writeUI64(off_sequence_end);
off_font_end = font_end_address == 0 ? 1 : font_end_address - stream.position();
stream.writeUI64(off_font_end);
off_sequence_start1 = sequence_start_address1 == 0 ? 1 : sequence_start_address1 - stream.position();
stream.writeUI64(off_sequence_start1);
off_sequence_start2 = sequence_start_address2 == 0 ? 1 : sequence_start_address2 - stream.position();
stream.writeUI64(off_sequence_start2);
off_sequence_start3 = sequence_start_address3 == 0 ? 1 : sequence_start_address3 - stream.position();
stream.writeUI64(off_sequence_start3);
stream.writeUI32(xmin);
stream.writeUI32(ymin);
stream.writeUI32(xmax);
stream.writeUI32(ymax);
stream.writeUI32(unk_40);
stream.writeUI32(unk_44);
stream.writeUI32(unk_48);
stream.writeUI32(unk_4C);
stream.writeUI32(unk_50);
stream.writeUI32(unk_54);
stream.writeFloat(frame_rate);
stream.writeUI32(unk_5C);
stream.writeUI64(imported_guid);
stream.writeUI64(my_guid);
off_names = names_address == 0 ? 1 : names_address - stream.position();
stream.writeUI64(off_names);
off_unk78 = unk78_address == 0 ? 1 : unk78_address - stream.position();
stream.writeUI64(off_unk78);
stream.writeUI64(unk80);
off_last_section = last_section_address == 0 ? 1 : last_section_address - stream.position();
stream.writeUI64(off_last_section);
off_flash_filename = flash_filename_address == 0 ? 1 : flash_filename_address - stream.position();
stream.writeUI64(off_flash_filename);
off_decl_strings = decl_strings_address == 0 ? 1 : decl_strings_address - stream.position();
stream.writeUI64(off_decl_strings);
off_type_of_fonts = type_fonts_address == 0 ? 1 : type_fonts_address - stream.position();
stream.writeUI64(off_type_of_fonts);
stream.writeUI64(flags);
stream.writeUI32(font_count);
stream.writeUI32(zero2);
stream.getIndexing().writeLengthCustom(184, new int[]{0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x34, 0x38, 0x3C, 0x40, 0x44, 0x48, 0x4C, 0x50, 0x58, 0x70, 0x78, 0x80, 0x84, 0x88, 0x90, 0x98, 0xA0, 0xB0}, new int[]{2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2, 2, 2, 2, 5});
}
@Override
public String toString() {
return FieldPrinter.getObjectSummary(this);
}
@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;
}
}