mirror of
https://github.com/WiiDatabase/nusdownloader.git
synced 2024-11-27 12:44:13 +01:00
364 lines
11 KiB
C#
364 lines
11 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: libWiiSharp.Lz77
|
|
// Assembly: NUS Downloader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
|
// MVID: DDAF9FEC-76DE-4BD8-8A6D-D7CAD5827AC6
|
|
// Assembly location: C:\dotpeek\NUS Downloader.exe
|
|
|
|
using System;
|
|
using System.IO;
|
|
|
|
namespace libWiiSharp
|
|
{
|
|
public class Lz77
|
|
{
|
|
private const int N = 4096;
|
|
private const int F = 18;
|
|
private const int threshold = 2;
|
|
private static uint lz77Magic = 1280980791;
|
|
private int[] leftSon = new int[4097];
|
|
private int[] rightSon = new int[4353];
|
|
private int[] dad = new int[4097];
|
|
private ushort[] textBuffer = new ushort[4113];
|
|
private int matchPosition;
|
|
private int matchLength;
|
|
|
|
public static uint Lz77Magic => Lz77.lz77Magic;
|
|
|
|
public static bool IsLz77Compressed(string file) => Lz77.IsLz77Compressed(File.ReadAllBytes(file));
|
|
|
|
public static bool IsLz77Compressed(byte[] file)
|
|
{
|
|
Headers.HeaderType startIndex = Headers.DetectHeader(file);
|
|
return (int) Shared.Swap(BitConverter.ToUInt32(file, (int) startIndex)) == (int) Lz77.lz77Magic;
|
|
}
|
|
|
|
public static bool IsLz77Compressed(Stream file)
|
|
{
|
|
Headers.HeaderType offset = Headers.DetectHeader(file);
|
|
byte[] buffer = new byte[4];
|
|
file.Seek((long) offset, SeekOrigin.Begin);
|
|
file.Read(buffer, 0, buffer.Length);
|
|
return (int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Lz77.lz77Magic;
|
|
}
|
|
|
|
public void Compress(string inFile, string outFile)
|
|
{
|
|
Stream stream;
|
|
using (FileStream inFile1 = new FileStream(inFile, FileMode.Open))
|
|
stream = this.compress((Stream) inFile1);
|
|
byte[] buffer = new byte[stream.Length];
|
|
stream.Read(buffer, 0, buffer.Length);
|
|
if (File.Exists(outFile))
|
|
File.Delete(outFile);
|
|
using (FileStream fileStream = new FileStream(outFile, FileMode.Create))
|
|
fileStream.Write(buffer, 0, buffer.Length);
|
|
}
|
|
|
|
public byte[] Compress(byte[] file) => ((MemoryStream) this.compress((Stream) new MemoryStream(file))).ToArray();
|
|
|
|
public Stream Compress(Stream file) => this.compress(file);
|
|
|
|
public void Decompress(string inFile, string outFile)
|
|
{
|
|
Stream stream;
|
|
using (FileStream inFile1 = new FileStream(inFile, FileMode.Open))
|
|
stream = this.decompress((Stream) inFile1);
|
|
byte[] buffer = new byte[stream.Length];
|
|
stream.Read(buffer, 0, buffer.Length);
|
|
if (File.Exists(outFile))
|
|
File.Delete(outFile);
|
|
using (FileStream fileStream = new FileStream(outFile, FileMode.Create))
|
|
fileStream.Write(buffer, 0, buffer.Length);
|
|
}
|
|
|
|
public byte[] Decompress(byte[] file) => ((MemoryStream) this.decompress((Stream) new MemoryStream(file))).ToArray();
|
|
|
|
public Stream Decompress(Stream file) => this.decompress(file);
|
|
|
|
private Stream decompress(Stream inFile)
|
|
{
|
|
if (!Lz77.IsLz77Compressed(inFile))
|
|
return inFile;
|
|
inFile.Seek(0L, SeekOrigin.Begin);
|
|
uint num1 = 0;
|
|
Headers.HeaderType offset = Headers.DetectHeader(inFile);
|
|
byte[] buffer = new byte[8];
|
|
inFile.Seek((long) offset, SeekOrigin.Begin);
|
|
inFile.Read(buffer, 0, 8);
|
|
if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) Lz77.lz77Magic)
|
|
{
|
|
inFile.Dispose();
|
|
throw new Exception("Invaild Magic!");
|
|
}
|
|
if (buffer[4] != (byte) 16)
|
|
{
|
|
inFile.Dispose();
|
|
throw new Exception("Unsupported Compression Type!");
|
|
}
|
|
uint num2 = BitConverter.ToUInt32(buffer, 4) >> 8;
|
|
for (int index = 0; index < 4078; ++index)
|
|
this.textBuffer[index] = (ushort) 223;
|
|
int num3 = 4078;
|
|
uint num4 = 7;
|
|
int num5 = 7;
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
label_10:
|
|
while (true)
|
|
{
|
|
num4 <<= 1;
|
|
++num5;
|
|
if (num5 == 8)
|
|
{
|
|
int num6;
|
|
if ((num6 = inFile.ReadByte()) != -1)
|
|
{
|
|
num4 = (uint) num6;
|
|
num5 = 0;
|
|
}
|
|
else
|
|
goto label_24;
|
|
}
|
|
if (((int) num4 & 128) == 0)
|
|
{
|
|
int num7;
|
|
if ((long) (num7 = inFile.ReadByte()) != inFile.Length - 1L)
|
|
{
|
|
if (num1 < num2)
|
|
memoryStream.WriteByte((byte) num7);
|
|
ushort[] textBuffer = this.textBuffer;
|
|
int index = num3;
|
|
int num8 = index + 1;
|
|
int num9 = (int) (byte) num7;
|
|
textBuffer[index] = (ushort) num9;
|
|
num3 = num8 & 4095;
|
|
++num1;
|
|
}
|
|
else
|
|
goto label_24;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
int num10;
|
|
int num11;
|
|
if ((num10 = inFile.ReadByte()) != -1 && (num11 = inFile.ReadByte()) != -1)
|
|
{
|
|
int num12 = num11 | num10 << 8 & 3840;
|
|
int num13 = (num10 >> 4 & 15) + 2;
|
|
for (int index1 = 0; index1 <= num13; ++index1)
|
|
{
|
|
int num14 = (int) this.textBuffer[num3 - num12 - 1 & 4095];
|
|
if (num1 < num2)
|
|
memoryStream.WriteByte((byte) num14);
|
|
ushort[] textBuffer = this.textBuffer;
|
|
int index2 = num3;
|
|
int num15 = index2 + 1;
|
|
int num16 = (int) (byte) num14;
|
|
textBuffer[index2] = (ushort) num16;
|
|
num3 = num15 & 4095;
|
|
++num1;
|
|
}
|
|
goto label_10;
|
|
}
|
|
label_24:
|
|
return (Stream) memoryStream;
|
|
}
|
|
|
|
private Stream compress(Stream inFile)
|
|
{
|
|
if (Lz77.IsLz77Compressed(inFile))
|
|
return inFile;
|
|
inFile.Seek(0L, SeekOrigin.Begin);
|
|
int num1 = 0;
|
|
int[] numArray1 = new int[17];
|
|
uint num2 = (uint) (((int) Convert.ToUInt32(inFile.Length) << 8) + 16);
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
memoryStream.Write(BitConverter.GetBytes(Shared.Swap(Lz77.lz77Magic)), 0, 4);
|
|
memoryStream.Write(BitConverter.GetBytes(num2), 0, 4);
|
|
this.InitTree();
|
|
numArray1[0] = 0;
|
|
int num3 = 1;
|
|
int num4 = 128;
|
|
int p = 0;
|
|
int r = 4078;
|
|
for (int index = p; index < r; ++index)
|
|
this.textBuffer[index] = ushort.MaxValue;
|
|
int num5;
|
|
int num6;
|
|
for (num5 = 0; num5 < 18 && (num6 = inFile.ReadByte()) != -1; ++num5)
|
|
this.textBuffer[r + num5] = (ushort) num6;
|
|
if (num5 == 0)
|
|
return inFile;
|
|
for (int index = 1; index <= 18; ++index)
|
|
this.InsertNode(r - index);
|
|
this.InsertNode(r);
|
|
do
|
|
{
|
|
if (this.matchLength > num5)
|
|
this.matchLength = num5;
|
|
if (this.matchLength <= 2)
|
|
{
|
|
this.matchLength = 1;
|
|
numArray1[num3++] = (int) this.textBuffer[r];
|
|
}
|
|
else
|
|
{
|
|
numArray1[0] |= num4;
|
|
int[] numArray2 = numArray1;
|
|
int index1 = num3;
|
|
int num7 = index1 + 1;
|
|
int num8 = (int) (ushort) (r - this.matchPosition - 1 >> 8 & 15) | this.matchLength - 3 << 4;
|
|
numArray2[index1] = num8;
|
|
int[] numArray3 = numArray1;
|
|
int index2 = num7;
|
|
num3 = index2 + 1;
|
|
int num9 = (int) (ushort) (r - this.matchPosition - 1 & (int) byte.MaxValue);
|
|
numArray3[index2] = num9;
|
|
}
|
|
if ((num4 >>= 1) == 0)
|
|
{
|
|
for (int index = 0; index < num3; ++index)
|
|
memoryStream.WriteByte((byte) numArray1[index]);
|
|
num1 += num3;
|
|
numArray1[0] = 0;
|
|
num3 = 1;
|
|
num4 = 128;
|
|
}
|
|
int matchLength = this.matchLength;
|
|
int num10;
|
|
int num11;
|
|
for (num10 = 0; num10 < matchLength && (num11 = inFile.ReadByte()) != -1; ++num10)
|
|
{
|
|
this.DeleteNode(p);
|
|
this.textBuffer[p] = (ushort) num11;
|
|
if (p < 17)
|
|
this.textBuffer[p + 4096] = (ushort) num11;
|
|
p = p + 1 & 4095;
|
|
r = r + 1 & 4095;
|
|
this.InsertNode(r);
|
|
}
|
|
while (num10++ < matchLength)
|
|
{
|
|
this.DeleteNode(p);
|
|
p = p + 1 & 4095;
|
|
r = r + 1 & 4095;
|
|
if (--num5 != 0)
|
|
this.InsertNode(r);
|
|
}
|
|
}
|
|
while (num5 > 0);
|
|
if (num3 > 1)
|
|
{
|
|
for (int index = 0; index < num3; ++index)
|
|
memoryStream.WriteByte((byte) numArray1[index]);
|
|
num1 += num3;
|
|
}
|
|
if (num1 % 4 != 0)
|
|
{
|
|
for (int index = 0; index < 4 - num1 % 4; ++index)
|
|
memoryStream.WriteByte((byte) 0);
|
|
}
|
|
return (Stream) memoryStream;
|
|
}
|
|
|
|
private void InitTree()
|
|
{
|
|
for (int index = 4097; index <= 4352; ++index)
|
|
this.rightSon[index] = 4096;
|
|
for (int index = 0; index < 4096; ++index)
|
|
this.dad[index] = 4096;
|
|
}
|
|
|
|
private void InsertNode(int r)
|
|
{
|
|
int num1 = 1;
|
|
int index = 4097 + (this.textBuffer[r] == ushort.MaxValue ? 0 : (int) this.textBuffer[r]);
|
|
this.rightSon[r] = this.leftSon[r] = 4096;
|
|
this.matchLength = 0;
|
|
int num2;
|
|
do
|
|
{
|
|
do
|
|
{
|
|
if (num1 >= 0)
|
|
{
|
|
if (this.rightSon[index] != 4096)
|
|
{
|
|
index = this.rightSon[index];
|
|
}
|
|
else
|
|
{
|
|
this.rightSon[index] = r;
|
|
this.dad[r] = index;
|
|
return;
|
|
}
|
|
}
|
|
else if (this.leftSon[index] != 4096)
|
|
{
|
|
index = this.leftSon[index];
|
|
}
|
|
else
|
|
{
|
|
this.leftSon[index] = r;
|
|
this.dad[r] = index;
|
|
return;
|
|
}
|
|
num2 = 1;
|
|
while (num2 < 18 && (num1 = (int) this.textBuffer[r + num2] - (int) this.textBuffer[index + num2]) == 0)
|
|
++num2;
|
|
}
|
|
while (num2 <= this.matchLength);
|
|
this.matchPosition = index;
|
|
}
|
|
while ((this.matchLength = num2) < 18);
|
|
this.dad[r] = this.dad[index];
|
|
this.leftSon[r] = this.leftSon[index];
|
|
this.rightSon[r] = this.rightSon[index];
|
|
this.dad[this.leftSon[index]] = r;
|
|
this.dad[this.rightSon[index]] = r;
|
|
if (this.rightSon[this.dad[index]] == index)
|
|
this.rightSon[this.dad[index]] = r;
|
|
else
|
|
this.leftSon[this.dad[index]] = r;
|
|
this.dad[index] = 4096;
|
|
}
|
|
|
|
private void DeleteNode(int p)
|
|
{
|
|
if (this.dad[p] == 4096)
|
|
return;
|
|
int index;
|
|
if (this.rightSon[p] == 4096)
|
|
index = this.leftSon[p];
|
|
else if (this.leftSon[p] == 4096)
|
|
{
|
|
index = this.rightSon[p];
|
|
}
|
|
else
|
|
{
|
|
index = this.leftSon[p];
|
|
if (this.rightSon[index] != 4096)
|
|
{
|
|
do
|
|
{
|
|
index = this.rightSon[index];
|
|
}
|
|
while (this.rightSon[index] != 4096);
|
|
this.rightSon[this.dad[index]] = this.leftSon[index];
|
|
this.dad[this.leftSon[index]] = this.dad[index];
|
|
this.leftSon[index] = this.leftSon[p];
|
|
this.dad[this.leftSon[p]] = index;
|
|
}
|
|
this.rightSon[index] = this.rightSon[p];
|
|
this.dad[this.rightSon[p]] = index;
|
|
}
|
|
this.dad[index] = this.dad[p];
|
|
if (this.rightSon[this.dad[p]] == p)
|
|
this.rightSon[this.dad[p]] = index;
|
|
else
|
|
this.leftSon[this.dad[p]] = index;
|
|
this.dad[p] = 4096;
|
|
}
|
|
}
|
|
}
|