mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-26 04:46:19 +00:00
read/write fixes, refactorings
This commit is contained in:
@@ -43,30 +43,29 @@ public class IggyFile implements StructureInterface {
|
||||
|
||||
public static final int FIRST_TAG_POSITION = 3;
|
||||
|
||||
public void replaceTag(int swfIndex, int tagIndex, IggyTag newTag) throws IOException {
|
||||
WriteDataStreamInterface stream = new TemporaryDataStream();
|
||||
newTag.writeToDataStream(stream);
|
||||
public void replaceFontTag(int targetSwfIndex, int fontIndex, IggyFont newFont) throws IOException {
|
||||
IggySwf iggySwf = iggySwfs.get(targetSwfIndex);
|
||||
iggySwf.replaceFontTag(fontIndex, newFont);
|
||||
|
||||
setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize());
|
||||
}
|
||||
|
||||
public void saveTag(int swfIndex, IggyTag newTag) throws IOException {
|
||||
WriteDataStreamInterface stream = new TemporaryDataStream();
|
||||
newTag.writeToDataStream(stream);
|
||||
|
||||
int tagIndex = 0;
|
||||
List<IggyTag> taglist = iggySwfs.get(swfIndex).getTags();
|
||||
for (IggyTag t : taglist) {
|
||||
if (t == newTag) {
|
||||
break;
|
||||
DataStreamInterface flashStream = new TemporaryDataStream();
|
||||
iggySwf.writeToDataStream(flashStream);
|
||||
byte flashData[] = flashStream.getAllBytes();
|
||||
int swfIndex = 0;
|
||||
int offsetChange = 0;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
if (swfIndex == targetSwfIndex) {
|
||||
long newLen = flashData.length;
|
||||
long oldLen = entry.size;
|
||||
offsetChange += (newLen - oldLen);
|
||||
}
|
||||
swfIndex++;
|
||||
}
|
||||
tagIndex++;
|
||||
}
|
||||
if (tagIndex < taglist.size()) {
|
||||
setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Tag does not exists in this iggy file");
|
||||
}
|
||||
subFileEntriesData.set(targetSwfIndex, flashData);
|
||||
//TODO: Update index
|
||||
}
|
||||
|
||||
private boolean setSwfItemLength(int swfIndex, int itemindex, long newLength) {
|
||||
@@ -103,14 +102,6 @@ public class IggyFile implements StructureInterface {
|
||||
return iggySwfs.get(swfIndex).fonts.get(fontId);
|
||||
}
|
||||
|
||||
public IggyText getText(int swfIndex, int textId) {
|
||||
return iggySwfs.get(swfIndex).texts.get(textId);
|
||||
}
|
||||
|
||||
public Set<Integer> getTextIds(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).texts.keySet();
|
||||
}
|
||||
|
||||
public IggyFile(String filePath) throws IOException {
|
||||
this(new File(filePath));
|
||||
}
|
||||
@@ -202,7 +193,8 @@ public class IggyFile implements StructureInterface {
|
||||
File outFile = new File(outFileName);
|
||||
IggyFile iggyFile = new IggyFile(inFile);
|
||||
IggySwf iswf = iggyFile.getSwf(0);
|
||||
iggyFile.replaceSwf(0, iswf);
|
||||
IggyFont ifont = iswf.fonts.get(0);
|
||||
iggyFile.replaceFontTag(0, 0, ifont);
|
||||
outFile.delete();
|
||||
try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) {
|
||||
iggyFile.writeToDataStream(outputStream);
|
||||
@@ -649,7 +641,9 @@ public class IggyFile implements StructureInterface {
|
||||
|
||||
//WIP
|
||||
public boolean replaceSwf(int targetSwfIndex, IggySwf iggySwf) {
|
||||
if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) {
|
||||
return false; //Not working yet - need to make IggySWF.writeToDataStream work
|
||||
|
||||
/*if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No such SWF file index");
|
||||
}
|
||||
byte replacementData[];
|
||||
@@ -680,7 +674,7 @@ public class IggyFile implements StructureInterface {
|
||||
}
|
||||
}
|
||||
subFileEntriesData.set(targetSwfIndex, replacementData);
|
||||
return true;
|
||||
return true;*/
|
||||
}
|
||||
|
||||
private void parseEntries() throws IOException {
|
||||
@@ -697,23 +691,9 @@ public class IggyFile implements StructureInterface {
|
||||
indexTables.add(indexTable);
|
||||
offsetTables.add(offsets);
|
||||
} else if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
IggyFlashHeaderInterface hdr;
|
||||
if (header.is64()) {
|
||||
hdr = new IggyFlashHeader64(dataStream);
|
||||
} else {
|
||||
hdr = new IggyFlashHeader32(dataStream);
|
||||
throw new UnsupportedOperationException("Iggy 32bit files are not supported"); //TODO
|
||||
}
|
||||
headers.add(hdr);
|
||||
flashDataStreams.add(dataStream);
|
||||
iggySwfs.add(new IggySwf(dataStream));
|
||||
}
|
||||
}
|
||||
|
||||
for (int swfIndex = 0; swfIndex < headers.size(); swfIndex++) {
|
||||
IggyFlashHeaderInterface hdr = headers.get(swfIndex);
|
||||
IggySwf dataReader = new IggySwf((IggyFlashHeader64) hdr, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex));
|
||||
iggySwfs.add(dataReader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -64,7 +64,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
@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_unk8C; // 0x78 relative offset to something
|
||||
long off_unk78; // 0x78 relative offset to something
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_unk80;
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
@@ -97,13 +97,35 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
private long font_end_address;
|
||||
private long sequence_start_address;
|
||||
private long names_address;
|
||||
private long unk8C_address;
|
||||
private long unk78_address;
|
||||
private long unk80_address;
|
||||
private long last_section_address;
|
||||
private long flash_filename_address;
|
||||
private long decl_strings_address;
|
||||
private long type_fonts_address;
|
||||
|
||||
/**
|
||||
* 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 boolean isImported() {
|
||||
return imported == 1;
|
||||
}
|
||||
@@ -120,6 +142,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
return font_end_address;
|
||||
}
|
||||
|
||||
public void setFontEndAddress(long val) {
|
||||
this.font_end_address = val;
|
||||
}
|
||||
|
||||
public long getSequenceStartAddress() {
|
||||
return sequence_start_address;
|
||||
}
|
||||
@@ -128,8 +154,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
return names_address;
|
||||
}
|
||||
|
||||
public long getUnk8CAddress() {
|
||||
return unk8C_address;
|
||||
public long getUnk78Address() {
|
||||
return unk78_address;
|
||||
}
|
||||
|
||||
public long getUnk80Address() {
|
||||
@@ -191,8 +217,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
|
||||
off_names = stream.readUI64();
|
||||
names_address = off_names + stream.position() - 8;
|
||||
off_unk8C = stream.readUI64();
|
||||
unk8C_address = off_unk8C + stream.position() - 8;
|
||||
off_unk78 = stream.readUI64();
|
||||
unk78_address = off_unk78 + stream.position() - 8;
|
||||
off_unk80 = stream.readUI64();
|
||||
unk80_address = off_unk80 + stream.position() - 8;
|
||||
off_last_section = stream.readUI64();
|
||||
@@ -211,11 +237,16 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
|
||||
off_start = base_address - stream.position();
|
||||
stream.writeUI64(off_start);
|
||||
off_seq_end = sequence_end_address - stream.position();
|
||||
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();
|
||||
stream.writeUI64(off_seq_start1);
|
||||
stream.writeUI64(pad_to_match);
|
||||
off_seq_start2 = sequence_start_address - stream.position();
|
||||
stream.writeUI64(off_seq_start2);
|
||||
stream.writeUI32(xmin);
|
||||
stream.writeUI32(ymin);
|
||||
@@ -232,12 +263,19 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
stream.writeUI32(additional_import1);
|
||||
stream.writeUI32(zero1);
|
||||
stream.writeUI64(unk_guid);
|
||||
off_names = names_address - stream.position();
|
||||
stream.writeUI64(off_names);
|
||||
stream.writeUI64(off_unk8C);
|
||||
off_unk78 = unk78_address - stream.position();
|
||||
stream.writeUI64(off_unk78);
|
||||
off_unk80 = unk80_address - stream.position();
|
||||
stream.writeUI64(off_unk80);
|
||||
off_last_section = last_section_address - stream.position();
|
||||
stream.writeUI64(off_last_section);
|
||||
off_flash_filename = flash_filename_address - stream.position();
|
||||
stream.writeUI64(off_flash_filename);
|
||||
off_decl_strings = decl_strings_address - stream.position();
|
||||
stream.writeUI64(off_decl_strings);
|
||||
off_type_of_fonts = type_fonts_address - stream.position();
|
||||
stream.writeUI64(off_type_of_fonts);
|
||||
stream.writeUI64(flags);
|
||||
stream.writeUI32(font_count);
|
||||
|
||||
@@ -25,35 +25,57 @@ public class IggySwf implements StructureInterface {
|
||||
String name;
|
||||
|
||||
Map<Integer, IggyFont> fonts;
|
||||
Map<Integer, IggyText> texts;
|
||||
Map<Integer, Integer> text2Font;
|
||||
|
||||
private IggyFlashHeader64 hdr;
|
||||
private Map<Long, Long> sizesOfOffsets;
|
||||
private List<Long> offsets;
|
||||
private List<IggyTag> tags = new ArrayList<>();
|
||||
|
||||
public List<IggyTag> getTags() {
|
||||
return tags;
|
||||
}
|
||||
private byte[] allFontBytes;
|
||||
|
||||
public IggySwf(IggyFlashHeader64 header, ReadDataStreamInterface stream, List<Long> offsets) throws IOException {
|
||||
this.hdr = header;
|
||||
this.offsets = offsets;
|
||||
calcSizesFromOffsets();
|
||||
public IggySwf(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
private void calcSizesFromOffsets() {
|
||||
sizesOfOffsets = new HashMap<>();
|
||||
for (int i = 0; i < offsets.size() - 1; i++) {
|
||||
sizesOfOffsets.put(offsets.get(i), offsets.get(i + 1) - offsets.get(i));
|
||||
private long font_data_addresses[];
|
||||
private long font_data_sizes[];
|
||||
private List<Long> text_addresses = new ArrayList<>();
|
||||
private List<Long> text_data_sizes = new ArrayList<>();
|
||||
private List<Long> font_add_off = new ArrayList<>();
|
||||
private List<Long> font_add_size = new ArrayList<>();
|
||||
|
||||
public void replaceFontTag(int fontIndex, IggyFont newFont) throws IOException {
|
||||
long newLen;
|
||||
byte newData[];
|
||||
try (WriteDataStreamInterface stream = new TemporaryDataStream()) {
|
||||
newFont.writeToDataStream(stream);
|
||||
newData = stream.getAllBytes();
|
||||
newLen = newData.length;
|
||||
}
|
||||
sizesOfOffsets.put(offsets.get(offsets.size() - 1), 0L); //Last offset has 0L length?
|
||||
long oldLen = font_data_sizes[fontIndex];
|
||||
long diff = newLen - oldLen;
|
||||
if (diff != 0) {
|
||||
font_data_sizes[fontIndex] = newLen;
|
||||
for (int i = fontIndex; i < hdr.font_count; i++) {
|
||||
font_data_addresses[i] += diff;
|
||||
}
|
||||
for (int i = 0; i < text_addresses.size(); i++) {
|
||||
text_addresses.set(i, text_addresses.get(i) + diff);
|
||||
}
|
||||
for (int i = 0; i < font_add_off.size(); i++) {
|
||||
font_add_off.set(i, font_add_off.get(i) + diff);
|
||||
}
|
||||
}
|
||||
hdr.insertGapAfter(font_data_addresses[fontIndex], diff);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
this.hdr = new IggyFlashHeader64(s);
|
||||
//Save all font bytes to buffer for later easy modification
|
||||
long curPos = s.position();
|
||||
long maxPos = hdr.getFontEndAddress();
|
||||
allFontBytes = s.readBytes((int) (maxPos - curPos));
|
||||
s.seek(curPos, SeekMode.SET);
|
||||
|
||||
//here is offset[0]
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
do {
|
||||
@@ -71,8 +93,8 @@ public class IggySwf implements StructureInterface {
|
||||
s.seek(hdr.getBaseAddress(), SeekMode.SET);
|
||||
s.readUI64(); //one pad
|
||||
|
||||
long font_data_addresses[] = new long[(int) hdr.font_count];
|
||||
long font_data_sizes[] = new long[(int) hdr.font_count];
|
||||
font_data_addresses = new long[(int) hdr.font_count];
|
||||
font_data_sizes = new long[(int) hdr.font_count];
|
||||
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
long offset = s.readUI64();
|
||||
@@ -85,8 +107,6 @@ public class IggySwf implements StructureInterface {
|
||||
font_data_sizes[i] = next_offset - offset;
|
||||
}
|
||||
}
|
||||
List<Long> text_addresses = new ArrayList<>();
|
||||
List<Long> text_data_sizes = new ArrayList<>();
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
long text_addr = offset + s.position() - 8;
|
||||
@@ -101,8 +121,6 @@ public class IggySwf implements StructureInterface {
|
||||
}
|
||||
}
|
||||
|
||||
List<Long> font_add_off = new ArrayList<>();
|
||||
List<Long> font_add_size = new ArrayList<>();
|
||||
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);
|
||||
@@ -129,7 +147,6 @@ public class IggySwf implements StructureInterface {
|
||||
s.seek(font_data_addresses[i], SeekMode.SET);
|
||||
//byte font_data[] = s.readBytes((int) font_data_sizes[i]);
|
||||
IggyFont font = new IggyFont(s);
|
||||
tags.add(font);
|
||||
fonts.put(i/*??*/, font);
|
||||
}
|
||||
|
||||
@@ -151,30 +168,26 @@ public class IggySwf implements StructureInterface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
|
||||
List<Long> newOffsets = new ArrayList<>();
|
||||
|
||||
try {
|
||||
newOffsets.add(stream.position());
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
stream.writeUI16(name.charAt(i));
|
||||
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);
|
||||
}
|
||||
stream.writeUI16(0);
|
||||
newOffsets.add(stream.position());
|
||||
long pad8 = 8 - (stream.position() % 8);
|
||||
for (int i = 0; i < pad8; i++) {
|
||||
stream.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);
|
||||
}
|
||||
newOffsets.add(stream.position());
|
||||
for (IggyTag tag : tags) {
|
||||
tag.writeToDataStream(stream);
|
||||
newOffsets.add(stream.position());
|
||||
s.writeUI64(1);
|
||||
s.seek(840, SeekMode.SET);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
st.writeBytes(s.getAllBytes());
|
||||
}
|
||||
this.offsets = newOffsets;
|
||||
calcSizesFromOffsets();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,8 @@ public interface WriteDataStreamInterface extends AutoCloseable {
|
||||
|
||||
public void seek(long pos, SeekMode mode) throws IOException;
|
||||
|
||||
public byte[] getAllBytes() throws IOException;
|
||||
|
||||
@Override
|
||||
public void close();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user