diff --git a/Ryujinx.HLE/Loaders/Compression/BackwardsLz.cs b/Ryujinx.HLE/Loaders/Compression/BackwardsLz.cs index 166ae60a9d..0a76dc950c 100644 --- a/Ryujinx.HLE/Loaders/Compression/BackwardsLz.cs +++ b/Ryujinx.HLE/Loaders/Compression/BackwardsLz.cs @@ -1,5 +1,4 @@ using System; -using System.IO; namespace Ryujinx.HLE.Loaders.Compression { @@ -7,22 +6,26 @@ namespace Ryujinx.HLE.Loaders.Compression { private class BackwardsReader { - private Stream _baseStream; + private byte[] _data; - public BackwardsReader(Stream baseStream) + private int _position; + + public int Position => _position; + + public BackwardsReader(byte[] data, int end) { - _baseStream = baseStream; + _data = data; + _position = end; + } + + public void SeekCurrent(int offset) + { + _position += offset; } public byte ReadByte() { - _baseStream.Seek(-1, SeekOrigin.Current); - - byte value = (byte)_baseStream.ReadByte(); - - _baseStream.Seek(-1, SeekOrigin.Current); - - return value; + return _data[--_position]; } public short ReadInt16() @@ -39,30 +42,24 @@ namespace Ryujinx.HLE.Loaders.Compression } } - public static byte[] Decompress(Stream input, int decompressedLength) + public static void DecompressInPlace(byte[] buffer, int headerEnd) { - long end = input.Position; - - BackwardsReader reader = new BackwardsReader(input); + BackwardsReader reader = new BackwardsReader(buffer, headerEnd); int additionalDecLength = reader.ReadInt32(); int startOffset = reader.ReadInt32(); int compressedLength = reader.ReadInt32(); - input.Seek(12 - startOffset, SeekOrigin.Current); + reader.SeekCurrent(12 - startOffset); - byte[] dec = new byte[decompressedLength]; + int decBase = headerEnd - compressedLength; - int decompressedLengthUnpadded = compressedLength + additionalDecLength; - - int decompressionStart = decompressedLength - decompressedLengthUnpadded; - - int decPos = dec.Length; + int decPos = compressedLength + additionalDecLength; byte mask = 0; byte header = 0; - while (decPos > decompressionStart) + while (decPos > 0) { if ((mask >>= 1) == 0) { @@ -72,7 +69,7 @@ namespace Ryujinx.HLE.Loaders.Compression if ((header & mask) == 0) { - dec[--decPos] = reader.ReadByte(); + buffer[decBase + --decPos] = reader.ReadByte(); } else { @@ -81,25 +78,30 @@ namespace Ryujinx.HLE.Loaders.Compression int length = (pair >> 12) + 3; int position = (pair & 0xfff) + 3; + if (length > decPos) + { + length = decPos; + } + decPos -= length; + int dstPos = decBase + decPos; + if (length <= position) { - int srcPos = decPos + position; + int srcPos = dstPos + position; - Buffer.BlockCopy(dec, srcPos, dec, decPos, length); + Buffer.BlockCopy(buffer, srcPos, buffer, dstPos, length); } else { for (int offset = 0; offset < length; offset++) { - dec[decPos + offset] = dec[decPos + position + offset]; + buffer[dstPos + offset] = buffer[dstPos + position + offset]; } } } } - - return dec; } } } \ No newline at end of file diff --git a/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs b/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs index 8b09bfcd2d..383bce8f57 100644 --- a/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs +++ b/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs @@ -114,13 +114,11 @@ namespace Ryujinx.HLE.Loaders.Executables private byte[] ReadSegment(SegmentHeader header, Stream input) { - long end = input.Position + header.CompressedSize; + byte[] data = new byte[header.DecompressedSize]; - input.Seek(end, SeekOrigin.Begin); + input.Read(data, 0, header.CompressedSize); - byte[] data = BackwardsLz.Decompress(input, header.DecompressedSize); - - input.Seek(end, SeekOrigin.Begin); + BackwardsLz.DecompressInPlace(data, header.CompressedSize); return data; }