diff --git a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs index 14746ca9..fff3ad89 100644 --- a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs +++ b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs @@ -19,7 +19,7 @@ namespace LibMSPackSharp.Compression { private const int CHAR_BIT = 8; - private const int BITBUF_WIDTH = 4 * CHAR_BIT; + public const int BITBUF_WIDTH = 4 * CHAR_BIT; /// /// I/O routines @@ -132,150 +132,39 @@ namespace LibMSPackSharp.Compression * to the bit buffer when the bit buffer already has 1 to 15 bits left. */ - public void INIT_BITS() + public void READ_BITS_MSB(ref int val, int nbits, ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer) { - InputPointer = 0; - InputLength = 0; - BitBuffer = 0; - BitsLeft = 0; - InputEnd = 0; - } - - public void STORE_BITS(int inputPointer, int inputLength, uint bit_buffer, int bits_left) - { - InputPointer = inputPointer; - InputLength = inputLength; - BitBuffer = bit_buffer; - BitsLeft = bits_left; - } - - public void RESTORE_BITS(ref int inputPointer, ref int inputLength, ref uint bit_buffer, ref int bits_left) - { - inputPointer = InputPointer; - inputLength = InputLength; - bit_buffer = BitBuffer; - bits_left = BitsLeft; - } - - public void ENSURE_BITS(int nbits, ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - while (bits_left < nbits) + //READ_BITS(val, nbits) { - READ_BYTES(ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb); - if (Error != Error.MSPACK_ERR_OK) - return; - } - - Error = Error.MSPACK_ERR_OK; - } - - public void READ_BITS(ref int val, int nbits, ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb); - if (Error != Error.MSPACK_ERR_OK) - return; - - val = PEEK_BITS(nbits, bit_buffer, msb); - REMOVE_BITS(nbits, ref bits_left, ref bit_buffer, msb); - Error = Error.MSPACK_ERR_OK; - } - - public void READ_MANY_BITS(ref uint val, byte bits, ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - byte needed = bits, bitrun; - val = 0; - while (needed > 0) - { - if (bits_left <= (BITBUF_WIDTH - 16)) + //ENSURE_BITS(nbits) + while (bits_left < (nbits)) { - READ_BYTES(ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb); - if (Error != Error.MSPACK_ERR_OK) - return; + READ_BYTES; } - bitrun = (byte)((bits_left < needed) ? bits_left : needed); - val = (uint)((val << bitrun) | PEEK_BITS(bitrun, bit_buffer, msb)); - REMOVE_BITS(bitrun, ref bits_left, ref bit_buffer, msb); - needed -= bitrun; + val = (int)(bit_buffer >> (BITBUF_WIDTH - (nbits))); + + // REMOVE_BITS(nbits); + bit_buffer <<= (nbits); + bits_left -= (nbits); } - - Error = Error.MSPACK_ERR_OK; } - public int PEEK_BITS(int nbits, uint bit_buffer, bool msb) + public void READ_BITS_LSB(ref int val, int nbits, ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer) { - if (msb) - return (int)(bit_buffer >> (BITBUF_WIDTH - (nbits))); - else - return (int)(bit_buffer & ((1 << (nbits)) - 1)); - } + //READ_BITS(val, nbits) - public void REMOVE_BITS(int nbits, ref int bits_left, ref uint bit_buffer, bool msb) - { - if (msb) + //ENSURE_BITS(nbits) + while (bits_left < nbits) { - bit_buffer <<= nbits; - bits_left -= nbits; - } - else - { - bit_buffer >>= nbits; - bits_left -= nbits; - } - } - - public void INJECT_BITS(uint bitdata, int nbits, ref int bits_left, ref uint bit_buffer, bool msb) - { - if (msb) - { - bit_buffer |= bitdata << (int)bits_left; - bits_left += nbits; - } - else - { - bit_buffer |= bitdata << (int)bits_left; - bits_left += nbits; - } - } - - public abstract void READ_BYTES(ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb); - - // lsb_bit_mask[n] = (1 << n) - 1 */ - private static readonly ushort[] lsb_bit_mask = new ushort[17] - { - 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff - }; - - public int PEEK_BITS_T(int nbits) - { - return (int)(BitBuffer & lsb_bit_mask[nbits]); - } - - public void READ_BITS_T(ref int val, int nbits, ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb); - if (Error != Error.MSPACK_ERR_OK) - return; - - val = PEEK_BITS_T(nbits); - REMOVE_BITS(nbits, ref bits_left, ref bit_buffer, msb); - Error = Error.MSPACK_ERR_OK; - } - - public void READ_IF_NEEDED(ref int i_ptr, ref int i_end) - { - if (i_ptr >= i_end) - { - ReadInput(); - if (Error != Error.MSPACK_ERR_OK) - return; - - i_ptr = InputPointer; - i_end = InputLength; + READ_BYTES; } - Error = Error.MSPACK_ERR_OK; + val = (int)(bit_buffer & ((1 << (nbits)) - 1)); + + //REMOVE_BITS(nbits); + bit_buffer >>= (nbits); + bits_left -= (nbits); } public Error ReadInput() @@ -319,11 +208,22 @@ namespace LibMSPackSharp.Compression /// public int READ_HUFFSYM(ushort[] decodingTable, ref uint var, int tablebits, byte[] lengthTable, int maxsymbols, ref int i, ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) { - ENSURE_BITS(HUFF_MAXBITS, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb); + // ENSURE_BITS(HUFF_MAXBITS) + while (bits_left < HUFF_MAXBITS) + { + READ_BYTES; + } + if (Error != Error.MSPACK_ERR_OK) return (int)Error; - ushort sym = decodingTable[PEEK_BITS(tablebits, bit_buffer, msb)]; + int peek; + if (msb) + peek = (int)(bit_buffer >> (BITBUF_WIDTH - (tablebits))); + else + peek = (int)(bit_buffer & ((1 << (tablebits)) - 1)); + + ushort sym = decodingTable[peek]; if (sym >= maxsymbols) { int ret = HUFF_TRAVERSE(decodingTable, tablebits, maxsymbols, ref i, ref sym, bit_buffer, msb); @@ -333,7 +233,19 @@ namespace LibMSPackSharp.Compression var = sym; i = lengthTable[sym]; - REMOVE_BITS(i, ref bits_left, ref bit_buffer, msb); + + // REMOVE_BITS(i); + if (msb) + { + bit_buffer <<= i; + bits_left -= i; + } + else + { + bit_buffer >>= i; + bits_left -= i; + } + return (int)Error.MSPACK_ERR_OK; } diff --git a/BurnOutSharp/External/libmspack/Compression/LZSS.cs b/BurnOutSharp/External/libmspack/Compression/LZSS.cs index a0573af3..082d6075 100644 --- a/BurnOutSharp/External/libmspack/Compression/LZSS.cs +++ b/BurnOutSharp/External/libmspack/Compression/LZSS.cs @@ -56,115 +56,116 @@ namespace LibMSPackSharp.Compression /// /// one of LZSSMode values /// an error code, or MSPACK_ERR_OK if successful - public static Error Decompress(SystemImpl system, FileStream input, FileStream output, int inputBufferSize, LZSSMode mode) + public static Error Decompress(SystemImpl system, FileStream input, FileStream output, int input_buffer_size, LZSSMode mode) { - uint i, c, mpos, len; - int read; - // Check parameters - if (system == null - || inputBufferSize < 1 - || (mode != LZSSMode.LZSS_MODE_EXPAND && mode != LZSSMode.LZSS_MODE_MSHELP && mode != LZSSMode.LZSS_MODE_QBASIC)) - { + if (system == null || input_buffer_size < 1 || (mode != LZSSMode.LZSS_MODE_EXPAND && mode != LZSSMode.LZSS_MODE_MSHELP && mode != LZSSMode.LZSS_MODE_QBASIC)) return Error.MSPACK_ERR_ARGS; - } // Allocate memory - byte[] window = new byte[LZSS_WINDOW_SIZE + inputBufferSize]; + byte[] window = new byte[LZSS_WINDOW_SIZE + input_buffer_size]; // Initialise decompression int inbuf = LZSS_WINDOW_SIZE; - for (i = 0; i < LZSS_WINDOW_SIZE; i++) + for (int j = inbuf; j < window.Length; j++) { - window[i] = LZSS_WINDOW_FILL; + window[j] = LZSS_WINDOW_FILL; } uint pos = LZSS_WINDOW_SIZE - (uint)((mode == LZSSMode.LZSS_MODE_QBASIC) ? 18 : 16); uint invert = (uint)((mode == LZSSMode.LZSS_MODE_MSHELP) ? ~0 : 0); - int i_ptr = 0, i_end = 0; + int i_ptr = 0, i_end = 0, read; // Loop forever; exit condition is in ENSURE_BYTES macro for (; ; ) { //ENSURE_BYTES - if (i_ptr >= i_end) { - read = system.Read(input, window, inbuf, inputBufferSize); - if (read <= 0) - return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; + if (i_ptr >= i_end) + { + read = input.Read(window, inbuf, input_buffer_size); + if (read <= 0) + return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; - i_ptr = 0; - i_end = read; + i_ptr = inbuf; + i_end = read; + } } - c = window[i_ptr++] ^ invert; - for (i = 0x01; (i & 0xFF) != 0; i <<= 1) + uint c = window[i_ptr++] ^ invert; + for (uint i = 0x01; (i & 0xFF) != 0; i <<= 1) { + // Literal if (c != 0 & i != 0) { - // Literal //ENSURE_BYTES - if (i_ptr >= i_end) { - read = system.Read(input, window, inbuf, inputBufferSize); - if (read <= 0) - return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; + if (i_ptr >= i_end) + { + read = input.Read(window, inbuf, input_buffer_size); + if (read <= 0) + return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; - i_ptr = 0; - i_end = read; + i_ptr = inbuf; + i_end = read; + } } window[pos] = window[i_ptr++]; - //ENSURE_BYTES - if (i_ptr >= i_end) + //WRITE_BYTE { - read = system.Read(input, window, inbuf, inputBufferSize); - if (read <= 0) - return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; - - i_ptr = 0; - i_end = read; + try { output.Write(window, (int)pos, 1); } + catch { return Error.MSPACK_ERR_WRITE; } } - pos++; pos &= LZSS_WINDOW_SIZE - 1; + pos++; + pos &= LZSS_WINDOW_SIZE - 1; } + + // Match else { - // Match //ENSURE_BYTES - if (i_ptr >= i_end) { - read = system.Read(input, window, inbuf, inputBufferSize); - if (read <= 0) - return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; + if (i_ptr >= i_end) + { + read = input.Read(window, inbuf, input_buffer_size); + if (read <= 0) + return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; - i_ptr = 0; - i_end = read; + i_ptr = inbuf; + i_end = read; + } } - mpos = window[i_ptr++]; + uint mpos = window[i_ptr++]; //ENSURE_BYTES - if (i_ptr >= i_end) { - read = system.Read(input, window, inbuf, inputBufferSize); - if (read <= 0) - return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; + if (i_ptr >= i_end) + { + read = input.Read(window, inbuf, input_buffer_size); + if (read <= 0) + return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK; - i_ptr = 0; - i_end = read; + i_ptr = inbuf; + i_end = read; + } } mpos |= (uint)(window[i_ptr] & 0xF0) << 4; - len = (uint)(window[i_ptr++] & 0x0F) + 3; + uint len = (uint)(window[i_ptr++] & 0x0F) + 3; + while (len-- != 0) { window[pos] = window[mpos]; - //WRITE_BYTE; - if (system.Write(output, window, (int)pos, 1) != 1) - return Error.MSPACK_ERR_WRITE; + //WRITE_BYTE + { + try { output.Write(window, (int)pos, 1); } + catch { return Error.MSPACK_ERR_WRITE; } + } pos++; pos &= LZSS_WINDOW_SIZE - 1; @@ -174,6 +175,9 @@ namespace LibMSPackSharp.Compression } } } + + /* not reached */ + return Error.MSPACK_ERR_OK; } } } diff --git a/BurnOutSharp/External/libmspack/Compression/LZX.cs b/BurnOutSharp/External/libmspack/Compression/LZX.cs index 07c3ad16..05e54e96 100644 --- a/BurnOutSharp/External/libmspack/Compression/LZX.cs +++ b/BurnOutSharp/External/libmspack/Compression/LZX.cs @@ -268,74 +268,81 @@ namespace LibMSPackSharp.Compression /// a pointer to an initialised LZXDStream structure, or null if /// there was not enough memory or parameters to the function were wrong. /// - public static LZXDStream Init(SystemImpl system, FileStream input, FileStream output, int windowBits, int resetInterval, int inputBufferSize, long outputLength, bool isDelta) + public static LZXDStream Init(SystemImpl system, FileStream input, FileStream output, int window_bits, int reset_interval, int input_buffer_size, long output_length, bool is_delta) { - uint windowSize = (uint)(1 << windowBits); + uint window_size = (uint)(1 << window_bits); + LZXDStream lzx; - if (system == null) return null; + if (system == null) + return null; // LZX DELTA window sizes are between 2^17 (128KiB) and 2^25 (32MiB), // regular LZX windows are between 2^15 (32KiB) and 2^21 (2MiB) - if (isDelta) + if (is_delta) { - if (windowBits < 17 || windowBits > 25) + if (window_bits < 17 || window_bits > 25) return null; } else { - if (windowBits < 15 || windowBits > 21) + if (window_bits < 15 || window_bits > 21) return null; } - if (resetInterval < 0 || outputLength < 0) + if (reset_interval < 0 || output_length < 0) { - Console.WriteLine("reset interval or output length < 0"); + Console.WriteLine("Reset interval or output length < 0"); return null; } // Round up input buffer size to multiple of two - inputBufferSize = (inputBufferSize + 1) & -2; - if (inputBufferSize < 2) + input_buffer_size = (input_buffer_size + 1) & -2; + if (input_buffer_size < 2) return null; // Allocate decompression state - LZXDStream lzx = new LZXDStream(); + lzx = new LZXDStream() + { + // Allocate decompression window and input buffer + Window = new byte[window_size], + InputBuffer = new byte[input_buffer_size], - // Allocate decompression window and input buffer - lzx.Window = new byte[windowSize]; - lzx.InputBuffer = new byte[inputBufferSize]; + Sys = system, + Input = input, + Output = output, + Offset = 0, + Length = output_length, - // Initialise decompression state - lzx.Sys = system; - lzx.Input = input; - lzx.Output = output; - lzx.Offset = 0; - lzx.Length = outputLength; + InputBufferSize = (uint)input_buffer_size, + WindowSize = (uint)(1 << window_bits), + ReferenceDataSize = 0, + WindowPosition = 0, + FramePosition = 0, + Frame = 0, + ResetInterval = (uint)reset_interval, + IntelFileSize = 0, + IntelStarted = false, + Error = Error.MSPACK_ERR_OK, + NumOffsets = position_slots[window_bits - 15] << 3, + IsDelta = is_delta, - lzx.InputBufferSize = (uint)inputBufferSize; - lzx.WindowSize = (uint)(1 << windowBits); - lzx.ReferenceDataSize = 0; - lzx.WindowPosition = 0; - lzx.FramePosition = 0; - lzx.Frame = 0; - lzx.ResetInterval = (uint)resetInterval; - lzx.IntelFileSize = 0; - lzx.IntelStarted = false; - lzx.Error = Error.MSPACK_ERR_OK; - lzx.NumOffsets = position_slots[windowBits - 15] << 3; - lzx.IsDelta = isDelta; + // e8_buf + OutputPointer = 0, + OutputLength = 0, + }; - lzx.OutputPointer = lzx.OutputLength = 0; ResetState(lzx); - lzx.INIT_BITS(); - return lzx; - } - // See description of outputLength in lzxd_init() - public static void SetOutputLength(LZXDStream lzx, long outputLength) - { - if (lzx != null && outputLength > 0) - lzx.Length = outputLength; + //INIT_BITS + { + lzx.InputPointer = 0; + lzx.InputLength = 0; + lzx.BitBuffer = 0; + lzx.BitsLeft = 0; + lzx.InputEnd = 0; + } + + return lzx; } /// @@ -362,25 +369,25 @@ namespace LibMSPackSharp.Compression if (!lzx.IsDelta) { - Console.WriteLine("only LZX DELTA streams support reference data"); + Console.WriteLine("Only LZX DELTA streams support reference data"); return Error.MSPACK_ERR_ARGS; } if (lzx.Offset != 0) { - Console.WriteLine("too late to set reference data after decoding starts"); + Console.WriteLine("Too late to set reference data after decoding starts"); return Error.MSPACK_ERR_ARGS; } if (length > lzx.WindowSize) { - Console.WriteLine($"reference length ({length}) is longer than the window"); + Console.WriteLine($"Reference length ({length}) is longer than the window"); return Error.MSPACK_ERR_ARGS; } if (length > 0 && (system == null || input == null)) { - Console.WriteLine("length > 0 but no system or input"); + Console.WriteLine("Length > 0 but no system or input"); return Error.MSPACK_ERR_ARGS; } @@ -391,7 +398,7 @@ namespace LibMSPackSharp.Compression int pos = (int)(lzx.WindowSize - length); int bytes = system.Read(input, lzx.Window, pos, (int)length); - // length can't be more than 2^25, so no signedness problem + // Length can't be more than 2^25, so no signedness problem if (bytes < (int)length) return Error.MSPACK_ERR_READ; } @@ -400,6 +407,13 @@ namespace LibMSPackSharp.Compression return Error.MSPACK_ERR_OK; } + // See description of outputLength in lzxd_init() + public static void SetOutputLength(LZXDStream lzx, long outputLength) + { + if (lzx != null && outputLength > 0) + lzx.Length = outputLength; + } + /// /// Decompresses entire or partial LZX streams. /// @@ -422,60 +436,71 @@ namespace LibMSPackSharp.Compression /// should be considered unusable and lzxd_decompress() should not be /// called again on this stream. /// - /// LZX decompression state, as allocated by lzxd_init(). - /// the number of bytes of data to decompress. + /// LZX decompression state, as allocated by lzxd_init(). + /// the number of bytes of data to decompress. /// an error code, or MSPACK_ERR_OK if successful - public static Error Decompress(object o, long outBytes) + // TODO: Huffman tree implementation + public static Error Decompress(object o, long out_bytes) { LZXDStream lzx = o as LZXDStream; if (lzx == null) return Error.MSPACK_ERR_ARGS; // Bitstream and huffman reading variables - uint bit_buffer = 0; - int bits_left = 0; - int i_ptr = 0, i_end = 0; + uint bit_buffer; + int bits_left, i = 0; + int i_ptr, i_end; + ushort sym; - int match_length, extra, verbatim_bits = 0, bytes_todo; - int this_run, j = 0, warned = 0; - uint main_element = 0, length_footer = 0, aligned_bits = 0; + int match_length, length_footer, extra, verbatim_bits, bytes_todo; + int this_run, main_element, aligned_bits, j, warned = 0; byte[] window, buf = new byte[12]; int runsrc, rundest; uint frame_size = 0, end_frame, match_offset, window_posn; uint R0, R1, R2; // Easy answers - if (lzx == null || (outBytes < 0)) + if (lzx == null || (out_bytes < 0)) return Error.MSPACK_ERR_ARGS; if (lzx.Error != Error.MSPACK_ERR_OK) return lzx.Error; // Flush out any stored-up bytes before we begin - int i = lzx.OutputLength - lzx.OutputPointer; - if (i > outBytes) - i = (int)outBytes; + i = lzx.OutputLength - lzx.OutputPointer; + if (i > out_bytes) + i = (int)out_bytes; if (i != 0) { - if (lzx.Sys.Write(lzx.Output, lzx.e8_buf, lzx.OutputPointer, i) != i) - return lzx.Error = Error.MSPACK_ERR_WRITE; + try { lzx.Output.Write(lzx.e8_buf, lzx.OutputPointer, i); } + catch { return lzx.Error = Error.MSPACK_ERR_WRITE; } lzx.OutputPointer += i; lzx.Offset += i; - outBytes -= i; + out_bytes -= i; } - if (outBytes == 0) return Error.MSPACK_ERR_OK; + + if (out_bytes == 0) + return Error.MSPACK_ERR_OK; // Restore local state - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + + //RESTORE_BITS + { + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + bit_buffer = lzx.BitBuffer; + bits_left = lzx.BitsLeft; + } + window = lzx.Window; window_posn = lzx.WindowPosition; R0 = lzx.R0; R1 = lzx.R1; R2 = lzx.R2; - end_frame = (uint)((lzx.Offset + outBytes) / LZX_FRAME_SIZE) + 1; + end_frame = (uint)((lzx.Offset + out_bytes) / LZX_FRAME_SIZE) + 1; while (lzx.Frame < end_frame) { @@ -485,7 +510,7 @@ namespace LibMSPackSharp.Compression if (lzx.BlockRemaining != 0) { // This is a file format error, we can make a best effort to extract what we can - Console.WriteLine("%d bytes remaining at reset interval", lzx.BlockRemaining); + Console.WriteLine($"{lzx.BlockRemaining} bytes remaining at reset interval"); if (warned == 0) { lzx.Sys.Message(null, "WARNING; invalid reset interval detected during LZX decompression"); @@ -503,32 +528,226 @@ namespace LibMSPackSharp.Compression // LZX DELTA format has chunk_size, not present in LZX format if (lzx.IsDelta) { - lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //ENSURE_BITS(16) + { + while (bits_left < (16)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; - lzx.REMOVE_BITS(16, ref bits_left, ref bit_buffer, msb: true); + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + //REMOVE_BITS(16) + { + bit_buffer <<= (16); + bits_left -= (16); + } } // Read header if necessary if (lzx.HeaderRead == 0) { - /* read 1 bit. if bit=0, intel filesize = 0. - * if bit=1, read intel filesize (32 bits) */ + // Read 1 bit. if bit=0, intel filesize = 0. + // if bit=1, read intel filesize (32 bits) j = 0; - lzx.READ_BITS(ref i, 1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + + //READ_BITS(i, 1) + { + //ENSURE_BITS(1) + { + while (bits_left < (1)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (i) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (1))); //PEEK_BITS(1) + + //REMOVE_BITS(1) + { + bit_buffer <<= (1); + bits_left -= (1); + } + } if (i != 0) { - lzx.READ_BITS(ref i, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(i, 16) + { + //ENSURE_BITS(16) + { + while (bits_left < (16)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; - lzx.READ_BITS(ref j, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (i) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (16))); //PEEK_BITS(16) + + //REMOVE_BITS(16) + { + bit_buffer <<= (16); + bits_left -= (16); + } + } + + //READ_BITS(j, 16) + { + //ENSURE_BITS(16) + { + while (bits_left < (16)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (j) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (16))); //PEEK_BITS(16) + + //REMOVE_BITS(16) + { + bit_buffer <<= (16); + bits_left -= (16); + } + } } lzx.IntelFileSize = (i << 16) | j; @@ -552,154 +771,282 @@ namespace LibMSPackSharp.Compression // Realign if previous block was an odd-sized UNCOMPRESSED block if ((lzx.BlockType == LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED) && (lzx.BlockLength & 1) != 0) { - lzx.READ_IF_NEEDED(ref i_ptr, ref i_end); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } i_ptr++; } // Read block type (3 bits) and block length (24 bits) - int blockType = 0; - lzx.READ_BITS(ref blockType, 3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; - lzx.BlockType = (LZXBlockType)blockType; - lzx.READ_BITS(ref i, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(lzx.BlockType, 3) + { + //ENSURE_BITS(3) + { + while (bits_left < (3)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; - lzx.READ_BITS(ref j, 8, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + }; + } + } + + (lzx.BlockType) = (LZXBlockType)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (3))); //PEEK_BITS(3) + + //REMOVE_BITS(3) + { + bit_buffer <<= (3); + bits_left -= (3); + } + } + + //READ_BITS(i, 16) + { + //ENSURE_BITS(16) + { + while (bits_left < (16)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (i) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (16))); //PEEK_BITS(16) + + //REMOVE_BITS(16) + { + bit_buffer <<= (16); + bits_left -= (16); + } + } + + //READ_BITS(j, 8) + { + //ENSURE_BITS(8) + { + while (bits_left < (8)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (j) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (8))); //PEEK_BITS(8) + + //REMOVE_BITS(8) + { + bit_buffer <<= (8); + bits_left -= (8); + } + } lzx.BlockRemaining = lzx.BlockLength = (uint)((i << 8) | j); - // Console.WriteLine("new block t%d len %u", lzx.BlockType, lzx.BlockLength); + // Console.WriteLine($"New block t{lzx.BlockType} len {lzx.BlockLength}"); // Read individual block headers switch (lzx.BlockType) { - // Read lengths of and build aligned huffman decoding tree case LZXBlockType.LZX_BLOCKTYPE_ALIGNED: + // Read lengths of and build aligned huffman decoding tree for (i = 0; i < 8; i++) { - lzx.READ_BITS(ref j, 3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(j, 3) + { + //ENSURE_BITS(3) + { + while (bits_left < (3)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + }; + } + } + + (j) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (3))); //PEEK_BITS(3) + + //REMOVE_BITS(3) + { + bit_buffer <<= (3); + bits_left -= (3); + } + } lzx.ALIGNED_len[i] = (byte)j; } - //BUILD_TABLE(ALIGNED) - if (!LZXDStream.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(ALIGNED); // Read lengths of and build main huffman decoding tree - - //READ_LENGTHS(tbl, first, last) - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); - if (ReadLens(lzx, lzx.MAINTREE_len, 0, 256) != 0) - return lzx.Error; - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - - //READ_LENGTHS(tbl, first, last) - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); - if (ReadLens(lzx, lzx.MAINTREE_len, 256, LZX_NUM_CHARS + lzx.NumOffsets) != 0) - return lzx.Error; - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - - //BUILD_TABLE(MAINTREE) - if (!LZXDStream.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; - } + READ_LENGTHS(MAINTREE, 0, 256); + READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + lzx.NumOffsets); + BUILD_TABLE(MAINTREE); // 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(tbl, first, last) - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); - if (ReadLens(lzx, lzx.LENGTH_len, 0, LZX_NUM_SECONDARY_LENGTHS) != 0) - return lzx.Error; - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - - //BUILD_TABLE_MAYBE_EMPTY(LENGTH) - lzx.LENGTH_empty = 0; - if (!LZXDStream.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 LENGTH table"); - return lzx.Error = Error.MSPACK_ERR_DECRUNCH; - } - } - - // Empty tree - allow it, but don't decode symbols with it - lzx.LENGTH_empty = 1; - } + READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS); + BUILD_TABLE_MAYBE_EMPTY(LENGTH); break; case LZXBlockType.LZX_BLOCKTYPE_VERBATIM: // Read lengths of and build main huffman decoding tree - - //READ_LENGTHS(tbl, first, last) - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); - if (ReadLens(lzx, lzx.MAINTREE_len, 0, 256) != 0) - return lzx.Error; - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - - //READ_LENGTHS(tbl, first, last) - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); - if (ReadLens(lzx, lzx.MAINTREE_len, 256, LZX_NUM_CHARS + lzx.NumOffsets) != 0) - return lzx.Error; - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - - //BUILD_TABLE(MAINTREE) - if (!LZXDStream.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; - } + READ_LENGTHS(MAINTREE, 0, 256); + READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + lzx.NumOffsets); + BUILD_TABLE(MAINTREE); // 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(tbl, first, last) - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); - if (ReadLens(lzx, lzx.LENGTH_len, 0, LZX_NUM_SECONDARY_LENGTHS) != 0) - return lzx.Error; - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - - //BUILD_TABLE_MAYBE_EMPTY(LENGTH) - lzx.LENGTH_empty = 0; - if (!LZXDStream.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 LENGTH table"); - return lzx.Error = Error.MSPACK_ERR_DECRUNCH; - } - } - - // Empty tree - allow it, but don't decode symbols with it - lzx.LENGTH_empty = 1; - } + READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS); + BUILD_TABLE_MAYBE_EMPTY(LENGTH); break; @@ -710,9 +1057,48 @@ namespace LibMSPackSharp.Compression // Read 1-16 (not 0-15) bits to align to bytes if (bits_left == 0) { - lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //ENSURE_BITS(16) + { + while (bits_left < (16)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } } bits_left = 0; bit_buffer = 0; @@ -720,9 +1106,17 @@ namespace LibMSPackSharp.Compression // Read 12 bytes of stored R0 / R1 / R2 values for (rundest = 0, i = 0; i < 12; i++) { - lzx.READ_IF_NEEDED(ref i_ptr, ref i_end); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } buf[rundest++] = lzx.InputBuffer[i_ptr++]; } @@ -734,12 +1128,12 @@ namespace LibMSPackSharp.Compression break; default: - Console.WriteLine("bad block type"); + Console.WriteLine("Bad block type"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } } - // decode more of the block: + // Decode more of the block: // run = min(what's available, what's needed) this_run = (int)lzx.BlockRemaining; if (this_run > bytes_todo) @@ -756,8 +1150,7 @@ namespace LibMSPackSharp.Compression case LZXBlockType.LZX_BLOCKTYPE_VERBATIM: while (this_run > 0) { - if (lzx.READ_HUFFSYM(lzx.MAINTREE_table, ref main_element, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, LZX_MAINTREE_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0) - return Error.MSPACK_ERR_DECRUNCH; + READ_HUFFSYM(MAINTREE, main_element); if (main_element < LZX_NUM_CHARS) { @@ -771,7 +1164,7 @@ namespace LibMSPackSharp.Compression main_element -= LZX_NUM_CHARS; // Get match length - match_length = (int)(main_element & LZX_NUM_PRIMARY_LENGTHS); + match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; if (match_length == LZX_NUM_PRIMARY_LENGTHS) { if (lzx.LENGTH_empty != 0) @@ -780,10 +1173,9 @@ namespace LibMSPackSharp.Compression return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } - if (lzx.READ_HUFFSYM(lzx.LENGTH_table, ref length_footer, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, LZX_LENGTH_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0) - return Error.MSPACK_ERR_DECRUNCH; + READ_HUFFSYM(LENGTH, length_footer); - match_length += (int)length_footer; + match_length += length_footer; } match_length += LZX_MIN_MATCH; @@ -791,9 +1183,22 @@ namespace LibMSPackSharp.Compression // Get match offset switch ((match_offset = (uint)(main_element >> 3))) { - case 0: match_offset = R0; break; - case 1: match_offset = R1; R1 = R0; R0 = match_offset; break; - case 2: match_offset = R2; R2 = R0; R0 = match_offset; break; + case 0: + match_offset = R0; + break; + + case 1: + match_offset = R1; + R1 = R0; + R0 = match_offset; + break; + + case 2: + match_offset = R2; + R2 = R0; + R0 = match_offset; + break; + default: if (lzx.BlockType == LZXBlockType.LZX_BLOCKTYPE_VERBATIM) { @@ -804,9 +1209,60 @@ namespace LibMSPackSharp.Compression else { extra = (match_offset >= 36) ? 17 : extra_bits[match_offset]; - lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + + //READ_BITS(verbatim_bits, extra) + { + //ENSURE_BITS(extra) + { + while (bits_left < (extra)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (verbatim_bits) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (extra))); //PEEK_BITS(extra) + + //REMOVE_BITS(extra) + { + bit_buffer <<= (extra); + bits_left -= (extra); + } + } match_offset = (uint)(position_base[match_offset] - 2 + verbatim_bits); } @@ -817,40 +1273,144 @@ namespace LibMSPackSharp.Compression { extra = (match_offset >= 36) ? 17 : extra_bits[match_offset]; match_offset = position_base[match_offset] - 2; + + // >3: verbatim and aligned bits if (extra > 3) { - // >3: verbatim and aligned bits extra -= 3; - lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + + //READ_BITS(verbatim_bits, extra) + { + //ENSURE_BITS(extra) + { + while (bits_left < (extra)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (verbatim_bits) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (extra))); //PEEK_BITS(extra) + + //REMOVE_BITS(extra) + { + bit_buffer <<= (extra); + bits_left -= (extra); + } + } match_offset += (uint)(verbatim_bits << 3); - if (lzx.READ_HUFFSYM(lzx.ALIGNED_table, ref aligned_bits, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, LZX_ALIGNED_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0) - return Error.MSPACK_ERR_DECRUNCH; - match_offset += aligned_bits; + READ_HUFFSYM(ALIGNED, aligned_bits); + + match_offset += (uint)aligned_bits; } + + // 3: aligned bits only else if (extra == 3) { - // 3: aligned bits only - if (lzx.READ_HUFFSYM(lzx.ALIGNED_table, ref aligned_bits, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, LZX_ALIGNED_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0) - return Error.MSPACK_ERR_DECRUNCH; + READ_HUFFSYM(ALIGNED, aligned_bits); - match_offset += aligned_bits; + match_offset += (uint)aligned_bits; } + + // 1-2: verbatim bits only else if (extra > 0) { - // 1-2: verbatim bits only - lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(verbatim_bits, extra) + { + //ENSURE_BITS(extra) + { + while (bits_left < (extra)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (verbatim_bits) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (extra))); //PEEK_BITS(extra) + + //REMOVE_BITS(extra) + { + bit_buffer <<= (extra); + bits_left -= (extra); + } + } match_offset += (uint)verbatim_bits; } + + // 0: not defined in LZX specification! else { - // 0: not defined in LZX specification! match_offset = 1; } } @@ -865,42 +1425,309 @@ namespace LibMSPackSharp.Compression { int extra_len = 0; - /* 4 entry huffman tree */ - lzx.ENSURE_BITS(3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + // 4 entry huffman tree - if (lzx.PEEK_BITS(1, bit_buffer, msb: true) == 0) + //ENSURE_BITS(3) { - lzx.REMOVE_BITS(1, ref bits_left, ref bit_buffer, msb: true); /* '0' . 8 extra length bits */ - lzx.READ_BITS(ref extra_len, 8, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + while (bits_left < (3)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } } - else if (lzx.PEEK_BITS(2, bit_buffer, msb: true) == 2) + + // '0' . 8 extra length bits + if ((bit_buffer >> (CompressionStream.BITBUF_WIDTH - (1))) == 0) //PEEK_BITS(1) { - lzx.REMOVE_BITS(2, ref bits_left, ref bit_buffer, msb: true); /* '10' . 10 extra length bits + 0x100 */ - lzx.READ_BITS(ref extra_len, 10, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //REMOVE_BITS(1) + { + bit_buffer <<= (1); + bits_left -= (1); + } + + //READ_BITS(extra_len, 8) + { + //ENSURE_BITS(8) + { + while (bits_left < (8)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (extra_len) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (8))); //PEEK_BITS(8) + + //REMOVE_BITS(nbits) + { + bit_buffer <<= (8); + bits_left -= (8); + } + } + } + + // '10' . 10 extra length bits + 0x100 + if ((bit_buffer >> (CompressionStream.BITBUF_WIDTH - (2))) == 2) //PEEK_BITS(2) + { + //REMOVE_BITS(2) + { + bit_buffer <<= (2); + bits_left -= (2); + } + + //READ_BITS(extra_len, 10) + { + //ENSURE_BITS(10) + { + while (bits_left < (10)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (extra_len) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (10))); //PEEK_BITS(10) + + //REMOVE_BITS(10) + { + bit_buffer <<= (10); + bits_left -= (10); + } + } extra_len += 0x100; } - else if (lzx.PEEK_BITS(3, bit_buffer, msb: true) == 6) + + // '110' . 12 extra length bits + 0x500 + if ((bit_buffer >> (CompressionStream.BITBUF_WIDTH - (3))) == 6) //PEEK_BITS(3) { - lzx.REMOVE_BITS(3, ref bits_left, ref bit_buffer, msb: true); /* '110' . 12 extra length bits + 0x500 */ - lzx.READ_BITS(ref extra_len, 12, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //REMOVE_BITS(3) + { + bit_buffer <<= (3); + bits_left -= (3); + } + + //READ_BITS(extra_len, 12) + { + //ENSURE_BITS(12) + { + while (bits_left < (12)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (extra_len) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (12))); //PEEK_BITS(12) + + //REMOVE_BITS(12) + { + bit_buffer <<= (12); + bits_left -= (12); + } + } extra_len += 0x500; } + + // '111' . 15 extra length bits else { - lzx.REMOVE_BITS(3, ref bits_left, ref bit_buffer, msb: true); /* '111' . 15 extra length bits */ - lzx.READ_BITS(ref extra_len, 15, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //REMOVE_BITS(3) + { + bit_buffer <<= (3); + bits_left -= (3); + } + + //READ_BITS(extra_len, 15) + { + //ENSURE_BITS(15) + { + while (bits_left < (15)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (extra_len) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (15))); //PEEK_BITS(15) + + //REMOVE_BITS(15) + { + bit_buffer <<= (15); + bits_left -= (15); + } + } } match_length += extra_len; @@ -908,7 +1735,7 @@ namespace LibMSPackSharp.Compression if ((window_posn + match_length) > lzx.WindowSize) { - Console.WriteLine("match ran over window wrap"); + Console.WriteLine("Match ran over window wrap"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } @@ -919,25 +1746,24 @@ namespace LibMSPackSharp.Compression // Does match offset wrap the window? if (match_offset > window_posn) { - if (match_offset > lzx.Offset && - (match_offset - window_posn) > lzx.ReferenceDataSize) + if (match_offset > lzx.Offset && (match_offset - window_posn) > lzx.ReferenceDataSize) { - Console.WriteLine("match offset beyond LZX stream"); + Console.WriteLine("Match offset beyond LZX stream"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } - /* j = length from match offset to end of window */ + // j = length from match offset to end of window j = (int)(match_offset - window_posn); if (j > (int)lzx.WindowSize) { - Console.WriteLine("match offset beyond window boundaries"); + Console.WriteLine("Match offset beyond window boundaries"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } runsrc = (int)(lzx.WindowSize - j); if (j < i) { - // if match goes over the window edge, do two copy runs + // If match goes over the window edge, do two copy runs i -= j; while (j-- > 0) { @@ -977,9 +1803,17 @@ namespace LibMSPackSharp.Compression { if ((i = i_end - i_ptr) == 0) { - lzx.READ_IF_NEEDED(ref i_ptr, ref i_end); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } } else { @@ -987,6 +1821,7 @@ namespace LibMSPackSharp.Compression i = this_run; Array.Copy(lzx.InputBuffer, i_ptr, window, rundest, i); + rundest += i; i_ptr += i; this_run -= i; @@ -1003,7 +1838,7 @@ namespace LibMSPackSharp.Compression { if ((uint)(-this_run) > lzx.BlockRemaining) { - Console.WriteLine($"overrun went past end of block by {-this_run} ({lzx.BlockRemaining} remaining)"); + Console.WriteLine($"Overrun went past end of block by {-this_run} ({lzx.BlockRemaining} remaining)"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } @@ -1014,20 +1849,65 @@ namespace LibMSPackSharp.Compression // Streams don't extend over frame boundaries if ((window_posn - lzx.FramePosition) != frame_size) { - Console.WriteLine("decode beyond output frame limits! %d != %d", window_posn - lzx.FramePosition, frame_size); + Console.WriteLine($"Decode beyond output frame limits! {window_posn - lzx.FramePosition} != {frame_size}"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } // Re-align input bitstream if (bits_left > 0) { - lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //ENSURE_BITS(16) + { + while (bits_left < (16)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } } if ((bits_left & 15) != 0) - lzx.REMOVE_BITS((int)(bits_left & 15), ref bits_left, ref bit_buffer, msb: true); + { + //REMOVE_BITS(bits_left & 15) + { + bit_buffer <<= (bits_left & 15); + bits_left -= (bits_left & 15); + } + } // Check that we've used all of the previous frame first if (lzx.OutputPointer != lzx.OutputLength) @@ -1045,8 +1925,9 @@ namespace LibMSPackSharp.Compression int filesize = lzx.IntelFileSize; int abs_off, rel_off; + // Copy e8 block to the e8 buffer and tweak if needed lzx.OutputPointer = data; - Array.Copy(lzx.Window, (int)lzx.FramePosition, lzx.e8_buf, data, (int)frame_size); + Array.Copy(lzx.Window, lzx.FramePosition, lzx.e8_buf, data, frame_size); while (data < dataend) { @@ -1069,22 +1950,28 @@ namespace LibMSPackSharp.Compression data += 4; curpos += 5; } + + lzx.OutputLength = (int)(lzx.OutputPointer + frame_size); + + // Write a frame + i = (int)((out_bytes < frame_size) ? out_bytes : frame_size); + try { lzx.Output.Write(lzx.e8_buf, lzx.OutputPointer, i); } + catch { return lzx.Error = Error.MSPACK_ERR_WRITE; } } else { lzx.OutputPointer = (int)lzx.FramePosition; + lzx.OutputLength = (int)(lzx.OutputPointer + frame_size); + + // Write a frame + i = (int)((out_bytes < frame_size) ? out_bytes : frame_size); + try { lzx.Output.Write(lzx.Window, lzx.OutputPointer, i); } + catch { return lzx.Error = Error.MSPACK_ERR_WRITE; } } - lzx.OutputLength = (int)(lzx.OutputPointer + frame_size); - - // Write a frame - i = (int)((outBytes < frame_size) ? outBytes : frame_size); - if (lzx.Sys.Write(lzx.Output, lzx.Window, lzx.OutputPointer, i) != i) - return lzx.Error = Error.MSPACK_ERR_WRITE; - lzx.OutputPointer += i; lzx.Offset += i; - outBytes -= i; + out_bytes -= i; // Advance frame start position lzx.FramePosition += frame_size; @@ -1098,14 +1985,22 @@ namespace LibMSPackSharp.Compression } - if (outBytes != 0) + if (out_bytes != 0) { - Console.WriteLine("bytes left to output"); + Console.WriteLine("Bytes left to output"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; } // Store local state - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + + //STORE_BITS + { + lzx.InputPointer = i_ptr; + lzx.InputLength = i_end; + lzx.BitBuffer = bit_buffer; + lzx.BitsLeft = bits_left; + } + lzx.WindowPosition = window_posn; lzx.R0 = R0; lzx.R1 = R1; @@ -1114,47 +2009,148 @@ namespace LibMSPackSharp.Compression return Error.MSPACK_ERR_OK; } + // TODO: Huffman tree implementation private static Error ReadLens(LZXDStream lzx, byte[] lens, uint first, uint last) { // Bit buffer and huffman symbol decode variables - uint bit_buffer = 0; - int bits_left = 0; - int i = 0; - int i_ptr = 0, i_end = 0; + uint bit_buffer; + int bits_left, i; + ushort sym; + int i_ptr, i_end; - int x, y = 0; - uint z = 0; + uint x, y; + int z; - lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + //RESTORE_BITS + { + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + bit_buffer = lzx.BitBuffer; + bits_left = lzx.BitsLeft; + } - // Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits) + // Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits) for (x = 0; x < 20; x++) { - lzx.READ_BITS(ref y, 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(y, 4) + { + //ENSURE_BITS(4) + { + while (bits_left < (4)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (y) = (bit_buffer >> (CompressionStream.BITBUF_WIDTH - (4))); //PEEK_BITS(4) + + //REMOVE_BITS(4) + { + bit_buffer <<= (4); + bits_left -= (4); + } + } lzx.PRETREE_len[x] = (byte)y; } - //BUILD_TABLE(PRETREE) - if (!LZXDStream.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(PRETREE); - for (x = (int)first; x < last;) + for (x = first; x < last;) { - if (lzx.READ_HUFFSYM(lzx.PRETREE_table, ref z, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, LZX_PRETREE_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0) - return Error.MSPACK_ERR_OK; + READ_HUFFSYM(PRETREE, z); + // Code = 17, run of ([read 4 bits]+4) zeros if (z == 17) { - // Code = 17, run of ([read 4 bits]+4) zeros - lzx.READ_BITS(ref y, 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(y, 4) + { + //ENSURE_BITS(4) + { + while (bits_left < (4)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (y) = (bit_buffer >> (CompressionStream.BITBUF_WIDTH - (4))); //PEEK_BITS(nbits) + + //REMOVE_BITS(4) + { + bit_buffer <<= (4); + bits_left -= (4); + } + } y += 4; while (y-- != 0) @@ -1162,12 +2158,63 @@ namespace LibMSPackSharp.Compression lens[x++] = 0; } } + + // Code = 18, run of ([read 5 bits]+20) zeros else if (z == 18) { - // Code = 18, run of ([read 5 bits]+20) zeros - lzx.READ_BITS(ref y, 5, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(y, 5) + { + //ENSURE_BITS(5) + { + while (bits_left < (5)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (y) = (bit_buffer >> (CompressionStream.BITBUF_WIDTH - (5))); //PEEK_BITS(5) + + //REMOVE_BITS(5) + { + bit_buffer <<= (5); + bits_left -= (5); + } + } y += 20; while (y-- != 0) @@ -1175,16 +2222,67 @@ namespace LibMSPackSharp.Compression lens[x++] = 0; } } + + // Code = 19, run of ([read 1 bit]+4) [read huffman symbol] else if (z == 19) { - // Code = 19, run of ([read 1 bit]+4) [read huffman symbol] - lzx.READ_BITS(ref y, 1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzx.Error != Error.MSPACK_ERR_OK) - return lzx.Error; + //READ_BITS(y, 1) + { + //ENSURE_BITS(1) + { + while (bits_left < (1)) + { + //READ_BYTES + { + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b0 = lzx.InputBuffer[i_ptr++]; + + //READ_IF_NEEDED + { + if (i_ptr >= i_end) + { + if (lzx.ReadInput() != Error.MSPACK_ERR_OK) + return lzx.Error; + + i_ptr = lzx.InputPointer; + i_end = lzx.InputLength; + } + } + + byte b1 = lzx.InputBuffer[i_ptr++]; + + //INJECT_BITS(bitdata, 16) + { + bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left); + bits_left += (16); + } + } + } + } + + (y) = (bit_buffer >> (CompressionStream.BITBUF_WIDTH - (1))); //PEEK_BITS(1) + + //REMOVE_BITS(1) + { + bit_buffer <<= (1); + bits_left -= (1); + } + } y += 4; - if (lzx.READ_HUFFSYM(lzx.PRETREE_table, ref z, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, LZX_PRETREE_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0) - return Error.MSPACK_ERR_DECRUNCH; + + READ_HUFFSYM(PRETREE, z); z = lens[x] - z; if (z < 0) @@ -1195,9 +2293,10 @@ namespace LibMSPackSharp.Compression lens[x++] = (byte)z; } } + + // Code = 0 to 16, delta current length entry else { - // Code = 0 to 16, delta current length entry z = lens[x] - z; if (z < 0) z += 17; @@ -1206,7 +2305,13 @@ namespace LibMSPackSharp.Compression } } - lzx.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + //STORE_BITS + { + lzx.InputPointer = i_ptr; + lzx.InputLength = i_end; + lzx.BitBuffer = bit_buffer; + lzx.BitsLeft = bits_left; + } return Error.MSPACK_ERR_OK; } diff --git a/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs b/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs index d2914f24..a9edbba9 100644 --- a/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs +++ b/BurnOutSharp/External/libmspack/Compression/LZXDStream.cs @@ -137,23 +137,6 @@ namespace LibMSPackSharp.Compression // This is used purely for doing the intel E8 transform public byte[] e8_buf { get; set; } = new byte[LZX.LZX_FRAME_SIZE]; - public override void READ_BYTES(ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - READ_IF_NEEDED(ref i_ptr, ref i_end); - if (Error != Error.MSPACK_ERR_OK) - return; - - byte b0 = InputBuffer[i_ptr++]; - - READ_IF_NEEDED(ref i_ptr, ref i_end); - if (Error != Error.MSPACK_ERR_OK) - return; - - byte b1 = InputBuffer[i_ptr++]; - INJECT_BITS((uint)((b1 << 8) | b0), 16, ref bits_left, ref bit_buffer, msb); - Error = Error.MSPACK_ERR_OK; - } - public override int HUFF_ERROR() => (int)(Error = Error.MSPACK_ERR_DECRUNCH); } } diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs index 1ef51889..03ff9207 100644 --- a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs +++ b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs @@ -106,26 +106,28 @@ namespace LibMSPackSharp.Compression return null; // Allocate decompression state - MSZIPDStream zip = new MSZIPDStream(); + return new MSZIPDStream + { + // Allocate input buffer + InputBuffer = new byte[input_buffer_size], - // Allocate input buffer - zip.InputBuffer = new byte[input_buffer_size]; + // Initialise decompression state + Sys = system, + Input = input, + Output = output, + InputBufferSize = (uint)input_buffer_size, + InputEnd = 0, + Error = Error.MSPACK_ERR_OK, + RepairMode = repair_mode, + FlushWindow = FlushWindow, - // Initialise decompression state - zip.Sys = system; - zip.Input = input; - zip.Output = output; - zip.InputBufferSize = (uint)input_buffer_size; - zip.InputEnd = 0; - zip.Error = Error.MSPACK_ERR_OK; - zip.RepairMode = repair_mode; - zip.FlushWindow = FlushWindow; - - zip.InputPointer = zip.InputLength = 0; - zip.OutputPointer = zip.OutputLength = 0; - zip.BitBuffer = 0; zip.BitsLeft = 0; - - return zip; + InputPointer = 0, + InputLength = 0, + OutputPointer = 0, + OutputLength = 0, + BitBuffer = 0, + BitsLeft = 0, + }; } /// @@ -195,8 +197,12 @@ namespace LibMSPackSharp.Compression bits_left = zip.BitsLeft; // Skip to next read 'CK' header - i = (int)(bits_left & 7); - bit_buffer >>= (i); bits_left -= (i); //REMOVE_BITS(i); + i = bits_left & 7; + + //REMOVE_BITS(i); + bit_buffer >>= (i); + bits_left -= (i); + state = 0; do @@ -207,7 +213,7 @@ namespace LibMSPackSharp.Compression while (bits_left < 8) { //READ_BYTES; - + //READ_IF_NEEDED; if (i_ptr >= i_end) { @@ -222,7 +228,10 @@ namespace LibMSPackSharp.Compression } i = (int)(bit_buffer & ((1 << (8)) - 1)); //PEEK_BITS(8); - bit_buffer >>= (8); bits_left -= (8); //REMOVE_BITS(8); + + //REMOVE_BITS(8); + bit_buffer >>= (8); + bits_left -= (8); if (i == 'C') state = 1; @@ -244,7 +253,7 @@ namespace LibMSPackSharp.Compression if ((error = (int)Inflate(zip)) != 0) { - Console.WriteLine($"inflate error {(InflateErrorCode)error}"); + Console.WriteLine($"Inflate error {(InflateErrorCode)error}"); if (zip.RepairMode) { // Recover partially-inflated buffers @@ -304,11 +313,11 @@ namespace LibMSPackSharp.Compression public static Error DecompressKWAJ(MSZIPDStream zip) { // For the bit buffer - uint bit_buffer = 0; - int bits_left = 0; - int i_ptr = 0, i_end = 0; + uint bit_buffer; + int bits_left; + int i_ptr, i_end; - int i = 0, error, block_len = 0; + int i, error, block_len; // Unpack blocks until block_len == 0 for (; ; ) @@ -321,7 +330,10 @@ namespace LibMSPackSharp.Compression // Align to bytestream, read block_len i = (int)(bits_left & 7); - bit_buffer >>= (i); bits_left -= (i); //REMOVE_BITS(i); + + //REMOVE_BITS(i); + bit_buffer >>= (i); + bits_left -= (i); //READ_BITS(block_len, 8); @@ -344,9 +356,12 @@ namespace LibMSPackSharp.Compression } block_len = (int)(bit_buffer & ((1 << (8)) - 1)); //PEEK_BITS(8); - bit_buffer >>= (8); bits_left -= (8); //REMOVE_BITS(8); - // READ_BITS(block_len, 8); + //REMOVE_BITS(8); + bit_buffer >>= (8); + bits_left -= (8); + + // READ_BITS(i, 8); //ENSURE_BITS(8); while (bits_left < 8) @@ -367,7 +382,10 @@ namespace LibMSPackSharp.Compression } i = (int)(bit_buffer & ((1 << (8)) - 1)); //PEEK_BITS(8); - bit_buffer >>= (8); bits_left -= (8); //REMOVE_BITS(8); + + //REMOVE_BITS(8); + bit_buffer >>= (8); + bits_left -= (8); block_len |= i << 8; @@ -397,7 +415,10 @@ namespace LibMSPackSharp.Compression } i = (int)(bit_buffer & ((1 << (8)) - 1)); //PEEK_BITS(8); - bit_buffer >>= (8); bits_left -= (8); //REMOVE_BITS(8); + + //REMOVE_BITS(8); + bit_buffer >>= (8); + bits_left -= (8); if (i != 'C') return Error.MSPACK_ERR_DATAFORMAT; @@ -423,7 +444,10 @@ namespace LibMSPackSharp.Compression } i = (int)(bit_buffer & ((1 << (8)) - 1)); //PEEK_BITS(8); - bit_buffer >>= (8); bits_left -= (8); //REMOVE_BITS(8); + + //REMOVE_BITS(8); + bit_buffer >>= (8); + bits_left -= (8); if (i != 'K') return Error.MSPACK_ERR_DATAFORMAT; @@ -475,7 +499,7 @@ namespace LibMSPackSharp.Compression // Read the number of codes // READ_BITS(lit_codes, 5); - + //ENSURE_BITS(5); while (bits_left < 5) { @@ -495,7 +519,10 @@ namespace LibMSPackSharp.Compression } lit_codes = (bit_buffer & ((1 << (5)) - 1)); //PEEK_BITS(5); - bit_buffer >>= (5); bits_left -= (5); //REMOVE_BITS(5); + + //REMOVE_BITS(5); + bit_buffer >>= (5); + bits_left -= (5); lit_codes += 257; @@ -520,7 +547,10 @@ namespace LibMSPackSharp.Compression } dist_codes = (bit_buffer & ((1 << (5)) - 1)); //PEEK_BITS(5); - bit_buffer >>= (5); bits_left -= (5); //REMOVE_BITS(5); + + //REMOVE_BITS(5); + bit_buffer >>= (5); + bits_left -= (5); dist_codes += 1; @@ -545,7 +575,10 @@ namespace LibMSPackSharp.Compression } bitlen_codes = (bit_buffer & ((1 << (8)) - 1)); //PEEK_BITS(4); - bit_buffer >>= (4); bits_left -= (4); //REMOVE_BITS(4); + + //REMOVE_BITS(4); + bit_buffer >>= (4); + bits_left -= (4); bitlen_codes += 4; if (lit_codes > MSZIP_LITERAL_MAXSYMBOLS) @@ -577,7 +610,10 @@ namespace LibMSPackSharp.Compression } bl_len[bitlen_order[i]] = (byte)(bit_buffer & ((1 << (3)) - 1)); //PEEK_BITS(3); - bit_buffer >>= (3); bits_left -= (3); //REMOVE_BITS(3); + + //REMOVE_BITS(3); + bit_buffer >>= (3); + bits_left -= (3); } while (i < 19) @@ -613,7 +649,10 @@ namespace LibMSPackSharp.Compression } code = bl_table[(bit_buffer & ((1 << (7)) - 1))]; //PEEK_BITS(7); - bit_buffer >>= (bl_len[code]); bits_left -= (bl_len[code]); //REMOVE_BITS(bl_len[code]); + + //REMOVE_BITS(bl_len[code]); + bit_buffer >>= (bl_len[code]); + bits_left -= (bl_len[code]); if (code < 16) { @@ -624,84 +663,61 @@ namespace LibMSPackSharp.Compression switch (code) { case 16: - //READ_BITS(run, 2); - - //ENSURE_BITS(2); - while (bits_left < 2) + //READ_BITS(run, 2) { - //READ_BYTES; - - //READ_IF_NEEDED; - if (i_ptr >= i_end) + //ENSURE_BITS(2) + while (bits_left < (2)) { - if (zip.ReadInput() != Error.MSPACK_ERR_OK) - return (InflateErrorCode)zip.Error; - - i_ptr = zip.InputPointer; - i_end = zip.InputLength; + READ_BYTES; } - bit_buffer |= (uint)(zip.InputBuffer[i_ptr++]) << bits_left; bits_left += (8); // INJECT_BITS(zip.InputBuffer[i_ptr++], 8); - } + run = (int)(bit_buffer >> (BITBUF_WIDTH - (2))); - run = (bit_buffer & ((1 << (2)) - 1)); //PEEK_BITS(2); - bit_buffer >>= (2); bits_left -= (2); //REMOVE_BITS(2); + // REMOVE_BITS(2); + bit_buffer <<= (2); + bits_left -= (2); + } run += 3; code = last_code; break; case 17: - //READ_BITS(run, 3); - - //ENSURE_BITS(3); - while (bits_left < 3) + //READ_BITS(run, 3) { - //READ_BYTES; - - //READ_IF_NEEDED; - if (i_ptr >= i_end) + //ENSURE_BITS(3) + while (bits_left < (3)) { - if (zip.ReadInput() != Error.MSPACK_ERR_OK) - return (InflateErrorCode)zip.Error; - - i_ptr = zip.InputPointer; - i_end = zip.InputLength; + READ_BYTES; } - bit_buffer |= (uint)(zip.InputBuffer[i_ptr++]) << bits_left; bits_left += (8); // INJECT_BITS(zip.InputBuffer[i_ptr++], 8); + run = (int)(bit_buffer >> (BITBUF_WIDTH - (3))); + + // REMOVE_BITS(3); + bit_buffer <<= (3); + bits_left -= (3); } - run = (bit_buffer & ((1 << (3)) - 1)); //PEEK_BITS(3); - bit_buffer >>= (3); bits_left -= (3); //REMOVE_BITS(3); run += 3; code = 0; break; case 18: - //READ_BITS(run, 7); - - //ENSURE_BITS(7); - while (bits_left < 7) + //READ_BITS(run, 7) { - //READ_BYTES; - - //READ_IF_NEEDED; - if (i_ptr >= i_end) + //ENSURE_BITS(7) + while (bits_left < (7)) { - if (zip.ReadInput() != Error.MSPACK_ERR_OK) - return (InflateErrorCode)zip.Error; - - i_ptr = zip.InputPointer; - i_end = zip.InputLength; + READ_BYTES; } - bit_buffer |= (uint)(zip.InputBuffer[i_ptr++]) << bits_left; bits_left += (8); // INJECT_BITS(zip.InputBuffer[i_ptr++], 8); - } + run = (int)(bit_buffer >> (BITBUF_WIDTH - (7))); - run = (bit_buffer & ((1 << (7)) - 1)); //PEEK_BITS(7); - bit_buffer >>= (7); bits_left -= (7); //REMOVE_BITS(7); + // REMOVE_BITS(7); + bit_buffer <<= (7); + bits_left -= (7); + } run += 11; code = 0; @@ -771,53 +787,37 @@ namespace LibMSPackSharp.Compression { // Read in last block bit - //READ_BITS(last_block, 1); - - //ENSURE_BITS(1); - while (bits_left < 1) + //READ_BITS(last_block, 1) { - //READ_BYTES; - - //READ_IF_NEEDED; - if (i_ptr >= i_end) + //ENSURE_BITS(1) + while (bits_left < (1)) { - if (zip.ReadInput() != Error.MSPACK_ERR_OK) - return (InflateErrorCode)zip.Error; - - i_ptr = zip.InputPointer; - i_end = zip.InputLength; + READ_BYTES; } - bit_buffer |= (uint)(zip.InputBuffer[i_ptr++]) << bits_left; bits_left += (8); // INJECT_BITS(zip.InputBuffer[i_ptr++], 8); - } + last_block = (int)(bit_buffer >> (BITBUF_WIDTH - (1))); - last_block = (int)(bit_buffer & ((1 << (1)) - 1)); //PEEK_BITS(1); - bit_buffer >>= (1); bits_left -= (1); //REMOVE_BITS(1); + // REMOVE_BITS(1); + bit_buffer <<= (1); + bits_left -= (1); + } // Read in block type - //READ_BITS(block_type, 2); - - //ENSURE_BITS(2); - while (bits_left < 2) + //READ_BITS(block_type, 2) { - //READ_BYTES; - - //READ_IF_NEEDED; - if (i_ptr >= i_end) + //ENSURE_BITS(2) + while (bits_left < (2)) { - if (zip.ReadInput() != Error.MSPACK_ERR_OK) - return (InflateErrorCode)zip.Error; - - i_ptr = zip.InputPointer; - i_end = zip.InputLength; + READ_BYTES; } - bit_buffer |= (uint)(zip.InputBuffer[i_ptr++]) << bits_left; bits_left += (8); // INJECT_BITS(zip.InputBuffer[i_ptr++], 8); - } + block_type = (int)(bit_buffer >> (BITBUF_WIDTH - (2))); - block_type = (int)(bit_buffer & ((1 << (2)) - 1)); //PEEK_BITS(2); - bit_buffer >>= (2); bits_left -= (2); //REMOVE_BITS(2); + // REMOVE_BITS(2); + bit_buffer <<= (2); + bits_left -= (2); + } // Uncompressed block if (block_type == 0) @@ -826,7 +826,10 @@ namespace LibMSPackSharp.Compression // Go to byte boundary i = bits_left & 7; - bit_buffer >>= (i); bits_left -= (i); //REMOVE_BITS(i); + + //REMOVE_BITS(i); + bit_buffer >>= (i); + bits_left -= (i); // Read 4 bytes of data, emptying the bit-buffer if necessary for (i = 0; (bits_left >= 8); i++) @@ -835,7 +838,10 @@ namespace LibMSPackSharp.Compression return InflateErrorCode.INF_ERR_BITBUF; lens_buf[i] = (byte)(bit_buffer & ((1 << (8)) - 1)); //PEEK_BITS(8); - bit_buffer >>= (8); bits_left -= (8); //REMOVE_BITS(8); + + //REMOVE_BITS(8); + bit_buffer >>= (8); + bits_left -= (8); } if (bits_left != 0) @@ -1010,7 +1016,10 @@ namespace LibMSPackSharp.Compression } (length) = (int)(bit_buffer & lsb_bit_mask[(lit_extrabits[code])]); //PEEK_BITS_T(lit_extrabits[code]); - bit_buffer >>= (lit_extrabits[code]); bits_left -= (lit_extrabits[code]); //REMOVE_BITS(lit_extrabits[code]); + + //REMOVE_BITS(lit_extrabits[code]); + bit_buffer >>= (lit_extrabits[code]); + bits_left -= (lit_extrabits[code]); length += lit_lengths[code]; @@ -1041,7 +1050,10 @@ namespace LibMSPackSharp.Compression } (distance) = (int)(bit_buffer & lsb_bit_mask[(dist_extrabits[code])]); //PEEK_BITS_T(dist_extrabits[code]); - bit_buffer >>= (dist_extrabits[code]); bits_left -= (dist_extrabits[code]); //REMOVE_BITS(lit_extrabits[code]); + + //REMOVE_BITS(lit_extrabits[code]); + bit_buffer >>= (dist_extrabits[code]); + bits_left -= (dist_extrabits[code]); distance += dist_offsets[code]; diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs b/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs index b70a6f30..dab87e26 100644 --- a/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs +++ b/BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs @@ -49,16 +49,6 @@ namespace LibMSPackSharp.Compression #endregion - public override void READ_BYTES(ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - READ_IF_NEEDED(ref i_ptr, ref i_end); - if (Error != Error.MSPACK_ERR_OK) - return; - - INJECT_BITS(InputBuffer[i_ptr++], 8, ref bits_left, ref bit_buffer, msb); - Error = Error.MSPACK_ERR_OK; - } - public override int HUFF_ERROR() => (int)InflateErrorCode.INF_ERR_HUFFSYM; } } diff --git a/BurnOutSharp/External/libmspack/Compression/QTM.cs b/BurnOutSharp/External/libmspack/Compression/QTM.cs index dd293685..49e9a67a 100644 --- a/BurnOutSharp/External/libmspack/Compression/QTM.cs +++ b/BurnOutSharp/External/libmspack/Compression/QTM.cs @@ -209,7 +209,13 @@ namespace LibMSPackSharp.Compression return Error.MSPACK_ERR_OK; // Restore local state - qtm.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + + //RESTORE_BITS + i_ptr = qtm.InputPointer; + i_end = qtm.InputLength; + bit_buffer = qtm.BitBuffer; + bits_left = qtm.BitsLeft; + byte[] window = qtm.Window; uint window_posn = qtm.WindowPosition; uint frame_todo = qtm.FrameTODO; @@ -226,9 +232,22 @@ namespace LibMSPackSharp.Compression { high = 0xFFFF; low = 0; - int tempCurrent = current; - qtm.READ_BITS(ref tempCurrent, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - current = (ushort)tempCurrent; + + //READ_BITS(i, 16) + { + //ENSURE_BITS(16) + while (bits_left < (16)) + { + READ_BYTES; + } + + i = (int)(bit_buffer >> (BITBUF_WIDTH - (16))); + + // REMOVE_BITS(16); + bit_buffer <<= (16); + bits_left -= (16); + } + qtm.HeaderRead = 1; } @@ -263,14 +282,35 @@ namespace LibMSPackSharp.Compression else { // Match repeated string + byte needed, bitrun; switch (selector) { // Selector 4 = fixed length match (3 bytes) case 4: GET_SYMBOL(qtm, qtm.Model4, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (qtm.Error != Error.MSPACK_ERR_OK) - return qtm.Error; + + // READ_MANY_BITS(extra, extra_bits[sym]) + needed = extra_bits[sym]; + extra = 0; + while (needed > 0) + { + if (bits_left <= (QTMDStream.BITBUF_WIDTH - 16)) + { + READ_BYTES; + } + + bitrun = (byte)((bits_left < needed) ? bits_left : needed); + + int peek = (int)(bit_buffer >> (QTMDStream.BITBUF_WIDTH - (bitrun))); + + extra = (uint)((extra << bitrun) | peek); + + // REMOVE_BITS(bitrun); + bit_buffer <<= bitrun; + bits_left -= bitrun; + + needed -= bitrun; + } match_offset = position_base[sym] + extra + 1; match_length = 3; @@ -279,9 +319,29 @@ namespace LibMSPackSharp.Compression // Selector 5 = fixed length match (4 bytes) case 5: GET_SYMBOL(qtm, qtm.Model5, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (qtm.Error != Error.MSPACK_ERR_OK) - return qtm.Error; + + // READ_MANY_BITS(extra, extra_bits[sym]) + needed = extra_bits[sym]; + extra = 0; + while (needed > 0) + { + if (bits_left <= (QTMDStream.BITBUF_WIDTH - 16)) + { + READ_BYTES; + } + + bitrun = (byte)((bits_left < needed) ? bits_left : needed); + + int peek = (int)(bit_buffer >> (QTMDStream.BITBUF_WIDTH - (bitrun))); + + extra = (uint)((extra << bitrun) | peek); + + // REMOVE_BITS(bitrun); + bit_buffer <<= bitrun; + bits_left -= bitrun; + + needed -= bitrun; + } match_offset = position_base[sym] + extra + 1; match_length = 4; @@ -290,16 +350,56 @@ namespace LibMSPackSharp.Compression // Selector 6 = variable length match case 6: GET_SYMBOL(qtm, qtm.Model6Len, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - qtm.READ_MANY_BITS(ref extra, length_extra[sym], ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (qtm.Error != Error.MSPACK_ERR_OK) - return qtm.Error; + + // READ_MANY_BITS(extra, length_extra[sym]) + needed = length_extra[sym]; + extra = 0; + while (needed > 0) + { + if (bits_left <= (QTMDStream.BITBUF_WIDTH - 16)) + { + READ_BYTES; + } + + bitrun = (byte)((bits_left < needed) ? bits_left : needed); + + int peek = (int)(bit_buffer >> (QTMDStream.BITBUF_WIDTH - (bitrun))); + + extra = (uint)((extra << bitrun) | peek); + + // REMOVE_BITS(bitrun); + bit_buffer <<= bitrun; + bits_left -= bitrun; + + needed -= bitrun; + } match_length = (int)(length_base[sym] + extra + 5); GET_SYMBOL(qtm, qtm.Model6, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); - qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (qtm.Error != Error.MSPACK_ERR_OK) - return qtm.Error; + + // READ_MANY_BITS(extra, extra_bits[sym]) + needed = extra_bits[sym]; + extra = 0; + while (needed > 0) + { + if (bits_left <= (QTMDStream.BITBUF_WIDTH - 16)) + { + READ_BYTES; + } + + bitrun = (byte)((bits_left < needed) ? bits_left : needed); + + int peek = (int)(bit_buffer >> (QTMDStream.BITBUF_WIDTH - (bitrun))); + + extra = (uint)((extra << bitrun) | peek); + + // REMOVE_BITS(bitrun); + bit_buffer <<= bitrun; + bits_left -= bitrun; + + needed -= bitrun; + } match_offset = position_base[sym] + extra + 1; break; @@ -421,14 +521,31 @@ namespace LibMSPackSharp.Compression { // Re-align input if ((bits_left & 7) != 0) - qtm.REMOVE_BITS(bits_left & 7, ref bits_left, ref bit_buffer, msb: true); + { + //REMOVE_BITS(bits_left & 7); + bit_buffer <<= bits_left & 7; + bits_left -= bits_left & 7; + } // Special Quantum hack -- cabd.c injects a trailer byte to allow the // decompressor to realign itself. CAB Quantum blocks, unlike LZX // blocks, can have anything from 0 to 4 trailing null bytes. */ do { - qtm.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS(i, 8) + { + //ENSURE_BITS(8) + while (bits_left < (8)) + { + READ_BYTES; + } + + i = (int)(bit_buffer >> (BITBUF_WIDTH - (8))); + + // REMOVE_BITS(8); + bit_buffer <<= (8); + bits_left -= (8); + } } while (i != 0xFF); qtm.HeaderRead = 0; @@ -466,7 +583,13 @@ namespace LibMSPackSharp.Compression } // Store local state - qtm.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + + //STORE_BITS + qtm.InputPointer = i_ptr; + qtm.InputLength = i_end; + qtm.BitBuffer = bit_buffer; + qtm.BitsLeft = bits_left; + qtm.WindowPosition = window_posn; qtm.FrameTODO = frame_todo; qtm.High = high; @@ -532,12 +655,20 @@ namespace LibMSPackSharp.Compression low <<= 1; high = (ushort)((high << 1) | 1); - qtm.ENSURE_BITS(1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + // ENSURE_BITS(1) + while (bits_left < 1) + { + READ_BYTES; + } + if (qtm.Error != Error.MSPACK_ERR_OK) return; - current = (ushort)((current << 1) | qtm.PEEK_BITS(1, bit_buffer, msb: true)); - qtm.REMOVE_BITS(1, ref bits_left, ref bit_buffer, msb: true); + current = (ushort)((current << 1) | (bit_buffer >> (LZXDStream.BITBUF_WIDTH - (1)))); //PEEK_BITS(1) + + //REMOVE_BITS(1); + bit_buffer <<= (1); + bits_left -= (1); } } diff --git a/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs b/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs index 09e251e0..6132645b 100644 --- a/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs +++ b/BurnOutSharp/External/libmspack/Compression/QTMDStream.cs @@ -120,23 +120,6 @@ namespace LibMSPackSharp.Compression public QTMDModelSym[] Model7Symbols { get; set; } = new QTMDModelSym[7 + 1]; - public override void READ_BYTES(ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - READ_IF_NEEDED(ref i_ptr, ref i_end); - if (Error != Error.MSPACK_ERR_OK) - return; - - byte b0 = InputBuffer[i_ptr++]; - - READ_IF_NEEDED(ref i_ptr, ref i_end); - if (Error != Error.MSPACK_ERR_OK) - return; - - byte b1 = InputBuffer[i_ptr++]; - INJECT_BITS((uint)((b0 << 8) | b1), 16, ref bits_left, ref bit_buffer, msb); - Error = Error.MSPACK_ERR_OK; - } - public override int HUFF_ERROR() => (int)Error.MSPACK_ERR_OK; } } diff --git a/BurnOutSharp/External/libmspack/KWAJ/Implementation.cs b/BurnOutSharp/External/libmspack/KWAJ/Implementation.cs index d3977439..61597f84 100644 --- a/BurnOutSharp/External/libmspack/KWAJ/Implementation.cs +++ b/BurnOutSharp/External/libmspack/KWAJ/Implementation.cs @@ -417,16 +417,28 @@ namespace LibMSPackSharp.KWAJ private static Error LZHDecompress(InternalStream lzh) { - uint bit_buffer = 0, len = 0, j = 0; - int i, bits_left = 0; - int i_ptr = 0, i_end = 0; + uint bit_buffer, len = 0, j = 0; + int i, bits_left; + int i_ptr, i_end; bool lit_run = false; int pos = 0, offset; int[] types = new int[6]; // Reset global state - lzh.INIT_BITS(); - lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + + //INIT_BITS + lzh.InputPointer = 0; + lzh.InputLength = 0; + lzh.BitBuffer = 0; + lzh.BitsLeft = 0; + lzh.InputEnd = 0; + + //RESTORE_BITS + i_ptr = lzh.InputPointer; + i_end = lzh.InputLength; + bit_buffer = lzh.BitBuffer; + bits_left = lzh.BitsLeft; + for (i = 0; i < LZSS.LZSS_WINDOW_SIZE; i++) { lzh.Window[i] = LZSS.LZSS_WINDOW_FILL; @@ -435,10 +447,23 @@ namespace LibMSPackSharp.KWAJ // Read 6 encoding types (for byte alignment) but only 5 are needed for (i = 0; i < 6; i++) { - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref types[i], 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzh.Error != Error.MSPACK_ERR_OK) - return lzh.Error; + //READ_BITS_SAFE(types[i], 4) + + //READ_BITS(types[i], 4) + { + //ENSURE_BITS(nbits) + while (bits_left < (4)) + { + READ_BYTES; + } + + types[i] = (int)(bit_buffer >> (BITBUF_WIDTH - (4))); + + // REMOVE_BITS(4); + bit_buffer <<= (4); + bits_left -= (4); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; } @@ -446,52 +471,107 @@ namespace LibMSPackSharp.KWAJ // Read huffman table symbol lengths and build huffman trees //BUILD_TREE(tbl, type) - lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + + //STORE_BITS + lzh.InputPointer = i_ptr; + lzh.InputLength = i_end; + lzh.BitBuffer = bit_buffer; + lzh.BitsLeft = bits_left; + Error err = LZHReadLens(lzh, (uint)types[0], KWAJ_MATCHLEN1_SYMS, lzh.MATCHLEN1_len); if (err != Error.MSPACK_ERR_OK) return err; - lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + //RESTORE_BITS + i_ptr = lzh.InputPointer; + i_end = lzh.InputLength; + bit_buffer = lzh.BitBuffer; + bits_left = lzh.BitsLeft; + if (!InternalStream.MakeDecodeTable(KWAJ_MATCHLEN1_SYMS, KWAJ_MATCHLEN1_TBLSIZE, lzh.MATCHLEN1_len, lzh.MATCHLEN1_table, msb: true)) return Error.MSPACK_ERR_DATAFORMAT; //BUILD_TREE(tbl, type) - lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + + //STORE_BITS + lzh.InputPointer = i_ptr; + lzh.InputLength = i_end; + lzh.BitBuffer = bit_buffer; + lzh.BitsLeft = bits_left; + err = LZHReadLens(lzh, (uint)types[1], KWAJ_MATCHLEN2_SYMS, lzh.MATCHLEN2_len); if (err != Error.MSPACK_ERR_OK) return err; - lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + //RESTORE_BITS + i_ptr = lzh.InputPointer; + i_end = lzh.InputLength; + bit_buffer = lzh.BitBuffer; + bits_left = lzh.BitsLeft; + if (!InternalStream.MakeDecodeTable(KWAJ_MATCHLEN2_SYMS, KWAJ_MATCHLEN2_TBLSIZE, lzh.MATCHLEN2_len, lzh.MATCHLEN2_table, msb: true)) return Error.MSPACK_ERR_DATAFORMAT; //BUILD_TREE(tbl, type) - lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + + //STORE_BITS + lzh.InputPointer = i_ptr; + lzh.InputLength = i_end; + lzh.BitBuffer = bit_buffer; + lzh.BitsLeft = bits_left; + err = LZHReadLens(lzh, (uint)types[2], KWAJ_LITLEN_SYMS, lzh.LITLEN_len); if (err != Error.MSPACK_ERR_OK) return err; - lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + //RESTORE_BITS + i_ptr = lzh.InputPointer; + i_end = lzh.InputLength; + bit_buffer = lzh.BitBuffer; + bits_left = lzh.BitsLeft; + if (!InternalStream.MakeDecodeTable(KWAJ_LITLEN_SYMS, KWAJ_LITLEN_TBLSIZE, lzh.LITLEN_len, lzh.LITLEN_table, msb: true)) return Error.MSPACK_ERR_DATAFORMAT; //BUILD_TREE(tbl, type) - lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + + //STORE_BITS + lzh.InputPointer = i_ptr; + lzh.InputLength = i_end; + lzh.BitBuffer = bit_buffer; + lzh.BitsLeft = bits_left; + err = LZHReadLens(lzh, (uint)types[3], KWAJ_OFFSET_SYMS, lzh.OFFSET_len); if (err != Error.MSPACK_ERR_OK) return err; - lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + //RESTORE_BITS + i_ptr = lzh.InputPointer; + i_end = lzh.InputLength; + bit_buffer = lzh.BitBuffer; + bits_left = lzh.BitsLeft; + if (!InternalStream.MakeDecodeTable(KWAJ_OFFSET_SYMS, KWAJ_OFFSET_TBLSIZE, lzh.OFFSET_len, lzh.OFFSET_table, msb: true)) return Error.MSPACK_ERR_DATAFORMAT; //BUILD_TREE(tbl, type) - lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + + //STORE_BITS + lzh.InputPointer = i_ptr; + lzh.InputLength = i_end; + lzh.BitBuffer = bit_buffer; + lzh.BitsLeft = bits_left; + err = LZHReadLens(lzh, (uint)types[4], KWAJ_LITERAL_SYMS, lzh.LITERAL_len); if (err != Error.MSPACK_ERR_OK) return err; - lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + //RESTORE_BITS + i_ptr = lzh.InputPointer; + i_end = lzh.InputLength; + bit_buffer = lzh.BitBuffer; + bits_left = lzh.BitsLeft; + if (!InternalStream.MakeDecodeTable(KWAJ_LITERAL_SYMS, KWAJ_LITERAL_TBLSIZE, lzh.LITERAL_len, lzh.LITERAL_table, msb: true)) return Error.MSPACK_ERR_DATAFORMAT; @@ -527,16 +607,27 @@ namespace LibMSPackSharp.KWAJ offset = (int)(j << 6); - //READ_BITS_SAFE(val, n) - int tempj = (int)j; - lzh.READ_BITS(ref tempj, 6, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); - if (lzh.Error != Error.MSPACK_ERR_OK) - return lzh.Error; + //READ_BITS_SAFE(j, 6) + + //READ_BITS(j, 6) + { + //ENSURE_BITS(6) + while (bits_left < (6)) + { + READ_BYTES; + } + + j = (int)(bit_buffer >> (BITBUF_WIDTH - (6))); + + // REMOVE_BITS(6); + bit_buffer <<= (6); + bits_left -= (6); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; - j = (uint)tempj; - offset |= tempj; + offset |= j; // Copy match as output and into the ring buffer while (len-- > 0) @@ -583,13 +674,18 @@ namespace LibMSPackSharp.KWAJ public static Error LZHReadLens(InternalStream lzh, uint type, uint numsyms, byte[] lens) { - uint bit_buffer = 0; - int bits_left = 0; - int i_ptr = 0, i_end = 0; + uint bit_buffer; + int bits_left; + int i_ptr, i_end; uint i; int c = 0, sel = 0; - lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); + //RESTORE_BITS + i_ptr = lzh.InputPointer; + i_end = lzh.InputLength; + bit_buffer = lzh.BitBuffer; + bits_left = lzh.BitsLeft; + switch (type) { case 0: @@ -603,16 +699,46 @@ namespace LibMSPackSharp.KWAJ break; case 1: - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(c, 4) + + //READ_BITS(c, 4) + { + //ENSURE_BITS(4) + while (bits_left < (4)) + { + READ_BYTES; + } + + c = (int)(bit_buffer >> (BITBUF_WIDTH - (4))); + + // REMOVE_BITS(4); + bit_buffer <<= (4); + bits_left -= (4); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; lens[0] = (byte)c; for (i = 1; i < numsyms; i++) { - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref sel, 1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(sel, 1) + + //READ_BITS(sel, 1) + { + //ENSURE_BITS(1) + while (bits_left < (1)) + { + READ_BYTES; + } + + sel = (int)(bit_buffer >> (BITBUF_WIDTH - (1))); + + // REMOVE_BITS(1); + bit_buffer <<= (1); + bits_left -= (1); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; @@ -622,8 +748,23 @@ namespace LibMSPackSharp.KWAJ } else { - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref sel, 1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(sel, 1) + + //READ_BITS(sel, 1) + { + //ENSURE_BITS(1) + while (bits_left < (1)) + { + READ_BYTES; + } + + sel = (int)(bit_buffer >> (BITBUF_WIDTH - (1))); + + // REMOVE_BITS(1); + bit_buffer <<= (1); + bits_left -= (1); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; @@ -633,8 +774,23 @@ namespace LibMSPackSharp.KWAJ } else { - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(c, 4) + + //READ_BITS(c, 4) + { + //ENSURE_BITS(nbits) + while (bits_left < (4)) + { + READ_BYTES; + } + + c = (int)(bit_buffer >> (BITBUF_WIDTH - (4))); + + // REMOVE_BITS(4); + bit_buffer <<= (4); + bits_left -= (4); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; @@ -645,23 +801,68 @@ namespace LibMSPackSharp.KWAJ break; case 2: - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(c, 4) + + //READ_BITS(c, 4) + { + //ENSURE_BITS(4) + while (bits_left < (4)) + { + READ_BYTES; + } + + c = (int)(bit_buffer >> (BITBUF_WIDTH - (4))); + + // REMOVE_BITS(4); + bit_buffer <<= (4); + bits_left -= (4); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; lens[0] = (byte)c; for (i = 1; i < numsyms; i++) { - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref sel, 2, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(sel, 2) + + //READ_BITS(sel, 2) + { + //ENSURE_BITS(2) + while (bits_left < (2)) + { + READ_BYTES; + } + + sel = (int)(bit_buffer >> (BITBUF_WIDTH - (2))); + + // REMOVE_BITS(2); + bit_buffer <<= (2); + bits_left -= (2); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; if (sel == 3) { - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(c, 4) + + //READ_BITS(c, 4) + { + //ENSURE_BITS(4) + while (bits_left < (4)) + { + READ_BYTES; + } + + c = (int)(bit_buffer >> (BITBUF_WIDTH - (4))); + + // REMOVE_BITS(4); + bit_buffer <<= (4); + bits_left -= (4); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; } @@ -678,8 +879,23 @@ namespace LibMSPackSharp.KWAJ case 3: for (i = 0; i < numsyms; i++) { - //READ_BITS_SAFE(val, n) - lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true); + //READ_BITS_SAFE(c, 4) + + //READ_BITS(c, 4) + { + //ENSURE_BITS(4) + while (bits_left < (4)) + { + READ_BYTES; + } + + c = (int)(bit_buffer >> (BITBUF_WIDTH - (4))); + + // REMOVE_BITS(4); + bit_buffer <<= (4); + bits_left -= (4); + } + if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd) return Error.MSPACK_ERR_OK; @@ -689,7 +905,11 @@ namespace LibMSPackSharp.KWAJ break; } - lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left); + //STORE_BITS + lzh.InputPointer = i_ptr; + lzh.InputLength = i_end; + lzh.BitBuffer = bit_buffer; + lzh.BitsLeft = bits_left; return Error.MSPACK_ERR_OK; } diff --git a/BurnOutSharp/External/libmspack/KWAJ/InternalStream.cs b/BurnOutSharp/External/libmspack/KWAJ/InternalStream.cs index 62237ff9..1a00daeb 100644 --- a/BurnOutSharp/External/libmspack/KWAJ/InternalStream.cs +++ b/BurnOutSharp/External/libmspack/KWAJ/InternalStream.cs @@ -33,21 +33,6 @@ namespace LibMSPackSharp.KWAJ public byte[] Window { get; set; } = new byte[LZSS.LZSS_WINDOW_SIZE]; - public override void READ_BYTES(ref int i_ptr, ref int i_end, ref int bits_left, ref uint bit_buffer, bool msb) - { - if (i_ptr >= i_end) - { - if ((Error = Implementation.LZHReadInput(this)) != Error.MSPACK_ERR_OK) - return; - - i_ptr = InputPointer; - i_end = InputLength; - } - - INJECT_BITS(InputBuffer[i_ptr++], 8, ref bits_left, ref bit_buffer, msb); - Error = Error.MSPACK_ERR_OK; - } - public override int HUFF_ERROR() => (int)Error.MSPACK_ERR_DATAFORMAT; } }