mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-12 18:18:34 +00:00
index stub
This commit is contained in:
@@ -6,6 +6,8 @@ import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IndexingDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IndexingDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.File;
|
||||
@@ -48,7 +50,9 @@ public class IggyFile implements StructureInterface {
|
||||
IggySwf iggySwf = iggySwfs.get(targetSwfIndex);
|
||||
iggySwf.replaceFontTag(fontIndex, newFont);
|
||||
|
||||
IndexingDataStreamInterface indexStream = new IndexingDataStream();
|
||||
DataStreamInterface flashStream = new TemporaryDataStream();
|
||||
flashStream.setIndexing(indexStream);
|
||||
iggySwf.writeToDataStream(flashStream);
|
||||
byte flashData[] = flashStream.getAllBytes();
|
||||
int swfIndex = 0;
|
||||
@@ -56,17 +60,29 @@ public class IggyFile implements StructureInterface {
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
if (swfIndex == targetSwfIndex) {
|
||||
byte indexData[] = indexStream.getIndexBytes();
|
||||
long newLen = indexData.length;
|
||||
long oldLen = entry.size;
|
||||
entry.size = newLen;
|
||||
entry.size2 = newLen;
|
||||
offsetChange += (newLen - oldLen);
|
||||
subFileEntriesData.set(i, indexData);
|
||||
}
|
||||
swfIndex++;
|
||||
}
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
if (swfIndex == targetSwfIndex) {
|
||||
long newLen = flashData.length;
|
||||
long oldLen = entry.size;
|
||||
entry.size = newLen;
|
||||
entry.size2 = newLen;
|
||||
offsetChange += (newLen - oldLen);
|
||||
subFileEntriesData.set(i, flashData);
|
||||
}
|
||||
swfIndex++;
|
||||
}
|
||||
}
|
||||
subFileEntriesData.set(targetSwfIndex, flashData);
|
||||
//TODO: Update index
|
||||
}
|
||||
|
||||
private boolean setSwfItemLength(int swfIndex, int itemindex, long newLength) {
|
||||
@@ -187,19 +203,31 @@ public class IggyFile implements StructureInterface {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
/*String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy";
|
||||
String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy";
|
||||
String outFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font2.iggy";
|
||||
|
||||
File extractDirOrig = new File("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig");
|
||||
File extractDirNew = new File("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new");
|
||||
|
||||
if (!extractDirOrig.exists()) {
|
||||
extractDirOrig.mkdir();
|
||||
}
|
||||
if (!extractDirNew.exists()) {
|
||||
extractDirNew.mkdir();
|
||||
}
|
||||
|
||||
File inFile = new File(inFileName);
|
||||
File outFile = new File(outFileName);
|
||||
IggyFile iggyFile = new IggyFile(inFile);
|
||||
extractIggyFile(inFile, extractDirOrig);
|
||||
IggySwf iswf = iggyFile.getSwf(0);
|
||||
IggyFont ifont = iswf.fonts.get(0);
|
||||
iggyFile.replaceFontTag(0, 0, ifont);
|
||||
outFile.delete();
|
||||
try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) {
|
||||
iggyFile.writeToDataStream(outputStream);
|
||||
}*/
|
||||
}
|
||||
extractIggyFile(outFile, extractDirNew);
|
||||
}
|
||||
|
||||
private static void copyStream(InputStream is, OutputStream os) {
|
||||
|
||||
@@ -255,22 +255,14 @@ public class IggyFont extends IggyTag {
|
||||
zeroes48b = s.readBytes(48);
|
||||
|
||||
if (abs_start_of_name != 0) {
|
||||
//here is offset [5] - 1096
|
||||
s.seek(abs_start_of_name, SeekMode.SET);
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
int nameCharCnt = 0;
|
||||
do {
|
||||
char c = (char) s.readUI16();
|
||||
nameCharCnt++;
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
nameBuilder.append(c);
|
||||
} while (true);
|
||||
s.seek(32 - nameCharCnt * 2, SeekMode.CUR);
|
||||
name = nameBuilder.toString();
|
||||
name = s.readWChar();
|
||||
//here is offset [6] - 1130
|
||||
s.pad8bytes();
|
||||
}
|
||||
s.readUI64(); //pad zero
|
||||
if (abs_start_of_char_struct != 0) {
|
||||
//here is offset [7] - 1136
|
||||
s.seek(abs_start_of_char_struct, SeekMode.SET);
|
||||
charOffsets = new ArrayList<>();
|
||||
for (int i = 0; i < char_count; i++) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyIndexBuilder {
|
||||
|
||||
public void writeTable(int cnt, DataType type, boolean pad) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,13 @@ package com.jpexs.decompiler.flash.iggy;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.AbstractDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
@@ -15,14 +20,24 @@ public class IggyIndexParser {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(IggyIndexParser.class.getName());
|
||||
|
||||
/*
|
||||
Offsets:
|
||||
1) name
|
||||
2) UI16 - zero
|
||||
3) tag list
|
||||
4) ... tag data offsets
|
||||
|
||||
*/
|
||||
static {
|
||||
LOGGER.setLevel(Level.ALL);
|
||||
LOGGER.addHandler(new Handler() {
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
System.out.println("" + record.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser for index data. It creates table of indices and table of offsets
|
||||
*
|
||||
@@ -36,7 +51,7 @@ public class IggyIndexParser {
|
||||
int[] indexTable = new int[indexTableSize];
|
||||
for (int i = 0; i < indexTableSize; i++) {
|
||||
int offset = indexStream.readUI8();
|
||||
LOGGER.fine(String.format("index_table_entry: %02x\n", offset));
|
||||
LOGGER.fine(String.format("index_table_entry: %02x", offset));
|
||||
indexTable[i] = offset;
|
||||
indexTableEntry.add(offset);
|
||||
int num = indexStream.readUI8();
|
||||
@@ -47,28 +62,32 @@ public class IggyIndexParser {
|
||||
int code;
|
||||
|
||||
while ((code = indexStream.readUI8()) > -1) {
|
||||
LOGGER.finer(String.format("Code = %x\n", code));
|
||||
LOGGER.finer(String.format("Code = %x", code));
|
||||
|
||||
if (code < 0x80) // 0-0x7F
|
||||
{
|
||||
LOGGER.finest("0-0x7F: code is directly an index to the index_table");
|
||||
// code is directly an index to the index_table
|
||||
if (code >= indexTableSize) {
|
||||
LOGGER.severe(String.format("< 0x80: index is greater than index_table_size. %x > %x\n", code, indexTableSize));
|
||||
LOGGER.severe(String.format("< 0x80: index is greater than index_table_size. %x > %x", code, indexTableSize));
|
||||
return;
|
||||
}
|
||||
|
||||
offset += indexTable[code];
|
||||
LOGGER.finest(String.format("ofset += %d", indexTable[code]));
|
||||
|
||||
} else if (code < 0xC0) // 0x80-BF
|
||||
{
|
||||
LOGGER.finest("0x80-BF: table[0..255]*(code-0x7F)");
|
||||
int index;
|
||||
|
||||
if ((index = indexStream.readUI8()) < 0) {
|
||||
LOGGER.severe(String.format("< 0xC0: Cannot read index.\n"));
|
||||
LOGGER.severe(String.format("< 0xC0: Cannot read index."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (index >= indexTableSize) {
|
||||
LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x\n", index, indexTableSize));
|
||||
LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, indexTableSize));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -76,92 +95,116 @@ public class IggyIndexParser {
|
||||
offset += indexTable[index] * n;
|
||||
} else if (code < 0xD0) // 0xC0-0xCF
|
||||
{
|
||||
LOGGER.finest("0xC0-CF: code*2-0x17E");
|
||||
offset += ((code * 2) - 0x17E);
|
||||
} else if (code < 0xE0) // 0xD0-0xDF
|
||||
{
|
||||
LOGGER.finest("0xD0-0xDF: platform based");
|
||||
|
||||
// Code here depends on plattform[0], we are assuming it is 1, as we checked in load function
|
||||
int i = code & 0xF;
|
||||
int n8;
|
||||
int n;
|
||||
|
||||
if ((n8 = indexStream.readUI8()) < 0) {
|
||||
LOGGER.severe(String.format("< 0xE0: Cannot read n.\n"));
|
||||
LOGGER.severe(String.format("< 0xE0: Cannot read n."));
|
||||
return;
|
||||
}
|
||||
|
||||
n = n8 + 1;
|
||||
|
||||
LOGGER.finest(String.format("i=%X", i));
|
||||
LOGGER.finest(String.format("n=%d", n));
|
||||
|
||||
if (is64) {
|
||||
if (i <= 2) {
|
||||
offset += 8 * n; // Ptr type
|
||||
LOGGER.finest(String.format("offset += %d", 8 * n));
|
||||
} else if (i <= 4) {
|
||||
offset += 2 * n;
|
||||
LOGGER.finest(String.format("offset += %d", 2 * n));
|
||||
} else if (i == 5) {
|
||||
offset += 4 * n;
|
||||
LOGGER.finest(String.format("offset += %d", 4 * n));
|
||||
} else if (i == 6) {
|
||||
offset += 8 * n; // 64 bits type
|
||||
LOGGER.finest(String.format("offset += %d", 8 * n));
|
||||
} else {
|
||||
LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)\n", i, code));
|
||||
LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)", i, code));
|
||||
}
|
||||
} else {
|
||||
switch (i) {
|
||||
case 2:
|
||||
offset += 4 * n; // Ptr type
|
||||
LOGGER.finest(String.format("offset += %d", 4 * n));
|
||||
break;
|
||||
case 4:
|
||||
offset += 2 * n;
|
||||
LOGGER.finest(String.format("offset += %d", 2 * n));
|
||||
break;
|
||||
case 5:
|
||||
offset += 4 * n; // 32 bits type
|
||||
LOGGER.finest(String.format("offset += %d", 4 * n));
|
||||
break;
|
||||
case 6:
|
||||
offset += 8 * n;
|
||||
LOGGER.finest(String.format("offset += %d", 8 * n));
|
||||
break;
|
||||
default:
|
||||
LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)\n", i, code));
|
||||
LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)", i, code));
|
||||
}
|
||||
}
|
||||
} else if (code == 0xFC) {
|
||||
LOGGER.finest(String.format("0xFC: skip 1 "));
|
||||
indexStream.seek(1, SeekMode.CUR);
|
||||
} else if (code == 0xFD) {
|
||||
LOGGER.finest(String.format("0xFD: 0..255, skip 2 * 0..255 "));
|
||||
int n, m;
|
||||
|
||||
if ((n = indexStream.readUI8()) < 0) {
|
||||
LOGGER.severe(String.format("0xFD: Cannot read n.\n"));
|
||||
LOGGER.severe(String.format("0xFD: Cannot read n."));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m = indexStream.readUI8()) < 0) {
|
||||
LOGGER.severe(String.format("0xFD: Cannot read m.\n"));
|
||||
LOGGER.severe(String.format("0xFD: Cannot read m."));
|
||||
return;
|
||||
}
|
||||
|
||||
offset += n;
|
||||
LOGGER.finest(String.format("offset += %d", n));
|
||||
indexStream.seek(m * 2, SeekMode.CUR);
|
||||
LOGGER.finest(String.format("skip %d", m * 2));
|
||||
} else if (code == 0xFE) {
|
||||
LOGGER.finest(String.format("0xFD: 0..255 + 1 "));
|
||||
int n8;
|
||||
int n;
|
||||
|
||||
if ((n8 = indexStream.readUI8()) < 0) {
|
||||
LOGGER.severe(String.format("0xFE: Cannot read n.\n"));
|
||||
LOGGER.severe(String.format("0xFE: Cannot read n."));
|
||||
return;
|
||||
}
|
||||
|
||||
n = n8 + 1;
|
||||
offset += n;
|
||||
LOGGER.finest(String.format("offset += %d", n));
|
||||
} else if (code == 0xFF) {
|
||||
LOGGER.finest(String.format("0xFF: 32bit "));
|
||||
long n;
|
||||
|
||||
if ((n = indexStream.readUI32()) < 0) {
|
||||
LOGGER.severe(String.format("0xFF: Cannot read n.\n"));
|
||||
LOGGER.severe(String.format("0xFF: Cannot read n."));
|
||||
return;
|
||||
}
|
||||
|
||||
offset += n;
|
||||
LOGGER.finest(String.format("offset += %d", n));
|
||||
} else {
|
||||
LOGGER.warning(String.format("Unrecognized code: %x\n", code));
|
||||
LOGGER.warning(String.format("Unrecognized code: %x", code));
|
||||
}
|
||||
|
||||
LOGGER.finer(String.format("OFFSET: %d", offset));
|
||||
|
||||
offsets.add(offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,21 +88,14 @@ public class IggySwf implements StructureInterface {
|
||||
long maxPos = hdr.getFontEndAddress();
|
||||
allFontBytes = s.readBytes((int) (maxPos - curPos));
|
||||
s.seek(curPos, SeekMode.SET);
|
||||
|
||||
//here is offset[0]
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
do {
|
||||
char c = (char) s.readUI16();
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
nameBuilder.append(c);
|
||||
} while (true);
|
||||
name = nameBuilder.toString();
|
||||
//here is offset[1]
|
||||
//here is offset[0] - 184
|
||||
name = s.readWChar();
|
||||
//here is offset[1] - 230
|
||||
int pad8 = 8 - (int) (s.position() % 8);
|
||||
s.seek(pad8, SeekMode.CUR);
|
||||
//here is offset [2]
|
||||
if (pad8 > 8) {
|
||||
s.seek(pad8, SeekMode.CUR);
|
||||
}
|
||||
//here is offset [2] - 232
|
||||
s.seek(hdr.getBaseAddress(), SeekMode.SET);
|
||||
s.readUI64(); //pad 1
|
||||
|
||||
@@ -157,6 +150,7 @@ public class IggySwf implements StructureInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
//here is offset [3] - 744
|
||||
fonts = new HashMap<>();
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
s.seek(font_data_addresses[i], SeekMode.SET);
|
||||
@@ -176,10 +170,12 @@ public class IggySwf implements StructureInterface {
|
||||
font_add_data = s.readBytes((int) (long) font_add_size.get(0));
|
||||
}
|
||||
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
|
||||
//here is offset [4] - 856 ?
|
||||
font_bin_info = new FontBinInfo[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i] = new FontBinInfo(s);
|
||||
}
|
||||
|
||||
s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET);
|
||||
sequence = new IggySequence(s);
|
||||
s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
@@ -194,7 +190,6 @@ public class IggySwf implements StructureInterface {
|
||||
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings = new IggyDeclStrings(s);
|
||||
//TODO: binarydata
|
||||
/*WriteDataStreamInterface outs = new TemporaryDataStream();
|
||||
writeToDataStream(outs);
|
||||
Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());*/
|
||||
@@ -207,17 +202,9 @@ public class IggySwf implements StructureInterface {
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
hdr.writeToDataStream(s);
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
s.writeUI16(name.charAt(i));
|
||||
}
|
||||
s.writeUI16(0);
|
||||
|
||||
int pad8 = 8 - (int) (s.position() % 8);
|
||||
if (pad8 < 8) {
|
||||
for (int i = 0; i < pad8; i++) {
|
||||
s.write(0);
|
||||
}
|
||||
}
|
||||
s.getIndexing().writeIndexUI8SkipTwice8(184, 25);
|
||||
s.writeWChar(name);
|
||||
s.pad8bytes();
|
||||
s.writeUI64(1);
|
||||
for (int i = 0; i < font_data_addresses.length; i++) {
|
||||
long offset = font_data_addresses[i] - s.position();
|
||||
@@ -227,8 +214,6 @@ public class IggySwf implements StructureInterface {
|
||||
long offset = text_addresses.get(i) - s.position();
|
||||
s.writeUI64(offset);
|
||||
}
|
||||
s.writeUI64(1);
|
||||
|
||||
if (hdr.font_count > 0) {
|
||||
while (s.position() < font_data_addresses[0]) {
|
||||
s.writeUI64(1);
|
||||
@@ -264,8 +249,6 @@ public class IggySwf implements StructureInterface {
|
||||
}
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings.writeToDataStream(s);
|
||||
|
||||
//TODO: binarydata
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.jpexs.decompiler.flash.iggy.streams;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -171,4 +175,36 @@ public abstract class AbstractDataStream implements DataStreamInterface {
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeWChar(String name) throws IOException {
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
writeUI16(name.charAt(i));
|
||||
}
|
||||
writeUI16(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readWChar() throws IOException {
|
||||
StringBuilder strBuilder = new StringBuilder();
|
||||
do {
|
||||
char c = (char) readUI16();
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
strBuilder.append(c);
|
||||
} while (true);
|
||||
return strBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pad8bytes() throws IOException {
|
||||
int pad8 = 8 - (int) (position() % 8);
|
||||
if (pad8 < 8) {
|
||||
for (int i = 0; i < pad8; i++) {
|
||||
write(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.jpexs.decompiler.flash.iggy.streams;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class EmptyIndexing implements IndexingDataStreamInterface {
|
||||
|
||||
@Override
|
||||
public void writeIndexToTable(int val0to255) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexFromTable(int tableIndex0to127) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex40(int num1to40, int countUI8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexMultiply2(int num0to15) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexPtr(boolean is64, long cnt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex16bit(long cnt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex32bit(long cnt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex64bit(long cnt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexSkip1() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexUI8SkipTwice8(int ofs, int skipTwice) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexUI8Positive(int val) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexUI32(long offset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex(int code, boolean is64, long val, long val2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getIndexTableBytes() {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getIndexBytes() {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
package com.jpexs.decompiler.flash.iggy.streams;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IndexingDataStream implements IndexingDataStreamInterface {
|
||||
|
||||
public static final int CODE_FC_SKIP1 = 0xFC;
|
||||
public static final int CODE_FD_OFS8_SKIP_TWICE8 = 0xFD;
|
||||
public static final int CODE_FE_OFS8_POSITIVE = 0xFE;
|
||||
public static final int CODE_FF_OFS32 = 0xFF;
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(IndexingDataStream.class.getName());
|
||||
|
||||
private List<Integer> indexTable;
|
||||
private WriteDataStreamInterface indexStream;
|
||||
|
||||
public IndexingDataStream() throws IOException {
|
||||
indexStream = new TemporaryDataStream();
|
||||
indexTable = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getIndexTableBytes() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
baos.write(indexTable.size());
|
||||
for (int i = 0; i < indexTable.size(); i++) {
|
||||
baos.write(indexTable.get(i));
|
||||
if (i == indexTable.size() - 1) {
|
||||
int pad8 = (indexTable.size() * 2) % 8;
|
||||
baos.write(pad8 / 2); //pad to 8 bytes(?)
|
||||
} else {
|
||||
baos.write(0); //how many bytes to skip
|
||||
}
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public byte[] getIndexBytes() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
baos.write(getIndexTableBytes());
|
||||
baos.write(indexStream.getAllBytes());
|
||||
} catch (IOException ex) {
|
||||
//should not happen
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeIndexToTable(int val0to255) {
|
||||
indexTable.add(val0to255);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexFromTable(int tableIndex0to127) {
|
||||
return writeIndex(tableIndex0to127, false, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex40(int num1to40, int countUI8) {
|
||||
return writeIndex(0x80 + num1to40, false, countUI8, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexMultiply2(int num0to15) {
|
||||
return writeIndex(0xC0 + num0to15, false, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexPtr(boolean is64, long cnt) {
|
||||
return writeIndex(0xD0 + 0x2, false, cnt - 1, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex16bit(long cnt) {
|
||||
return writeIndex(0xD0 + 0x4, false, cnt - 1, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex32bit(long cnt) {
|
||||
return writeIndex(0xD0 + 0x5, false, cnt - 1, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex64bit(long cnt) {
|
||||
return writeIndex(0xD0 + 0x6, false, cnt - 1, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexSkip1() {
|
||||
return writeIndex(CODE_FC_SKIP1, false, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexUI8SkipTwice8(int ofs, int skipTwice) {
|
||||
return writeIndex(CODE_FD_OFS8_SKIP_TWICE8, false, ofs, skipTwice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexUI8Positive(int val) {
|
||||
return writeIndex(CODE_FE_OFS8_POSITIVE, false, val, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndexUI32(long offset) {
|
||||
return writeIndex(CODE_FF_OFS32, false, offset, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeIndex(int code, boolean is64, long val, long skipNum) {
|
||||
try {
|
||||
indexStream.writeUI8(code);
|
||||
if (code < 0x80) // 0-0x7F
|
||||
{
|
||||
LOGGER.finest("0-0x7F: code is directly an index to the index_table");
|
||||
// code is directly an index to the index_table
|
||||
if (code >= indexTable.size()) {
|
||||
LOGGER.severe(String.format("< 0x80: index is greater than index_table_size. %x > %x", code, indexTable.size()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGGER.finest(String.format("ofset += %d", indexTable.get(code)));
|
||||
return indexTable.get(code);
|
||||
} else if (code < 0xC0) // 0x80-BF
|
||||
{
|
||||
LOGGER.finest("0x80-BF: table[0..255]*(code-0x7F)");
|
||||
int index;
|
||||
|
||||
indexStream.writeUI8((int) val);
|
||||
if ((index = (int) val) < 0) {
|
||||
LOGGER.severe(String.format("< 0xC0: Cannot read index."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (index >= indexTable.size()) {
|
||||
LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, indexTable.size()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n = code - 0x7F;
|
||||
return indexTable.get(index) * n;
|
||||
} else if (code < 0xD0) // 0xC0-0xCF
|
||||
{
|
||||
LOGGER.finest("0xC0-CF: code*2-0x17E");
|
||||
return ((code * 2) - 0x17E);
|
||||
} else if (code < 0xE0) // 0xD0-0xDF
|
||||
{
|
||||
LOGGER.finest("0xD0-0xDF: platform based");
|
||||
|
||||
// Code here depends on plattform[0], we are assuming it is 1, as we checked in load function
|
||||
int i = code & 0xF;
|
||||
int n8;
|
||||
int n;
|
||||
|
||||
indexStream.writeUI8((int) val);
|
||||
if ((n8 = (int) val) < 0) {
|
||||
LOGGER.severe(String.format("< 0xE0: Cannot read n."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = n8 + 1;
|
||||
|
||||
LOGGER.finest(String.format("i=%X", i));
|
||||
LOGGER.finest(String.format("n=%d", n));
|
||||
|
||||
if (is64) {
|
||||
if (i <= 2) {
|
||||
LOGGER.finest(String.format("offset += %d", 8 * n));
|
||||
return 8 * n; // Ptr type
|
||||
|
||||
} else if (i <= 4) {
|
||||
LOGGER.finest(String.format("offset += %d", 2 * n));
|
||||
return 2 * n;
|
||||
} else if (i == 5) {
|
||||
LOGGER.finest(String.format("offset += %d", 4 * n));
|
||||
return 4 * n;
|
||||
} else if (i == 6) {
|
||||
LOGGER.finest(String.format("offset += %d", 8 * n));
|
||||
return 8 * n; // 64 bits type
|
||||
} else {
|
||||
LOGGER.severe(String.format("< 0xE0: Invalid value for i (%x %x)", i, code));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
switch (i) {
|
||||
case 2:
|
||||
LOGGER.finest(String.format("offset += %d", 4 * n));
|
||||
return 4 * n; // Ptr type;
|
||||
case 4:
|
||||
LOGGER.finest(String.format("offset += %d", 2 * n));
|
||||
return 2 * n;
|
||||
case 5:
|
||||
LOGGER.finest(String.format("offset += %d", 4 * n));
|
||||
return 4 * n; // 32 bits type
|
||||
case 6:
|
||||
LOGGER.finest(String.format("offset += %d", 8 * n));
|
||||
return 8 * n;
|
||||
default:
|
||||
LOGGER.severe(String.format("< 0xE0: invalid value for i (%x %x)", i, code));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (code == CODE_FC_SKIP1) {
|
||||
LOGGER.finest(String.format("0xFC: skip 1 "));
|
||||
//indexStream.seek(1, SeekMode.CUR);
|
||||
return 1; //seek 1
|
||||
} else if (code == CODE_FD_OFS8_SKIP_TWICE8) {
|
||||
LOGGER.finest(String.format("0xFD: 0..255, skip 2 * 0..255 "));
|
||||
int n, m;
|
||||
|
||||
indexStream.writeUI8((int) val);
|
||||
|
||||
if ((n = (int) val) < 0) {
|
||||
LOGGER.severe(String.format("0xFD: Cannot read n."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
indexStream.writeUI8((int) skipNum);
|
||||
|
||||
if ((m = (int) skipNum) < 0) {
|
||||
LOGGER.severe(String.format("0xFD: Cannot read m."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
long offset = n;
|
||||
LOGGER.finest(String.format("offset += %d", n));
|
||||
long skip = m * 2;
|
||||
LOGGER.finest(String.format("skip %d", m * 2));
|
||||
return offset + skip;
|
||||
} else if (code == CODE_FE_OFS8_POSITIVE) {
|
||||
LOGGER.finest(String.format("0xFD: 0..255 + 1 "));
|
||||
int n8;
|
||||
int n;
|
||||
|
||||
indexStream.writeUI8((int) val);
|
||||
if ((n8 = (int) val) < 0) {
|
||||
LOGGER.severe(String.format("0xFE: Cannot read n."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = n8 + 1;
|
||||
LOGGER.finest(String.format("offset += %d", n));
|
||||
return n;
|
||||
} else if (code == CODE_FF_OFS32) {
|
||||
LOGGER.finest(String.format("0xFF: 32bit "));
|
||||
long n;
|
||||
|
||||
indexStream.writeUI32(val);
|
||||
if ((n = val) < 0) {
|
||||
LOGGER.severe(String.format("0xFF: Cannot read n."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGGER.finest(String.format("offset += %d", n));
|
||||
return n;
|
||||
} else {
|
||||
LOGGER.warning(String.format("Unrecognized code: %x", code));
|
||||
return 0;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.jpexs.decompiler.flash.iggy.streams;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface IndexingDataStreamInterface {
|
||||
|
||||
public void writeIndexToTable(int val0to255);
|
||||
|
||||
public long writeIndexFromTable(int tableIndex0to127);
|
||||
|
||||
public long writeIndex40(int num1to40, int countUI8);
|
||||
|
||||
public long writeIndexMultiply2(int num0to15);
|
||||
|
||||
public long writeIndexPtr(boolean is64, long cnt);
|
||||
|
||||
public long writeIndex16bit(long cnt);
|
||||
|
||||
public long writeIndex32bit(long cnt);
|
||||
|
||||
public long writeIndex64bit(long cnt);
|
||||
|
||||
public long writeIndexSkip1();
|
||||
|
||||
public long writeIndexUI8SkipTwice8(int ofs, int skipTwice);
|
||||
|
||||
public long writeIndexUI8Positive(int val);
|
||||
|
||||
public long writeIndexUI32(long offset);
|
||||
|
||||
public long writeIndex(int code, boolean is64, long val, long val2);
|
||||
|
||||
public byte[] getIndexTableBytes();
|
||||
|
||||
public byte[] getIndexBytes();
|
||||
}
|
||||
@@ -16,13 +16,24 @@ public class RandomAccessFileDataStream extends AbstractDataStream {
|
||||
|
||||
private File file;
|
||||
private RandomAccessFile raf;
|
||||
private IndexingDataStreamInterface indexing;
|
||||
|
||||
protected File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndexing(IndexingDataStreamInterface indexing) {
|
||||
this.indexing = indexing;
|
||||
}
|
||||
|
||||
public RandomAccessFileDataStream(File file) throws FileNotFoundException {
|
||||
this(file, new EmptyIndexing());
|
||||
}
|
||||
|
||||
public RandomAccessFileDataStream(File file, IndexingDataStreamInterface indexing) throws FileNotFoundException {
|
||||
this.file = file;
|
||||
this.indexing = indexing;
|
||||
raf = new RandomAccessFile(file, "rw");
|
||||
}
|
||||
|
||||
@@ -104,4 +115,24 @@ public class RandomAccessFileDataStream extends AbstractDataStream {
|
||||
raf.write(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexingDataStreamInterface getIndexing() {
|
||||
return indexing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeWChar(String name) throws IOException {
|
||||
indexing.writeIndex16bit(name.length() + 1);
|
||||
return super.writeWChar(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pad8bytes() throws IOException {
|
||||
int pad8 = 8 - (int) (position() % 8);
|
||||
if (pad8 < 8) {
|
||||
indexing.writeIndexMultiply2(pad8 / 2);
|
||||
}
|
||||
super.pad8bytes();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ public interface ReadDataStreamInterface extends AutoCloseable {
|
||||
|
||||
public byte[] getAllBytes() throws IOException;
|
||||
|
||||
public String readWChar() throws IOException;
|
||||
|
||||
public void pad8bytes() throws IOException;
|
||||
|
||||
@Override
|
||||
public void close();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ public interface WriteDataStreamInterface extends AutoCloseable {
|
||||
|
||||
public boolean writeUI16(int val) throws IOException;
|
||||
|
||||
public boolean writeWChar(String val) throws IOException;
|
||||
|
||||
public void pad8bytes() throws IOException;
|
||||
|
||||
public boolean writeUI8(int val) throws IOException;
|
||||
|
||||
public void write(int val) throws IOException;
|
||||
@@ -41,4 +45,8 @@ public interface WriteDataStreamInterface extends AutoCloseable {
|
||||
|
||||
@Override
|
||||
public void close();
|
||||
|
||||
public void setIndexing(IndexingDataStreamInterface indexing);
|
||||
|
||||
public IndexingDataStreamInterface getIndexing();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user