mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-09 02:16:46 +00:00
Nearly finish demacroificiation
This commit is contained in:
@@ -17,6 +17,8 @@ namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public abstract class CompressionStream : BaseDecompressState
|
||||
{
|
||||
#region Constants
|
||||
|
||||
/// <summary>
|
||||
/// Number of bits in a character
|
||||
/// </summary>
|
||||
@@ -27,6 +29,13 @@ namespace LibMSPackSharp.Compression
|
||||
/// </summary>
|
||||
public const int BITBUF_WIDTH = 4 * CHAR_BIT;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum bits in a Huffman code
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// This function was originally coded by David Tritscher.
|
||||
@@ -379,6 +388,7 @@ namespace LibMSPackSharp.Compression
|
||||
/// Should be ((1<<nbits) + (nsyms*2)) in length.
|
||||
/// </param>
|
||||
/// <returns>true for OK or false for error</returns>
|
||||
/// <remarks>TODO: Split into MSB and LSB variants</remarks>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Per compression error code for decoding failure
|
||||
/// </summary>
|
||||
public abstract Error HUFF_ERROR();
|
||||
|
||||
#endregion
|
||||
|
||||
#region MSB
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the next huffman symbol from the input bitstream into var.
|
||||
/// Do not use this macro on a table unless build_decode_table() succeeded.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Traverse for a single symbol
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the next huffman symbol from the input bitstream into var.
|
||||
/// Do not use this macro on a table unless build_decode_table() succeeded.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Traverse for a single symbol
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Safely read bits from the buffer
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely read a symbol from a Huffman tree
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a single byte to the output stream
|
||||
/// </summary>
|
||||
public void WRITE_BYTE(int pos)
|
||||
{
|
||||
if (System.Write(OutputFileHandle, Window, pos, 1) != 1)
|
||||
Error = Error.MSPACK_ERR_WRITE;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Error HUFF_ERROR() => Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
|
||||
{
|
||||
|
||||
372
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
372
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
@@ -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)
|
||||
|
||||
@@ -141,6 +141,9 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Error HUFF_ERROR() => Error.MSPACK_ERR_DECRUNCH;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
|
||||
{
|
||||
|
||||
118
BurnOutSharp/External/libmspack/Compression/MSZIP.cs
vendored
118
BurnOutSharp/External/libmspack/Compression/MSZIP.cs
vendored
@@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// inflate() calls this whenever the window should be flushed. As
|
||||
/// MSZIP only expands to the size of the window, the implementation used
|
||||
|
||||
@@ -53,6 +53,9 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Error HUFF_ERROR() => Error.INF_ERR_HUFFSYM;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
|
||||
{
|
||||
|
||||
373
BurnOutSharp/External/libmspack/Compression/QTM.cs
vendored
373
BurnOutSharp/External/libmspack/Compression/QTM.cs
vendored
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Error HUFF_ERROR() => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bit_buffer, ref int bits_left)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user