Skip to content

Commit

Permalink
Fixed homebrew kip1 loading
Browse files Browse the repository at this point in the history
  • Loading branch information
Adubbz committed Mar 24, 2019
1 parent 38d3d31 commit 4e608f3
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ protected void loadDefaultSegments(TaskMonitor monitor) throws IOException, Addr
if (this.kip1.isSectionCompressed(SectionType.TEXT))
{
byte[] compressedText = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.TEXT), this.kip1.getCompressedSectionSize(SectionType.TEXT));
decompressedText = new byte[this.textSize];
ByteUtil.kip1BlzDecompress(decompressedText, compressedText);
decompressedText = ByteUtil.kip1BlzDecompress(compressedText);
}
else
{
Expand All @@ -78,8 +77,7 @@ protected void loadDefaultSegments(TaskMonitor monitor) throws IOException, Addr
if (this.kip1.isSectionCompressed(SectionType.RODATA))
{
byte[] compressedRodata = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.RODATA), this.kip1.getCompressedSectionSize(SectionType.RODATA));
decompressedRodata = new byte[this.rodataSize];
ByteUtil.kip1BlzDecompress(decompressedRodata, compressedRodata);
decompressedRodata = ByteUtil.kip1BlzDecompress(compressedRodata);
}
else
{
Expand All @@ -91,8 +89,7 @@ protected void loadDefaultSegments(TaskMonitor monitor) throws IOException, Addr
if (this.kip1.isSectionCompressed(SectionType.DATA))
{
byte[] compressedData = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.DATA), this.kip1.getCompressedSectionSize(SectionType.DATA));
decompressedData = new byte[this.dataSize];
ByteUtil.kip1BlzDecompress(decompressedData, compressedData);
decompressedData = ByteUtil.kip1BlzDecompress(compressedData);
}
else
{
Expand Down
53 changes: 34 additions & 19 deletions src/main/java/adubbz/switchloader/util/ByteUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,52 @@
import java.nio.ByteOrder;
import java.util.Arrays;

import adubbz.switchloader.common.SectionType;
import ghidra.util.Msg;

public class ByteUtil
{
public static void kip1BlzDecompress(byte[] out, byte[] in)
public static byte[] kip1BlzDecompress(byte[] compressed)
{
int compressedSize = ByteBuffer.wrap(in, in.length - 12, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
int initIndex = ByteBuffer.wrap(in, in.length - 8, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
int uncompressedAdditionalSize = ByteBuffer.wrap(in, in.length - 4, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
int compressedSize = ByteBuffer.wrap(compressed, compressed.length - 12, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
int initIndex = ByteBuffer.wrap(compressed, compressed.length - 8, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
int uncompressedAdditionalSize = ByteBuffer.wrap(compressed, compressed.length - 4, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
int decompressedSize = compressed.length + uncompressedAdditionalSize;
byte[] decompressed = new byte[decompressedSize];

if (in.length != compressedSize)
// Copy the compressed array to the decompressed array
System.arraycopy(compressed, 0, decompressed, 0, compressed.length);
Arrays.fill(decompressed, compressed.length, decompressed.length - 1, (byte)0);

// Homebrew kips often have a mismatch. This is probably a bug with elf2kip.
if (compressed.length != compressedSize)
{
if (in.length < compressedSize)
Msg.warn(null, String.format("Compressed size mismatch. Given 0x%x bytes, expected 0x%x.", compressed.length, compressedSize));

if (compressed.length < compressedSize)
throw new IllegalArgumentException("In buffer is too small!");

System.arraycopy(in, 0, in, 0, compressedSize);
byte[] tmp = new byte[compressedSize];
System.arraycopy(compressed, compressed.length - compressedSize, tmp, 0, compressedSize);
compressed = tmp;
}

if (compressedSize + uncompressedAdditionalSize == 0)
{
Msg.error(null, "Compressed size is zero!");
return;
throw new IllegalArgumentException("Compressed size is zero!");
}

// Copy the compressed array to the decompressed array
System.arraycopy(in, 0, out, 0, compressedSize);
Arrays.fill(out, compressedSize, out.length - 1, (byte)0);

int decompressedSize = in.length + uncompressedAdditionalSize;
int index = compressedSize - initIndex;
int outIndex = decompressedSize;
byte control = 0;

while (outIndex > 0)
{
index--;
control = in[index];
// Wrap back around
if (index < 0) index = compressed.length - 1;

control = compressed[index];

for (int i = 0; i < 8; i++)
{
Expand All @@ -62,7 +71,7 @@ public static void kip1BlzDecompress(byte[] out, byte[] in)

// Java has no concept of unsigned bytes, so when converting them to ints it'll think they're sometimes
// negative. We obviously don't want this.
int segmentOffset = Byte.toUnsignedInt(in[index]) | (Byte.toUnsignedInt(in[index + 1]) << 8);
int segmentOffset = Byte.toUnsignedInt(compressed[index]) | (Byte.toUnsignedInt(compressed[index + 1]) << 8);
int segmentSize = ((segmentOffset >> 12) & 0xF) + 3;

segmentOffset &= 0x0FFF;
Expand All @@ -78,9 +87,9 @@ public static void kip1BlzDecompress(byte[] out, byte[] in)
throw new IndexOutOfBoundsException("Compression out of bounds!");
}

byte data = out[outIndex + segmentOffset];
byte data = decompressed[outIndex + segmentOffset];
outIndex--;
out[outIndex] = data;
decompressed[outIndex] = data;
}
}
else
Expand All @@ -90,7 +99,11 @@ public static void kip1BlzDecompress(byte[] out, byte[] in)

outIndex--;
index--;
out[outIndex] = in[index];

// Wrap back around
if (index < 0) index = compressed.length - 1;

decompressed[outIndex] = compressed[index];
}

control <<= 1;
Expand All @@ -100,6 +113,8 @@ public static void kip1BlzDecompress(byte[] out, byte[] in)
break;
}
}

return decompressed;
}

public static void logBytes(byte[] data)
Expand Down

0 comments on commit 4e608f3

Please sign in to comment.