2018-11-28 22:18:09 +00:00
|
|
|
using System;
|
|
|
|
using System.IO;
|
|
|
|
|
|
|
|
namespace Ryujinx.HLE.Loaders.Compression
|
|
|
|
{
|
|
|
|
static class BackwardsLz
|
|
|
|
{
|
|
|
|
private class BackwardsReader
|
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
private Stream _baseStream;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
public BackwardsReader(Stream baseStream)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
_baseStream = baseStream;
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public byte ReadByte()
|
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
_baseStream.Seek(-1, SeekOrigin.Current);
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
byte value = (byte)_baseStream.ReadByte();
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
_baseStream.Seek(-1, SeekOrigin.Current);
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
return value;
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public short ReadInt16()
|
|
|
|
{
|
|
|
|
return (short)((ReadByte() << 8) | (ReadByte() << 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
public int ReadInt32()
|
|
|
|
{
|
|
|
|
return ((ReadByte() << 24) |
|
|
|
|
(ReadByte() << 16) |
|
|
|
|
(ReadByte() << 8) |
|
|
|
|
(ReadByte() << 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
public static byte[] Decompress(Stream input, int decompressedLength)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
long end = input.Position;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
BackwardsReader reader = new BackwardsReader(input);
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
int additionalDecLength = reader.ReadInt32();
|
|
|
|
int startOffset = reader.ReadInt32();
|
|
|
|
int compressedLength = reader.ReadInt32();
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
input.Seek(12 - startOffset, SeekOrigin.Current);
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
byte[] dec = new byte[decompressedLength];
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
int decompressedLengthUnpadded = compressedLength + additionalDecLength;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
int decompressionStart = decompressedLength - decompressedLengthUnpadded;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
int decPos = dec.Length;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
byte mask = 0;
|
|
|
|
byte header = 0;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
while (decPos > decompressionStart)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
if ((mask >>= 1) == 0)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
header = reader.ReadByte();
|
|
|
|
mask = 0x80;
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
if ((header & mask) == 0)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
dec[--decPos] = reader.ReadByte();
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
ushort pair = (ushort)reader.ReadInt16();
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
int length = (pair >> 12) + 3;
|
|
|
|
int position = (pair & 0xfff) + 3;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
decPos -= length;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
if (length <= position)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
int srcPos = decPos + position;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
Buffer.BlockCopy(dec, srcPos, dec, decPos, length);
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
for (int offset = 0; offset < length; offset++)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
dec[decPos + offset] = dec[decPos + position + offset];
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
return dec;
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|