diff --git a/BurnOutSharp/External/libmspack/CHM/Decompressor.cs b/BurnOutSharp/External/libmspack/CHM/Decompressor.cs
index 97bffc8b..cb2706d4 100644
--- a/BurnOutSharp/External/libmspack/CHM/Decompressor.cs
+++ b/BurnOutSharp/External/libmspack/CHM/Decompressor.cs
@@ -19,6 +19,7 @@ using System.IO;
using System.Text;
using LibMSPackSharp.Compression;
using static LibMSPackSharp.Constants;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.CHM
{
@@ -242,7 +243,7 @@ namespace LibMSPackSharp.CHM
return Error = err;
// Validate reset_interval
- if (lzxControlData.ResetInterval == 0 || (lzxControlData.ResetInterval % LZX.LZX_FRAME_SIZE) != 0)
+ if (lzxControlData.ResetInterval == 0 || (lzxControlData.ResetInterval % LZX_FRAME_SIZE) != 0)
{
Console.WriteLine("Bad controldata reset interval");
return Error = Error.MSPACK_ERR_DATAFORMAT;
@@ -252,7 +253,7 @@ namespace LibMSPackSharp.CHM
int entry = (int)(file.Offset / lzxControlData.ResetInterval);
// Convert from reset interval multiple (usually 64k) to 32k frames
- entry *= (int)lzxControlData.ResetInterval / LZX.LZX_FRAME_SIZE;
+ entry *= (int)lzxControlData.ResetInterval / LZX_FRAME_SIZE;
// Read the reset table entry
if (ReadResetTable(sec, (uint)entry, out long length, out long offset))
@@ -284,11 +285,11 @@ namespace LibMSPackSharp.CHM
State.InOffset = file.Section.Header.Sec0.Offset + sec.Content.Offset + offset;
// Set start offset and overall remaining stream length
- State.Offset = entry * LZX.LZX_FRAME_SIZE;
+ State.Offset = entry * LZX_FRAME_SIZE;
length -= State.Offset;
// Initialise LZX stream
- State.State = LZX.Init(State.System, State.InputFileHandle, State.OutputFileHandle, windowBits, (int)lzxControlData.ResetInterval / LZX.LZX_FRAME_SIZE, 4096, length, false);
+ State.State = LZX.Init(State.System, State.InputFileHandle, State.OutputFileHandle, windowBits, (int)lzxControlData.ResetInterval / LZX_FRAME_SIZE, 4096, length, false);
if (State.State == null)
Error = Error.MSPACK_ERR_NOMEMORY;
@@ -1081,7 +1082,7 @@ namespace LibMSPackSharp.CHM
return false;
// Check sanity of reset table
- if (lzxResetTable.FrameLength != LZX.LZX_FRAME_SIZE)
+ if (lzxResetTable.FrameLength != LZX_FRAME_SIZE)
{
Console.WriteLine("Bad reset table frame length");
return false;
diff --git a/BurnOutSharp/External/libmspack/CHM/_LZXControlData.cs b/BurnOutSharp/External/libmspack/CHM/_LZXControlData.cs
index 6d8e5687..c8f3ed09 100644
--- a/BurnOutSharp/External/libmspack/CHM/_LZXControlData.cs
+++ b/BurnOutSharp/External/libmspack/CHM/_LZXControlData.cs
@@ -8,7 +8,7 @@
*/
using System;
-using LibMSPackSharp.Compression;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.CHM
{
@@ -94,8 +94,8 @@ namespace LibMSPackSharp.CHM
controlData.WindowSize = BitConverter.ToUInt32(buffer, 0x0010);
break;
case 2:
- controlData.ResetInterval = BitConverter.ToUInt32(buffer, 0x000C) * LZX.LZX_FRAME_SIZE;
- controlData.WindowSize = BitConverter.ToUInt32(buffer, 0x0010) * LZX.LZX_FRAME_SIZE;
+ controlData.ResetInterval = BitConverter.ToUInt32(buffer, 0x000C) * LZX_FRAME_SIZE;
+ controlData.WindowSize = BitConverter.ToUInt32(buffer, 0x0010) * LZX_FRAME_SIZE;
break;
default:
return Error.MSPACK_ERR_DATAFORMAT;
diff --git a/BurnOutSharp/External/libmspack/Compression/BufferState.cs b/BurnOutSharp/External/libmspack/Compression/BufferState.cs
new file mode 100644
index 00000000..4d52c162
--- /dev/null
+++ b/BurnOutSharp/External/libmspack/Compression/BufferState.cs
@@ -0,0 +1,78 @@
+/* This file is part of libmspack.
+ * (C) 2003-2013 Stuart Caie.
+ *
+ * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted
+ * by Microsoft Corporation.
+ *
+ * libmspack is free software { get; set; } you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
+ *
+ * For further details, see the file COPYING.LIB distributed with libmspack
+ */
+
+namespace LibMSPackSharp.Compression
+{
+ public class BufferState
+ {
+ ///
+ /// i_ptr
+ ///
+ public int InputPointer { get; set; }
+
+ ///
+ /// i_end
+ ///
+ public int InputEnd { get; set; }
+
+ ///
+ /// bit_buffer
+ ///
+ public uint BitBuffer { get; set; }
+
+ ///
+ /// bits_left
+ ///
+ public int BitsLeft { get; set; }
+
+ #region Common
+
+ ///
+ /// Initialises bitstream state in state structure
+ ///
+ public void Init()
+ {
+ InputPointer = 0;
+ InputEnd = 0;
+ BitBuffer = 0;
+ BitsLeft = 0;
+ }
+
+ #endregion
+
+ #region MSB
+
+ ///
+ /// Removes N bits from the bit buffer
+ ///
+ public void REMOVE_BITS_MSB(int nbits)
+ {
+ BitBuffer <<= nbits;
+ BitsLeft -= nbits;
+ }
+
+ #endregion
+
+ #region LSB
+
+ ///
+ /// Removes N bits from the bit buffer
+ ///
+ public void REMOVE_BITS_LSB(int nbits)
+ {
+ BitBuffer >>= nbits;
+ BitsLeft -= nbits;
+ }
+
+ #endregion
+ }
+}
diff --git a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
index 1d01bc06..1ddeac7d 100644
--- a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
@@ -17,42 +17,17 @@ namespace LibMSPackSharp.Compression
{
public abstract class CompressionStream : BaseDecompressState
{
- #region Constants
-
- ///
- /// Number of bits in a character
- ///
- private const int CHAR_BIT = 8;
-
- ///
- /// Bit width of a UInt32 bit buffer
- ///
- public const int BITBUF_WIDTH = 4 * CHAR_BIT;
-
- ///
- /// Maximum bits in a Huffman code
- ///
- public const int HUFF_MAXBITS = 16;
-
- #endregion
-
#region I/O buffering
public byte[] InputBuffer { get; set; }
public uint InputBufferSize { get; set; }
- public int InputPointer { get; set; }
-
- public int InputEnd { get; set; }
-
public int OutputPointer { get; set; }
public int OutputEnd { get; set; }
- public uint BitBuffer { get; set; }
-
- public int BitsLeft { get; set; }
+ internal BufferState BufferState { get; set; }
///
/// Have we reached the end of input?
@@ -137,43 +112,44 @@ namespace LibMSPackSharp.Compression
///
public void INIT_BITS()
{
- InputPointer = 0;
- InputEnd = 0;
- BitBuffer = 0;
- BitsLeft = 0;
+ BufferState = new BufferState();
+ BufferState.Init();
EndOfInput = 0;
}
///
/// Stores bitstream state in state structure
///
- public void STORE_BITS(int i_ptr, int i_end, uint bit_buffer, int bits_left)
+ public void STORE_BITS(BufferState state)
{
- InputPointer = i_ptr;
- InputEnd = i_end;
- BitBuffer = bit_buffer;
- BitsLeft = bits_left;
+ BufferState.InputPointer = state.InputPointer;
+ BufferState.InputEnd = state.InputEnd;
+ BufferState.BitBuffer = state.BitBuffer;
+ BufferState.BitsLeft = state.BitsLeft;
}
///
/// Restores bitstream state from state structure
///
- public void RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left)
+ public BufferState RESTORE_BITS()
{
- i_ptr = InputPointer;
- i_end = InputEnd;
- bit_buffer = BitBuffer;
- bits_left = BitsLeft;
+ return new BufferState()
+ {
+ InputPointer = BufferState.InputPointer,
+ InputEnd = BufferState.InputEnd,
+ BitBuffer = BufferState.BitBuffer,
+ BitsLeft = BufferState.BitsLeft,
+ };
}
///
/// Ensure there are at least N bits in the bit buffer
///
- public void ENSURE_BITS(int nbits, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public void ENSURE_BITS(int nbits, BufferState state)
{
- while (bits_left < nbits)
+ while (state.BitsLeft < nbits)
{
- READ_BYTES(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ READ_BYTES(state);
if (Error != Error.MSPACK_ERR_OK)
return;
}
@@ -182,23 +158,23 @@ namespace LibMSPackSharp.Compression
///
/// Read from the input if the buffer is empty
///
- public void READ_IF_NEEDED(ref int i_ptr, ref int i_end)
+ public void READ_IF_NEEDED(BufferState state)
{
- if (i_ptr >= i_end)
+ if (state.InputPointer >= state.InputEnd)
{
ReadInput();
if (Error != Error.MSPACK_ERR_OK)
return;
- i_ptr = InputPointer;
- i_end = InputEnd;
+ state.InputPointer = BufferState.InputPointer;
+ state.InputEnd = BufferState.InputEnd;
}
}
///
/// Read bytes from the input into the bit buffer
///
- public abstract void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left);
+ public abstract void READ_BYTES(BufferState state);
///
/// Read an input stream and fill the buffer
@@ -231,8 +207,8 @@ namespace LibMSPackSharp.Compression
}
// Update i_ptr and i_end
- InputPointer = 0;
- InputEnd = read;
+ BufferState.InputPointer = 0;
+ BufferState.InputEnd = read;
}
#endregion
@@ -242,10 +218,10 @@ namespace LibMSPackSharp.Compression
///
/// Inject data into the bit buffer
///
- public void INJECT_BITS_MSB(int bitdata, int nbits, ref uint bit_buffer, ref int bits_left)
+ public void INJECT_BITS_MSB(int bitdata, int nbits, BufferState state)
{
- bit_buffer |= (uint)(bitdata << (BITBUF_WIDTH - nbits - bits_left));
- bits_left += nbits;
+ state.BitBuffer |= (uint)(bitdata << (BITBUF_WIDTH - nbits - state.BitsLeft));
+ state.BitsLeft += nbits;
}
///
@@ -256,52 +232,43 @@ namespace LibMSPackSharp.Compression
///
/// Takes N bits from the buffer and puts them in var
///
- public long READ_BITS_MSB(int nbits, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_BITS_MSB(int nbits, BufferState state)
{
- ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ ENSURE_BITS(nbits, state);
if (Error != Error.MSPACK_ERR_OK)
return -1;
- long temp = PEEK_BITS_MSB(nbits, bit_buffer);
+ long temp = PEEK_BITS_MSB(nbits, state.BitBuffer);
- REMOVE_BITS_MSB(nbits, ref bit_buffer, ref bits_left);
+ state.REMOVE_BITS_MSB(nbits);
return temp;
}
///
/// Read multiple bits and put them in var
///
- public long READ_MANY_BITS_MSB(int nbits, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_MANY_BITS_MSB(int nbits, BufferState state)
{
byte needed = (byte)(nbits), bitrun;
long temp = 0;
while (needed > 0)
{
- if (bits_left <= (BITBUF_WIDTH - 16))
+ if (state.BitsLeft <= (BITBUF_WIDTH - 16))
{
- READ_BYTES(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ READ_BYTES(state);
if (Error != Error.MSPACK_ERR_OK)
return -1;
}
- bitrun = (byte)((bits_left < needed) ? bits_left : needed);
- temp = (temp << bitrun) | PEEK_BITS_MSB(bitrun, bit_buffer);
- REMOVE_BITS_MSB(bitrun, ref bit_buffer, ref bits_left);
+ bitrun = (byte)((state.BitsLeft < needed) ? state.BitsLeft : needed);
+ temp = (temp << bitrun) | PEEK_BITS_MSB(bitrun, state.BitBuffer);
+ state.REMOVE_BITS_MSB(bitrun);
needed -= bitrun;
}
return temp;
}
- ///
- /// Removes N bits from the bit buffer
- ///
- public void REMOVE_BITS_MSB(int nbits, ref uint bit_buffer, ref int bits_left)
- {
- bit_buffer <<= nbits;
- bits_left -= nbits;
- }
-
#endregion
#region LSB
@@ -309,10 +276,10 @@ namespace LibMSPackSharp.Compression
///
/// Inject data into the bit buffer
///
- public void INJECT_BITS_LSB(int bitdata, int nbits, ref uint bit_buffer, ref int bits_left)
+ public void INJECT_BITS_LSB(int bitdata, int nbits, BufferState state)
{
- bit_buffer |= (uint)(bitdata << bits_left);
- bits_left += nbits;
+ state.BitBuffer |= (uint)(bitdata << state.BitsLeft);
+ state.BitsLeft += nbits;
}
///
@@ -323,47 +290,38 @@ namespace LibMSPackSharp.Compression
///
/// Extracts without removing N bits from the bit buffer using a bit mask
///
- public long PEEK_BITS_T_LSB(int nbits, uint bit_buffer) => bit_buffer & lsb_bit_mask[(nbits)];
+ public long PEEK_BITS_T_LSB(int nbits, uint bit_buffer) => bit_buffer & LSBBitMask[(nbits)];
///
/// Takes N bits from the buffer and puts them in var
///
- public long READ_BITS_LSB(int nbits, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_BITS_LSB(int nbits, BufferState state)
{
- ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ ENSURE_BITS(nbits, state);
if (Error != Error.MSPACK_ERR_OK)
return -1;
- long temp = PEEK_BITS_LSB(nbits, bit_buffer);
+ long temp = PEEK_BITS_LSB(nbits, state.BitBuffer);
- REMOVE_BITS_LSB(nbits, ref bit_buffer, ref bits_left);
+ state.REMOVE_BITS_LSB(nbits);
return temp;
}
///
/// Takes N bits from the buffer and puts them in var using a bit mask
///
- public long READ_BITS_T_LSB(int nbits, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_BITS_T_LSB(int nbits, BufferState state)
{
- ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ ENSURE_BITS(nbits, state);
if (Error != Error.MSPACK_ERR_OK)
return -1;
- long temp = PEEK_BITS_T_LSB(nbits, bit_buffer);
+ long temp = PEEK_BITS_T_LSB(nbits, state.BitBuffer);
- REMOVE_BITS_LSB(nbits, ref bit_buffer, ref bits_left);
+ state.REMOVE_BITS_LSB(nbits);
return temp;
}
- ///
- /// Removes N bits from the bit buffer
- ///
- public void REMOVE_BITS_LSB(int nbits, ref uint bit_buffer, ref int bits_left)
- {
- bit_buffer >>= nbits;
- bits_left -= nbits;
- }
-
#endregion
#endregion
@@ -385,14 +343,14 @@ namespace LibMSPackSharp.Compression
/// Decodes the next huffman symbol from the input bitstream into var.
/// Do not use this macro on a table unless build_decode_table() succeeded.
///
- public long READ_HUFFSYM_MSB(ushort[] table, byte[] lengths, int tablebits, int maxsymbols, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_HUFFSYM_MSB(ushort[] table, byte[] lengths, int tablebits, int maxsymbols, BufferState state)
{
- ENSURE_BITS(HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- ushort sym = table[PEEK_BITS_MSB(tablebits, bit_buffer)];
+ ENSURE_BITS(HUFF_MAXBITS, state);
+ ushort sym = table[PEEK_BITS_MSB(tablebits, state.BitBuffer)];
if (sym >= maxsymbols)
- HUFF_TRAVERSE_MSB(ref sym, table, tablebits, maxsymbols, bit_buffer);
+ HUFF_TRAVERSE_MSB(ref sym, table, tablebits, maxsymbols, state.BitBuffer);
- REMOVE_BITS_MSB(lengths[sym], ref bit_buffer, ref bits_left);
+ state.REMOVE_BITS_MSB(lengths[sym]);
return sym;
}
@@ -523,14 +481,14 @@ namespace LibMSPackSharp.Compression
/// Decodes the next huffman symbol from the input bitstream into var.
/// Do not use this macro on a table unless build_decode_table() succeeded.
///
- public long READ_HUFFSYM_LSB(ushort[] table, byte[] lengths, int tablebits, int maxsymbols, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_HUFFSYM_LSB(ushort[] table, byte[] lengths, int tablebits, int maxsymbols, BufferState state)
{
- ENSURE_BITS(HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- ushort sym = table[PEEK_BITS_LSB(tablebits, bit_buffer)];
+ ENSURE_BITS(HUFF_MAXBITS, state);
+ ushort sym = table[PEEK_BITS_LSB(tablebits, state.BitBuffer)];
if (sym >= maxsymbols)
- HUFF_TRAVERSE_LSB(ref sym, table, tablebits, maxsymbols, bit_buffer);
+ HUFF_TRAVERSE_LSB(ref sym, table, tablebits, maxsymbols, state.BitBuffer);
- REMOVE_BITS_LSB(lengths[sym], ref bit_buffer, ref bits_left);
+ state.REMOVE_BITS_LSB(lengths[sym]);
return sym;
}
diff --git a/BurnOutSharp/External/libmspack/Compression/Constants.cs b/BurnOutSharp/External/libmspack/Compression/Constants.cs
index f205d21f..2ebc4788 100644
--- a/BurnOutSharp/External/libmspack/Compression/Constants.cs
+++ b/BurnOutSharp/External/libmspack/Compression/Constants.cs
@@ -11,11 +11,282 @@ namespace LibMSPackSharp.Compression
{
internal static class Constants
{
- /* lsb_bit_mask[n] = (1 << n) - 1 */
- internal static readonly ushort[] lsb_bit_mask = new ushort[17]
+ #region readbits.h
+
+ ///
+ /// Bit width of a UInt32 bit buffer
+ ///
+ public const int BITBUF_WIDTH = 4 * CHAR_BIT;
+
+ ///
+ /// Number of bits in a character
+ ///
+ internal const int CHAR_BIT = 8;
+
+ // lsb_bit_mask[n] = (1 << n) - 1
+ internal static readonly ushort[] LSBBitMask = new ushort[17]
{
0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
+
+ #endregion
+
+ #region readhuff.h
+
+ ///
+ /// Maximum bits in a Huffman code
+ ///
+ public const int HUFF_MAXBITS = 16;
+
+ #endregion
+
+ #region LZSS
+
+ ///
+ /// Size of an LZSS window
+ ///
+ public const int LZSS_WINDOW_SIZE = 4096;
+
+ ///
+ /// LZSS window fill byte
+ ///
+ public const byte LZSS_WINDOW_FILL = 0x20;
+
+ #endregion
+
+ #region LZX
+
+ // Some constants defined by the LZX specification
+ public const int LZX_MIN_MATCH = 2;
+ public const int LZX_MAX_MATCH = 257;
+ public const int LZX_NUM_CHARS = 256;
+
+ public const int LZX_PRETREE_NUM_ELEMENTS = 20;
+ public const int LZX_ALIGNED_NUM_ELEMENTS = 8; // Aligned offset tree #elements
+ public const int LZX_NUM_PRIMARY_LENGTHS = 7; // This one missing from spec!
+ public const int LZX_NUM_SECONDARY_LENGTHS = 249; // Length tree #elements
+
+ // LZX huffman defines: tweak tablebits as desired
+
+ public const int LZX_PRETREE_MAXSYMBOLS = LZX_PRETREE_NUM_ELEMENTS;
+ public const byte LZX_PRETREE_TABLEBITS = 6;
+ public const int LZX_MAINTREE_MAXSYMBOLS = LZX_NUM_CHARS + 290 * 8;
+ public const byte LZX_MAINTREE_TABLEBITS = 12;
+ public const int LZX_LENGTH_MAXSYMBOLS = LZX_NUM_SECONDARY_LENGTHS + 1;
+ public const byte LZX_LENGTH_TABLEBITS = 12;
+ public const int LZX_ALIGNED_MAXSYMBOLS = LZX_ALIGNED_NUM_ELEMENTS;
+ public const byte LZX_ALIGNED_TABLEBITS = 7;
+ public const int LZX_LENTABLE_SAFETY = 64; // Table decoding overruns are allowed
+
+ public const int LZX_FRAME_SIZE = 32768; // The size of a frame in LZX
+
+ #region LZX static data tables
+
+ /* LZX static data tables:
+ *
+ * LZX uses 'position slots' to represent match offsets. For every match,
+ * a small 'position slot' number and a small offset from that slot are
+ * encoded instead of one large offset.
+ *
+ * The number of slots is decided by how many are needed to encode the
+ * largest offset for a given window size. This is easy when the gap between
+ * slots is less than 128Kb, it's a linear relationship. But when extra_bits
+ * reaches its limit of 17 (because LZX can only ensure reading 17 bits of
+ * data at a time), we can only jump 128Kb at a time and have to start
+ * using more and more position slots as each window size doubles.
+ *
+ * position_base[] is an index to the position slot bases
+ *
+ * extra_bits[] states how many bits of offset-from-base data is needed.
+ *
+ * They are calculated as follows:
+ * extra_bits[i] = 0 where i < 4
+ * extra_bits[i] = floor(i/2)-1 where i >= 4 && i < 36
+ * extra_bits[i] = 17 where i >= 36
+ * position_base[0] = 0
+ * position_base[i] = position_base[i-1] + (1 << extra_bits[i-1])
+ */
+
+ public static readonly uint[] LZXPositionSlots = new uint[11]
+ {
+ 30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290
+ };
+
+ public static readonly byte[] LZXExtraBits = new byte[36]
+ {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16
+ };
+
+ public static readonly uint[] LZXPositionBase = new uint[290]
+ {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512,
+ 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768,
+ 49152, 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
+ 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
+ 1835008, 1966080, 2097152, 2228224, 2359296, 2490368, 2621440, 2752512,
+ 2883584, 3014656, 3145728, 3276800, 3407872, 3538944, 3670016, 3801088,
+ 3932160, 4063232, 4194304, 4325376, 4456448, 4587520, 4718592, 4849664,
+ 4980736, 5111808, 5242880, 5373952, 5505024, 5636096, 5767168, 5898240,
+ 6029312, 6160384, 6291456, 6422528, 6553600, 6684672, 6815744, 6946816,
+ 7077888, 7208960, 7340032, 7471104, 7602176, 7733248, 7864320, 7995392,
+ 8126464, 8257536, 8388608, 8519680, 8650752, 8781824, 8912896, 9043968,
+ 9175040, 9306112, 9437184, 9568256, 9699328, 9830400, 9961472, 10092544,
+ 10223616, 10354688, 10485760, 10616832, 10747904, 10878976, 11010048,
+ 11141120, 11272192, 11403264, 11534336, 11665408, 11796480, 11927552,
+ 12058624, 12189696, 12320768, 12451840, 12582912, 12713984, 12845056,
+ 12976128, 13107200, 13238272, 13369344, 13500416, 13631488, 13762560,
+ 13893632, 14024704, 14155776, 14286848, 14417920, 14548992, 14680064,
+ 14811136, 14942208, 15073280, 15204352, 15335424, 15466496, 15597568,
+ 15728640, 15859712, 15990784, 16121856, 16252928, 16384000, 16515072,
+ 16646144, 16777216, 16908288, 17039360, 17170432, 17301504, 17432576,
+ 17563648, 17694720, 17825792, 17956864, 18087936, 18219008, 18350080,
+ 18481152, 18612224, 18743296, 18874368, 19005440, 19136512, 19267584,
+ 19398656, 19529728, 19660800, 19791872, 19922944, 20054016, 20185088,
+ 20316160, 20447232, 20578304, 20709376, 20840448, 20971520, 21102592,
+ 21233664, 21364736, 21495808, 21626880, 21757952, 21889024, 22020096,
+ 22151168, 22282240, 22413312, 22544384, 22675456, 22806528, 22937600,
+ 23068672, 23199744, 23330816, 23461888, 23592960, 23724032, 23855104,
+ 23986176, 24117248, 24248320, 24379392, 24510464, 24641536, 24772608,
+ 24903680, 25034752, 25165824, 25296896, 25427968, 25559040, 25690112,
+ 25821184, 25952256, 26083328, 26214400, 26345472, 26476544, 26607616,
+ 26738688, 26869760, 27000832, 27131904, 27262976, 27394048, 27525120,
+ 27656192, 27787264, 27918336, 28049408, 28180480, 28311552, 28442624,
+ 28573696, 28704768, 28835840, 28966912, 29097984, 29229056, 29360128,
+ 29491200, 29622272, 29753344, 29884416, 30015488, 30146560, 30277632,
+ 30408704, 30539776, 30670848, 30801920, 30932992, 31064064, 31195136,
+ 31326208, 31457280, 31588352, 31719424, 31850496, 31981568, 32112640,
+ 32243712, 32374784, 32505856, 32636928, 32768000, 32899072, 33030144,
+ 33161216, 33292288, 33423360
+ };
+
+ #endregion
+
+ #endregion
+
+ #region MSZIP
+
+ public const int MSZIP_FRAME_SIZE = 32768; // Size of LZ history window
+ public const int MSZIP_LITERAL_MAXSYMBOLS = 288; // literal/length huffman tree
+ public const int MSZIP_LITERAL_TABLEBITS = 9;
+ public const int MSZIP_DISTANCE_MAXSYMBOLS = 32; // Distance huffman tree
+ public const int MSZIP_DISTANCE_TABLEBITS = 6;
+
+ // If there are less direct lookup entries than symbols, the longer
+ // code pointers will be <= maxsymbols. This must not happen, or we
+ // will decode entries badly
+
+ //public const int MSZIP_LITERAL_TABLESIZE = (MSZIP_LITERAL_MAXSYMBOLS * 4);
+ public const int MSZIP_LITERAL_TABLESIZE = ((1 << MSZIP_LITERAL_TABLEBITS) + (MSZIP_LITERAL_MAXSYMBOLS * 2));
+
+ //public const int MSZIP_DISTANCE_TABLESIZE = (MSZIP_DISTANCE_MAXSYMBOLS * 4);
+ public const int MSZIP_DISTANCE_TABLESIZE = ((1 << MSZIP_DISTANCE_TABLEBITS) + (MSZIP_DISTANCE_MAXSYMBOLS * 2));
+
+ ///
+ /// Match lengths for literal codes 257.. 285
+ ///
+ public static readonly ushort[] LiteralLengths = new ushort[29]
+ {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
+ 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
+ };
+
+ ///
+ /// Match offsets for distance codes 0 .. 29
+ ///
+ public static readonly ushort[] DistanceOffsets = new ushort[30]
+ {
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
+ 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
+ };
+
+ ///
+ /// Extra bits required for literal codes 257.. 285
+ ///
+ public static readonly byte[] LiteralExtraBits = new byte[29]
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
+ 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
+ };
+
+ ///
+ /// Extra bits required for distance codes 0 .. 29
+ ///
+ public static readonly byte[] DistanceExtraBits = new byte[30]
+ {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
+ };
+
+ ///
+ /// The order of the bit length Huffman code lengths
+ ///
+ public static readonly byte[] BitLengthOrder = new byte[19]
+ {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ #endregion
+
+ #region QTM
+
+ public const int QTM_FRAME_SIZE = 32768;
+
+ /* Quantum static data tables:
+ *
+ * Quantum uses 'position slots' to represent match offsets. For every
+ * match, a small 'position slot' number and a small offset from that slot
+ * are encoded instead of one large offset.
+ *
+ * position_base[] is an index to the position slot bases
+ *
+ * extra_bits[] states how many bits of offset-from-base data is needed.
+ *
+ * length_base[] and length_extra[] are equivalent in function, but are
+ * used for encoding selector 6 (variable length match) match lengths,
+ * instead of match offsets.
+ *
+ * They are generated with the following code:
+ * uint i, offset;
+ * for (i = 0, offset = 0; i < 42; i++) {
+ * position_base[i] = offset;
+ * extra_bits[i] = ((i < 2) ? 0 : (i - 2)) >> 1;
+ * offset += 1 << extra_bits[i];
+ * }
+ * for (i = 0, offset = 0; i < 26; i++) {
+ * length_base[i] = offset;
+ * length_extra[i] = (i < 2 ? 0 : i - 2) >> 2;
+ * offset += 1 << length_extra[i];
+ * }
+ * length_base[26] = 254; length_extra[26] = 0;
+ */
+
+ public static readonly uint[] QTMPositionBase = new uint[42]
+ {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
+ 65536, 98304, 131072, 196608, 262144, 393216, 524288, 786432, 1048576, 1572864
+ };
+
+ public static readonly byte[] QTMExtraBits = new byte[42]
+ {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
+ 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19
+ };
+
+ public static readonly byte[] QTMLengthBase = new byte[27]
+ {
+ 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 18, 22, 26,
+ 30, 38, 46, 54, 62, 78, 94, 110, 126, 158, 190, 222, 254
+ };
+
+ public static readonly byte[] QTMLengthExtra = new byte[27]
+ {
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
+ };
+
+ #endregion
}
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs b/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs
index b72977ea..13a0004c 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs
@@ -9,6 +9,7 @@
using System.IO;
using static LibMSPackSharp.Constants;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
@@ -47,39 +48,39 @@ namespace LibMSPackSharp.Compression
// Reset global state
lzh.INIT_BITS();
- lzh.RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left);
+ BufferState state = lzh.RESTORE_BITS();
- for (i = 0; i < LZSS.LZSS_WINDOW_SIZE; i++)
+ for (i = 0; i < LZSS_WINDOW_SIZE; i++)
{
- lzh.Window[i] = LZSS.LZSS_WINDOW_FILL;
+ lzh.Window[i] = LZSS_WINDOW_FILL;
}
// Read 6 encoding types (for byte alignment) but only 5 are needed
for (i = 0; i < 6; i++)
{
- types[i] = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ types[i] = (uint)lzh.READ_BITS_SAFE(4, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
}
// Read huffman table symbol lengths and build huffman trees
- BUILD_TREE(lzh, types[0], lzh.MATCHLEN1_table, lzh.MATCHLEN1_len, KWAJ_TABLEBITS, KWAJ_MATCHLEN1_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- BUILD_TREE(lzh, types[1], lzh.MATCHLEN2_table, lzh.MATCHLEN2_len, KWAJ_TABLEBITS, KWAJ_MATCHLEN2_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- BUILD_TREE(lzh, types[2], lzh.LITLEN_table, lzh.LITLEN_len, KWAJ_TABLEBITS, KWAJ_LITLEN_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- BUILD_TREE(lzh, types[3], lzh.OFFSET_table, lzh.OFFSET_len, KWAJ_TABLEBITS, KWAJ_OFFSET_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- BUILD_TREE(lzh, types[4], lzh.LITERAL_table, lzh.LITERAL_len, KWAJ_TABLEBITS, KWAJ_LITERAL_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ BUILD_TREE(lzh, types[0], lzh.MATCHLEN1_table, lzh.MATCHLEN1_len, KWAJ_TABLEBITS, KWAJ_MATCHLEN1_SYMS, state);
+ BUILD_TREE(lzh, types[1], lzh.MATCHLEN2_table, lzh.MATCHLEN2_len, KWAJ_TABLEBITS, KWAJ_MATCHLEN2_SYMS, state);
+ BUILD_TREE(lzh, types[2], lzh.LITLEN_table, lzh.LITLEN_len, KWAJ_TABLEBITS, KWAJ_LITLEN_SYMS, state);
+ BUILD_TREE(lzh, types[3], lzh.OFFSET_table, lzh.OFFSET_len, KWAJ_TABLEBITS, KWAJ_OFFSET_SYMS, state);
+ BUILD_TREE(lzh, types[4], lzh.LITERAL_table, lzh.LITERAL_len, KWAJ_TABLEBITS, KWAJ_LITERAL_SYMS, state);
while (lzh.EndOfInput == 0)
{
if (lit_run != 0)
{
- len = (int)lzh.READ_HUFFSYM_SAFE(lzh.MATCHLEN2_table, lzh.MATCHLEN2_len, KWAJ_MATCHLEN2_TBLSIZE, KWAJ_MATCHLEN2_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ len = (int)lzh.READ_HUFFSYM_SAFE(lzh.MATCHLEN2_table, lzh.MATCHLEN2_len, KWAJ_MATCHLEN2_TBLSIZE, KWAJ_MATCHLEN2_SYMS, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
}
else
{
- len = (int)lzh.READ_HUFFSYM_SAFE(lzh.MATCHLEN1_table, lzh.MATCHLEN1_len, KWAJ_MATCHLEN1_TBLSIZE, KWAJ_MATCHLEN1_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ len = (int)lzh.READ_HUFFSYM_SAFE(lzh.MATCHLEN1_table, lzh.MATCHLEN1_len, KWAJ_MATCHLEN1_TBLSIZE, KWAJ_MATCHLEN1_SYMS, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
}
@@ -89,13 +90,13 @@ namespace LibMSPackSharp.Compression
len += 2;
lit_run = 0; // Not the end of a literal run
- j = (int)lzh.READ_HUFFSYM_SAFE(lzh.OFFSET_table, lzh.OFFSET_len, KWAJ_OFFSET_TBLSIZE, KWAJ_OFFSET_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ j = (int)lzh.READ_HUFFSYM_SAFE(lzh.OFFSET_table, lzh.OFFSET_len, KWAJ_OFFSET_TBLSIZE, KWAJ_OFFSET_SYMS, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
offset = j << 6;
- j = (int)lzh.READ_BITS_SAFE(6, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ j = (int)lzh.READ_BITS_SAFE(6, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
@@ -115,7 +116,7 @@ namespace LibMSPackSharp.Compression
}
else
{
- len = (int)lzh.READ_HUFFSYM_SAFE(lzh.LITLEN_table, lzh.LITLEN_len, KWAJ_LITLEN_TBLSIZE, KWAJ_LITLEN_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ len = (int)lzh.READ_HUFFSYM_SAFE(lzh.LITLEN_table, lzh.LITLEN_len, KWAJ_LITLEN_TBLSIZE, KWAJ_LITLEN_SYMS, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
@@ -123,7 +124,7 @@ namespace LibMSPackSharp.Compression
lit_run = (len == 32) ? 0 : 1; // End of a literal run?
while (len-- > 0)
{
- j = (int)lzh.READ_HUFFSYM_SAFE(lzh.LITERAL_table, lzh.LITERAL_len, KWAJ_LITERAL_TBLSIZE, KWAJ_LITERAL_SYMS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ j = (int)lzh.READ_HUFFSYM_SAFE(lzh.LITERAL_table, lzh.LITERAL_len, KWAJ_LITERAL_TBLSIZE, KWAJ_LITERAL_SYMS, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
@@ -142,15 +143,19 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
- private static Error BUILD_TREE(LZHKWAJStream lzh, uint type, ushort[] table, byte[] lengths, int tablebits, int maxsymbols, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ private static Error BUILD_TREE(LZHKWAJStream lzh, uint type, ushort[] table, byte[] lengths, int tablebits, int maxsymbols, BufferState state)
{
- lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ lzh.STORE_BITS(state);
Error err = ReadLens(lzh, type, (uint)maxsymbols, lzh.MATCHLEN1_len);
if (err != Error.MSPACK_ERR_OK)
return err;
- lzh.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
+ BufferState temp = lzh.RESTORE_BITS();
+ state.InputPointer = temp.InputPointer;
+ state.InputEnd = temp.InputEnd;
+ state.BitBuffer = temp.BitBuffer;
+ state.BitsLeft = temp.BitsLeft;
if (!CompressionStream.MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
return Error.MSPACK_ERR_DATAFORMAT;
@@ -162,7 +167,7 @@ namespace LibMSPackSharp.Compression
{
uint i, c, sel;
- lzh.RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left);
+ BufferState state = lzh.RESTORE_BITS();
switch (type)
{
@@ -177,14 +182,14 @@ namespace LibMSPackSharp.Compression
break;
case 1:
- c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ c = (uint)lzh.READ_BITS_SAFE(4, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
lens[0] = (byte)c;
for (i = 1; i < numsyms; i++)
{
- sel = (uint)lzh.READ_BITS_SAFE(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ sel = (uint)lzh.READ_BITS_SAFE(1, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
@@ -194,7 +199,7 @@ namespace LibMSPackSharp.Compression
}
else
{
- sel = (uint)lzh.READ_BITS_SAFE(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ sel = (uint)lzh.READ_BITS_SAFE(1, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
@@ -204,7 +209,7 @@ namespace LibMSPackSharp.Compression
}
else
{
- c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ c = (uint)lzh.READ_BITS_SAFE(4, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
@@ -216,20 +221,20 @@ namespace LibMSPackSharp.Compression
break;
case 2:
- c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ c = (uint)lzh.READ_BITS_SAFE(4, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
lens[0] = (byte)c;
for (i = 1; i < numsyms; i++)
{
- sel = (uint)lzh.READ_BITS_SAFE(2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ sel = (uint)lzh.READ_BITS_SAFE(2, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
if (sel == 3)
{
- c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ c = (uint)lzh.READ_BITS_SAFE(4, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
}
@@ -246,7 +251,7 @@ namespace LibMSPackSharp.Compression
case 3:
for (i = 0; i < numsyms; i++)
{
- c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ c = (uint)lzh.READ_BITS_SAFE(4, state);
if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
return Error.MSPACK_ERR_OK;
@@ -256,7 +261,7 @@ namespace LibMSPackSharp.Compression
break;
}
- lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ lzh.STORE_BITS(state);
return Error.MSPACK_ERR_OK;
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs b/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs
index 4f84eb4e..094c33e1 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs
@@ -8,6 +8,7 @@
*/
using static LibMSPackSharp.Constants;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
@@ -33,7 +34,7 @@ namespace LibMSPackSharp.Compression
// History window
- public byte[] Window { get; set; } = new byte[LZSS.LZSS_WINDOW_SIZE];
+ public byte[] Window { get; set; } = new byte[LZSS_WINDOW_SIZE];
#endregion
@@ -53,10 +54,10 @@ namespace LibMSPackSharp.Compression
///
/// Safely read bits from the buffer
///
- public long READ_BITS_SAFE(int nbits, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_BITS_SAFE(int nbits, BufferState state)
{
- long val = READ_BITS_MSB(nbits, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (EndOfInput != 0 && BitsLeft < EndOfInput)
+ long val = READ_BITS_MSB(nbits, state);
+ if (EndOfInput != 0 && BufferState.BitsLeft < EndOfInput)
Error = Error.MSPACK_ERR_NOMEMORY;
else
Error = Error.MSPACK_ERR_OK;
@@ -67,10 +68,10 @@ namespace LibMSPackSharp.Compression
///
/// Safely read a symbol from a Huffman tree
///
- public long READ_HUFFSYM_SAFE(ushort[] table, byte[] lengths, int tablebits, int maxsymbols, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public long READ_HUFFSYM_SAFE(ushort[] table, byte[] lengths, int tablebits, int maxsymbols, BufferState state)
{
- long val = READ_HUFFSYM_MSB(table, lengths, tablebits, maxsymbols, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (EndOfInput != 0 && BitsLeft < EndOfInput)
+ long val = READ_HUFFSYM_MSB(table, lengths, tablebits, maxsymbols, state);
+ if (EndOfInput != 0 && BufferState.BitsLeft < EndOfInput)
Error = Error.MSPACK_ERR_NOMEMORY;
else
Error = Error.MSPACK_ERR_OK;
@@ -93,19 +94,19 @@ namespace LibMSPackSharp.Compression
public override Error HUFF_ERROR() => Error.MSPACK_ERR_DATAFORMAT;
///
- public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public override void READ_BYTES(BufferState state)
{
- if (i_ptr >= i_end)
+ if (state.InputPointer >= state.InputEnd)
{
ReadInput();
if (Error != Error.MSPACK_ERR_OK)
return;
- i_ptr = InputPointer;
- i_end = InputEnd;
+ state.InputPointer = BufferState.InputPointer;
+ state.InputEnd = BufferState.InputEnd;
}
- INJECT_BITS_MSB(InputBuffer[i_ptr++], 8, ref bit_buffer, ref bits_left);
+ INJECT_BITS_MSB(InputBuffer[state.InputPointer++], 8, state);
}
///
@@ -129,15 +130,15 @@ namespace LibMSPackSharp.Compression
if (read == 0)
{
- InputEnd = 8;
+ BufferState.InputEnd = 8;
InputBuffer[0] = 0;
read = 1;
}
}
// Update InputPointer and InputLength
- InputPointer = 0;
- InputEnd = read;
+ BufferState.InputPointer = 0;
+ BufferState.InputEnd = read;
}
}
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZSS.cs b/BurnOutSharp/External/libmspack/Compression/LZSS.cs
index 082d6075..f9859432 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZSS.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZSS.cs
@@ -12,18 +12,12 @@
*/
using System.IO;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
public class LZSS
{
- #region LZSS compression / decompression definitions
-
- public const int LZSS_WINDOW_SIZE = 4096;
- public const byte LZSS_WINDOW_FILL = 0x20;
-
- #endregion
-
///
/// Decompresses an LZSS stream.
///
diff --git a/BurnOutSharp/External/libmspack/Compression/LZX.cs b/BurnOutSharp/External/libmspack/Compression/LZX.cs
index 667a6c09..680311a0 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZX.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZX.cs
@@ -76,142 +76,12 @@
using System;
using System.IO;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
public class LZX
{
- #region LZX compression / decompression definitions
-
- // Some constants defined by the LZX specification
- public const int LZX_MIN_MATCH = 2;
- public const int LZX_MAX_MATCH = 257;
- public const int LZX_NUM_CHARS = 256;
-
- public const int LZX_PRETREE_NUM_ELEMENTS = 20;
- public const int LZX_ALIGNED_NUM_ELEMENTS = 8; // Aligned offset tree #elements
- public const int LZX_NUM_PRIMARY_LENGTHS = 7; // This one missing from spec!
- public const int LZX_NUM_SECONDARY_LENGTHS = 249; // Length tree #elements
-
- // LZX huffman defines: tweak tablebits as desired
-
- public const int LZX_PRETREE_MAXSYMBOLS = LZX_PRETREE_NUM_ELEMENTS;
- public const byte LZX_PRETREE_TABLEBITS = 6;
- public const int LZX_MAINTREE_MAXSYMBOLS = LZX_NUM_CHARS + 290 * 8;
- public const byte LZX_MAINTREE_TABLEBITS = 12;
- public const int LZX_LENGTH_MAXSYMBOLS = LZX_NUM_SECONDARY_LENGTHS + 1;
- public const byte LZX_LENGTH_TABLEBITS = 12;
- public const int LZX_ALIGNED_MAXSYMBOLS = LZX_ALIGNED_NUM_ELEMENTS;
- public const byte LZX_ALIGNED_TABLEBITS = 7;
- public const int LZX_LENTABLE_SAFETY = 64; // Table decoding overruns are allowed
-
- public const int LZX_FRAME_SIZE = 32768; // The size of a frame in LZX
-
- #endregion
-
- #region LZX static data tables
-
- /* LZX static data tables:
- *
- * LZX uses 'position slots' to represent match offsets. For every match,
- * a small 'position slot' number and a small offset from that slot are
- * encoded instead of one large offset.
- *
- * The number of slots is decided by how many are needed to encode the
- * largest offset for a given window size. This is easy when the gap between
- * slots is less than 128Kb, it's a linear relationship. But when extra_bits
- * reaches its limit of 17 (because LZX can only ensure reading 17 bits of
- * data at a time), we can only jump 128Kb at a time and have to start
- * using more and more position slots as each window size doubles.
- *
- * position_base[] is an index to the position slot bases
- *
- * extra_bits[] states how many bits of offset-from-base data is needed.
- *
- * They are calculated as follows:
- * extra_bits[i] = 0 where i < 4
- * extra_bits[i] = floor(i/2)-1 where i >= 4 && i < 36
- * extra_bits[i] = 17 where i >= 36
- * position_base[0] = 0
- * position_base[i] = position_base[i-1] + (1 << extra_bits[i-1])
- */
-
- private static readonly uint[] position_slots = new uint[11]
- {
- 30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290
- };
-
- private static readonly byte[] extra_bits = new byte[36]
- {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
- 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16
- };
-
- private static readonly uint[] position_base = new uint[290]
- {
- 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512,
- 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768,
- 49152, 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
- 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
- 1835008, 1966080, 2097152, 2228224, 2359296, 2490368, 2621440, 2752512,
- 2883584, 3014656, 3145728, 3276800, 3407872, 3538944, 3670016, 3801088,
- 3932160, 4063232, 4194304, 4325376, 4456448, 4587520, 4718592, 4849664,
- 4980736, 5111808, 5242880, 5373952, 5505024, 5636096, 5767168, 5898240,
- 6029312, 6160384, 6291456, 6422528, 6553600, 6684672, 6815744, 6946816,
- 7077888, 7208960, 7340032, 7471104, 7602176, 7733248, 7864320, 7995392,
- 8126464, 8257536, 8388608, 8519680, 8650752, 8781824, 8912896, 9043968,
- 9175040, 9306112, 9437184, 9568256, 9699328, 9830400, 9961472, 10092544,
- 10223616, 10354688, 10485760, 10616832, 10747904, 10878976, 11010048,
- 11141120, 11272192, 11403264, 11534336, 11665408, 11796480, 11927552,
- 12058624, 12189696, 12320768, 12451840, 12582912, 12713984, 12845056,
- 12976128, 13107200, 13238272, 13369344, 13500416, 13631488, 13762560,
- 13893632, 14024704, 14155776, 14286848, 14417920, 14548992, 14680064,
- 14811136, 14942208, 15073280, 15204352, 15335424, 15466496, 15597568,
- 15728640, 15859712, 15990784, 16121856, 16252928, 16384000, 16515072,
- 16646144, 16777216, 16908288, 17039360, 17170432, 17301504, 17432576,
- 17563648, 17694720, 17825792, 17956864, 18087936, 18219008, 18350080,
- 18481152, 18612224, 18743296, 18874368, 19005440, 19136512, 19267584,
- 19398656, 19529728, 19660800, 19791872, 19922944, 20054016, 20185088,
- 20316160, 20447232, 20578304, 20709376, 20840448, 20971520, 21102592,
- 21233664, 21364736, 21495808, 21626880, 21757952, 21889024, 22020096,
- 22151168, 22282240, 22413312, 22544384, 22675456, 22806528, 22937600,
- 23068672, 23199744, 23330816, 23461888, 23592960, 23724032, 23855104,
- 23986176, 24117248, 24248320, 24379392, 24510464, 24641536, 24772608,
- 24903680, 25034752, 25165824, 25296896, 25427968, 25559040, 25690112,
- 25821184, 25952256, 26083328, 26214400, 26345472, 26476544, 26607616,
- 26738688, 26869760, 27000832, 27131904, 27262976, 27394048, 27525120,
- 27656192, 27787264, 27918336, 28049408, 28180480, 28311552, 28442624,
- 28573696, 28704768, 28835840, 28966912, 29097984, 29229056, 29360128,
- 29491200, 29622272, 29753344, 29884416, 30015488, 30146560, 30277632,
- 30408704, 30539776, 30670848, 30801920, 30932992, 31064064, 31195136,
- 31326208, 31457280, 31588352, 31719424, 31850496, 31981568, 32112640,
- 32243712, 32374784, 32505856, 32636928, 32768000, 32899072, 33030144,
- 33161216, 33292288, 33423360
- };
-
- private static void ResetState(LZXDStream lzx)
- {
- lzx.R0 = 1;
- lzx.R1 = 1;
- lzx.R2 = 1;
- lzx.HeaderRead = 0;
- lzx.BlockRemaining = 0;
- lzx.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++)
- {
- lzx.MAINTREE_len[i] = 0;
- }
-
- for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
- {
- lzx.LENGTH_len[i] = 0;
- }
- }
-
- #endregion
-
///
/// Allocates and initialises LZX decompression state for decoding an LZX
/// stream.
@@ -268,9 +138,6 @@ namespace LibMSPackSharp.Compression
///
public static LZXDStream Init(SystemImpl system, FileStream input, FileStream output, int window_bits, int reset_interval, int input_buffer_size, long output_length, bool is_delta)
{
- uint window_size = (uint)(1 << window_bits);
- LZXDStream lzx;
-
if (system == null)
return null;
@@ -299,10 +166,10 @@ namespace LibMSPackSharp.Compression
return null;
// Allocate decompression state
- lzx = new LZXDStream()
+ LZXDStream lzx = new LZXDStream()
{
// Allocate decompression window and input buffer
- Window = new byte[window_size],
+ Window = new byte[1 << window_bits],
InputBuffer = new byte[input_buffer_size],
System = system,
@@ -321,15 +188,15 @@ namespace LibMSPackSharp.Compression
IntelFileSize = 0,
IntelStarted = false,
Error = Error.MSPACK_ERR_OK,
- NumOffsets = position_slots[window_bits - 15] << 3,
+ NumOffsets = LZXPositionSlots[window_bits - 15] << 3,
IsDelta = is_delta,
- // e8_buf
OutputPointer = 0,
OutputEnd = 0,
+ OutputIsE8 = true,
};
- ResetState(lzx);
+ lzx.ResetState();
lzx.INIT_BITS();
return lzx;
@@ -351,7 +218,7 @@ namespace LibMSPackSharp.Compression
/// the length of the reference data. Cannot be longer
/// than the LZX window size.
///
- /// an error code, or MSPACK_ERR_OK if successful
+ /// An error code, or MSPACK_ERR_OK if successful
public static Error SetReferenceData(LZXDStream lzx, SystemImpl system, FileStream input, uint length)
{
if (lzx == null)
@@ -397,7 +264,7 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
- // See description of outputLength in lzxd_init()
+ // See description of outputLength in Init()
public static void SetOutputLength(LZXDStream lzx, long outputLength)
{
if (lzx != null && outputLength > 0)
@@ -435,12 +302,8 @@ namespace LibMSPackSharp.Compression
if (lzx == null)
return Error.MSPACK_ERR_ARGS;
- int match_length, length_footer, extra, verbatim_bits, bytes_todo;
- int this_run, main_element, aligned_bits, j, warned = 0;
- byte[] window, buf = new byte[12];
- int runsrc, rundest;
- uint frame_size, end_frame, match_offset, window_posn;
- uint R0, R1, R2;
+ int warned = 0;
+ byte[] buf = new byte[12];
// Easy answers
if (lzx == null || (out_bytes < 0))
@@ -450,32 +313,30 @@ namespace LibMSPackSharp.Compression
return lzx.Error;
// Flush out any stored-up bytes before we begin
- int i = lzx.OutputEnd - lzx.OutputPointer;
- if (i > out_bytes)
- i = (int)out_bytes;
+ int leftover_bytes = lzx.OutputEnd - lzx.OutputPointer;
+ if (leftover_bytes > out_bytes)
+ leftover_bytes = (int)out_bytes;
- if (i != 0)
+ if (leftover_bytes != 0)
{
- try { lzx.System.Write(lzx.OutputFileHandle, lzx.e8_buf, lzx.OutputPointer, i); }
+ try { lzx.System.Write(lzx.OutputFileHandle, lzx.OutputIsE8 ? lzx.E8Buffer : lzx.Window, lzx.OutputPointer, leftover_bytes); }
catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
- lzx.OutputPointer += i;
- lzx.Offset += i;
- out_bytes -= i;
+ lzx.OutputPointer += leftover_bytes;
+ lzx.Offset += leftover_bytes;
+ out_bytes -= leftover_bytes;
}
if (out_bytes == 0)
return Error.MSPACK_ERR_OK;
// Restore local state
- lzx.RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left);
- window = lzx.Window;
- window_posn = lzx.WindowPosition;
- R0 = lzx.R0;
- R1 = lzx.R1;
- R2 = lzx.R2;
+ BufferState state = lzx.RESTORE_BITS();
+ byte[] window = lzx.Window;
+ int window_posn = lzx.WindowPosition;
+ uint[] R = lzx.R;
- end_frame = (uint)((lzx.Offset + out_bytes) / LZX_FRAME_SIZE) + 1;
+ uint end_frame = (uint)((lzx.Offset + out_bytes) / LZX_FRAME_SIZE) + 1;
while (lzx.Frame < end_frame)
{
@@ -494,410 +355,93 @@ namespace LibMSPackSharp.Compression
}
// Re-read the intel header and reset the huffman lengths
- ResetState(lzx);
- R0 = lzx.R0;
- R1 = lzx.R1;
- R2 = lzx.R2;
+ lzx.ResetState();
+ R = lzx.R;
}
// LZX DELTA format has chunk_size, not present in LZX format
if (lzx.IsDelta)
{
- lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- lzx.REMOVE_BITS_MSB(16, ref bit_buffer, ref bits_left);
+ lzx.ENSURE_BITS(16, state);
+ state.REMOVE_BITS_MSB(16);
}
+ //// Read header if necessary
+ //if (lzx.HeaderRead == 0)
+ //{
+ // // Read 1 bit. If bit=0, intel_filesize = 0.
+ // // If bit=1, read intel filesize (32 bits)
+ // int j = 0;
+ // int i = (int)lzx.READ_BITS_MSB(1, state);
+
+ // if (i != 0)
+ // {
+ // i = (int)lzx.READ_BITS_MSB(16, state);
+ // j = (int)lzx.READ_BITS_MSB(16, state);
+ // }
+
+ // lzx.IntelFileSize = (i << 16) | j;
+ // lzx.HeaderRead = 1;
+ //}
+
// Calculate size of frame: all frames are 32k except the final frame
// which is 32kb or less. this can only be calculated when lzx.Length
// has been filled in.
- frame_size = LZX_FRAME_SIZE;
+ uint frame_size = LZX_FRAME_SIZE;
if (lzx.Length != 0 && (lzx.Length - lzx.Offset) < frame_size)
frame_size = (uint)(lzx.Length - lzx.Offset);
// Decode until one more frame is available
- bytes_todo = (int)(lzx.FramePosition + frame_size - window_posn);
+ int bytes_todo = (int)(lzx.FramePosition + frame_size - window_posn);
while (bytes_todo > 0)
{
- // Initialise new block, if one is needed
- if (lzx.BlockRemaining == 0)
+ // Realign if previous block was an odd-sized UNCOMPRESSED block
+ if ((lzx.BlockType == LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED) && (lzx.BlockLength & 1) != 0)
{
- // Realign if previous block was an odd-sized UNCOMPRESSED block
- if ((lzx.BlockType == LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED) && (lzx.BlockLength & 1) != 0)
- {
- lzx.READ_IF_NEEDED(ref i_ptr, ref i_end);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
+ lzx.READ_IF_NEEDED(state);
+ if (lzx.Error != Error.MSPACK_ERR_OK)
+ return lzx.Error;
- i_ptr++;
- }
-
- // Read block type (3 bits) and block length (24 bits)
-
- // THIS IS NOT 3 BECAUSE OF OTHER CODE I FOUND
- lzx.BlockType = (LZXBlockType)lzx.READ_BITS_MSB(3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
-
- // Read header if necessary
- if (lzx.HeaderRead == 0)
- {
- // Read 1 bit. if bit=0, intel_filesize = 0.
- // if bit=1, read intel filesize (32 bits)
- j = 0;
- i = (int)lzx.READ_BITS_MSB(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
-
- if (i != 0)
- {
- i = (int)lzx.READ_BITS_MSB(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- j = (int)lzx.READ_BITS_MSB(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- }
-
- lzx.IntelFileSize = (i << 16) | j;
- lzx.HeaderRead = 1;
- }
-
- i = (int)lzx.READ_BITS_MSB(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- j = (int)lzx.READ_BITS_MSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
-
- lzx.BlockRemaining = lzx.BlockLength = (uint)((i << 8) | j);
- // Console.WriteLine($"New block t {lzx.BlockType} len {lzx.BlockLength}");
-
- // Read individual block headers
- switch (lzx.BlockType)
- {
- case LZXBlockType.LZX_BLOCKTYPE_ALIGNED:
- // Read lengths of and build aligned huffman decoding tree
- for (i = 0; i < 8; i++)
- {
- j = (int)lzx.READ_BITS_MSB(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- lzx.ALIGNED_len[i] = (byte)j;
- }
-
- BUILD_TABLE(lzx, lzx.ALIGNED_table, lzx.ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- // Read lengths of and build main huffman decoding tree
- READ_LENGTHS(lzx, lzx.MAINTREE_len, 0, 256, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- READ_LENGTHS(lzx, lzx.MAINTREE_len, 256, LZX_NUM_CHARS + lzx.NumOffsets, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- BUILD_TABLE(lzx, lzx.MAINTREE_table, lzx.MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- // If the literal 0xE8 is anywhere in the block...
- if (lzx.MAINTREE_len[0xE8] != 0)
- lzx.IntelStarted = true;
-
- // Read lengths of and build lengths huffman decoding tree
- READ_LENGTHS(lzx, lzx.LENGTH_len, 0, LZX_NUM_SECONDARY_LENGTHS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- BUILD_TABLE_MAYBE_EMPTY(lzx);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- break;
-
- case LZXBlockType.LZX_BLOCKTYPE_VERBATIM:
- // Read lengths of and build main huffman decoding tree
- READ_LENGTHS(lzx, lzx.MAINTREE_len, 0, 256, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- READ_LENGTHS(lzx, lzx.MAINTREE_len, 256, LZX_NUM_CHARS + lzx.NumOffsets, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- BUILD_TABLE(lzx, lzx.MAINTREE_table, lzx.MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- // If the literal 0xE8 is anywhere in the block...
- if (lzx.MAINTREE_len[0xE8] != 0)
- lzx.IntelStarted = true;
-
- // Read lengths of and build lengths huffman decoding tree
- READ_LENGTHS(lzx, lzx.LENGTH_len, 0, LZX_NUM_SECONDARY_LENGTHS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- BUILD_TABLE_MAYBE_EMPTY(lzx);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- break;
-
- case LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED:
- // Because we can't assume otherwise
- lzx.IntelStarted = true;
-
- // Read 1-16 (not 0-15) bits to align to bytes
- if (bits_left == 0)
- lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
-
- bits_left = 0; bit_buffer = 0;
-
- // Read 12 bytes of stored R0 / R1 / R2 values
- for (rundest = 0, i = 0; i < 12; i++)
- {
- lzx.READ_IF_NEEDED(ref i_ptr, ref i_end);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- buf[rundest++] = lzx.InputBuffer[i_ptr++];
- }
-
- R0 = (uint)(buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
- R1 = (uint)(buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24));
- R2 = (uint)(buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24));
-
- break;
-
- default:
- Console.WriteLine("Bad block type");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
+ state.InputPointer++;
}
+ lzx.ReadBlockHeader(buf, ref R, state);
+ if (lzx.Error != Error.MSPACK_ERR_OK)
+ return lzx.Error;
+
// Decode more of the block:
- // run = min(what's available, what's needed)
- this_run = (int)lzx.BlockRemaining;
- if (this_run > bytes_todo)
- this_run = bytes_todo;
+ int this_run = Math.Min(lzx.BlockRemaining, bytes_todo);
// Assume we decode exactly this_run bytes, for now
bytes_todo -= this_run;
- lzx.BlockRemaining -= (uint)this_run;
+ lzx.BlockRemaining -= this_run;
// Decode at least this_run bytes
switch (lzx.BlockType)
{
case LZXBlockType.LZX_BLOCKTYPE_ALIGNED:
case LZXBlockType.LZX_BLOCKTYPE_VERBATIM:
- while (this_run > 0)
- {
- main_element = (int)lzx.READ_HUFFSYM_MSB(lzx.MAINTREE_table, lzx.MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (main_element < LZX_NUM_CHARS)
- {
- // Literal: 0 to LZX_NUM_CHARS-1
- window[window_posn++] = (byte)main_element;
- this_run--;
- }
- else
- {
- // Match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits))
- main_element -= LZX_NUM_CHARS;
+ lzx.DecompressBlock(window, ref window_posn, ref this_run, ref R, state);
+ if (lzx.Error != Error.MSPACK_ERR_OK)
+ return lzx.Error;
- // Get match length
- match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
- if (match_length == LZX_NUM_PRIMARY_LENGTHS)
- {
- if (lzx.LENGTH_empty != 0)
- {
- Console.WriteLine("LENGTH symbol needed but tree is empty");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
-
- length_footer = (int)lzx.READ_HUFFSYM_MSB(lzx.LENGTH_table, lzx.LENGTH_len, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_length += length_footer;
- }
-
- match_length += LZX_MIN_MATCH;
-
- // Get match offset
- switch ((match_offset = (uint)(main_element >> 3)))
- {
- case 0:
- match_offset = R0;
- break;
-
- case 1:
- match_offset = R1;
- R1 = R0;
- R0 = match_offset;
- break;
-
- case 2:
- match_offset = R2;
- R2 = R0;
- R0 = match_offset;
- break;
-
- default:
- if (lzx.BlockType == LZXBlockType.LZX_BLOCKTYPE_VERBATIM)
- {
- if (match_offset == 3)
- {
- match_offset = 1;
- }
- else
- {
- extra = (match_offset >= 36) ? 17 : extra_bits[match_offset];
- verbatim_bits = (int)lzx.READ_BITS_MSB(extra, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset = (uint)(position_base[match_offset] - 2 + verbatim_bits);
- }
- }
-
- // LZX_BLOCKTYPE_ALIGNED
- else
- {
- extra = (match_offset >= 36) ? 17 : extra_bits[match_offset];
- match_offset = position_base[match_offset] - 2;
-
- // >3: verbatim and aligned bits
- if (extra > 3)
- {
- extra -= 3;
- verbatim_bits = (int)lzx.READ_BITS_MSB(extra, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset += (uint)(verbatim_bits << 3);
-
- aligned_bits = (int)lzx.READ_HUFFSYM_MSB(lzx.ALIGNED_table, lzx.ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset += (uint)aligned_bits;
- }
-
- // 3: aligned bits only
- else if (extra == 3)
- {
- aligned_bits = (int)lzx.READ_HUFFSYM_MSB(lzx.ALIGNED_table, lzx.ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset += (uint)aligned_bits;
- }
-
- // 1-2: verbatim bits only
- else if (extra > 0)
- {
- verbatim_bits = (int)lzx.READ_BITS_MSB(extra, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset += (uint)verbatim_bits;
- }
-
- // 0: not defined in LZX specification!
- else
- {
- match_offset = 1;
- }
- }
-
- // Update repeated offset LRU queue
- R2 = R1; R1 = R0; R0 = match_offset;
- break;
- }
-
- // LZX DELTA uses max match length to signal even longer match
- if (match_length == LZX_MAX_MATCH && lzx.IsDelta)
- {
- int extra_len;
-
- // 4 entry huffman tree
- lzx.ENSURE_BITS(3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
-
- // '0' . 8 extra length bits
- if (lzx.PEEK_BITS_MSB(1, bit_buffer) == 0)
- {
- lzx.REMOVE_BITS_MSB(1, ref bit_buffer, ref bits_left);
- extra_len = (int)lzx.READ_BITS_MSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- }
-
- // '10' . 10 extra length bits + 0x100
- else if (lzx.PEEK_BITS_MSB(2, bit_buffer) == 2)
- {
- lzx.REMOVE_BITS_MSB(2, ref bit_buffer, ref bits_left);
- extra_len = (int)lzx.READ_BITS_MSB(10, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- extra_len += 0x100;
- }
-
- // '110' . 12 extra length bits + 0x500
- else if (lzx.PEEK_BITS_MSB(3, bit_buffer) == 6)
- {
- lzx.REMOVE_BITS_MSB(3, ref bit_buffer, ref bits_left);
- extra_len = (int)lzx.READ_BITS_MSB(12, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- extra_len += 0x500;
- }
-
- // '111' . 15 extra length bits
- else
- {
- lzx.REMOVE_BITS_MSB(3, ref bit_buffer, ref bits_left);
- extra_len = (int)lzx.READ_BITS_MSB(15, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- }
-
- match_length += extra_len;
- }
-
- if ((window_posn + match_length) > lzx.WindowSize)
- {
- Console.WriteLine("Match ran over window wrap");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
-
- // Copy match
- rundest = (int)window_posn;
- i = match_length;
-
- // Does match offset wrap the window?
- if (match_offset > window_posn)
- {
- if (match_offset > lzx.Offset && (match_offset - window_posn) > lzx.ReferenceDataSize)
- {
- Console.WriteLine("Match offset beyond LZX stream");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
-
- // j = length from match offset to end of window
- j = (int)(match_offset - window_posn);
- if (j > (int)lzx.WindowSize)
- {
- Console.WriteLine("Match offset beyond window boundaries");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
-
- runsrc = (int)(lzx.WindowSize - j);
- if (j < i)
- {
- // If match goes over the window edge, do two copy runs
- i -= j;
- while (j-- > 0)
- {
- window[rundest++] = window[runsrc++];
- }
-
- runsrc = 0;
- }
-
- while (i-- > 0)
- {
- window[rundest++] = window[runsrc++];
- }
- }
- else
- {
- runsrc = (int)(rundest - match_offset);
- while (i-- > 0)
- {
- window[rundest++] = window[runsrc++];
- }
- }
-
- this_run -= match_length;
- window_posn += (uint)match_length;
- }
- }
+ // If the literal 0xE8 is anywhere in the block...
+ if (lzx.MAINTREE_len[0xE8] != 0)
+ lzx.IntelStarted = true;
break;
case LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED:
// As this_run is limited not to wrap a frame, this also means it
// won't wrap the window (as the window is a multiple of 32k)
- rundest = (int)window_posn;
- window_posn += (uint)this_run;
+ int rundest = window_posn;
+ window_posn += this_run;
while (this_run > 0)
{
- if ((i = i_end - i_ptr) == 0)
+ int i = state.InputEnd - state.InputPointer;
+ if (i == 0)
{
- lzx.READ_IF_NEEDED(ref i_ptr, ref i_end);
+ lzx.READ_IF_NEEDED(state);
if (lzx.Error != Error.MSPACK_ERR_OK)
return lzx.Error;
}
@@ -906,13 +450,17 @@ namespace LibMSPackSharp.Compression
if (i > this_run)
i = this_run;
- Array.Copy(lzx.InputBuffer, i_ptr, window, rundest, i);
+ Array.Copy(lzx.InputBuffer, state.InputPointer, window, rundest, i);
rundest += i;
- i_ptr += i;
+ state.InputPointer += i;
this_run -= i;
}
}
+
+ // Because we can't assume otherwise
+ lzx.IntelStarted = true;
+
break;
default:
@@ -928,7 +476,7 @@ namespace LibMSPackSharp.Compression
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
}
- lzx.BlockRemaining -= (uint)-this_run;
+ lzx.BlockRemaining -= -this_run;
}
}
@@ -940,10 +488,10 @@ namespace LibMSPackSharp.Compression
}
// Re-align input bitstream
- if (bits_left > 0)
- lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if ((bits_left & 15) != 0)
- lzx.REMOVE_BITS_MSB(bits_left & 15, ref bit_buffer, ref bits_left);
+ if (state.BitsLeft > 0)
+ lzx.ENSURE_BITS(16, state);
+ if ((state.BitsLeft & 15) != 0)
+ state.REMOVE_BITS_MSB(state.BitsLeft & 15);
// Check that we've used all of the previous frame first
if (lzx.OutputPointer != lzx.OutputEnd)
@@ -955,59 +503,24 @@ namespace LibMSPackSharp.Compression
// Does this intel block _really_ need decoding?
if (lzx.IntelStarted && lzx.IntelFileSize != 0 && (lzx.Frame < 32768) && (frame_size > 10))
{
- int data = 0;
- int dataend = (int)(frame_size - 10);
- int curpos = (int)lzx.Offset;
- int filesize = lzx.IntelFileSize;
- int abs_off, rel_off;
-
- // Copy e8 block to the e8 buffer and tweak if needed
- lzx.OutputPointer = data;
- Array.Copy(lzx.Window, lzx.FramePosition, lzx.e8_buf, data, frame_size);
-
- while (data < dataend)
- {
- if (lzx.e8_buf[data++] != 0xE8)
- {
- curpos++;
- continue;
- }
-
- abs_off = lzx.e8_buf[data + 0] | (lzx.e8_buf[data + 1] << 8) | (lzx.e8_buf[data + 2] << 16) | (lzx.e8_buf[data + 3] << 24);
- if ((abs_off >= -curpos) && (abs_off < filesize))
- {
- rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
- lzx.e8_buf[data + 0] = (byte)rel_off;
- lzx.e8_buf[data + 1] = (byte)(rel_off >> 8);
- lzx.e8_buf[data + 2] = (byte)(rel_off >> 16);
- lzx.e8_buf[data + 3] = (byte)(rel_off >> 24);
- }
-
- data += 4;
- curpos += 5;
- }
-
- lzx.OutputEnd = (int)(lzx.OutputPointer + frame_size);
-
- // Write a frame
- i = (int)((out_bytes < frame_size) ? out_bytes : frame_size);
- try { lzx.System.Write(lzx.OutputFileHandle, lzx.e8_buf, lzx.OutputPointer, i); }
- catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
+ lzx.UndoE8Preprocessing(frame_size);
}
else
{
+ lzx.OutputIsE8 = false;
lzx.OutputPointer = (int)lzx.FramePosition;
- lzx.OutputEnd = (int)(lzx.OutputPointer + frame_size);
-
- // Write a frame
- i = (int)((out_bytes < frame_size) ? out_bytes : frame_size);
- try { lzx.System.Write(lzx.OutputFileHandle, lzx.Window, lzx.OutputPointer, i); }
- catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
}
- lzx.OutputPointer += i;
- lzx.Offset += i;
- out_bytes -= i;
+ lzx.OutputEnd = (int)(lzx.OutputPointer + frame_size);
+
+ // Write a frame
+ int new_out_bytes = (int)((out_bytes < frame_size) ? out_bytes : frame_size);
+ try { lzx.System.Write(lzx.OutputFileHandle, lzx.OutputIsE8 ? lzx.E8Buffer : lzx.Window, lzx.OutputPointer, new_out_bytes); }
+ catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
+
+ lzx.OutputPointer += new_out_bytes;
+ lzx.Offset += new_out_bytes;
+ out_bytes -= new_out_bytes;
// Advance frame start position
lzx.FramePosition += frame_size;
@@ -1028,131 +541,9 @@ namespace LibMSPackSharp.Compression
}
// Store local state
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ lzx.STORE_BITS(state);
lzx.WindowPosition = window_posn;
- lzx.R0 = R0;
- lzx.R1 = R1;
- lzx.R2 = R2;
-
- return Error.MSPACK_ERR_OK;
- }
-
- private static Error BUILD_TABLE(LZXDStream lzx, ushort[] table, byte[] lengths, int tablebits, int maxsymbols)
- {
- if (!CompressionStream.MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
- {
- Console.WriteLine($"Failed to build table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
-
- return lzx.Error = Error.MSPACK_ERR_OK;
- }
-
- private static Error BUILD_TABLE_MAYBE_EMPTY(LZXDStream lzx)
- {
- lzx.LENGTH_empty = 0;
- if (!CompressionStream.MakeDecodeTableMSB(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table))
- {
- for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
- {
- if (lzx.LENGTH_len[i] > 0)
- {
- Console.WriteLine("Failed to build table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
-
- // Empty tree - allow it, but don't decode symbols with it
- lzx.LENGTH_empty = 1;
- }
-
- return lzx.Error = Error.MSPACK_ERR_OK;
- }
-
- private static Error READ_LENGTHS(LZXDStream lzx, byte[] lengths, uint first, uint last, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
- {
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- if (ReadLens(lzx, lengths, first, last) != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
- return lzx.Error = Error.MSPACK_ERR_OK;
- }
-
- private static Error ReadLens(LZXDStream lzx, byte[] lens, uint first, uint last)
- {
- uint x, y;
- int z;
-
- lzx.RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left);
-
- // Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits)
- for (x = 0; x < 20; x++)
- {
- y = (uint)lzx.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- lzx.PRETREE_len[x] = (byte)y;
- }
-
- BUILD_TABLE(lzx, lzx.PRETREE_table, lzx.PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
- if (lzx.Error != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- for (x = first; x < last;)
- {
- z = (int)lzx.READ_HUFFSYM_MSB(lzx.PRETREE_table, lzx.PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
-
- // Code = 17, run of ([read 4 bits]+4) zeros
- if (z == 17)
- {
- y = (uint)lzx.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- y += 4;
- while (y-- != 0)
- {
- lens[x++] = 0;
- }
- }
-
- // Code = 18, run of ([read 5 bits]+20) zeros
- else if (z == 18)
- {
- y = (uint)lzx.READ_BITS_MSB(5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- y += 20;
- while (y-- != 0)
- {
- lens[x++] = 0;
- }
- }
-
- // Code = 19, run of ([read 1 bit]+4) [read huffman symbol]
- else if (z == 19)
- {
- y = (uint)lzx.READ_BITS_MSB(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- y += 4;
- z = (int)lzx.READ_HUFFSYM_MSB(lzx.PRETREE_table, lzx.PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
-
- z = lens[x] - z;
- if (z < 0)
- z += 17;
-
- while (y-- != 0)
- {
- lens[x++] = (byte)z;
- }
- }
-
- // Code = 0 to 16, delta current length entry
- else
- {
- z = lens[x] - z;
- if (z < 0)
- z += 17;
-
- lens[x++] = (byte)z;
- }
- }
-
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ lzx.R = R;
return Error.MSPACK_ERR_OK;
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs b/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
index 3cb656cf..95676cfa 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
@@ -10,6 +10,9 @@
* For further details, see the file COPYING.LIB distributed with libmspack
*/
+using System;
+using static LibMSPackSharp.Compression.Constants;
+
namespace LibMSPackSharp.Compression
{
public class LZXDStream : CompressionStream
@@ -49,7 +52,7 @@ namespace LibMSPackSharp.Compression
///
/// Decompression offset within window
///
- public uint WindowPosition { get; set; }
+ public int WindowPosition { get; set; }
///
/// Current frame offset within in window
@@ -69,27 +72,17 @@ namespace LibMSPackSharp.Compression
///
/// For the LRU offset system
///
- public uint R0 { get; set; }
-
- ///
- /// For the LRU offset system
- ///
- public uint R1 { get; set; }
-
- ///
- /// For the LRU offset system
- ///
- public uint R2 { get; set; }
+ public uint[] R { get; set; } = new uint[3];
///
/// Uncompressed length of this LZX block
///
- public uint BlockLength { get; set; }
+ public int BlockLength { get; set; }
///
/// Uncompressed bytes still left to decode
///
- public uint BlockRemaining { get; set; }
+ public int BlockRemaining { get; set; }
///
/// Magic header value used for transform
@@ -118,26 +111,564 @@ namespace LibMSPackSharp.Compression
#region Huffman code lengths
- public byte[] PRETREE_len { get; set; } = new byte[LZX.LZX_PRETREE_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
- public byte[] MAINTREE_len { get; set; } = new byte[LZX.LZX_MAINTREE_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
- public byte[] LENGTH_len { get; set; } = new byte[LZX.LZX_LENGTH_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
- public byte[] ALIGNED_len { get; set; } = new byte[LZX.LZX_ALIGNED_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
+ public byte[] PRETREE_len { get; set; } = new byte[LZX_PRETREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
+ public byte[] MAINTREE_len { get; set; } = new byte[LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
+ public byte[] LENGTH_len { get; set; } = new byte[LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
+ public byte[] ALIGNED_len { get; set; } = new byte[LZX_ALIGNED_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
#endregion
#region Huffman decoding tables
- public ushort[] PRETREE_table { get; set; } = new ushort[(1 << LZX.LZX_PRETREE_TABLEBITS) + (LZX.LZX_PRETREE_MAXSYMBOLS * 2)];
- public ushort[] MAINTREE_table { get; set; } = new ushort[(1 << LZX.LZX_MAINTREE_TABLEBITS) + (LZX.LZX_MAINTREE_MAXSYMBOLS * 2)];
- public ushort[] LENGTH_table { get; set; } = new ushort[(1 << LZX.LZX_LENGTH_TABLEBITS) + (LZX.LZX_LENGTH_MAXSYMBOLS * 2)];
- public ushort[] ALIGNED_table { get; set; } = new ushort[(1 << LZX.LZX_ALIGNED_TABLEBITS) + (LZX.LZX_ALIGNED_MAXSYMBOLS * 2)];
+ public ushort[] PRETREE_table { get; set; } = new ushort[(1 << LZX_PRETREE_TABLEBITS) + (LZX_PRETREE_MAXSYMBOLS * 2)];
+ public ushort[] MAINTREE_table { get; set; } = new ushort[(1 << LZX_MAINTREE_TABLEBITS) + (LZX_MAINTREE_MAXSYMBOLS * 2)];
+ public ushort[] LENGTH_table { get; set; } = new ushort[(1 << LZX_LENGTH_TABLEBITS) + (LZX_LENGTH_MAXSYMBOLS * 2)];
+ public ushort[] ALIGNED_table { get; set; } = new ushort[(1 << LZX_ALIGNED_TABLEBITS) + (LZX_ALIGNED_MAXSYMBOLS * 2)];
#endregion
public byte LENGTH_empty { get; set; }
// This is used purely for doing the intel E8 transform
- public byte[] e8_buf { get; set; } = new byte[LZX.LZX_FRAME_SIZE];
+ public byte[] E8Buffer { get; set; } = new byte[LZX_FRAME_SIZE];
+
+ ///
+ /// Is the output pointer referring to E8?
+ ///
+ public bool OutputIsE8 { get; set; }
+
+ #endregion
+
+ #region Specialty Methods
+
+ public Error DecompressBlock(byte[] window, ref int window_posn, ref int this_run, ref uint[] R, BufferState state)
+ {
+ while (this_run > 0)
+ {
+ int main_element = (int)READ_HUFFSYM_MSB(MAINTREE_table, MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS, state);
+ if (main_element < LZX_NUM_CHARS)
+ {
+ // Literal: 0 to LZX_NUM_CHARS-1
+ window[window_posn++] = (byte)main_element;
+ this_run--;
+ }
+ else
+ {
+ // Match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits))
+ main_element -= LZX_NUM_CHARS;
+
+ // Get match length
+ int match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
+ if (match_length == LZX_NUM_PRIMARY_LENGTHS)
+ {
+ if (LENGTH_empty != 0)
+ {
+ Console.WriteLine("LENGTH symbol needed but tree is empty");
+ return Error = Error.MSPACK_ERR_DECRUNCH;
+ }
+
+ int length_footer = (int)READ_HUFFSYM_MSB(LENGTH_table, LENGTH_len, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS, state);
+ match_length += length_footer;
+ }
+
+ match_length += LZX_MIN_MATCH;
+
+ // Get match offset
+ uint match_offset = (uint)(main_element >> 3);
+ switch (match_offset)
+ {
+ case 0:
+ match_offset = R[0];
+ break;
+
+ case 1:
+ match_offset = R[1];
+ R[1] = R[0];
+ R[0] = match_offset;
+ break;
+
+ case 2:
+ match_offset = R[2];
+ R[2] = R[0];
+ R[0] = match_offset;
+ break;
+
+ default:
+ if (BlockType == LZXBlockType.LZX_BLOCKTYPE_VERBATIM)
+ {
+ if (match_offset == 3)
+ {
+ match_offset = 1;
+ }
+ else
+ {
+ int extra = (match_offset >= 36) ? 17 : LZXExtraBits[match_offset];
+ int verbatim_bits = (int)READ_BITS_MSB(extra, state);
+ match_offset = (uint)(LZXPositionBase[match_offset] - 2 + verbatim_bits);
+ }
+ }
+
+ // LZX_BLOCKTYPE_ALIGNED
+ else
+ {
+ int extra = (match_offset >= 36) ? 17 : LZXExtraBits[match_offset];
+ match_offset = LZXPositionBase[match_offset] - 2;
+
+ // >3: verbatim and aligned bits
+ if (extra > 3)
+ {
+ extra -= 3;
+ int verbatim_bits = (int)READ_BITS_MSB(extra, state);
+ match_offset += (uint)(verbatim_bits << 3);
+
+ int aligned_bits = (int)READ_HUFFSYM_MSB(ALIGNED_table, ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, state);
+ match_offset += (uint)aligned_bits;
+ }
+
+ // 3: aligned bits only
+ else if (extra == 3)
+ {
+ int aligned_bits = (int)READ_HUFFSYM_MSB(ALIGNED_table, ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, state);
+ match_offset += (uint)aligned_bits;
+ }
+
+ // 1-2: verbatim bits only
+ else if (extra > 0)
+ {
+ int verbatim_bits = (int)READ_BITS_MSB(extra, state);
+ match_offset += (uint)verbatim_bits;
+ }
+
+ // 0: not defined in LZX specification!
+ else
+ {
+ match_offset = 1;
+ }
+ }
+
+ // Update repeated offset LRU queue
+ R[2] = R[1]; R[1] = R[0]; R[0] = match_offset;
+ break;
+ }
+
+ // LZX DELTA uses max match length to signal even longer match
+ if (match_length == LZX_MAX_MATCH && IsDelta)
+ {
+ int extra_len;
+
+ // 4 entry huffman tree
+ ENSURE_BITS(3, state);
+
+ // '0' . 8 extra length bits
+ if (PEEK_BITS_MSB(1, state.BitBuffer) == 0)
+ {
+ state.REMOVE_BITS_MSB(1);
+ extra_len = (int)READ_BITS_MSB(8, state);
+ }
+
+ // '10' . 10 extra length bits + 0x100
+ else if (PEEK_BITS_MSB(2, state.BitBuffer) == 2)
+ {
+ state.REMOVE_BITS_MSB(2);
+ extra_len = (int)READ_BITS_MSB(10, state);
+ extra_len += 0x100;
+ }
+
+ // '110' . 12 extra length bits + 0x500
+ else if (PEEK_BITS_MSB(3, state.BitBuffer) == 6)
+ {
+ state.REMOVE_BITS_MSB(3);
+ extra_len = (int)READ_BITS_MSB(12, state);
+ extra_len += 0x500;
+ }
+
+ // '111' . 15 extra length bits
+ else
+ {
+ state.REMOVE_BITS_MSB(3);
+ extra_len = (int)READ_BITS_MSB(15, state);
+ }
+
+ match_length += extra_len;
+ }
+
+ if ((window_posn + match_length) > WindowSize)
+ {
+ Console.WriteLine("Match ran over window wrap");
+ return Error = Error.MSPACK_ERR_DECRUNCH;
+ }
+
+ // Copy match
+ int rundest = window_posn;
+ int i = match_length;
+
+ // Does match offset wrap the window?
+ if (match_offset > window_posn)
+ {
+ if (match_offset > Offset && (match_offset - window_posn) > ReferenceDataSize)
+ {
+ Console.WriteLine("Match offset beyond LZX stream");
+ return Error = Error.MSPACK_ERR_DECRUNCH;
+ }
+
+ // j = length from match offset to end of window
+ int j = (int)(match_offset - window_posn);
+ if (j > (int)WindowSize)
+ {
+ Console.WriteLine("Match offset beyond window boundaries");
+ return Error = Error.MSPACK_ERR_DECRUNCH;
+ }
+
+ int runsrc = (int)(WindowSize - j);
+ if (j < i)
+ {
+ // If match goes over the window edge, do two copy runs
+ i -= j;
+ while (j-- > 0)
+ {
+ window[rundest++] = window[runsrc++];
+ }
+
+ runsrc = 0;
+ }
+
+ while (i-- > 0)
+ {
+ window[rundest++] = window[runsrc++];
+ }
+ }
+ else
+ {
+ int runsrc = (int)(rundest - match_offset);
+ while (i-- > 0)
+ {
+ window[rundest++] = window[runsrc++];
+ }
+ }
+
+ this_run -= match_length;
+ window_posn += match_length;
+ }
+ }
+
+ return Error = Error.MSPACK_ERR_OK;
+ }
+
+ public Error ReadBlockHeader(byte[] buffer, ref uint[] R, BufferState state)
+ {
+ ENSURE_BITS(4, state);
+
+ // Read block type (3 bits) and block length (24 bits)
+ byte block_type = (byte)READ_BITS_MSB(3, state);
+ BlockType = (LZXBlockType)block_type;
+
+ // Read the block size
+ int block_size;
+ if (READ_BITS_MSB(1, state) == 1)
+ {
+ block_size = LZX_FRAME_SIZE;
+ }
+ else
+ {
+ int tmp;
+ block_size = 0;
+
+ tmp = (int)READ_BITS_MSB(8, state);
+ block_size |= tmp;
+ tmp = (int)READ_BITS_MSB(8, state);
+ block_size <<= 8;
+ block_size |= tmp;
+
+ if (WindowSize >= 65536)
+ {
+ tmp = (int)READ_BITS_MSB(8, state);
+ block_size <<= 8;
+ block_size |= tmp;
+ }
+ }
+
+ BlockRemaining = BlockLength = block_size;
+ Console.WriteLine($"New block t {BlockType} len {BlockLength}");
+
+ // Read individual block headers
+ switch (BlockType)
+ {
+ case LZXBlockType.LZX_BLOCKTYPE_ALIGNED:
+ // Read lengths of and build aligned huffman decoding tree
+ for (byte i = 0; i < 8; i++)
+ {
+ ALIGNED_len[i] = (byte)READ_BITS_MSB(3, state);
+ }
+
+ BUILD_TABLE(ALIGNED_table, ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ // Read lengths of and build main huffman decoding tree
+ READ_LENGTHS(MAINTREE_len, 0, 256, state);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ READ_LENGTHS(MAINTREE_len, 256, LZX_NUM_CHARS + NumOffsets, state);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ BUILD_TABLE(MAINTREE_table, MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ // Read lengths of and build lengths huffman decoding tree
+ READ_LENGTHS(LENGTH_len, 0, LZX_NUM_SECONDARY_LENGTHS, state);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ BUILD_TABLE_MAYBE_EMPTY();
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ break;
+
+ case LZXBlockType.LZX_BLOCKTYPE_VERBATIM:
+ // Read lengths of and build main huffman decoding tree
+ READ_LENGTHS(MAINTREE_len, 0, 256, state);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ READ_LENGTHS(MAINTREE_len, 256, LZX_NUM_CHARS + NumOffsets, state);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ BUILD_TABLE(MAINTREE_table, MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ // If the literal 0xE8 is anywhere in the block...
+ if (MAINTREE_len[0xE8] != 0)
+ IntelStarted = true;
+
+ // Read lengths of and build lengths huffman decoding tree
+ READ_LENGTHS(LENGTH_len, 0, LZX_NUM_SECONDARY_LENGTHS, state);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ BUILD_TABLE_MAYBE_EMPTY();
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ break;
+
+ case LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED:
+ // Read 1-16 (not 0-15) bits to align to bytes
+ if (state.BitsLeft == 0)
+ ENSURE_BITS(16, state);
+
+ state.BitsLeft = 0; state.BitBuffer = 0;
+
+ // Read 12 bytes of stored R[0] / R[1] / R[2] values
+ for (int rundest = 0, k = 0; k < 12; k++)
+ {
+ READ_IF_NEEDED(state);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ buffer[rundest++] = InputBuffer[state.InputPointer++];
+ }
+
+ // TODO: uint[] R should be a part of a state object
+ R[0] = (uint)(buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24));
+ R[1] = (uint)(buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | (buffer[7] << 24));
+ R[2] = (uint)(buffer[8] | (buffer[9] << 8) | (buffer[10] << 16) | (buffer[11] << 24));
+
+ break;
+
+ default:
+ Console.WriteLine($"Bad block type: {BlockType}");
+ return Error = Error.MSPACK_ERR_DECRUNCH;
+ }
+
+ return Error = Error.MSPACK_ERR_OK;
+ }
+
+ public Error ReadLens(byte[] lens, uint first, uint last)
+ {
+ BufferState state = RESTORE_BITS();
+
+ // Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits)
+ for (int i = 0; i < LZX_PRETREE_MAXSYMBOLS; i++)
+ {
+ uint y = (uint)READ_BITS_MSB(4, state);
+ PRETREE_len[i] = (byte)y;
+ }
+
+ BUILD_TABLE(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
+ if (Error != Error.MSPACK_ERR_OK)
+ return Error;
+
+ for (uint lensPtr = first; lensPtr < last;)
+ {
+ uint num_zeroes, num_same;
+ int tree_code = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, state);
+ switch (tree_code)
+ {
+ // Code = 17, run of ([read 4 bits]+4) zeros
+ case 17:
+ num_zeroes = (uint)READ_BITS_MSB(4, state);
+ num_zeroes += 4;
+ while (num_zeroes-- != 0)
+ {
+ lens[lensPtr++] = 0;
+ }
+
+ break;
+
+ // Code = 18, run of ([read 5 bits]+20) zeros
+ case 18:
+ num_zeroes = (uint)READ_BITS_MSB(5, state);
+ num_zeroes += 20;
+ while (num_zeroes-- != 0)
+ {
+ lens[lensPtr++] = 0;
+ }
+
+ break;
+
+ // Code = 19, run of ([read 1 bit]+4) [read huffman symbol]
+ case 19:
+ num_same = (uint)READ_BITS_MSB(1, state);
+ num_same += 4;
+
+ tree_code = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, state);
+ tree_code = lens[lensPtr] - tree_code;
+ if (tree_code < 0)
+ tree_code += 17;
+
+ while (num_same-- != 0)
+ {
+ lens[lensPtr++] = (byte)tree_code;
+ }
+
+ break;
+
+ // Code = 0 to 16, delta current length entry
+ default:
+ tree_code = lens[lensPtr] - tree_code;
+ if (tree_code < 0)
+ tree_code += 17;
+
+ lens[lensPtr++] = (byte)tree_code;
+ break;
+ }
+ }
+
+ STORE_BITS(state);
+
+ return Error.MSPACK_ERR_OK;
+ }
+
+ public 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;
+ }
+ }
+
+ public void UndoE8Preprocessing(uint frame_size)
+ {
+ int data = 0;
+ int dataend = (int)(frame_size - 10);
+ int curpos = (int)Offset;
+ int filesize = IntelFileSize;
+ int abs_off, rel_off;
+
+ // Copy e8 block to the e8 buffer and tweak if needed
+ OutputIsE8 = true;
+ OutputPointer = data;
+ Array.Copy(Window, FramePosition, E8Buffer, data, frame_size);
+
+ while (data < dataend)
+ {
+ if (E8Buffer[data++] != 0xE8)
+ {
+ curpos++;
+ continue;
+ }
+
+ abs_off = E8Buffer[data + 0] | (E8Buffer[data + 1] << 8) | (E8Buffer[data + 2] << 16) | (E8Buffer[data + 3] << 24);
+ if ((abs_off >= -curpos) && (abs_off < filesize))
+ {
+ rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
+ E8Buffer[data + 0] = (byte)rel_off;
+ E8Buffer[data + 1] = (byte)(rel_off >> 8);
+ E8Buffer[data + 2] = (byte)(rel_off >> 16);
+ E8Buffer[data + 3] = (byte)(rel_off >> 24);
+ }
+
+ data += 4;
+ curpos += 5;
+ }
+ }
+
+ 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, BufferState state)
+ {
+ STORE_BITS(state);
+
+ if (ReadLens(lengths, first, last) != Error.MSPACK_ERR_OK)
+ return Error;
+
+ BufferState temp = RESTORE_BITS();
+ state.InputPointer = temp.InputPointer;
+ state.InputEnd = temp.InputEnd;
+ state.BitBuffer = temp.BitBuffer;
+ state.BitsLeft = temp.BitsLeft;
+
+ return Error = Error.MSPACK_ERR_OK;
+ }
#endregion
@@ -145,20 +676,20 @@ namespace LibMSPackSharp.Compression
public override Error HUFF_ERROR() => Error.MSPACK_ERR_DECRUNCH;
///
- public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public override void READ_BYTES(BufferState state)
{
- READ_IF_NEEDED(ref i_ptr, ref i_end);
+ READ_IF_NEEDED(state);
if (Error != Error.MSPACK_ERR_OK)
return;
- byte b0 = InputBuffer[i_ptr++];
+ byte b0 = InputBuffer[state.InputPointer++];
- READ_IF_NEEDED(ref i_ptr, ref i_end);
+ READ_IF_NEEDED(state);
if (Error != Error.MSPACK_ERR_OK)
return;
- byte b1 = InputBuffer[i_ptr++];
- INJECT_BITS_MSB((b1 << 8) | b0, 16, ref bit_buffer, ref bits_left);
+ byte b1 = InputBuffer[state.InputPointer++];
+ INJECT_BITS_MSB((b1 << 8) | b0, 16, state);
}
}
}
diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
index 6009411d..431b36ae 100644
--- a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
+++ b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
@@ -12,75 +12,12 @@
using System;
using System.IO;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
public class MSZIP
{
- #region MSZIP (deflate) compression / (inflate) decompression definitions
-
- public const int MSZIP_FRAME_SIZE = 32768; // Size of LZ history window
- public const int MSZIP_LITERAL_MAXSYMBOLS = 288; // literal/length huffman tree
- public const int MSZIP_LITERAL_TABLEBITS = 9;
- public const int MSZIP_DISTANCE_MAXSYMBOLS = 32; // Distance huffman tree
- public const int MSZIP_DISTANCE_TABLEBITS = 6;
-
- // If there are less direct lookup entries than symbols, the longer
- // code pointers will be <= maxsymbols. This must not happen, or we
- // will decode entries badly
-
- //public const int MSZIP_LITERAL_TABLESIZE = (MSZIP_LITERAL_MAXSYMBOLS * 4);
- public const int MSZIP_LITERAL_TABLESIZE = ((1 << MSZIP_LITERAL_TABLEBITS) + (MSZIP_LITERAL_MAXSYMBOLS * 2));
-
- //public const int MSZIP_DISTANCE_TABLESIZE = (MSZIP_DISTANCE_MAXSYMBOLS * 4);
- public const int MSZIP_DISTANCE_TABLESIZE = ((1 << MSZIP_DISTANCE_TABLEBITS) + (MSZIP_DISTANCE_MAXSYMBOLS * 2));
-
- ///
- /// Match lengths for literal codes 257.. 285
- ///
- private static readonly ushort[] lit_lengths = new ushort[29]
- {
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
- 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
- };
-
- ///
- /// Match offsets for distance codes 0 .. 29
- ///
- private static readonly ushort[] dist_offsets = new ushort[30]
- {
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
- 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
- };
-
- ///
- /// Extra bits required for literal codes 257.. 285
- ///
- private static readonly byte[] lit_extrabits = new byte[29]
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
- 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
- };
-
- ///
- /// Extra bits required for distance codes 0 .. 29
- ///
- private static readonly byte[] dist_extrabits = new byte[30]
- {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
- 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
- };
-
- ///
- /// The order of the bit length Huffman code lengths
- ///
- private static readonly byte[] bitlen_order = new byte[19]
- {
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
- };
-
- #endregion
-
///
/// Allocates MS-ZIP decompression stream for decoding the given stream.
///
@@ -120,12 +57,16 @@ namespace LibMSPackSharp.Compression
RepairMode = repair_mode,
FlushWindow = FlushWindow,
- InputPointer = 0,
- InputEnd = 0,
OutputPointer = 0,
OutputEnd = 0,
- BitBuffer = 0,
- BitsLeft = 0,
+
+ BufferState = new BufferState()
+ {
+ InputPointer = 0,
+ InputEnd = 0,
+ BitBuffer = 0,
+ BitsLeft = 0,
+ }
};
}
@@ -159,7 +100,7 @@ namespace LibMSPackSharp.Compression
int bits_left;
int i_ptr, i_end;
- int i, state;
+ int i, readState;
Error error;
// Easy answers
@@ -188,32 +129,32 @@ namespace LibMSPackSharp.Compression
while (out_bytes > 0)
{
// Unpack another block
- zip.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
+ BufferState state = zip.RESTORE_BITS();
// Skip to next read 'CK' header
- i = bits_left & 7;
+ i = state.BitsLeft & 7;
// Align to bytestream
- zip.REMOVE_BITS_LSB(i, ref bit_buffer, ref bits_left);
+ state.REMOVE_BITS_LSB(i);
- state = 0;
+ readState = 0;
do
{
- i = (int)zip.READ_BITS_LSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ i = (int)zip.READ_BITS_LSB(8, state);
if (i == 'C')
- state = 1;
- else if ((state == 1) && (i == 'K'))
- state = 2;
+ readState = 1;
+ else if ((readState == 1) && (i == 'K'))
+ readState = 2;
else
- state = 0;
- } while (state != 2);
+ readState = 0;
+ } while (readState != 2);
// Inflate a block, repair and realign if necessary
zip.WindowPosition = 0;
zip.BytesOutput = 0;
- zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ zip.STORE_BITS(state);
if ((error = Inflate(zip)) != Error.MSPACK_ERR_OK)
{
@@ -269,36 +210,31 @@ namespace LibMSPackSharp.Compression
///
public static Error DecompressKWAJ(MSZIPDStream zip)
{
- // For the bit buffer
- uint bit_buffer;
- int bits_left;
- int i_ptr, i_end;
-
int i, block_len;
Error error;
// Unpack blocks until block_len == 0
for (; ; )
{
- zip.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
+ BufferState state = zip.RESTORE_BITS();
// Align to bytestream, read block_len
- i = bits_left & 7;
- zip.REMOVE_BITS_LSB(i, ref bit_buffer, ref bits_left);
+ i = state.BitsLeft & 7;
+ state.REMOVE_BITS_LSB(i);
- block_len = (int)zip.READ_BITS_LSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- i = (int)zip.READ_BITS_LSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ block_len = (int)zip.READ_BITS_LSB(8, state);
+ i = (int)zip.READ_BITS_LSB(8, state);
block_len |= i << 8;
if (block_len == 0)
break;
// Read "CK" header
- i = (int)zip.READ_BITS_LSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ i = (int)zip.READ_BITS_LSB(8, state);
if (i != 'C')
return Error.MSPACK_ERR_DATAFORMAT;
- i = (int)zip.READ_BITS_LSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ i = (int)zip.READ_BITS_LSB(8, state);
if (i != 'K')
return Error.MSPACK_ERR_DATAFORMAT;
@@ -306,7 +242,7 @@ namespace LibMSPackSharp.Compression
zip.WindowPosition = 0;
zip.BytesOutput = 0;
- zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ zip.STORE_BITS(state);
if ((error = Inflate(zip)) != Error.MSPACK_ERR_OK)
{
@@ -331,16 +267,16 @@ namespace LibMSPackSharp.Compression
byte[] lens = new byte[MSZIP_LITERAL_MAXSYMBOLS + MSZIP_DISTANCE_MAXSYMBOLS];
uint lit_codes, dist_codes, code, last_code = 0, bitlen_codes, i, run;
- zip.RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left);
+ BufferState state = zip.RESTORE_BITS();
// Read the number of codes
- lit_codes = (uint)zip.READ_BITS_LSB(5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ lit_codes = (uint)zip.READ_BITS_LSB(5, state);
lit_codes += 257;
- dist_codes = (uint)zip.READ_BITS_LSB(5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ dist_codes = (uint)zip.READ_BITS_LSB(5, state);
dist_codes += 1;
- bitlen_codes = (uint)zip.READ_BITS_LSB(5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ bitlen_codes = (uint)zip.READ_BITS_LSB(5, state);
bitlen_codes += 4;
if (lit_codes > MSZIP_LITERAL_MAXSYMBOLS)
@@ -351,12 +287,12 @@ namespace LibMSPackSharp.Compression
// Read in the bit lengths in their unusual order
for (i = 0; i < bitlen_codes; i++)
{
- bl_len[bitlen_order[i]] = (byte)zip.READ_BITS_LSB(3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ bl_len[BitLengthOrder[i]] = (byte)zip.READ_BITS_LSB(3, state);
}
while (i < 19)
{
- bl_len[bitlen_order[i++]] = 0;
+ bl_len[BitLengthOrder[i++]] = 0;
}
// Create decoding table with an immediate lookup
@@ -368,9 +304,9 @@ namespace LibMSPackSharp.Compression
{
// Single-level huffman lookup
- zip.ENSURE_BITS(7, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- code = bl_table[zip.PEEK_BITS_LSB(7, bit_buffer)];
- zip.REMOVE_BITS_LSB(bl_len[code], ref bit_buffer, ref bits_left);
+ zip.ENSURE_BITS(7, state);
+ code = bl_table[zip.PEEK_BITS_LSB(7, state.BitBuffer)];
+ state.REMOVE_BITS_LSB(bl_len[code]);
if (code < 16)
{
@@ -381,19 +317,19 @@ namespace LibMSPackSharp.Compression
switch (code)
{
case 16:
- run = (uint)zip.READ_BITS_LSB(2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ run = (uint)zip.READ_BITS_LSB(2, state);
run += 3;
code = last_code;
break;
case 17:
- run = (uint)zip.READ_BITS_LSB(3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ run = (uint)zip.READ_BITS_LSB(3, state);
run += 3;
code = 0;
break;
case 18:
- run = (uint)zip.READ_BITS_LSB(7, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ run = (uint)zip.READ_BITS_LSB(7, state);
run += 11;
code = 0;
break;
@@ -430,7 +366,7 @@ namespace LibMSPackSharp.Compression
zip.DISTANCE_len[i++] = 0;
}
- zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ zip.STORE_BITS(state);
return 0;
}
@@ -444,15 +380,15 @@ namespace LibMSPackSharp.Compression
Error err;
ushort sym;
- zip.RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left);
+ BufferState state = zip.RESTORE_BITS();
do
{
// Read in last block bit
- last_block = (uint)zip.READ_BITS_LSB(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ last_block = (uint)zip.READ_BITS_LSB(1, state);
// Read in block type
- block_type = (uint)zip.READ_BITS_LSB(2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ block_type = (uint)zip.READ_BITS_LSB(2, state);
if (block_type == 0)
{
@@ -460,29 +396,29 @@ namespace LibMSPackSharp.Compression
byte[] lens_buf = new byte[4];
// Go to byte boundary
- i = (uint)(bits_left & 7);
- zip.REMOVE_BITS_LSB((int)i, ref bit_buffer, ref bits_left);
+ i = (uint)(state.BitsLeft & 7);
+ state.REMOVE_BITS_LSB((int)i);
// Read 4 bytes of data, emptying the bit-buffer if necessary
- for (i = 0; (bits_left >= 8); i++)
+ for (i = 0; (state.BitsLeft >= 8); i++)
{
if (i == 4)
return Error.INF_ERR_BITBUF;
- lens_buf[i] = (byte)zip.PEEK_BITS_LSB(8, bit_buffer);
- zip.REMOVE_BITS_LSB(8, ref bit_buffer, ref bits_left);
+ lens_buf[i] = (byte)zip.PEEK_BITS_LSB(8, state.BitBuffer);
+ state.REMOVE_BITS_LSB(8);
}
- if (bits_left != 0)
+ if (state.BitsLeft != 0)
return Error.INF_ERR_BITBUF;
while (i < 4)
{
- zip.READ_IF_NEEDED(ref i_ptr, ref i_end);
+ zip.READ_IF_NEEDED(state);
if (zip.Error != Error.MSPACK_ERR_OK)
return zip.Error;
- lens_buf[i++] = zip.InputBuffer[i_ptr++];
+ lens_buf[i++] = zip.InputBuffer[state.InputPointer++];
}
// Get the length and its complement
@@ -496,21 +432,21 @@ namespace LibMSPackSharp.Compression
// Read and copy the uncompressed data into the window
while (length > 0)
{
- zip.READ_IF_NEEDED(ref i_ptr, ref i_end);
+ zip.READ_IF_NEEDED(state);
if (zip.Error != Error.MSPACK_ERR_OK)
return zip.Error;
this_run = length;
- if (this_run > (uint)(i_end - i_ptr))
- this_run = (uint)(i_end - i_ptr);
+ if (this_run > (uint)(state.InputEnd - state.InputPointer))
+ this_run = (uint)(state.InputEnd - state.InputPointer);
if (this_run > (MSZIP_FRAME_SIZE - zip.WindowPosition))
this_run = MSZIP_FRAME_SIZE - zip.WindowPosition;
- Array.Copy(zip.InputBuffer, i_ptr, zip.Window, zip.WindowPosition, this_run);
+ Array.Copy(zip.InputBuffer, state.InputPointer, zip.Window, zip.WindowPosition, this_run);
zip.WindowPosition += this_run;
- i_ptr += (int)this_run;
+ state.InputPointer += (int)this_run;
length -= this_run;
err = FLUSH_IF_NEEDED(zip);
@@ -555,12 +491,12 @@ namespace LibMSPackSharp.Compression
else
{
// Block with dynamic Huffman codes
- zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ zip.STORE_BITS(state);
if ((err = ReadLens(zip)) != Error.MSPACK_ERR_OK)
return err;
- zip.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
+ state = zip.RESTORE_BITS();
}
// Now huffman lengths are read for either kind of block,
@@ -574,7 +510,7 @@ namespace LibMSPackSharp.Compression
// Decode forever until end of block code
for (; ; )
{
- code = (uint)zip.READ_HUFFSYM_LSB(zip.LITERAL_table, zip.LITERAL_len, MSZIP_LITERAL_TABLEBITS, MSZIP_LITERAL_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ code = (uint)zip.READ_HUFFSYM_LSB(zip.LITERAL_table, zip.LITERAL_len, MSZIP_LITERAL_TABLEBITS, MSZIP_LITERAL_MAXSYMBOLS, state);
if (code < 256)
{
@@ -594,16 +530,16 @@ namespace LibMSPackSharp.Compression
if (code >= 29)
return Error.INF_ERR_LITCODE; // Codes 286-287 are illegal
- length = (uint)zip.READ_BITS_T_LSB(lit_extrabits[code], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- length += lit_lengths[code];
+ length = (uint)zip.READ_BITS_T_LSB(LiteralExtraBits[code], state);
+ length += LiteralLengths[code];
- code = (uint)zip.READ_HUFFSYM_LSB(zip.DISTANCE_table, zip.DISTANCE_len, MSZIP_DISTANCE_TABLEBITS, MSZIP_DISTANCE_MAXSYMBOLS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ code = (uint)zip.READ_HUFFSYM_LSB(zip.DISTANCE_table, zip.DISTANCE_len, MSZIP_DISTANCE_TABLEBITS, MSZIP_DISTANCE_MAXSYMBOLS, state);
if (code >= 30)
return Error.INF_ERR_DISTCODE;
- distance = (uint)zip.READ_BITS_T_LSB(dist_extrabits[code], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- distance += dist_offsets[code];
+ distance = (uint)zip.READ_BITS_T_LSB(DistanceExtraBits[code], state);
+ distance += DistanceOffsets[code];
// Match position is window position minus distance. If distance
// is more than window position numerically, it must 'wrap
@@ -672,7 +608,7 @@ namespace LibMSPackSharp.Compression
return Error.INF_ERR_FLUSH;
}
- zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ zip.STORE_BITS(state);
// Return success
return Error.MSPACK_ERR_OK;
diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs b/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
index 52f9b7b9..ec1bbf75 100644
--- a/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
@@ -11,6 +11,7 @@
*/
using System;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
@@ -21,7 +22,7 @@ namespace LibMSPackSharp.Compression
///
/// 32kb history window
///
- public byte[] Window { get; set; } = new byte[MSZIP.MSZIP_FRAME_SIZE];
+ public byte[] Window { get; set; } = new byte[MSZIP_FRAME_SIZE];
///
/// Offset within window
@@ -39,15 +40,15 @@ namespace LibMSPackSharp.Compression
#region Huffman code lengths
- public byte[] LITERAL_len { get; set; } = new byte[MSZIP.MSZIP_LITERAL_MAXSYMBOLS];
- public byte[] DISTANCE_len { get; set; } = new byte[MSZIP.MSZIP_DISTANCE_MAXSYMBOLS];
+ public byte[] LITERAL_len { get; set; } = new byte[MSZIP_LITERAL_MAXSYMBOLS];
+ public byte[] DISTANCE_len { get; set; } = new byte[MSZIP_DISTANCE_MAXSYMBOLS];
#endregion
#region Huffman decoding tables
- public ushort[] LITERAL_table { get; set; } = new ushort[MSZIP.MSZIP_LITERAL_TABLESIZE];
- public ushort[] DISTANCE_table { get; set; } = new ushort[MSZIP.MSZIP_DISTANCE_TABLESIZE];
+ public ushort[] LITERAL_table { get; set; } = new ushort[MSZIP_LITERAL_TABLESIZE];
+ public ushort[] DISTANCE_table { get; set; } = new ushort[MSZIP_DISTANCE_TABLESIZE];
#endregion
@@ -57,13 +58,13 @@ namespace LibMSPackSharp.Compression
public override Error HUFF_ERROR() => Error.INF_ERR_HUFFSYM;
///
- public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public override void READ_BYTES(BufferState state)
{
- READ_IF_NEEDED(ref i_ptr, ref i_end);
+ READ_IF_NEEDED(state);
if (Error != Error.MSPACK_ERR_OK)
return;
- INJECT_BITS_LSB(InputBuffer[i_ptr++], 8, ref bit_buffer, ref bits_left);
+ INJECT_BITS_LSB(InputBuffer[state.InputPointer++], 8, state);
}
}
}
diff --git a/BurnOutSharp/External/libmspack/Compression/QTM.cs b/BurnOutSharp/External/libmspack/Compression/QTM.cs
index 7f1ba42b..5b6cdfc9 100644
--- a/BurnOutSharp/External/libmspack/Compression/QTM.cs
+++ b/BurnOutSharp/External/libmspack/Compression/QTM.cs
@@ -22,67 +22,12 @@
using System;
using System.IO;
+using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
public class QTM
{
- public const int QTM_FRAME_SIZE = 32768;
-
- /* Quantum static data tables:
- *
- * Quantum uses 'position slots' to represent match offsets. For every
- * match, a small 'position slot' number and a small offset from that slot
- * are encoded instead of one large offset.
- *
- * position_base[] is an index to the position slot bases
- *
- * extra_bits[] states how many bits of offset-from-base data is needed.
- *
- * length_base[] and length_extra[] are equivalent in function, but are
- * used for encoding selector 6 (variable length match) match lengths,
- * instead of match offsets.
- *
- * They are generated with the following code:
- * uint i, offset;
- * for (i = 0, offset = 0; i < 42; i++) {
- * position_base[i] = offset;
- * extra_bits[i] = ((i < 2) ? 0 : (i - 2)) >> 1;
- * offset += 1 << extra_bits[i];
- * }
- * for (i = 0, offset = 0; i < 26; i++) {
- * length_base[i] = offset;
- * length_extra[i] = (i < 2 ? 0 : i - 2) >> 2;
- * offset += 1 << length_extra[i];
- * }
- * length_base[26] = 254; length_extra[26] = 0;
- */
-
- private static readonly uint[] position_base = new uint[42]
- {
- 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
- 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
- 65536, 98304, 131072, 196608, 262144, 393216, 524288, 786432, 1048576, 1572864
- };
-
- private static readonly byte[] extra_bits = new byte[42]
- {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
- 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19
- };
-
- private static readonly byte[] length_base = new byte[27]
- {
- 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 18, 22, 26,
- 30, 38, 46, 54, 62, 78, 94, 110, 126, 158, 190, 222, 254
- };
-
- private static readonly byte[] length_extra = new byte[27]
- {
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
- };
-
///
/// allocates Quantum decompression state for decoding the given stream.
///
@@ -126,13 +71,17 @@ namespace LibMSPackSharp.Compression
HeaderRead = 0,
Error = Error.MSPACK_ERR_OK,
- InputPointer = 0,
- InputEnd = 0,
OutputPointer = 0,
OutputEnd = 0,
EndOfInput = 0,
- BitsLeft = 0,
- BitBuffer = 0,
+
+ BufferState = new BufferState()
+ {
+ InputPointer = 0,
+ InputEnd = 0,
+ BitBuffer = 0,
+ BitsLeft = 0,
+ }
};
// Initialise arithmetic coding models
@@ -214,7 +163,7 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
// Restore local state
- qtm.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
+ BufferState state = qtm.RESTORE_BITS();
window = qtm.Window;
window_posn = qtm.WindowPosition;
frame_todo = qtm.FrameTODO;
@@ -230,7 +179,7 @@ namespace LibMSPackSharp.Compression
{
H = 0xFFFF;
L = 0;
- C = (ushort)qtm.READ_BITS_MSB(16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ C = (ushort)qtm.READ_BITS_MSB(16, state);
qtm.HeaderRead = 1;
}
@@ -244,7 +193,7 @@ namespace LibMSPackSharp.Compression
while (window_posn < frame_end)
{
- selector = GET_SYMBOL(qtm, qtm.Model7, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ selector = GET_SYMBOL(qtm, qtm.Model7, ref H, ref L, ref C, state);
if (selector < 4)
{
// Literal byte
@@ -269,7 +218,7 @@ namespace LibMSPackSharp.Compression
break;
}
- sym = GET_SYMBOL(qtm, mdl, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ sym = GET_SYMBOL(qtm, mdl, ref H, ref L, ref C, state);
window[window_posn++] = (byte)sym;
frame_todo--;
}
@@ -280,29 +229,29 @@ namespace LibMSPackSharp.Compression
{
// Selector 4 = fixed length match (3 bytes)
case 4:
- sym = GET_SYMBOL(qtm, qtm.Model4, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- extra = (int)qtm.READ_MANY_BITS_MSB(extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset = (uint)(position_base[sym] + extra + 1);
+ sym = GET_SYMBOL(qtm, qtm.Model4, ref H, ref L, ref C, state);
+ extra = (int)qtm.READ_MANY_BITS_MSB(QTMExtraBits[sym], state);
+ match_offset = (uint)(QTMPositionBase[sym] + extra + 1);
match_length = 3;
break;
// Selector 5 = fixed length match (4 bytes)
case 5:
- sym = GET_SYMBOL(qtm, qtm.Model5, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- extra = (int)qtm.READ_MANY_BITS_MSB(extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset = (uint)(position_base[sym] + extra + 1);
+ sym = GET_SYMBOL(qtm, qtm.Model5, ref H, ref L, ref C, state);
+ extra = (int)qtm.READ_MANY_BITS_MSB(QTMExtraBits[sym], state);
+ match_offset = (uint)(QTMPositionBase[sym] + extra + 1);
match_length = 4;
break;
// Selector 6 = variable length match
case 6:
- sym = GET_SYMBOL(qtm, qtm.Model6Len, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- extra = (int)qtm.READ_MANY_BITS_MSB(length_extra[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_length = length_base[sym] + extra + 5;
+ sym = GET_SYMBOL(qtm, qtm.Model6Len, ref H, ref L, ref C, state);
+ extra = (int)qtm.READ_MANY_BITS_MSB(QTMLengthExtra[sym], state);
+ match_length = QTMLengthBase[sym] + extra + 5;
- sym = GET_SYMBOL(qtm, qtm.Model6, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- extra = (int)qtm.READ_MANY_BITS_MSB(extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- match_offset = (uint)(position_base[sym] + extra + 1);
+ sym = GET_SYMBOL(qtm, qtm.Model6, ref H, ref L, ref C, state);
+ extra = (int)qtm.READ_MANY_BITS_MSB(QTMExtraBits[sym], state);
+ match_offset = (uint)(QTMPositionBase[sym] + extra + 1);
break;
default:
@@ -422,15 +371,15 @@ namespace LibMSPackSharp.Compression
if (frame_todo == 0)
{
// Re-align input
- if ((bits_left & 7) != 0)
- qtm.REMOVE_BITS_MSB(bits_left & 7, ref bit_buffer, ref bits_left);
+ if ((state.BitsLeft & 7) != 0)
+ state.REMOVE_BITS_MSB(state.BitsLeft & 7);
// Special Quantum hack -- cabd.c injects a 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.
do
{
- i = (int)qtm.READ_BITS_MSB(8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ i = (int)qtm.READ_BITS_MSB(8, state);
} while (i != 0xFF);
qtm.HeaderRead = 0;
@@ -470,7 +419,7 @@ namespace LibMSPackSharp.Compression
}
// Store local state
- qtm.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ qtm.STORE_BITS(state);
qtm.WindowPosition = window_posn;
qtm.FrameTODO = frame_todo;
qtm.High = H;
@@ -480,7 +429,7 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
- private static ushort GET_SYMBOL(QTMDStream qtm, QTMDModel model, ref ushort H, ref ushort L, ref ushort C, ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ private static ushort GET_SYMBOL(QTMDStream qtm, QTMDModel model, ref ushort H, ref ushort L, ref ushort C, BufferState state)
{
uint range = (uint)((H - L) & 0xFFFF) + 1;
ushort symf = (ushort)(((((C - L + 1) * model.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
@@ -527,9 +476,9 @@ namespace LibMSPackSharp.Compression
L <<= 1;
H = (ushort)((H << 1) | 1);
- qtm.ENSURE_BITS(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- C = (ushort)((C << 1) | (qtm.PEEK_BITS_MSB(1, bit_buffer)));
- qtm.REMOVE_BITS_MSB(1, ref bit_buffer, ref bits_left);
+ qtm.ENSURE_BITS(1, state);
+ C = (ushort)((C << 1) | (qtm.PEEK_BITS_MSB(1, state.BitBuffer)));
+ state.REMOVE_BITS_MSB(1);
}
return temp;
diff --git a/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs b/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
index dd73b778..2d7ebb1e 100644
--- a/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
@@ -130,20 +130,20 @@ namespace LibMSPackSharp.Compression
public override Error HUFF_ERROR() => throw new NotImplementedException();
///
- public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
+ public override void READ_BYTES(BufferState state)
{
- READ_IF_NEEDED(ref i_ptr, ref i_end);
+ READ_IF_NEEDED(state);
if (Error != Error.MSPACK_ERR_OK)
return;
- byte b0 = InputBuffer[i_ptr++];
+ byte b0 = InputBuffer[state.InputPointer++];
- READ_IF_NEEDED(ref i_ptr, ref i_end);
+ READ_IF_NEEDED(state);
if (Error != Error.MSPACK_ERR_OK)
return;
- byte b1 = InputBuffer[i_ptr++];
- INJECT_BITS_MSB((b0 << 8) | b1, 16, ref bit_buffer, ref bits_left);
+ byte b1 = InputBuffer[state.InputPointer++];
+ INJECT_BITS_MSB((b0 << 8) | b1, 16, state);
}
}
}