Improved LZRW1 compression algorithm but it still doesn't work yet

This commit is contained in:
Michael Becker 2014-06-13 14:31:43 -04:00
parent 599a6bfe7f
commit c3246c9a73
2 changed files with 55 additions and 44 deletions

View File

@ -35,56 +35,75 @@ namespace UniversalEditor.Compression.Modules.LZRW1
Reader br = new Reader(sai);
Writer bw = new Writer(sao);
int flag = br.ReadInt32();
/*
byte *p_src = p_src_first + 4,
*p_dst = p_dst_first,
*p_dst_end = p_dst_first + dst_len;
byte *p_src_post = p_src_first + src_len;
byte *p_src_max16 = p_src_first + src_len - (16 * 2);
*/
uint control = 1;
uint flag = br.ReadUInt32();
if (flag == FLAG_COPY)
{
// entire stream is uncompressed, so read it all
byte[] data = br.ReadToEnd();
bw.WriteBytes(data);
}
else
while (!br.EndOfStream)
{
// flag is not copy, so we have to decompress
ushort controlbits = 0, control = 0;
while (!br.EndOfStream)
uint unroll;
if (control == 1)
{
byte byte1 = br.ReadByte();
byte byte2 = br.ReadByte();
uint primaryControlValue = (uint)(0x10000 | byte1);
uint secondaryControlValue = (uint)(byte2 << 8);
control = primaryControlValue;
control |= secondaryControlValue;
}
unroll = (uint)((br.Accessor.Position < br.Accessor.Length - 32) ? 16 : 1);
while (unroll-- != 0)
{
if (controlbits == 0)
{
// control bits are 0, so it's time to read a new control ushort
// don't use ReadUInt16 here because we need to keep the bytes
// for future use
control = br.ReadByte();
control |= (ushort)(br.ReadByte() << 8);
controlbits = 16;
}
if ((control & 1) != 0)
{
ushort offset, len;
offset = (ushort)((br.PeekByte() & 0xF0) << 4);
len = (ushort)(1 + (br.ReadByte() & 0xF));
offset += (ushort)(br.ReadByte() & 0xFF);
byte offsetCalcByte1 = br.ReadByte();
byte offsetCalcByte2 = br.ReadByte();
bw.Flush();
ushort offset = (ushort)(((offsetCalcByte1 & 0xF0) << 4) | offsetCalcByte2);
ushort len = (ushort)((offsetCalcByte1 & 0xF) | 4);
long oldpos = sao.Position;
sao.Position = sao.Length - offset;
byte[] nextdata = sao.Reader.ReadBytes(len);
IO.Reader bro = new Reader(sao);
byte value = bro.ReadByte();
sao.Position = oldpos;
bw.WriteBytes(nextdata);
// if((p_dst + offset) > p_dst_end) return(-1);
for (int i = 0; i < len; i++)
{
bw.WriteByte(value);
}
System.IO.File.WriteAllBytes(@"C:\Temp\Test.dat", outputStream.ToByteArray());
}
else
{
// control bit is 0, so perform a simple copy of the next byte
if (br.EndOfStream) return;
bw.WriteByte(br.ReadByte());
System.IO.File.WriteAllBytes(@"C:\Temp\Test.dat", outputStream.ToByteArray());
}
// pop the latest control bit off the control ushort
control >>= 1;
controlbits--;
}
}
bw.Flush();
}
}
}

View File

@ -66,43 +66,35 @@ namespace UniversalEditor.DataFormats
MemoryAccessor ma = new MemoryAccessor();
Writer bwms = new Writer(ma);
Accessor.Position = 0;
LZRW1CompressionModule module = new LZRW1CompressionModule();
byte[] compressed = new byte[0];
int i = 0;
Accessor.Position = 0;
while (!br.EndOfStream)
{
if (br.Remaining == 20)
{
// we are done reading the file, because we've encountered the footer!
break;
}
}
short CHUNKSIZE = br.ReadInt16();
byte[] input = br.ReadBytes(CHUNKSIZE);
Array.Resize<byte>(ref compressed, compressed.Length + input.Length);
Array.Copy(input, 0, compressed, i, input.Length);
i += input.Length;
byte[] compressed = br.ReadBytes(CHUNKSIZE);
byte[] decompressed = module.Decompress(compressed);
bwms.WriteBytes(decompressed);
if (br.EndOfStream) break;
}
LZRW1ACompressionModule module = new LZRW1ACompressionModule();
byte[] uncompressed = module.Decompress(compressed);
bwms.Write(uncompressed, 0, uncompressed.Length);
bwms.Flush();
ma.Position = 0;
System.IO.File.WriteAllBytes(@"C:\Temp\New Folder\test-compressed.dat", compressed);
System.IO.File.WriteAllBytes(@"C:\Temp\New Folder\test-uncompressed.dat", ma.ToArray());
Reader brms = new Reader(ma);
if (fileListOffset > brms.Accessor.Length) throw new InvalidDataFormatException("File must be larger than file list offset (" + fileListOffset.ToString() + ")");
brms.Accessor.Position = fileListOffset;
if (brms.Accessor.Position >= (brms.Accessor.Length - (572 * fileCount))) throw new InvalidOperationException();
if (brms.Accessor.Position >= (brms.Accessor.Length - (572 * fileCount))) throw new InvalidDataFormatException("No file data is present or the archive is too small");
for (int f = 0; f < fileCount; f++)
{