Yaz0 code must be rewritten
This commit is contained in:
@@ -1,135 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BMGEditor
|
||||
{
|
||||
public static class Yaz0 // ONLY WORKS WITH BIG ENDIAN - TO REWRITE !!
|
||||
{
|
||||
// TODO: put compression in use?
|
||||
// note: compression is slow when dealing with large files (eg. 3D models)
|
||||
// it should be made optional, and show a progress dialog and all
|
||||
|
||||
private static void FindOccurence(byte[] data, int pos, ref int offset, ref int length)
|
||||
{
|
||||
offset = -1;
|
||||
length = 0;
|
||||
|
||||
if (pos >= data.Length - 2) return;
|
||||
|
||||
Dictionary<int, int> occurences = new Dictionary<int, int>();
|
||||
|
||||
int len = 0;
|
||||
int start = (pos > 4096) ? pos - 4096 : 0;
|
||||
for (int i = start; i < pos; i++)
|
||||
{
|
||||
if (i >= data.Length - 2) break;
|
||||
|
||||
if (data[i] != data[pos] || data[i + 1] != data[pos + 1] || data[i + 2] != data[pos + 2])
|
||||
continue;
|
||||
|
||||
len = 3;
|
||||
while ((i + len < data.Length) && (pos + len < data.Length) && (data[i + len] == data[pos + len]))
|
||||
len++;
|
||||
|
||||
occurences.Add(i, len);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<int, int> occ in occurences)
|
||||
{
|
||||
if (occ.Value > length)
|
||||
{
|
||||
offset = occ.Key;
|
||||
length = occ.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Compress(ref byte[] data)
|
||||
{
|
||||
if (data[0] == 'Y' && data[1] == 'a' && data[2] == 'z' && data[3] == '0')
|
||||
return;
|
||||
|
||||
byte[] output = new byte[16 + data.Length + (data.Length / 8)];
|
||||
|
||||
output[0] = (byte)'Y';
|
||||
output[1] = (byte)'a';
|
||||
output[2] = (byte)'z';
|
||||
output[3] = (byte)'0';
|
||||
|
||||
uint fullsize = (uint)data.Length;
|
||||
output[4] = (byte)(fullsize >> 24);
|
||||
output[5] = (byte)(fullsize >> 16);
|
||||
output[6] = (byte)(fullsize >> 8);
|
||||
output[7] = (byte)fullsize;
|
||||
|
||||
int inpos = 0, outpos = 16;
|
||||
int occ_offset = -1, occ_length = 0;
|
||||
|
||||
while (inpos < fullsize)
|
||||
{
|
||||
int datastart = outpos + 1;
|
||||
byte block = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
block <<= 1;
|
||||
|
||||
if (inpos < data.Length)
|
||||
{
|
||||
if (occ_offset == -2)
|
||||
FindOccurence(data, inpos, ref occ_offset, ref occ_length);
|
||||
|
||||
int next_offset = -1, next_length = 0;
|
||||
FindOccurence(data, inpos + 1, ref next_offset, ref next_length);
|
||||
if (next_length > occ_length + 1) occ_offset = -1;
|
||||
|
||||
if (occ_offset != -1)
|
||||
{
|
||||
int disp = inpos - occ_offset - 1;
|
||||
if (disp > 4095) throw new Exception("DISP OUT OF RANGE!");
|
||||
|
||||
if (occ_length > 17)
|
||||
{
|
||||
if (occ_length > 273) occ_length = 273;
|
||||
|
||||
output[datastart++] = (byte)(disp >> 8);
|
||||
output[datastart++] = (byte)disp;
|
||||
output[datastart++] = (byte)(occ_length - 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
output[datastart++] = (byte)(((occ_length - 2) << 4) | (disp >> 8));
|
||||
output[datastart++] = (byte)disp;
|
||||
}
|
||||
|
||||
inpos += occ_length;
|
||||
occ_offset = -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
output[datastart++] = data[inpos++];
|
||||
block |= 0x01;
|
||||
}
|
||||
|
||||
if (occ_offset != -2)
|
||||
{
|
||||
occ_offset = next_offset;
|
||||
occ_length = next_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output[outpos] = block;
|
||||
outpos = datastart;
|
||||
}
|
||||
|
||||
Array.Resize(ref data, outpos);
|
||||
Array.Resize(ref output, outpos);
|
||||
output.CopyTo(data, 0);
|
||||
}
|
||||
|
||||
// inspired from http://www.amnoid.de/gc/yaz0.txt
|
||||
public static void Decompress(ref byte[] data)
|
||||
{
|
||||
|
||||
@@ -24,30 +24,6 @@ namespace BMGEditor
|
||||
Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
public void Flush(bool recompress)
|
||||
{
|
||||
byte[] buffer = new byte[Length];
|
||||
Position = 0;
|
||||
Read(buffer, 0, (int)Length);
|
||||
if (recompress) Yaz0.Compress(ref buffer);
|
||||
|
||||
m_Backend.Position = 0;
|
||||
m_Backend.SetLength(buffer.Length);
|
||||
m_Backend.Write(buffer, 0, buffer.Length);
|
||||
m_Backend.Flush();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
Flush(false);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
m_Backend.Close();
|
||||
base.Close();
|
||||
}
|
||||
|
||||
|
||||
private Stream m_Backend;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user