diff --git a/BurnOutSharp/External/libmspack/CAB/Decompressor.cs b/BurnOutSharp/External/libmspack/CAB/Decompressor.cs
index 8d50c233..ba5f34e8 100644
--- a/BurnOutSharp/External/libmspack/CAB/Decompressor.cs
+++ b/BurnOutSharp/External/libmspack/CAB/Decompressor.cs
@@ -357,7 +357,6 @@ namespace LibMSPackSharp.CAB
}
// Seek to start of data blocks
- // TODO: For LZX, they seem to start 8 bytes after the offset for some reason?
if (!System.Seek(State.InputFileHandle, file.Folder.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
return Error = Error.MSPACK_ERR_SEEK;
@@ -553,85 +552,74 @@ namespace LibMSPackSharp.CAB
/// use. will read data blocks (and merge split blocks) from the cabinet
/// and serve the read bytes to the decompressors
///
- internal static int SysRead(object file, byte[] buffer, int pointer, int bytes)
+ internal int SysRead(object file, byte[] buffer, int pointer, int bytes)
{
- if (file is Decompressor self)
+ int avail, todo, outlen = 0;
+
+ bool ignore_cksum = Salvage ||
+ (FixMSZip &&
+ ((State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_MSZIP));
+ bool ignore_blocksize = Salvage;
+
+ todo = bytes;
+ while (todo > 0)
{
- SystemImpl sys = self.System;
+ avail = State.InputEnd - State.InputPointer;
- int avail, todo, outlen = 0;
-
- bool ignore_cksum = self.Salvage ||
- (self.FixMSZip &&
- ((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_MSZIP));
- bool ignore_blocksize = self.Salvage;
-
- todo = bytes;
- while (todo > 0)
+ // If out of input data, read a new block
+ if (avail != 0)
{
- avail = self.State.InputEnd - self.State.InputPointer;
+ // Copy as many input bytes available as possible
+ if (avail > todo)
+ avail = todo;
- // If out of input data, read a new block
- if (avail != 0)
+ Array.Copy(State.Input, State.InputPointer, buffer, pointer, avail);
+ State.InputPointer += avail;
+ pointer += avail;
+ todo -= avail;
+ }
+ else
+ {
+ // Out of data, read a new block
+
+ // Check if we're out of input blocks, advance block counter
+ if (State.Block++ >= State.Folder.Header.NumBlocks)
{
- // Copy as many input bytes available as possible
- if (avail > todo)
- avail = todo;
+ if (!Salvage)
+ ReadError = Error.MSPACK_ERR_DATAFORMAT;
+ else
+ Console.WriteLine("Ran out of CAB input blocks prematurely");
- Array.Copy(self.State.Input, self.State.InputPointer, buffer, pointer, avail);
- self.State.InputPointer += avail;
- pointer += avail;
- todo -= avail;
+ break;
}
- else
+
+ // Read a block
+ ReadError = SysReadBlock(ref outlen, ignore_cksum, ignore_blocksize);
+ if (ReadError != Error.MSPACK_ERR_OK)
+ return -1;
+
+ State.Outlen += outlen;
+
+ // Special Quantum hack -- trailer byte to allow the decompressor
+ // to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
+ // anything from 0 to 4 trailing null bytes.
+ if ((State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_QUANTUM)
+ State.Input[State.InputEnd++] = 0xFF;
+
+ // Is this the last block?
+ if (State.Block >= State.Folder.Header.NumBlocks)
{
- // Out of data, read a new block
-
- // Check if we're out of input blocks, advance block counter
- if (self.State.Block++ >= self.State.Folder.Header.NumBlocks)
+ if ((State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_LZX)
{
- if (!self.Salvage)
- self.ReadError = Error.MSPACK_ERR_DATAFORMAT;
- else
- Console.WriteLine("Ran out of CAB input blocks prematurely");
-
- break;
- }
-
- // Read a block
- self.ReadError = SysReadBlock(sys, self.State, ref outlen, ignore_cksum, ignore_blocksize);
- if (self.ReadError != Error.MSPACK_ERR_OK)
- return -1;
-
- self.State.Outlen += outlen;
-
- // Special Quantum hack -- trailer byte to allow the decompressor
- // to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
- // anything from 0 to 4 trailing null bytes.
- if ((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_QUANTUM)
- self.State.Input[self.State.InputEnd++] = 0xFF;
-
- // Is this the last block?
- if (self.State.Block >= self.State.Folder.Header.NumBlocks)
- {
- if ((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_LZX)
- {
- // Special LZX hack -- on the last block, inform LZX of the
- // size of the output data stream.
- (self.State.DecompressorState as LZX).SetOutputLength(self.State.Outlen);
- }
+ // Special LZX hack -- on the last block, inform LZX of the
+ // size of the output data stream.
+ (State.DecompressorState as LZX).SetOutputLength(State.Outlen);
}
}
}
-
- return bytes - todo;
- }
- else if (file is FileStream impl)
- {
- return SystemImpl.DefaultSystem.Read(impl, buffer, pointer, bytes);
}
- return -1;
+ return bytes - todo;
}
///
@@ -640,50 +628,35 @@ namespace LibMSPackSharp.CAB
/// sys.write() function, or does nothing with the data when
/// self.State.OutputFileHandle == null. advances self.State.Offset
///
- internal static int SysWrite(object file, byte[] buffer, int pointer, int bytes)
+ internal int SysWrite(object file, byte[] buffer, int pointer, int bytes)
{
- // Null output file means skip those bytes
- if (file == null)
- {
- return bytes;
- }
- else if (file is Decompressor self)
- {
- self.State.Offset += (uint)bytes;
- if (self.State.OutputFileHandle != null)
- return self.System.Write(self.State.OutputFileHandle, buffer, pointer, bytes);
+ State.Offset += (uint)bytes;
+ if (State.OutputFileHandle != null)
+ return System.Write(State.OutputFileHandle, buffer, pointer, bytes);
- return bytes;
- }
- else if (file is FileStream impl)
- {
- return SystemImpl.DefaultSystem.Write(impl, buffer, pointer, bytes);
- }
-
- // Unknown file to write to
- return 0;
+ return bytes;
}
///
/// Reads a whole data block from a cab file. The block may span more than
/// one cab file, if it does then the fragments will be reassembled
///
- private static Error SysReadBlock(SystemImpl sys, DecompressState d, ref int output, bool ignore_cksum, bool ignore_blocksize)
+ private Error SysReadBlock(ref int output, bool ignore_cksum, bool ignore_blocksize)
{
byte[] hdr = new byte[_DataBlockHeader.Size];
int full_len;
// Reset the input block pointer and end of block pointer
- d.InputPointer = d.InputEnd = 0;
+ State.InputPointer = State.InputEnd = 0;
do
{
// Read the block header
- if (SystemImpl.DefaultSystem.Read(d.InputFileHandle, hdr, 0, _DataBlockHeader.Size) != _DataBlockHeader.Size)
+ if (SystemImpl.DefaultSystem.Read(State.InputFileHandle, hdr, 0, _DataBlockHeader.Size) != _DataBlockHeader.Size)
return Error.MSPACK_ERR_READ;
// Skip any reserved block headers
- if (d.Data.Cab.Header.HeaderReserved != 0 && !sys.Seek(d.InputFileHandle, d.Data.Cab.Header.HeaderReserved, SeekMode.MSPACK_SYS_SEEK_CUR))
+ if (State.Data.Cab.Header.DataReserved != 0 && !System.Seek(State.InputFileHandle, State.Data.Cab.Header.DataReserved, SeekMode.MSPACK_SYS_SEEK_CUR))
return Error.MSPACK_ERR_SEEK;
// Create a block header from the data
@@ -692,7 +665,7 @@ namespace LibMSPackSharp.CAB
return err;
// Blocks must not be over CAB_INPUTMAX in size
- full_len = (d.InputEnd - d.InputPointer) + dataBlockHeader.CompressedSize; // Include cab-spanning blocks
+ full_len = (State.InputEnd - State.InputPointer) + dataBlockHeader.CompressedSize; // Include cab-spanning blocks
if (full_len > CAB_INPUTMAX)
{
Console.WriteLine($"Block size {full_len} > CAB_INPUTMAX");
@@ -711,24 +684,24 @@ namespace LibMSPackSharp.CAB
}
// Read the block data
- if (SystemImpl.DefaultSystem.Read(d.InputFileHandle, d.Input, d.InputEnd, dataBlockHeader.CompressedSize) != dataBlockHeader.CompressedSize)
+ if (SystemImpl.DefaultSystem.Read(State.InputFileHandle, State.Input, State.InputEnd, dataBlockHeader.CompressedSize) != dataBlockHeader.CompressedSize)
return Error.MSPACK_ERR_READ;
// Perform checksum test on the block (if one is stored)
if (dataBlockHeader.CheckSum != 0)
{
- uint sum2 = Checksum(d.Input, d.InputEnd, dataBlockHeader.CompressedSize, 0);
+ uint sum2 = Checksum(State.Input, State.InputEnd, dataBlockHeader.CompressedSize, 0);
if (Checksum(hdr, 4, 4, sum2) != dataBlockHeader.CheckSum)
{
if (!ignore_cksum)
return Error.MSPACK_ERR_CHECKSUM;
- sys.Message(d.InputFileHandle, "WARNING; bad block checksum found");
+ System.Message(State.InputFileHandle, "WARNING; bad block checksum found");
}
}
// Advance end of block pointer to include newly read data
- d.InputEnd += dataBlockHeader.CompressedSize;
+ State.InputEnd += dataBlockHeader.CompressedSize;
// Uncompressed size == 0 means this block was part of a split block
// and it continues as the first block of the next cabinet in the set.
@@ -742,23 +715,23 @@ namespace LibMSPackSharp.CAB
// Otherwise, advance to next cabinet
// Close current file handle
- sys.Close(d.InputFileHandle);
- d.InputFileHandle = null;
+ System.Close(State.InputFileHandle);
+ State.InputFileHandle = null;
// Advance to next member in the cabinet set
- if ((d.Data = d.Data.Next) == null)
+ if ((State.Data = State.Data.Next) == null)
{
- sys.Message(d.InputFileHandle, "WARNING; ran out of cabinets in set. Are any missing?");
+ System.Message(State.InputFileHandle, "WARNING; ran out of cabinets in set. Are any missing?");
return Error.MSPACK_ERR_DATAFORMAT;
}
// Open next cab file
- d.InputCabinet = d.Data.Cab;
- if ((d.InputFileHandle = sys.Open(d.InputCabinet.Filename, OpenMode.MSPACK_SYS_OPEN_READ)) == null)
+ State.InputCabinet = State.Data.Cab;
+ if ((State.InputFileHandle = System.Open(State.InputCabinet.Filename, OpenMode.MSPACK_SYS_OPEN_READ)) == null)
return Error.MSPACK_ERR_OPEN;
// Seek to start of data blocks
- if (!sys.Seek(d.InputFileHandle, d.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
+ if (!System.Seek(State.InputFileHandle, State.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
return Error.MSPACK_ERR_SEEK;
} while (true);
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZX.Decompress.cs b/BurnOutSharp/External/libmspack/Compression/LZX.Decompress.cs
index 48a94c00..8a74e511 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZX.Decompress.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZX.Decompress.cs
@@ -321,7 +321,7 @@ namespace LibMSPackSharp.Compression
while (Frame < end_frame)
{
// Have we reached the reset interval? (if there is one?)
- if (ResetInterval != 0 && ((Frame & ResetInterval) == 0))
+ if (ResetInterval != 0 && ((Frame % ResetInterval) == 0))
{
if (BlockRemaining != 0)
{
@@ -800,9 +800,29 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
- ///
- /// Use the cleaned up code for decompression based on wimlib
- ///
+ private void ResetState()
+ {
+ R[0] = 1;
+ R[1] = 1;
+ R[2] = 1;
+ HeaderRead = 0;
+ BlockRemaining = 0;
+ BlockType = LZXBlockType.LZX_BLOCKTYPE_INVALID0;
+
+ // Initialise tables to 0 (because deltas will be applied to them)
+ for (int i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++)
+ {
+ MAINTREE_len[i] = 0;
+ }
+
+ for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
+ {
+ LENGTH_len[i] = 0;
+ }
+ }
+
+ #region wimlib
+
public Error DecompressNew(long out_bytes)
{
int warned = 0;
@@ -1012,56 +1032,6 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
- private Error BUILD_TABLE(ushort[] table, byte[] lengths, int tablebits, int maxsymbols)
- {
- if (!MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
- {
- Console.WriteLine($"Failed to build table");
- return Error = Error.MSPACK_ERR_DECRUNCH;
- }
-
- return Error = Error.MSPACK_ERR_OK;
- }
-
- private Error BUILD_TABLE_MAYBE_EMPTY()
- {
- LENGTH_empty = 0;
- if (!MakeDecodeTableMSB(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, LENGTH_len, LENGTH_table))
- {
- for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
- {
- if (LENGTH_len[i] > 0)
- {
- Console.WriteLine("Failed to build table");
- return Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
-
- // Empty tree - allow it, but don't decode symbols with it
- LENGTH_empty = 1;
- }
-
- return Error = Error.MSPACK_ERR_OK;
- }
-
- private Error READ_LENGTHS(byte[] lengths, uint first, uint last)
- {
- int i_ptr = InputPointer;
- int i_end = InputEnd;
- uint bit_buffer = BitBuffer;
- int bits_left = BitsLeft;
-
- if (ReadLens(lengths, first, last) != Error.MSPACK_ERR_OK)
- return Error;
-
- InputPointer = i_ptr;
- InputEnd = i_end;
- BitBuffer = bit_buffer;
- BitsLeft = bits_left;
-
- return Error = Error.MSPACK_ERR_OK;
- }
-
private Error Copy(uint match_offset, int match_len, ref int this_run)
{
// Copy match
@@ -1399,101 +1369,6 @@ namespace LibMSPackSharp.Compression
return Error = Error.MSPACK_ERR_OK;
}
- private Error ReadLens(byte[] lens, uint first, uint last)
- {
- uint x, y;
- int z;
-
- // Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits)
- for (x = 0; x < LZX_PRETREE_MAXSYMBOLS; x++)
- {
- y = (uint)READ_BITS_MSB(4);
- PRETREE_len[x] = (byte)y;
- }
-
- BUILD_TABLE(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
- if (Error != Error.MSPACK_ERR_OK)
- return Error;
-
- for (x = first; x < last;)
- {
- z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
- switch (z)
- {
- // Code = 17, run of ([read 4 bits]+4) zeros
- case 17:
- y = (uint)READ_BITS_MSB(4);
- y += 4;
- while (y-- != 0)
- {
- lens[x++] = 0;
- }
-
- break;
-
- // Code = 18, run of ([read 5 bits]+20) zeros
- case 18:
- y = (uint)READ_BITS_MSB(5);
- y += 20;
- while (y-- != 0)
- {
- lens[x++] = 0;
- }
-
- break;
-
- // Code = 19, run of ([read 1 bit]+4) [read huffman symbol]
- case 19:
- y = (uint)READ_BITS_MSB(1);
- y += 4;
-
- z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
- z = lens[x] - z;
- if (z < 0)
- z += 17;
-
- while (y-- != 0)
- {
- lens[x++] = (byte)z;
- }
-
- break;
-
- // Code = 0 to 16, delta current length entry
- default:
- z = lens[x] - z;
- if (z < 0)
- z += 17;
-
- lens[x++] = (byte)z;
- break;
- }
- }
-
- return Error.MSPACK_ERR_OK;
- }
-
- private void ResetState()
- {
- R[0] = 1;
- R[1] = 1;
- R[2] = 1;
- HeaderRead = 0;
- BlockRemaining = 0;
- BlockType = LZXBlockType.LZX_BLOCKTYPE_INVALID0;
-
- // Initialise tables to 0 (because deltas will be applied to them)
- for (int i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++)
- {
- MAINTREE_len[i] = 0;
- }
-
- for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
- {
- LENGTH_len[i] = 0;
- }
- }
-
private void UndoE8Preprocessing(int data, long out_bytes)
{
int p8 = data;
@@ -1540,5 +1415,7 @@ namespace LibMSPackSharp.Compression
} while (p8 < p8_end);
}
}
+
+ #endregion
}
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZX.ReadHuff.cs b/BurnOutSharp/External/libmspack/Compression/LZX.ReadHuff.cs
index 12a42af9..7d1824c0 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZX.ReadHuff.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZX.ReadHuff.cs
@@ -10,11 +10,146 @@
* For further details, see the file COPYING.LIB distributed with libmspack
*/
+using System;
+using static LibMSPackSharp.Compression.Constants;
+
namespace LibMSPackSharp.Compression
{
public partial class LZX : CompressionStream
{
///
public override Error HUFF_ERROR() => Error.MSPACK_ERR_DECRUNCH;
+
+ ///
+ /// BUILD_TABLE(tbl) builds a huffman lookup table from code lengths
+ ///
+ private Error BUILD_TABLE(ushort[] table, byte[] lengths, int tablebits, int maxsymbols)
+ {
+ if (!MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
+ {
+ Console.WriteLine("Failed to build table");
+ return Error = Error.MSPACK_ERR_DECRUNCH;
+ }
+
+ return Error = Error.MSPACK_ERR_OK;
+ }
+
+ private Error BUILD_TABLE_MAYBE_EMPTY()
+ {
+ LENGTH_empty = 0;
+ if (!MakeDecodeTableMSB(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, LENGTH_len, LENGTH_table))
+ {
+ for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
+ {
+ if (LENGTH_len[i] > 0)
+ {
+ Console.WriteLine("Failed to build table");
+ return Error = Error.MSPACK_ERR_DECRUNCH;
+ }
+ }
+
+ // Empty tree - allow it, but don't decode symbols with it
+ LENGTH_empty = 1;
+ }
+
+ return Error = Error.MSPACK_ERR_OK;
+ }
+
+ ///
+ /// READ_LENGTHS(tablename, first, last) reads in code lengths for symbols
+ /// first to last in the given table. The code lengths are stored in their
+ /// own special LZX way.
+ ///
+ private Error READ_LENGTHS(byte[] lengths, uint first, uint last)
+ {
+ int i_ptr = InputPointer;
+ int i_end = InputEnd;
+ uint bit_buffer = BitBuffer;
+ int bits_left = BitsLeft;
+
+ if (ReadLens(lengths, first, last) != Error.MSPACK_ERR_OK)
+ return Error;
+
+ InputPointer = i_ptr;
+ InputEnd = i_end;
+ BitBuffer = bit_buffer;
+ BitsLeft = bits_left;
+
+ return Error = Error.MSPACK_ERR_OK;
+ }
+
+ private Error ReadLens(byte[] lens, uint first, uint last)
+ {
+ uint x, y;
+ int z;
+
+ // Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits)
+ for (x = 0; x < LZX_PRETREE_MAXSYMBOLS; x++)
+ {
+ y = (uint)READ_BITS_MSB(4);
+ PRETREE_len[x] = (byte)y;
+ }
+
+ BUILD_TABLE(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ for (x = first; x < last;)
+ {
+ z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
+ switch (z)
+ {
+ // Code = 17, run of ([read 4 bits]+4) zeros
+ case 17:
+ y = (uint)READ_BITS_MSB(4);
+ y += 4;
+ while (y-- != 0)
+ {
+ lens[x++] = 0;
+ }
+
+ break;
+
+ // Code = 18, run of ([read 5 bits]+20) zeros
+ case 18:
+ y = (uint)READ_BITS_MSB(5);
+ y += 20;
+ while (y-- != 0)
+ {
+ lens[x++] = 0;
+ }
+
+ break;
+
+ // Code = 19, run of ([read 1 bit]+4) [read huffman symbol]
+ case 19:
+ y = (uint)READ_BITS_MSB(1);
+ y += 4;
+
+ z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
+ z = lens[x] - z;
+ if (z < 0)
+ z += 17;
+
+ while (y-- != 0)
+ {
+ lens[x++] = (byte)z;
+ }
+
+ break;
+
+ // Code = 0 to 16, delta current length entry
+ default:
+ z = lens[x] - z;
+ if (z < 0)
+ z += 17;
+
+ lens[x++] = (byte)z;
+ break;
+ }
+ }
+
+ return Error.MSPACK_ERR_OK;
+ }
}
}