mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-06 22:26:30 +00:00
Reading index, refactorings
This commit is contained in:
@@ -16,6 +16,8 @@ public abstract class AbstractDataStream {
|
||||
*/
|
||||
public abstract Long available();
|
||||
|
||||
public abstract boolean is64();
|
||||
|
||||
protected long readUI64() throws IOException {
|
||||
try {
|
||||
return (readUI32() + (readUI32() << 32)) & 0xffffffffffffffffL;
|
||||
|
||||
@@ -12,14 +12,21 @@ public class ByteArrayDataStream extends AbstractDataStream {
|
||||
|
||||
private byte[] data;
|
||||
private int pos;
|
||||
private boolean use64bit;
|
||||
|
||||
public ByteArrayDataStream(int initialSize) {
|
||||
this(new byte[initialSize]);
|
||||
public ByteArrayDataStream(int initialSize, boolean use64bit) {
|
||||
this(new byte[initialSize], use64bit);
|
||||
}
|
||||
|
||||
public ByteArrayDataStream(byte data[]) {
|
||||
public ByteArrayDataStream(byte data[], boolean use64bit) {
|
||||
this.data = data;
|
||||
pos = 0;
|
||||
this.use64bit = use64bit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is64() {
|
||||
return use64bit;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,5 +4,6 @@ package com.jpexs.decompiler.flash.iggy;
|
||||
* @author JPEXS
|
||||
*/
|
||||
public enum DataType {
|
||||
uint8_t, uint16_t, uint32_t, uint64_t, unknown
|
||||
ubits, uint8_t, uint16_t, uint32_t, uint64_t, unknown,
|
||||
widechar_t //or maybe just "string"? It has two bytes per character and is null terminated
|
||||
}
|
||||
|
||||
@@ -33,47 +33,47 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable {
|
||||
List<List<Integer>> indexTables = new ArrayList<>();
|
||||
List<List<Long>> offsetTables = new ArrayList<>();
|
||||
|
||||
IggyFlashHeader64 fh64 = null;
|
||||
IggyFlashHeader32 fh32 = null;
|
||||
List<IggyFlashHeaderInterface> headers = new ArrayList<>();
|
||||
List<IggyNameAndTagList> namesAndTagLists = new ArrayList<>();
|
||||
|
||||
public IggyExtractor(File file) throws IOException {
|
||||
raf = new RandomAccessFile(file, "r");
|
||||
header = new IggyHeader(this);
|
||||
for (int i = 0; i < header.num_subfiles; i++) {
|
||||
for (int i = 0; i < header.getNumSubfiles(); i++) {
|
||||
subFileEntries.add(new IggySubFileEntry(this));
|
||||
}
|
||||
|
||||
List<byte[]> indexDatas = new ArrayList<>();
|
||||
List<ByteArrayDataStream> flashStreams = 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) {
|
||||
indexDatas.add(getEntryData(i));
|
||||
List<Integer> indexTable = new ArrayList<>();
|
||||
List<Long> offsets = new ArrayList<>();
|
||||
IggyIndexParser.parseIndex(dataStream, indexTable, offsets);
|
||||
indexTables.add(indexTable);
|
||||
offsetTables.add(offsets);
|
||||
} else if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
flashStreams.add(getEntryDataStream(i));
|
||||
IggyFlashHeaderInterface hdr;
|
||||
if (is64()) {
|
||||
hdr = new IggyFlashHeader64(dataStream);
|
||||
} else {
|
||||
hdr = new IggyFlashHeader32(dataStream);
|
||||
}
|
||||
headers.add(hdr);
|
||||
namesAndTagLists.add(new IggyNameAndTagList(dataStream));
|
||||
flashStreams.add(dataStream);
|
||||
}
|
||||
}
|
||||
|
||||
for (byte[] index_data : indexDatas) {
|
||||
List<Integer> indexTableEntry = new ArrayList<>();
|
||||
List<Long> offsets = new ArrayList<>();
|
||||
parseIndex(is64(), index_data, indexTableEntry, offsets);
|
||||
indexTables.add(indexTableEntry);
|
||||
offsetTables.add(offsets);
|
||||
}
|
||||
|
||||
for (ByteArrayDataStream fs : flashStreams) {
|
||||
if (is64()) {
|
||||
fh64 = new IggyFlashHeader64(fs);
|
||||
System.out.println("" + fh64);
|
||||
} else {
|
||||
fh32 = new IggyFlashHeader32(fs);
|
||||
}
|
||||
for (int i = 0; i < flashStreams.size(); i++) {
|
||||
List<Long> offsets = offsetTables.get(i);
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
private boolean is64() {
|
||||
@Override
|
||||
public boolean is64() {
|
||||
return header.is64();
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable {
|
||||
baos.write(buf, 0, cnt);
|
||||
}
|
||||
byte data[] = baos.toByteArray();
|
||||
return new ByteArrayDataStream(data);
|
||||
return new ByteArrayDataStream(data, is64());
|
||||
}
|
||||
|
||||
public InputStream getEntryInputStream(int entryIndex) {
|
||||
@@ -252,7 +252,7 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable {
|
||||
}
|
||||
|
||||
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);
|
||||
ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes, is_64);
|
||||
|
||||
/*
|
||||
index_table:
|
||||
@@ -468,7 +468,7 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable {
|
||||
* @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);
|
||||
ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes, is_64);
|
||||
|
||||
/*
|
||||
index_table:
|
||||
@@ -648,156 +648,6 @@ public class IggyExtractor extends AbstractDataStream implements AutoCloseable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param is_64
|
||||
* @param index_bytes
|
||||
* @param indexTableEntry
|
||||
* @param offsets
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void parseIndex(boolean is_64, byte index_bytes[], List<Integer> indexTableEntry, List<Long> offsets) throws IOException {
|
||||
ByteArrayDataStream stream = new ByteArrayDataStream(index_bytes);
|
||||
|
||||
int index_table_size = stream.readUI8();
|
||||
int[] index_table = new int[index_table_size];
|
||||
|
||||
for (int i = 0; i < index_table_size; i++) {
|
||||
int offset = stream.readUI8();
|
||||
//System.err.printf("index_table_entry: %02x\n", offset);
|
||||
index_table[i] = offset;
|
||||
indexTableEntry.add(offset);
|
||||
int num = stream.readUI8();
|
||||
stream.seek(num * 2, SeekMode.CUR);
|
||||
}
|
||||
|
||||
long offset = 0;
|
||||
int code;
|
||||
|
||||
while ((code = stream.readUI8()) > -1) {
|
||||
//DPRINTF("Code = %x\n", code);
|
||||
|
||||
if (code < 0x80) // 0-0x7F
|
||||
{
|
||||
// code is directly an index to the index_table
|
||||
if (code >= index_table_size) {
|
||||
System.err.printf("< 0x80: index is greater than index_table_size. %x > %x\n", code, index_table_size);
|
||||
return;
|
||||
}
|
||||
|
||||
offset += index_table[code];
|
||||
} else if (code < 0xC0) // 0x80-BF
|
||||
{
|
||||
int index;
|
||||
|
||||
if ((index = stream.readUI8()) < 0) {
|
||||
System.err.printf("< 0xC0: Cannot read index.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index >= index_table_size) {
|
||||
System.err.printf("< 0xC0: index is greater than index_table_size. %x > %x\n", index, index_table_size);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
int n8;
|
||||
int n;
|
||||
|
||||
if ((n8 = stream.readUI8()) < 0) {
|
||||
System.err.printf("< 0xE0: Cannot read n.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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 {
|
||||
System.err.printf("< 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:
|
||||
System.err.printf("< 0xE0: invalid value for i (%x %x)\n", i, code);
|
||||
}
|
||||
}
|
||||
} else if (code == 0xFC) {
|
||||
stream.seek(1, SeekMode.CUR);
|
||||
} else if (code == 0xFD) {
|
||||
int n, m;
|
||||
|
||||
if ((n = stream.readUI8()) < 0) {
|
||||
System.err.printf("0xFD: Cannot read n.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m = stream.readUI8()) < 0) {
|
||||
System.err.printf("0xFD: Cannot read m.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
offset += n;
|
||||
stream.seek(m * 2, SeekMode.CUR);
|
||||
} else if (code == 0xFE) {
|
||||
int n8;
|
||||
int n;
|
||||
|
||||
if ((n8 = stream.readUI8()) < 0) {
|
||||
System.err.printf("0xFE: Cannot read n.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
n = n8 + 1;
|
||||
offset += n;
|
||||
} else if (code == 0xFF) {
|
||||
long n;
|
||||
|
||||
if ((n = stream.readUI32()) < 0) {
|
||||
System.err.printf("0xFF: Cannot read n.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
offset += n;
|
||||
} else {
|
||||
System.err.printf("Unrecognized code: %x\n", code);
|
||||
}
|
||||
|
||||
offsets.add(offset);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long available() {
|
||||
try {
|
||||
|
||||
@@ -17,7 +17,7 @@ import java.util.Map;
|
||||
* All relative offsets are relative from that specific field position All
|
||||
* relative offsets can get value "1" to indicate "nothing"
|
||||
*/
|
||||
public class IggyFlashHeader32 implements StructureInterface {
|
||||
public class IggyFlashHeader32 implements IggyFlashHeaderInterface {
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long main_offset; // 0 Relative offset to first section (matches sizeof header)
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Map;
|
||||
*
|
||||
* Based of works of somebody called eternity.
|
||||
*/
|
||||
public class IggyFlashHeader64 implements StructureInterface {
|
||||
public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long main_offset; // 0 Relative offset to first section (matches sizeof header);
|
||||
@@ -77,11 +77,6 @@ public class IggyFlashHeader64 implements StructureInterface {
|
||||
long unk_B0; // Maybe number of classes / as3 names
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_B4;
|
||||
@IggyFieldType(value = DataType.uint16_t, count = 20)
|
||||
String name;
|
||||
|
||||
List<Integer> tagIds = new ArrayList<>();
|
||||
List<Long> tagIdsExtendedInfo = new ArrayList<>();
|
||||
|
||||
/*@IggyArrayFieldType(value = DataType.uint32_t, count = 20)
|
||||
long unk_offsets_a[] = new long[20];
|
||||
@@ -97,8 +92,25 @@ public class IggyFlashHeader64 implements StructureInterface {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
private int ofs = 0;
|
||||
private List<Long> offsets;
|
||||
|
||||
private String currentOffset() {
|
||||
return String.format(" [offset: %d]", offsets.get(ofs++));
|
||||
}
|
||||
|
||||
/*
|
||||
offsets:
|
||||
name (UI16 chars, zero terminated)
|
||||
UI16
|
||||
taglist_offset (aka main_offset)
|
||||
after_taglist
|
||||
|
||||
|
||||
*/
|
||||
@Override
|
||||
public void readFromDataStream(AbstractDataStream stream) throws IOException {
|
||||
this.offsets = offsets;
|
||||
main_offset = stream.readUI64();
|
||||
as3_section_offset = stream.readUI64();
|
||||
unk_offset = stream.readUI64();
|
||||
@@ -130,26 +142,6 @@ public class IggyFlashHeader64 implements StructureInterface {
|
||||
unk_AC = stream.readUI32();
|
||||
unk_B0 = stream.readUI32();
|
||||
unk_B4 = stream.readUI32();
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
do {
|
||||
char c = (char) stream.readUI16();
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
nameBuilder.append(c);
|
||||
} while (true);
|
||||
name = nameBuilder.toString();
|
||||
|
||||
while (true) {
|
||||
long typeLen = stream.readUI32();
|
||||
if (typeLen == 0) {
|
||||
break;
|
||||
}
|
||||
long tagLength = stream.readUI32();
|
||||
int tagType = (int) ((typeLen >>> 6) + 10) & 0x3FF;
|
||||
tagIds.add(tagType);
|
||||
tagIdsExtendedInfo.add(tagLength);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,18 +153,18 @@ public class IggyFlashHeader64 implements StructureInterface {
|
||||
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(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("main_offset ").append(main_offset).append(currentOffset()).append("\r\n");
|
||||
sb.append("as3_section_offset ").append(as3_section_offset).append(currentOffset()).append("\r\n");
|
||||
sb.append("unk_offset ").append(unk_offset).append(currentOffset()).append("\r\n");
|
||||
sb.append("unk_offset2 ").append(unk_offset2).append(currentOffset()).append("\r\n");
|
||||
sb.append("unk_offset3 ").append(unk_offset3).append(currentOffset()).append("\r\n");
|
||||
sb.append("unk_offset4 ").append(unk_offset4).append(currentOffset()).append("\r\n");
|
||||
sb.append("xmin ").append(xmin).append(currentOffset()).append("\r\n");
|
||||
sb.append("ymin ").append(ymin).append(currentOffset()).append("\r\n");
|
||||
sb.append("xmax ").append(ymax).append(currentOffset()).append("\r\n");
|
||||
sb.append("ymax ").append(ymax).append(currentOffset()).append("\r\n");
|
||||
sb.append("unk_40 ").append(unk_40).append(currentOffset()).append("\r\n");
|
||||
sb.append("unk_44 ").append(unk_44).append(currentOffset()).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");
|
||||
@@ -192,17 +184,6 @@ public class IggyFlashHeader64 implements StructureInterface {
|
||||
sb.append("unk_AC ").append(unk_AC).append("\r\n");
|
||||
sb.append("unk_B0 ").append(unk_B0).append("\r\n");
|
||||
sb.append("unk_B4 ").append(unk_B4).append("\r\n");
|
||||
sb.append("name ").append(name).append("\r\n");
|
||||
Map<Integer, TagTypeInfo> map = Tag.getKnownClasses();
|
||||
sb.append("tags:").append("\r\n");
|
||||
for (int i = 0; i < tagIds.size(); i++) {
|
||||
TagTypeInfo tti = map.get(tagIds.get(i));
|
||||
sb.append(" tag ").append(tagIds.get(i)).append(":").append(tti == null ? "?" : tti.getName());
|
||||
if (tagIdsExtendedInfo.get(i) > 0) {
|
||||
sb.append(" (special: ").append(tagIdsExtendedInfo.get(i)).append(")");
|
||||
}
|
||||
sb.append("\r\n");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface IggyFlashHeaderInterface extends StructureInterface {
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.jpexs.decompiler.flash.iggy;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -19,51 +18,62 @@ public class IggyHeader implements StructureInterface {
|
||||
|
||||
//Must be 0xED0A6749
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
public long magic = MAGIC;
|
||||
private long magic = MAGIC;
|
||||
|
||||
//Assume 0x900
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
public long version;
|
||||
private long version;
|
||||
|
||||
//Assuming: 1
|
||||
@IggyFieldType(value = DataType.uint8_t)
|
||||
public int platform1;
|
||||
private int platform1;
|
||||
|
||||
//32/64
|
||||
@IggyFieldType(value = DataType.uint8_t)
|
||||
public int platform2_bittness;
|
||||
private int platform2;
|
||||
|
||||
//Assuming: 1
|
||||
@IggyFieldType(value = DataType.uint8_t)
|
||||
public int platform3;
|
||||
private int platform3;
|
||||
|
||||
//Usually: 3
|
||||
@IggyFieldType(value = DataType.uint8_t)
|
||||
public int platform4;
|
||||
private int platform4;
|
||||
|
||||
//flags for platform 64?
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
public long unk_0C;
|
||||
private long unk_0C;
|
||||
|
||||
@IggyArrayFieldType(value = DataType.uint8_t, count = 12)
|
||||
public byte[] reserved;
|
||||
private byte[] reserved;
|
||||
|
||||
@IggyFieldType(value = DataType.uint32_t)
|
||||
public long num_subfiles;
|
||||
private long numSubfiles;
|
||||
|
||||
public IggyHeader(AbstractDataStream stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
public IggyHeader(long version, int platform1, int platform2_bittness, int platform3, int platform4, long unk_0C, byte[] reserved, long num_subfiles) {
|
||||
/**
|
||||
*
|
||||
* @param version
|
||||
* @param platform1
|
||||
* @param platform2 32/64
|
||||
* @param platform3
|
||||
* @param platform4
|
||||
* @param unk_0C
|
||||
* @param reserved
|
||||
* @param num_subfiles
|
||||
*/
|
||||
public IggyHeader(long version, int platform1, int platform2, int platform3, int platform4, long unk_0C, byte[] reserved, long num_subfiles) {
|
||||
this.version = version;
|
||||
this.platform1 = platform1;
|
||||
this.platform2_bittness = platform2_bittness;
|
||||
this.platform2 = platform2;
|
||||
this.platform3 = platform3;
|
||||
this.platform4 = platform4;
|
||||
this.unk_0C = unk_0C;
|
||||
this.reserved = reserved;
|
||||
this.num_subfiles = num_subfiles;
|
||||
this.numSubfiles = num_subfiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,10 +81,10 @@ public class IggyHeader implements StructureInterface {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
sb.append("version: ").append(version).append(", ");
|
||||
sb.append("platform: ").append(platform1).append(" ").append(platform2_bittness).append(" ").append(platform3).append(" ").append(platform4).append(", ");
|
||||
sb.append("platform: ").append(platform1).append(" ").append(platform2).append(" ").append(platform3).append(" ").append(platform4).append(", ");
|
||||
sb.append("unk_0C: ").append(String.format("%08X", unk_0C)).append(", ");
|
||||
sb.append("reserved: 12 bytes").append(", ");
|
||||
sb.append("num_subfiles: ").append(num_subfiles);
|
||||
sb.append("num_subfiles: ").append(numSubfiles);
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -87,12 +97,12 @@ public class IggyHeader implements StructureInterface {
|
||||
}
|
||||
version = stream.readUI32();
|
||||
platform1 = stream.readUI8();
|
||||
platform2_bittness = stream.readUI8();
|
||||
platform2 = stream.readUI8(); //32/64
|
||||
platform3 = stream.readUI8();
|
||||
platform4 = stream.readUI8();
|
||||
unk_0C = stream.readUI32();
|
||||
reserved = stream.readBytes(12);
|
||||
num_subfiles = stream.readUI32();
|
||||
numSubfiles = stream.readUI32();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,7 +111,43 @@ public class IggyHeader implements StructureInterface {
|
||||
}
|
||||
|
||||
public boolean is64() {
|
||||
return platform2_bittness == 64;
|
||||
return platform2 == 64;
|
||||
}
|
||||
|
||||
public long getMagic() {
|
||||
return magic;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public int getPlatform1() {
|
||||
return platform1;
|
||||
}
|
||||
|
||||
public int getPlatform2() {
|
||||
return platform2;
|
||||
}
|
||||
|
||||
public int getPlatform3() {
|
||||
return platform3;
|
||||
}
|
||||
|
||||
public int getPlatform4() {
|
||||
return platform4;
|
||||
}
|
||||
|
||||
public long getUnk_0C() {
|
||||
return unk_0C;
|
||||
}
|
||||
|
||||
public byte[] getReserved() {
|
||||
return reserved;
|
||||
}
|
||||
|
||||
public long getNumSubfiles() {
|
||||
return numSubfiles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
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<Integer> indexTableEntry, List<Long> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyNameAndTagList implements StructureInterface {
|
||||
|
||||
@IggyFieldType(value = DataType.widechar_t)
|
||||
private String name;
|
||||
|
||||
@IggyArrayFieldType(value = DataType.ubits, count = 10)
|
||||
private List<Integer> tagIds;
|
||||
|
||||
@IggyArrayFieldType(value = DataType.uint16_t)
|
||||
private List<Long> tagIdsExtendedInfo;
|
||||
|
||||
public IggyNameAndTagList(String name, List<Integer> tagIds, List<Long> tagIdsExtendedInfo) {
|
||||
this.name = name;
|
||||
this.tagIds = tagIds;
|
||||
this.tagIdsExtendedInfo = tagIdsExtendedInfo;
|
||||
}
|
||||
|
||||
public IggyNameAndTagList(AbstractDataStream stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(AbstractDataStream stream) throws IOException {
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
do {
|
||||
char c = (char) stream.readUI16();
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
nameBuilder.append(c);
|
||||
} while (true);
|
||||
name = nameBuilder.toString();
|
||||
|
||||
tagIds = new ArrayList<>();
|
||||
tagIdsExtendedInfo = new ArrayList<>();
|
||||
while (true) {
|
||||
long typeLen = stream.readUI32();
|
||||
if (typeLen == 0) {
|
||||
break;
|
||||
}
|
||||
long tagLength = stream.readUI32();
|
||||
int tagType = (int) ((typeLen >>> 6) + 10) & 0x3FF;
|
||||
tagIds.add(tagType);
|
||||
tagIdsExtendedInfo.add(tagLength);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Integer> getTagIds() {
|
||||
return tagIds;
|
||||
}
|
||||
|
||||
public List<Long> getTagIdsExtendedInfo() {
|
||||
return tagIdsExtendedInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(AbstractDataStream stream) throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package com.jpexs.decompiler.flash.iggy;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user