diff --git a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
index 6ae59ec9..b54a0910 100644
--- a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
@@ -17,6 +17,8 @@ namespace LibMSPackSharp.Compression
{
public abstract class CompressionStream : BaseDecompressState
{
+ #region Constants
+
///
/// Number of bits in a character
///
@@ -27,6 +29,13 @@ namespace LibMSPackSharp.Compression
///
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; }
@@ -363,7 +372,7 @@ namespace LibMSPackSharp.Compression
// TODO: These should be in a separate file
#region ReadHuff Methods
- public const int HUFF_MAXBITS = 16;
+ #region Common
///
/// This function was originally coded by David Tritscher.
@@ -379,6 +388,7 @@ namespace LibMSPackSharp.Compression
/// Should be ((1<
/// true for OK or false for error
+ /// TODO: Split into MSB and LSB variants
public static bool MakeDecodeTable(int nsyms, int nbits, byte[] length, ushort[] table, bool msb)
{
ushort sym, next_symbol;
@@ -535,6 +545,87 @@ namespace LibMSPackSharp.Compression
return pos == table_mask;
}
+ ///
+ /// Per compression error code for decoding failure
+ ///
+ public abstract Error HUFF_ERROR();
+
+ #endregion
+
+ #region MSB
+
+ ///
+ /// 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)
+ {
+ 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)];
+ if (sym >= maxsymbols)
+ HUFF_TRAVERSE_MSB(ref sym, table, tablebits, maxsymbols, bit_buffer);
+
+ REMOVE_BITS_MSB(lengths[sym], ref bit_buffer, ref bits_left);
+ return sym;
+ }
+
+ ///
+ /// Traverse for a single symbol
+ ///
+ private void HUFF_TRAVERSE_MSB(ref ushort sym, ushort[] table, int tablebits, int maxsymbols, uint bit_buffer)
+ {
+ int i = 1 << (BITBUF_WIDTH - tablebits);
+ do
+ {
+ if ((i >>= 1) == 0)
+ {
+ Error = HUFF_ERROR();
+ return;
+ }
+
+ sym = table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
+ } while (sym >= maxsymbols);
+ }
+
+ #endregion
+
+ #region LSB
+
+ ///
+ /// 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)
+ {
+ 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)];
+ if (sym >= maxsymbols)
+ HUFF_TRAVERSE_LSB(ref sym, table, tablebits, maxsymbols, bit_buffer);
+
+ REMOVE_BITS_LSB(lengths[sym], ref bit_buffer, ref bits_left);
+ return sym;
+ }
+
+ ///
+ /// Traverse for a single symbol
+ ///
+ private void HUFF_TRAVERSE_LSB(ref ushort sym, ushort[] table, int tablebits, int maxsymbols, uint bit_buffer)
+ {
+ int i = tablebits - 1;
+ do
+ {
+ if (i++ > HUFF_MAXBITS)
+ {
+ Error = HUFF_ERROR();
+ return;
+ }
+
+ sym = table[(sym << 1) | ((bit_buffer >> i) & 1)];
+ } while (sym >= maxsymbols);
+ }
+
+ #endregion
+
#endregion
}
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs b/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs
index 64bcec2c..7efac2fc 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs
@@ -8,7 +8,6 @@
*/
using System.IO;
-using LibMSPackSharp.KWAJ;
using static LibMSPackSharp.Constants;
namespace LibMSPackSharp.Compression
@@ -42,10 +41,8 @@ namespace LibMSPackSharp.Compression
public static Error Decompress(LZHKWAJStream lzh)
{
int i;
- ushort sym;
int lit_run = 0;
int j, pos = 0, len, offset;
- Error err;
uint[] types = new uint[6];
// Reset global state
@@ -60,151 +57,31 @@ namespace LibMSPackSharp.Compression
// Read 6 encoding types (for byte alignment) but only 5 are needed
for (i = 0; i < 6; i++)
{
- //READ_BITS_SAFE(types[i], 4)
- {
- types[i] = (uint)lzh.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ types[i] = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
}
// Read huffman table symbol lengths and build huffman trees
-
- //BUILD_TREE(MATCHLEN1, types[0])
- {
- lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- err = ReadLens(lzh, types[0], KWAJ_MATCHLEN1_SYMS, 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);
-
- if (!CompressionStream.MakeDecodeTable(KWAJ_MATCHLEN1_SYMS, KWAJ_TABLEBITS, lzh.MATCHLEN1_len, lzh.MATCHLEN1_table, msb: true))
- return Error.MSPACK_ERR_DATAFORMAT;
- }
-
- //BUILD_TREE(MATCHLEN2, types[1])
- {
- lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- err = ReadLens(lzh, types[1], KWAJ_MATCHLEN2_SYMS, lzh.MATCHLEN2_len);
- if (err != Error.MSPACK_ERR_OK)
- return err;
-
- lzh.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
-
- if (!CompressionStream.MakeDecodeTable(KWAJ_MATCHLEN2_SYMS, KWAJ_TABLEBITS, lzh.MATCHLEN2_len, lzh.MATCHLEN2_table, msb: true))
- return Error.MSPACK_ERR_DATAFORMAT;
- }
-
- //BUILD_TREE(LITLEN, types[2])
- {
- lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- err = ReadLens(lzh, types[2], KWAJ_LITLEN_SYMS, lzh.LITLEN_len);
- if (err != Error.MSPACK_ERR_OK)
- return err;
-
- lzh.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
-
- if (!CompressionStream.MakeDecodeTable(KWAJ_LITLEN_SYMS, KWAJ_TABLEBITS, lzh.LITLEN_len, lzh.LITLEN_table, msb: true))
- return Error.MSPACK_ERR_DATAFORMAT;
- }
-
- //BUILD_TREE(OFFSET, types[3])
- {
- lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- err = ReadLens(lzh, types[3], KWAJ_OFFSET_SYMS, lzh.OFFSET_len);
- if (err != Error.MSPACK_ERR_OK)
- return err;
-
- lzh.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
-
- if (!CompressionStream.MakeDecodeTable(KWAJ_OFFSET_SYMS, KWAJ_TABLEBITS, lzh.OFFSET_len, lzh.OFFSET_table, msb: true))
- return Error.MSPACK_ERR_DATAFORMAT;
- }
-
- //BUILD_TREE(LITERAL, types[4])
- {
- lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- err = ReadLens(lzh, types[4], KWAJ_LITERAL_SYMS, lzh.LITERAL_len);
- if (err != Error.MSPACK_ERR_OK)
- return err;
-
- lzh.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
-
- if (!CompressionStream.MakeDecodeTable(KWAJ_LITERAL_SYMS, KWAJ_TABLEBITS, lzh.LITERAL_len, lzh.LITERAL_table, msb: true))
- return Error.MSPACK_ERR_DATAFORMAT;
- }
+ 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);
while (lzh.EndOfInput == 0)
{
if (lit_run != 0)
{
- //READ_HUFFSYM_SAFE(MATCHLEN2, len)
- {
- //READ_HUFFSYM(MATCHLEN2, len)
- {
- lzh.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzh.MATCHLEN2_table[lzh.PEEK_BITS_MSB(KWAJ_TABLEBITS, bit_buffer)];
- if (sym >= KWAJ_MATCHLEN2_SYMS)
- {
- //HUFF_TRAVERSE(MATCHLEN2)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - KWAJ_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return Error.MSPACK_ERR_DATAFORMAT;
-
- sym = lzh.MATCHLEN2_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= KWAJ_MATCHLEN2_SYMS);
- }
- }
-
- (len) = sym;
- i = lzh.MATCHLEN2_len[sym];
- lzh.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ 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);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
}
else
{
- //READ_HUFFSYM_SAFE(MATCHLEN1, len)
- {
- //READ_HUFFSYM(MATCHLEN1, len)
- {
- lzh.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzh.MATCHLEN1_table[lzh.PEEK_BITS_MSB(KWAJ_TABLEBITS, bit_buffer)];
- if (sym >= KWAJ_MATCHLEN1_SYMS)
- {
- //HUFF_TRAVERSE(MATCHLEN1)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - KWAJ_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return Error.MSPACK_ERR_DATAFORMAT;
-
- sym = lzh.MATCHLEN1_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= KWAJ_MATCHLEN1_SYMS);
- }
- }
-
- (len) = sym;
- i = lzh.MATCHLEN1_len[sym];
- lzh.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ 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);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
}
if (len > 0)
@@ -212,44 +89,15 @@ namespace LibMSPackSharp.Compression
len += 2;
lit_run = 0; // Not the end of a literal run
- //READ_HUFFSYM_SAFE(OFFSET, j)
- {
- //READ_HUFFSYM(OFFSET, j)
- {
- lzh.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzh.OFFSET_table[lzh.PEEK_BITS_MSB(KWAJ_TABLEBITS, bit_buffer)];
- if (sym >= KWAJ_OFFSET_SYMS)
- {
- //HUFF_TRAVERSE(OFFSET)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - KWAJ_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return Error.MSPACK_ERR_DATAFORMAT;
-
- sym = lzh.OFFSET_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= KWAJ_OFFSET_SYMS);
- }
- }
-
- (j) = sym;
- i = lzh.OFFSET_len[sym];
- lzh.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ 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);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
offset = j << 6;
- //READ_BITS_SAFE(j, 6)
- {
- j = (int)lzh.READ_BITS_MSB(6, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ j = (int)lzh.READ_BITS_SAFE(6, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
offset |= j;
@@ -257,12 +105,9 @@ namespace LibMSPackSharp.Compression
while (len-- > 0)
{
lzh.Window[pos] = lzh.Window[(pos + 4096 - offset) & 4095];
-
- //WRITE_BYTE
- {
- if (lzh.System.Write(lzh.OutputFileHandle, lzh.Window, pos, 1) != 1)
- return Error.MSPACK_ERR_WRITE;
- }
+ lzh.WRITE_BYTE(pos);
+ if (lzh.Error != Error.MSPACK_ERR_OK)
+ return lzh.Error;
pos++;
pos &= 4095;
@@ -270,78 +115,24 @@ namespace LibMSPackSharp.Compression
}
else
{
- //READ_HUFFSYM_SAFE(LITLEN, len)
- {
- //READ_HUFFSYM(LITLEN, len)
- {
- lzh.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzh.LITLEN_table[lzh.PEEK_BITS_MSB(KWAJ_TABLEBITS, bit_buffer)];
- if (sym >= KWAJ_LITLEN_SYMS)
- {
- //HUFF_TRAVERSE(tbl)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - KWAJ_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return Error.MSPACK_ERR_DATAFORMAT;
-
- sym = lzh.LITLEN_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= KWAJ_LITLEN_SYMS);
- }
- }
-
- (len) = sym;
- i = lzh.LITLEN_len[sym];
- lzh.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ 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);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
len++;
lit_run = (len == 32) ? 0 : 1; // End of a literal run?
while (len-- > 0)
{
- //READ_HUFFSYM_SAFE(LITERAL, j)
- {
- //READ_HUFFSYM(LITERAL, j)
- {
- lzh.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzh.LITERAL_table[lzh.PEEK_BITS_MSB(KWAJ_TABLEBITS, bit_buffer)];
- if (sym >= KWAJ_LITERAL_SYMS)
- {
- //HUFF_TRAVERSE(LITERAL)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - KWAJ_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return Error.MSPACK_ERR_DATAFORMAT;
-
- sym = lzh.LITERAL_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= KWAJ_LITERAL_SYMS);
- }
- }
-
- (j) = sym;
- i = lzh.LITERAL_len[sym];
- lzh.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ 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);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
// Copy as output and into the ring buffer
lzh.Window[pos] = (byte)j;
- //WRITE_BYTE
- {
- if (lzh.System.Write(lzh.OutputFileHandle, lzh.Window, pos, 1) != 1)
- return Error.MSPACK_ERR_WRITE;
- }
+ lzh.WRITE_BYTE(pos);
+ if (lzh.Error != Error.MSPACK_ERR_OK)
+ return lzh.Error;
pos++; pos &= 4095;
}
@@ -351,16 +142,28 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
- private static Error ReadLens(LZHKWAJStream lzh, uint type, uint numsyms, byte[] lens)
+ 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)
{
- uint bit_buffer;
- int bits_left;
- int i_ptr, i_end;
- uint i, c, sel;
- Error err;
+ lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+
+ 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);
+ if (!CompressionStream.MakeDecodeTable(maxsymbols, tablebits, lengths, table, msb: true))
+ return Error.MSPACK_ERR_DATAFORMAT;
+
+ return Error.MSPACK_ERR_OK;
+ }
+
+ private static Error ReadLens(LZHKWAJStream lzh, uint type, uint numsyms, byte[] lens)
+ {
+ uint i, c, sel;
+
+ lzh.RESTORE_BITS(out int i_ptr, out int i_end, out uint bit_buffer, out int bits_left);
+
switch (type)
{
case 0:
@@ -374,22 +177,16 @@ namespace LibMSPackSharp.Compression
break;
case 1:
- //READ_BITS_SAFE(c, 4)
- {
- c = (uint)lzh.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
lens[0] = (byte)c;
for (i = 1; i < numsyms; i++)
{
- //READ_BITS_SAFE(sel, 1)
- {
- sel = (uint)lzh.READ_BITS_MSB(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ sel = (uint)lzh.READ_BITS_SAFE(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
if (sel == 0)
{
@@ -397,12 +194,9 @@ namespace LibMSPackSharp.Compression
}
else
{
- //READ_BITS_SAFE(sel, 1)
- {
- sel = (uint)lzh.READ_BITS_MSB(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ sel = (uint)lzh.READ_BITS_SAFE(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
if (sel == 0)
{
@@ -410,12 +204,9 @@ namespace LibMSPackSharp.Compression
}
else
{
- //READ_BITS_SAFE(c, 4)
- {
- c = (uint)lzh.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
lens[i] = (byte)c;
}
@@ -425,31 +216,22 @@ namespace LibMSPackSharp.Compression
break;
case 2:
- //READ_BITS_SAFE(c, 4)
- {
- c = (uint)lzh.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
lens[0] = (byte)c;
for (i = 1; i < numsyms; i++)
{
- //READ_BITS_SAFE(sel, 2)
- {
- sel = (uint)lzh.READ_BITS_MSB(2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ sel = (uint)lzh.READ_BITS_SAFE(2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
if (sel == 3)
{
- //READ_BITS_SAFE(c, 4)
- {
- c = (uint)lzh.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
}
else
{
@@ -464,12 +246,9 @@ namespace LibMSPackSharp.Compression
case 3:
for (i = 0; i < numsyms; i++)
{
- //READ_BITS_SAFE(c, 4)
- {
- c = (uint)lzh.READ_BITS_MSB(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- if (lzh.EndOfInput != 0 && bits_left < lzh.EndOfInput)
- return Error.MSPACK_ERR_OK;
- }
+ c = (uint)lzh.READ_BITS_SAFE(4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (lzh.Error == Error.MSPACK_ERR_NOMEMORY)
+ return Error.MSPACK_ERR_OK;
lens[i] = (byte)c;
}
diff --git a/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs b/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs
index 4ea428d4..4f84eb4e 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZHKWAJStream.cs
@@ -37,6 +37,61 @@ namespace LibMSPackSharp.Compression
#endregion
+ #region Specialty Methods
+
+ /* In the KWAJ LZH format, there is no special 'eof' marker, it just
+ * ends. Depending on how many bits are left in the final byte when
+ * the stream ends, that might be enough to start another literal or
+ * match. The only easy way to detect that we've come to an end is to
+ * guard all bit-reading. We allow fake bits to be read once we reach
+ * the end of the stream, but we check if we then consumed any of
+ * those fake bits, after doing the READ_BITS / READ_HUFFSYM. This
+ * isn't how the default readbits.h read_input() works (it simply lets
+ * 2 fake bytes in then stops), so we implement our own.
+ */
+
+ ///
+ /// 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)
+ {
+ long val = READ_BITS_MSB(nbits, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
+ if (EndOfInput != 0 && BitsLeft < EndOfInput)
+ Error = Error.MSPACK_ERR_NOMEMORY;
+ else
+ Error = Error.MSPACK_ERR_OK;
+
+ return val;
+ }
+
+ ///
+ /// 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)
+ {
+ 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)
+ Error = Error.MSPACK_ERR_NOMEMORY;
+ else
+ Error = Error.MSPACK_ERR_OK;
+
+ return val;
+ }
+
+ ///
+ /// Write a single byte to the output stream
+ ///
+ public void WRITE_BYTE(int pos)
+ {
+ if (System.Write(OutputFileHandle, Window, pos, 1) != 1)
+ Error = Error.MSPACK_ERR_WRITE;
+ }
+
+ #endregion
+
+ ///
+ 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)
{
diff --git a/BurnOutSharp/External/libmspack/Compression/LZX.cs b/BurnOutSharp/External/libmspack/Compression/LZX.cs
index dff107f5..c5bd6e33 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZX.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZX.cs
@@ -435,12 +435,6 @@ namespace LibMSPackSharp.Compression
if (lzx == null)
return Error.MSPACK_ERR_ARGS;
- // Bitstream and huffman reading variables
- uint bit_buffer;
- int bits_left, i;
- int i_ptr, i_end;
- ushort sym;
-
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];
@@ -456,7 +450,7 @@ namespace LibMSPackSharp.Compression
return lzx.Error;
// Flush out any stored-up bytes before we begin
- i = lzx.OutputEnd - lzx.OutputPointer;
+ int i = lzx.OutputEnd - lzx.OutputPointer;
if (i > out_bytes)
i = (int)out_bytes;
@@ -474,7 +468,7 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
// Restore local state
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
+ 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;
@@ -577,149 +571,64 @@ namespace LibMSPackSharp.Compression
lzx.ALIGNED_len[i] = (byte)j;
}
- //BUILD_TABLE(ALIGNED)
- {
- if (!CompressionStream.MakeDecodeTable(LZX_ALIGNED_MAXSYMBOLS, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, lzx.ALIGNED_table, msb: true))
- {
- Console.WriteLine($"Failed to build ALIGNED table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
+ 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(MAINTREE, 0, 256)
- {
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ 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;
- if (ReadLens(lzx, lzx.MAINTREE_len, (0), (uint)(256)) != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
- }
-
- //READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + lzx.NumOffsets)
- {
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- if (ReadLens(lzx, lzx.MAINTREE_len, (256), (uint)(LZX_NUM_CHARS + lzx.NumOffsets)) != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
- }
-
- //BUILD_TABLE(MAINTREE)
- {
- if (!CompressionStream.MakeDecodeTable(LZX_MAINTREE_MAXSYMBOLS, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, lzx.MAINTREE_table, msb: true))
- {
- Console.WriteLine($"Failed to build MAINTREE table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
+ 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;
- //READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS)
- {
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- if (ReadLens(lzx, lzx.LENGTH_len, (0), (uint)(LZX_NUM_SECONDARY_LENGTHS)) != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
- }
-
- //BUILD_TABLE_MAYBE_EMPTY(LENGTH)
- {
- lzx.LENGTH_empty = 0;
- if (!CompressionStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table, msb: true))
- {
- for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
- {
- if (lzx.LENGTH_len[i] > 0)
- {
- Console.WriteLine("Failed to build TBL table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
-
- // Empty tree - allow it, but don't decode symbols with it
- lzx.LENGTH_empty = 1;
- }
- }
+ 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(MAINTREE, 0, 256)
- {
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
+ 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;
- if (ReadLens(lzx, lzx.MAINTREE_len, (0), (uint)(256)) != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
- }
-
- //READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + lzx.NumOffsets)
- {
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- if (ReadLens(lzx, lzx.MAINTREE_len, (256), (uint)(LZX_NUM_CHARS + lzx.NumOffsets)) != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
- }
-
- //BUILD_TABLE(MAINTREE)
- {
- if (!CompressionStream.MakeDecodeTable(LZX_MAINTREE_MAXSYMBOLS, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, lzx.MAINTREE_table, msb: true))
- {
- Console.WriteLine($"Failed to build MAINTREE table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
+ 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;
- //READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS)
- {
- lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
-
- if (ReadLens(lzx, lzx.LENGTH_len, (0), (uint)(LZX_NUM_SECONDARY_LENGTHS)) != Error.MSPACK_ERR_OK)
- return lzx.Error;
-
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
- }
-
- //BUILD_TABLE_MAYBE_EMPTY(LENGTH)
- {
- lzx.LENGTH_empty = 0;
- if (!CompressionStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table, msb: true))
- {
- for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
- {
- if (lzx.LENGTH_len[i] > 0)
- {
- Console.WriteLine("Failed to build TBL table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
-
- // Empty tree - allow it, but don't decode symbols with it
- lzx.LENGTH_empty = 1;
- }
- }
+ BUILD_TABLE_MAYBE_EMPTY(lzx);
+ if (lzx.Error != Error.MSPACK_ERR_OK)
+ return lzx.Error;
break;
@@ -772,30 +681,7 @@ namespace LibMSPackSharp.Compression
case LZXBlockType.LZX_BLOCKTYPE_VERBATIM:
while (this_run > 0)
{
- //READ_HUFFSYM(MAINTREE, main_element)
- {
- lzx.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzx.MAINTREE_table[lzx.PEEK_BITS_MSB(LZX_MAINTREE_TABLEBITS, bit_buffer)];
- if (sym >= LZX_MAINTREE_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(MAINTREE)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - LZX_MAINTREE_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
-
- sym = lzx.MAINTREE_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= LZX_MAINTREE_MAXSYMBOLS);
- }
- }
-
- (main_element) = sym;
- i = lzx.MAINTREE_len[sym];
- lzx.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
+ 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
@@ -817,30 +703,7 @@ namespace LibMSPackSharp.Compression
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
}
- //READ_HUFFSYM(LENGTH, length_footer)
- {
- lzx.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzx.LENGTH_table[lzx.PEEK_BITS_MSB(LZX_LENGTH_TABLEBITS, bit_buffer)];
- if (sym >= LZX_LENGTH_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(LENGTH)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - LZX_LENGTH_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
-
- sym = lzx.LENGTH_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= LZX_LENGTH_MAXSYMBOLS);
- }
- }
-
- (length_footer) = sym;
- i = lzx.LENGTH_len[sym];
- lzx.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
+ 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;
}
@@ -893,60 +756,14 @@ namespace LibMSPackSharp.Compression
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);
- //READ_HUFFSYM(ALIGNED, aligned_bits)
- {
- lzx.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzx.ALIGNED_table[lzx.PEEK_BITS_MSB(LZX_ALIGNED_TABLEBITS, bit_buffer)];
- if (sym >= LZX_ALIGNED_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(ALIGNED)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - LZX_ALIGNED_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
-
- sym = lzx.ALIGNED_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= LZX_ALIGNED_MAXSYMBOLS);
- }
- }
-
- (aligned_bits) = sym;
- i = lzx.ALIGNED_len[sym];
- lzx.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
+ 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)
{
- //READ_HUFFSYM(ALIGNED, aligned_bits)
- {
- lzx.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzx.ALIGNED_table[lzx.PEEK_BITS_MSB(LZX_ALIGNED_TABLEBITS, bit_buffer)];
- if (sym >= LZX_ALIGNED_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(ALIGNED)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - LZX_ALIGNED_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
-
- sym = lzx.ALIGNED_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= LZX_ALIGNED_MAXSYMBOLS);
- }
- }
-
- (aligned_bits) = sym;
- i = lzx.ALIGNED_len[sym];
- lzx.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
-
+ 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;
}
@@ -1220,18 +1037,55 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
+ private static Error BUILD_TABLE(LZXDStream lzx, ushort[] table, byte[] lengths, int tablebits, int maxsymbols)
+ {
+ if (!CompressionStream.MakeDecodeTable(maxsymbols, tablebits, lengths, table, msb: true))
+ {
+ 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.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table, msb: true))
+ {
+ 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)
{
- // Bit buffer and huffman symbol decode variables
- uint bit_buffer;
- int bits_left, i;
- ushort sym;
- int i_ptr, i_end;
-
uint x, y;
int z;
- lzx.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left);
+ 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++)
@@ -1240,40 +1094,13 @@ namespace LibMSPackSharp.Compression
lzx.PRETREE_len[x] = (byte)y;
}
- //BUILD_TABLE(PRETREE)
- {
- if (!CompressionStream.MakeDecodeTable(LZX_PRETREE_MAXSYMBOLS, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, lzx.PRETREE_table, msb: true))
- {
- Console.WriteLine($"failed to build PRETREE table");
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
- }
- }
+ 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;)
{
- //READ_HUFFSYM(PRETREE, z)
- {
- lzx.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzx.PRETREE_table[lzx.PEEK_BITS_MSB(LZX_PRETREE_TABLEBITS, bit_buffer)];
- if (sym >= LZX_PRETREE_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(PRETREE)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - LZX_PRETREE_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
-
- sym = lzx.PRETREE_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= LZX_PRETREE_MAXSYMBOLS);
- }
- }
-
- (z) = sym;
- i = lzx.PRETREE_len[sym];
- lzx.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
+ 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)
@@ -1302,30 +1129,7 @@ namespace LibMSPackSharp.Compression
{
y = (uint)lzx.READ_BITS_MSB(1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
y += 4;
-
- //READ_HUFFSYM(PRETREE, z)
- {
- lzx.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = lzx.PRETREE_table[lzx.PEEK_BITS_MSB(LZX_PRETREE_TABLEBITS, bit_buffer)];
- if (sym >= LZX_PRETREE_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(PRETREE)
- {
- i = 1 << (CompressionStream.BITBUF_WIDTH - LZX_PRETREE_TABLEBITS);
- do
- {
- if ((i >>= 1) == 0)
- return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
-
- sym = lzx.PRETREE_table[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
- } while (sym >= LZX_PRETREE_MAXSYMBOLS);
- }
- }
-
- (z) = sym;
- i = lzx.PRETREE_len[sym];
- lzx.REMOVE_BITS_MSB(i, ref bit_buffer, ref bits_left);
- }
+ 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)
diff --git a/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs b/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
index bd94147b..3cb656cf 100644
--- a/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
@@ -141,6 +141,9 @@ namespace LibMSPackSharp.Compression
#endregion
+ ///
+ 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)
{
diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
index f3fef598..5ef4e4ec 100644
--- a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
+++ b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
@@ -12,7 +12,6 @@
using System;
using System.IO;
-using static LibMSPackSharp.Compression.Constants;
namespace LibMSPackSharp.Compression
{
@@ -289,7 +288,7 @@ namespace LibMSPackSharp.Compression
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 |= i << 8;
if (block_len == 0)
break;
@@ -514,16 +513,9 @@ namespace LibMSPackSharp.Compression
i_ptr += (int)this_run;
length -= this_run;
- //FLUSH_IF_NEEDED
- {
- if (zip.WindowPosition == MSZIP_FRAME_SIZE)
- {
- if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
- return Error.INF_ERR_FLUSH;
-
- zip.WindowPosition = 0;
- }
- }
+ err = FLUSH_IF_NEEDED(zip);
+ if (err != Error.MSPACK_ERR_OK)
+ return err;
}
}
else if ((block_type == 1) || (block_type == 2))
@@ -582,44 +574,14 @@ namespace LibMSPackSharp.Compression
// Decode forever until end of block code
for (; ; )
{
- //READ_HUFFSYM(LITERAL, code)
- {
- zip.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = zip.LITERAL_table[zip.PEEK_BITS_LSB(MSZIP_LITERAL_TABLEBITS, bit_buffer)];
- if (sym >= MSZIP_LITERAL_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(LITERAL)
- {
- i = MSZIP_LITERAL_TABLEBITS - 1;
- do
- {
- if (i++ > CompressionStream.HUFF_MAXBITS)
- return Error.INF_ERR_HUFFSYM;
-
- sym = zip.LITERAL_table[(sym << 1) | ((bit_buffer >> (int)i) & 1)];
- } while (sym >= MSZIP_LITERAL_MAXSYMBOLS);
- }
- }
-
- (code) = sym;
- i = zip.LITERAL_len[sym];
- zip.REMOVE_BITS_LSB((int)i, ref bit_buffer, ref bits_left);
- }
+ 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);
if (code < 256)
{
zip.Window[zip.WindowPosition++] = (byte)code;
-
- //FLUSH_IF_NEEDED
- {
- if (zip.WindowPosition == MSZIP_FRAME_SIZE)
- {
- if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
- return Error.INF_ERR_FLUSH;
-
- zip.WindowPosition = 0;
- }
- }
+ err = FLUSH_IF_NEEDED(zip);
+ if (err != Error.MSPACK_ERR_OK)
+ return err;
}
else if (code == 256)
{
@@ -635,29 +597,7 @@ namespace LibMSPackSharp.Compression
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];
- //READ_HUFFSYM(DISTANCE, code)
- {
- zip.ENSURE_BITS(CompressionStream.HUFF_MAXBITS, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
- sym = zip.DISTANCE_table[zip.PEEK_BITS_LSB(MSZIP_DISTANCE_TABLEBITS, bit_buffer)];
- if (sym >= MSZIP_DISTANCE_MAXSYMBOLS)
- {
- //HUFF_TRAVERSE(DISTANCE)
- {
- i = MSZIP_DISTANCE_TABLEBITS - 1;
- do
- {
- if (i++ > CompressionStream.HUFF_MAXBITS)
- return Error.INF_ERR_HUFFSYM;
-
- sym = zip.DISTANCE_table[(sym << 1) | ((bit_buffer >> (int)i) & 1)];
- } while (sym >= MSZIP_DISTANCE_MAXSYMBOLS);
- }
- }
-
- (code) = sym;
- i = zip.DISTANCE_len[sym];
- zip.REMOVE_BITS_LSB((int)i, ref bit_buffer, ref bits_left);
- }
+ 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);
if (code >= 30)
return Error.INF_ERR_DISTCODE;
@@ -678,17 +618,9 @@ namespace LibMSPackSharp.Compression
{
zip.Window[zip.WindowPosition++] = zip.Window[match_posn++];
match_posn &= MSZIP_FRAME_SIZE - 1;
-
- //FLUSH_IF_NEEDED
- {
- if (zip.WindowPosition == MSZIP_FRAME_SIZE)
- {
- if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
- return Error.INF_ERR_FLUSH;
-
- zip.WindowPosition = 0;
- }
- }
+ err = FLUSH_IF_NEEDED(zip);
+ if (err != Error.MSPACK_ERR_OK)
+ return err;
}
}
else
@@ -716,16 +648,9 @@ namespace LibMSPackSharp.Compression
if (match_posn == MSZIP_FRAME_SIZE)
match_posn = 0;
- //FLUSH_IF_NEEDED
- {
- if (zip.WindowPosition == MSZIP_FRAME_SIZE)
- {
- if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
- return Error.INF_ERR_FLUSH;
-
- zip.WindowPosition = 0;
- }
- }
+ err = FLUSH_IF_NEEDED(zip);
+ if (err != Error.MSPACK_ERR_OK)
+ return err;
} while (length > 0);
}
@@ -753,6 +678,19 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
+ private static Error FLUSH_IF_NEEDED(MSZIPDStream zip)
+ {
+ if (zip.WindowPosition == MSZIP_FRAME_SIZE)
+ {
+ if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
+ return Error.INF_ERR_FLUSH;
+
+ zip.WindowPosition = 0;
+ }
+
+ return Error.MSPACK_ERR_OK;
+ }
+
///
/// inflate() calls this whenever the window should be flushed. As
/// MSZIP only expands to the size of the window, the implementation used
diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs b/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
index e0c5d12d..52f9b7b9 100644
--- a/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
@@ -53,6 +53,9 @@ namespace LibMSPackSharp.Compression
#endregion
+ ///
+ 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)
{
diff --git a/BurnOutSharp/External/libmspack/Compression/QTM.cs b/BurnOutSharp/External/libmspack/Compression/QTM.cs
index f83ad717..7f1ba42b 100644
--- a/BurnOutSharp/External/libmspack/Compression/QTM.cs
+++ b/BurnOutSharp/External/libmspack/Compression/QTM.cs
@@ -244,58 +244,7 @@ namespace LibMSPackSharp.Compression
while (window_posn < frame_end)
{
- //GET_SYMBOL(qtm.Model7, var)
- {
- range = (uint)((H - L) & 0xFFFF) + 1;
- symf = (ushort)(((((C - L + 1) * qtm.Model7.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
-
- for (i = 1; i < qtm.Model7.Entries; i++)
- {
- if (qtm.Model7.Syms[i].CumulativeFrequency <= symf)
- break;
- }
-
- (selector) = qtm.Model7.Syms[i - 1].Sym;
-
- range = (uint)(H - L) + 1;
- symf = qtm.Model7.Syms[0].CumulativeFrequency;
- H = (ushort)(L + ((qtm.Model7.Syms[i - 1].CumulativeFrequency * range) / symf) - 1);
- L = (ushort)(L + ((qtm.Model7.Syms[i].CumulativeFrequency * range) / symf));
-
- do
- {
- qtm.Model7.Syms[--i].CumulativeFrequency += 8;
- } while (i > 0);
-
- if (qtm.Model7.Syms[0].CumulativeFrequency > 3800)
- UpdateModel(qtm.Model7);
-
- while (true)
- {
- if ((L & 0x8000) != (H & 0x8000))
- {
- if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
- {
- // Underflow case
- C ^= 0x4000;
- L &= 0x3FFF;
- H |= 0x4000;
- }
- else
- {
- break;
- }
- }
-
- 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);
- }
- }
-
+ selector = GET_SYMBOL(qtm, qtm.Model7, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
if (selector < 4)
{
// Literal byte
@@ -320,58 +269,7 @@ namespace LibMSPackSharp.Compression
break;
}
- //GET_SYMBOL(mdl, sym)
- {
- range = (uint)((H - L) & 0xFFFF) + 1;
- symf = (ushort)(((((C - L + 1) * mdl.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
-
- for (i = 1; i < mdl.Entries; i++)
- {
- if (mdl.Syms[i].CumulativeFrequency <= symf)
- break;
- }
-
- (sym) = mdl.Syms[i - 1].Sym;
-
- range = (uint)(H - L) + 1;
- symf = mdl.Syms[0].CumulativeFrequency;
- H = (ushort)(L + ((mdl.Syms[i - 1].CumulativeFrequency * range) / symf) - 1);
- L = (ushort)(L + ((mdl.Syms[i].CumulativeFrequency * range) / symf));
-
- do
- {
- mdl.Syms[--i].CumulativeFrequency += 8;
- } while (i > 0);
-
- if (mdl.Syms[0].CumulativeFrequency > 3800)
- UpdateModel(mdl);
-
- while (true)
- {
- if ((L & 0x8000) != (H & 0x8000))
- {
- if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
- {
- // Underflow case
- C ^= 0x4000;
- L &= 0x3FFF;
- H |= 0x4000;
- }
- else
- {
- break;
- }
- }
-
- 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);
- }
- }
-
+ sym = GET_SYMBOL(qtm, mdl, ref H, ref L, ref C, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
window[window_posn++] = (byte)sym;
frame_todo--;
}
@@ -382,58 +280,7 @@ namespace LibMSPackSharp.Compression
{
// Selector 4 = fixed length match (3 bytes)
case 4:
- //GET_SYMBOL(qtm.Model4, sym)
- {
- range = (uint)((H - L) & 0xFFFF) + 1;
- symf = (ushort)(((((C - L + 1) * qtm.Model4.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
-
- for (i = 1; i < qtm.Model4.Entries; i++)
- {
- if (qtm.Model4.Syms[i].CumulativeFrequency <= symf)
- break;
- }
-
- (sym) = qtm.Model4.Syms[i - 1].Sym;
-
- range = (uint)(H - L) + 1;
- symf = qtm.Model4.Syms[0].CumulativeFrequency;
- H = (ushort)(L + ((qtm.Model4.Syms[i - 1].CumulativeFrequency * range) / symf) - 1);
- L = (ushort)(L + ((qtm.Model4.Syms[i].CumulativeFrequency * range) / symf));
-
- do
- {
- qtm.Model4.Syms[--i].CumulativeFrequency += 8;
- } while (i > 0);
-
- if (qtm.Model4.Syms[0].CumulativeFrequency > 3800)
- UpdateModel(qtm.Model4);
-
- while (true)
- {
- if ((L & 0x8000) != (H & 0x8000))
- {
- if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
- {
- // Underflow case
- C ^= 0x4000;
- L &= 0x3FFF;
- H |= 0x4000;
- }
- else
- {
- break;
- }
- }
-
- 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);
- }
- }
-
+ 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);
match_length = 3;
@@ -441,58 +288,7 @@ namespace LibMSPackSharp.Compression
// Selector 5 = fixed length match (4 bytes)
case 5:
- //GET_SYMBOL(qtm.Model5, sym)
- {
- range = (uint)((H - L) & 0xFFFF) + 1;
- symf = (ushort)(((((C - L + 1) * qtm.Model5.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
-
- for (i = 1; i < qtm.Model5.Entries; i++)
- {
- if (qtm.Model5.Syms[i].CumulativeFrequency <= symf)
- break;
- }
-
- (sym) = qtm.Model5.Syms[i - 1].Sym;
-
- range = (uint)(H - L) + 1;
- symf = qtm.Model5.Syms[0].CumulativeFrequency;
- H = (ushort)(L + ((qtm.Model5.Syms[i - 1].CumulativeFrequency * range) / symf) - 1);
- L = (ushort)(L + ((qtm.Model5.Syms[i].CumulativeFrequency * range) / symf));
-
- do
- {
- qtm.Model5.Syms[--i].CumulativeFrequency += 8;
- } while (i > 0);
-
- if (qtm.Model5.Syms[0].CumulativeFrequency > 3800)
- UpdateModel(qtm.Model5);
-
- while (true)
- {
- if ((L & 0x8000) != (H & 0x8000))
- {
- if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
- {
- // Underflow case
- C ^= 0x4000;
- L &= 0x3FFF;
- H |= 0x4000;
- }
- else
- {
- break;
- }
- }
-
- 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);
- }
- }
-
+ 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);
match_length = 4;
@@ -500,113 +296,11 @@ namespace LibMSPackSharp.Compression
// Selector 6 = variable length match
case 6:
- //GET_SYMBOL(qtm.Model6Len, sym)
- {
- range = (uint)((H - L) & 0xFFFF) + 1;
- symf = (ushort)(((((C - L + 1) * qtm.Model6Len.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
-
- for (i = 1; i < qtm.Model6Len.Entries; i++)
- {
- if (qtm.Model6Len.Syms[i].CumulativeFrequency <= symf)
- break;
- }
-
- (sym) = qtm.Model6Len.Syms[i - 1].Sym;
-
- range = (uint)(H - L) + 1;
- symf = qtm.Model6Len.Syms[0].CumulativeFrequency;
- H = (ushort)(L + ((qtm.Model6Len.Syms[i - 1].CumulativeFrequency * range) / symf) - 1);
- L = (ushort)(L + ((qtm.Model6Len.Syms[i].CumulativeFrequency * range) / symf));
-
- do
- {
- qtm.Model6Len.Syms[--i].CumulativeFrequency += 8;
- } while (i > 0);
-
- if (qtm.Model6Len.Syms[0].CumulativeFrequency > 3800)
- UpdateModel(qtm.Model6Len);
-
- while (true)
- {
- if ((L & 0x8000) != (H & 0x8000))
- {
- if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
- {
- // Underflow case
- C ^= 0x4000;
- L &= 0x3FFF;
- H |= 0x4000;
- }
- else
- {
- break;
- }
- }
-
- 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);
- }
- }
-
+ 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;
- //GET_SYMBOL(qtm.Model6, sym)
- {
- range = (uint)((H - L) & 0xFFFF) + 1;
- symf = (ushort)(((((C - L + 1) * qtm.Model6.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
-
- for (i = 1; i < qtm.Model6.Entries; i++)
- {
- if (qtm.Model6.Syms[i].CumulativeFrequency <= symf)
- break;
- }
-
- (sym) = qtm.Model6.Syms[i - 1].Sym;
-
- range = (uint)(H - L) + 1;
- symf = qtm.Model6.Syms[0].CumulativeFrequency;
- H = (ushort)(L + ((qtm.Model6.Syms[i - 1].CumulativeFrequency * range) / symf) - 1);
- L = (ushort)(L + ((qtm.Model6.Syms[i].CumulativeFrequency * range) / symf));
-
- do
- {
- qtm.Model6.Syms[--i].CumulativeFrequency += 8;
- } while (i > 0);
-
- if (qtm.Model6.Syms[0].CumulativeFrequency > 3800)
- UpdateModel(qtm.Model6);
-
- while (true)
- {
- if ((L & 0x8000) != (H & 0x8000))
- {
- if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
- {
- // Underflow case
- C ^= 0x4000;
- L &= 0x3FFF;
- H |= 0x4000;
- }
- else
- {
- break;
- }
- }
-
- 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);
- }
- }
-
+ 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);
break;
@@ -786,6 +480,61 @@ 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)
+ {
+ uint range = (uint)((H - L) & 0xFFFF) + 1;
+ ushort symf = (ushort)(((((C - L + 1) * model.Syms[0].CumulativeFrequency) - 1) / range) & 0xFFFF);
+
+ int i = 1;
+ for (; i < model.Entries; i++)
+ {
+ if (model.Syms[i].CumulativeFrequency <= symf)
+ break;
+ }
+
+ ushort temp = model.Syms[i - 1].Sym;
+
+ range = (uint)(H - L) + 1;
+ symf = model.Syms[0].CumulativeFrequency;
+ H = (ushort)(L + ((model.Syms[i - 1].CumulativeFrequency * range) / symf) - 1);
+ L = (ushort)(L + ((model.Syms[i].CumulativeFrequency * range) / symf));
+
+ do
+ {
+ model.Syms[--i].CumulativeFrequency += 8;
+ } while (i > 0);
+
+ if (model.Syms[0].CumulativeFrequency > 3800)
+ UpdateModel(model);
+
+ while (true)
+ {
+ if ((L & 0x8000) != (H & 0x8000))
+ {
+ if ((L & 0x4000) != 0 && (H & 0x4000) == 0)
+ {
+ // Underflow case
+ C ^= 0x4000;
+ L &= 0x3FFF;
+ H |= 0x4000;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ 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);
+ }
+
+ return temp;
+ }
+
private static void UpdateModel(QTMDModel model)
{
QTMDModelSym tmp;
diff --git a/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs b/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
index ca8d6e89..dd73b778 100644
--- a/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
+++ b/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
@@ -10,6 +10,8 @@
* For further details, see the file COPYING.LIB distributed with libmspack
*/
+using System;
+
namespace LibMSPackSharp.Compression
{
public class QTMDStream : CompressionStream
@@ -124,6 +126,9 @@ namespace LibMSPackSharp.Compression
#endregion
+ ///
+ 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)
{