2018-02-05 00:08:20 +01:00
|
|
|
using System;
|
|
|
|
|
2018-06-11 02:46:42 +02:00
|
|
|
namespace Ryujinx.HLE.Loaders.Compression
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
|
|
|
static class Lz4
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
public static byte[] Decompress(byte[] cmp, int decLength)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
byte[] dec = new byte[decLength];
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
int cmpPos = 0;
|
|
|
|
int decPos = 0;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
int GetLength(int length)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
byte sum;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (length == 0xf)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
length += (sum = cmp[cmpPos++]);
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
2018-12-06 12:16:24 +01:00
|
|
|
while (sum == 0xff);
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
return length;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
byte token = cmp[cmpPos++];
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
int encCount = (token >> 0) & 0xf;
|
|
|
|
int litCount = (token >> 4) & 0xf;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2019-07-02 04:39:22 +02:00
|
|
|
// Copy literal chunk
|
2018-12-06 12:16:24 +01:00
|
|
|
litCount = GetLength(litCount);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
Buffer.BlockCopy(cmp, cmpPos, dec, decPos, litCount);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
cmpPos += litCount;
|
|
|
|
decPos += litCount;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (cmpPos >= cmp.Length)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-07-02 04:39:22 +02:00
|
|
|
// Copy compressed chunk
|
2018-12-06 12:16:24 +01:00
|
|
|
int back = cmp[cmpPos++] << 0 |
|
|
|
|
cmp[cmpPos++] << 8;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
encCount = GetLength(encCount) + 4;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
int encPos = decPos - back;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (encCount <= back)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
Buffer.BlockCopy(dec, encPos, dec, decPos, encCount);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
decPos += encCount;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
while (encCount-- > 0)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
dec[decPos++] = dec[encPos++];
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-12-06 12:16:24 +01:00
|
|
|
while (cmpPos < cmp.Length &&
|
|
|
|
decPos < dec.Length);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
return dec;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|