2019-07-02 22:12:23 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Runtime.InteropServices;
|
2019-07-16 23:35:21 +02:00
|
|
|
|
using Toolbox.Library.IO;
|
2019-07-02 22:12:23 +02:00
|
|
|
|
|
2019-07-16 23:35:21 +02:00
|
|
|
|
namespace Toolbox.Library
|
2019-07-02 22:12:23 +02:00
|
|
|
|
{
|
|
|
|
|
public class LZ77_WII
|
|
|
|
|
{
|
2020-02-12 01:19:23 +01:00
|
|
|
|
private readonly static int N = 4096;
|
|
|
|
|
private readonly static ushort[] textBuffer = new ushort[N + 17];
|
|
|
|
|
private readonly static int F = 18;
|
|
|
|
|
private static readonly int threshold = 2;
|
|
|
|
|
|
2019-07-02 22:12:23 +02:00
|
|
|
|
public static byte[] Decompress(byte[] input)
|
|
|
|
|
{
|
|
|
|
|
if (input == null) throw new ArgumentNullException(nameof(input));
|
2020-02-12 01:19:23 +01:00
|
|
|
|
using (var reader = new FileReader(new MemoryStream(input), true))
|
|
|
|
|
{
|
|
|
|
|
reader.SetByteOrder(true);
|
|
|
|
|
reader.ReadSignature(4, "LZ77");
|
|
|
|
|
|
|
|
|
|
reader.Position = 0;
|
|
|
|
|
|
|
|
|
|
int i, j, k, r, c, z;
|
|
|
|
|
uint flags, decompressedSize, currentSize = 0;
|
|
|
|
|
|
|
|
|
|
byte[] temp = new byte[8];
|
|
|
|
|
reader.Read(temp, 0, 8);
|
|
|
|
|
|
|
|
|
|
if (temp[4] != 0x10)
|
|
|
|
|
{ reader.Dispose(); throw new Exception("Unsupported Compression Type!"); }
|
|
|
|
|
|
|
|
|
|
decompressedSize = (BitConverter.ToUInt32(temp, 4)) >> 8;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < N - F; i++) textBuffer[i] = 0xdf;
|
|
|
|
|
r = N - F; flags = 7; z = 7;
|
|
|
|
|
|
|
|
|
|
MemoryStream outFile = new MemoryStream();
|
|
|
|
|
while (outFile.Length < decompressedSize)
|
|
|
|
|
{
|
|
|
|
|
flags <<= 1;
|
|
|
|
|
z++;
|
|
|
|
|
|
|
|
|
|
if (z == 8)
|
|
|
|
|
{
|
|
|
|
|
if ((c = reader.ReadByte()) == -1) break;
|
|
|
|
|
|
|
|
|
|
flags = (uint)c;
|
|
|
|
|
z = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((flags & 0x80) == 0)
|
|
|
|
|
{
|
|
|
|
|
if ((c = reader.ReadByte()) == reader.Length - 1) break;
|
|
|
|
|
if (currentSize < decompressedSize) outFile.WriteByte((byte)c);
|
|
|
|
|
|
|
|
|
|
textBuffer[r++] = (byte)c;
|
|
|
|
|
r &= (N - 1);
|
|
|
|
|
currentSize++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((i = reader.ReadByte()) == -1) break;
|
|
|
|
|
if ((j = reader.ReadByte()) == -1) break;
|
|
|
|
|
|
|
|
|
|
j = j | ((i << 8) & 0xf00);
|
|
|
|
|
i = ((i >> 4) & 0x0f) + threshold;
|
|
|
|
|
for (k = 0; k <= i; k++)
|
|
|
|
|
{
|
|
|
|
|
c = textBuffer[(r - j - 1) & (N - 1)];
|
|
|
|
|
if (currentSize < decompressedSize) outFile.WriteByte((byte)c); textBuffer[r++] = (byte)c; r &= (N - 1); currentSize++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return outFile.ToArray();
|
|
|
|
|
}
|
2019-07-02 22:12:23 +02:00
|
|
|
|
return input;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|