diff --git a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs index b54a0910..1d01bc06 100644 --- a/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs +++ b/BurnOutSharp/External/libmspack/Compression/CompressionStream.cs @@ -61,7 +61,6 @@ namespace LibMSPackSharp.Compression #endregion - // TODO: These should be in a separate file #region ReadBits Methods /* This header defines macros that read data streams by @@ -369,182 +368,10 @@ namespace LibMSPackSharp.Compression #endregion - // TODO: These should be in a separate file #region ReadHuff Methods #region Common - /// - /// This function was originally coded by David Tritscher. - /// - /// It builds a fast huffman decoding table from - /// a canonical huffman code lengths table. - /// - /// total number of symbols in this huffman tree. - /// any symbols with a code length of nbits or less can be decoded in one lookup of the table. - /// A table to get code lengths from [0 to nsyms-1] - /// - /// The table to fill up with decoded symbols and pointers. - /// Should be ((1< - /// true for OK or false for error - /// TODO: Split into MSB and LSB variants - public static bool MakeDecodeTable(int nsyms, int nbits, byte[] length, ushort[] table, bool msb) - { - ushort sym, next_symbol; - uint leaf, fill; - uint reverse; // Only used when !msb - byte bit_num; - uint pos = 0; // The current position in the decode table - uint table_mask = (uint)1 << nbits; - uint bit_mask = table_mask >> 1; // Don't do 0 length codes - - // Fill entries for codes short enough for a direct mapping - for (bit_num = 1; bit_num <= nbits; bit_num++) - { - for (sym = 0; sym < nsyms; sym++) - { - if (length[sym] != bit_num) - continue; - - if (msb) - { - leaf = pos; - } - else - { - // Reverse the significant bits - fill = length[sym]; - reverse = pos >> (nbits - (byte)fill); - leaf = 0; - - do - { - leaf <<= 1; - leaf |= reverse & 1; - reverse >>= 1; - } while (--fill != 0); - } - - if ((pos += bit_mask) > table_mask) - return false; // Table overrun - - // Fill all possible lookups of this symbol with the symbol itself - if (msb) - { - for (fill = bit_mask; fill-- > 0;) - { - table[leaf++] = sym; - } - } - else - { - fill = bit_mask; - next_symbol = (ushort)(1 << bit_num); - - do - { - table[leaf] = sym; - leaf += next_symbol; - } while (--fill != 0); - } - } - - bit_mask >>= 1; - } - - // Exit with success if table is now complete - if (pos == table_mask) - return true; - - // Mark all remaining table entries as unused - for (sym = (ushort)pos; sym < table_mask; sym++) - { - if (msb) - { - table[sym] = 0xFFFF; - } - else - { - reverse = sym; - leaf = 0; - fill = (uint)nbits; - - do - { - leaf <<= 1; - leaf |= reverse & 1; - reverse >>= 1; - } while (--fill != 0); - - table[leaf] = 0xFFFF; - } - } - - // next_symbol = base of allocation for long codes - next_symbol = ((table_mask >> 1) < nsyms) ? (ushort)nsyms : (ushort)(table_mask >> 1); - - // Give ourselves room for codes to grow by up to 16 more bits. - // codes now start at bit nbits+16 and end at (nbits+16-codelength) - pos <<= 16; - table_mask <<= 16; - bit_mask = 1 << 15; - - for (bit_num = (byte)(nbits + 1); bit_num <= HUFF_MAXBITS; bit_num++) - { - for (sym = 0; sym < nsyms; sym++) - { - if (length[sym] != bit_num) - continue; - if (pos >= table_mask) - return false; // Table overflow - - if (msb) - { - leaf = pos >> 16; - } - else - { - // leaf = the first nbits of the code, reversed - reverse = pos >> 16; - leaf = 0; - fill = (uint)nbits; - - do - { - leaf <<= 1; - leaf |= reverse & 1; - reverse >>= 1; - } while (--fill != 0); - } - - for (fill = 0; fill < (bit_num - nbits); fill++) - { - // If this path hasn't been taken yet, 'allocate' two entries - if (table[leaf] == 0xFFFF) - { - table[(next_symbol << 1)] = 0xFFFF; - table[(next_symbol << 1) + 1] = 0xFFFF; - table[leaf] = (ushort)next_symbol++; - } - - // Follow the path and select either left or right for next bit - leaf = (uint)(table[leaf] << 1); - if (((pos >> (15 - (int)fill)) & 1) != 0) - leaf++; - } - - table[leaf] = sym; - pos += bit_mask; - } - - bit_mask >>= 1; - } - - // Full table? - return pos == table_mask; - } - /// /// Per compression error code for decoding failure /// @@ -587,6 +414,107 @@ namespace LibMSPackSharp.Compression } while (sym >= maxsymbols); } + /// + /// This function was originally coded by David Tritscher. + /// + /// It builds a fast huffman decoding table from + /// a canonical huffman code lengths table. + /// + /// total number of symbols in this huffman tree. + /// any symbols with a code length of nbits or less can be decoded in one lookup of the table. + /// A table to get code lengths from [0 to nsyms-1] + /// + /// The table to fill up with decoded symbols and pointers. + /// Should be ((1< + /// True for OK or false for error + public static bool MakeDecodeTableMSB(int nsyms, int nbits, byte[] length, ushort[] table) + { + ushort sym, next_symbol; + uint leaf, fill; + byte bit_num; + uint pos = 0; // The current position in the decode table + uint table_mask = (uint)1 << nbits; + uint bit_mask = table_mask >> 1; // Don't do 0 length codes + + // Fill entries for codes short enough for a direct mapping + for (bit_num = 1; bit_num <= nbits; bit_num++) + { + for (sym = 0; sym < nsyms; sym++) + { + if (length[sym] != bit_num) + continue; + + leaf = pos; + if ((pos += bit_mask) > table_mask) + return false; // Table overrun + + // Fill all possible lookups of this symbol with the symbol itself + for (fill = bit_mask; fill-- > 0;) + { + table[leaf++] = sym; + } + } + + bit_mask >>= 1; + } + + // Exit with success if table is now complete + if (pos == table_mask) + return true; + + // Mark all remaining table entries as unused + for (sym = (ushort)pos; sym < table_mask; sym++) + { + table[sym] = 0xFFFF; + } + + // next_symbol = base of allocation for long codes + next_symbol = ((table_mask >> 1) < nsyms) ? (ushort)nsyms : (ushort)(table_mask >> 1); + + // Give ourselves room for codes to grow by up to 16 more bits. + // codes now start at bit nbits+16 and end at (nbits+16-codelength) + pos <<= 16; + table_mask <<= 16; + bit_mask = 1 << 15; + + for (bit_num = (byte)(nbits + 1); bit_num <= HUFF_MAXBITS; bit_num++) + { + for (sym = 0; sym < nsyms; sym++) + { + if (length[sym] != bit_num) + continue; + if (pos >= table_mask) + return false; // Table overflow + + leaf = pos >> 16; + for (fill = 0; fill < (bit_num - nbits); fill++) + { + // If this path hasn't been taken yet, 'allocate' two entries + if (table[leaf] == 0xFFFF) + { + table[(next_symbol << 1)] = 0xFFFF; + table[(next_symbol << 1) + 1] = 0xFFFF; + table[leaf] = next_symbol++; + } + + // Follow the path and select either left or right for next bit + leaf = (uint)(table[leaf] << 1); + if (((pos >> (15 - (int)fill)) & 1) != 0) + leaf++; + } + + table[leaf] = sym; + pos += bit_mask; + } + + bit_mask >>= 1; + } + + // Full table? + return pos == table_mask; + } + #endregion #region LSB @@ -624,6 +552,145 @@ namespace LibMSPackSharp.Compression } while (sym >= maxsymbols); } + /// + /// This function was originally coded by David Tritscher. + /// + /// It builds a fast huffman decoding table from + /// a canonical huffman code lengths table. + /// + /// total number of symbols in this huffman tree. + /// any symbols with a code length of nbits or less can be decoded in one lookup of the table. + /// A table to get code lengths from [0 to nsyms-1] + /// + /// The table to fill up with decoded symbols and pointers. + /// Should be ((1< + /// True for OK or false for error + public static bool MakeDecodeTableLSB(int nsyms, int nbits, byte[] length, ushort[] table) + { + ushort sym, next_symbol; + uint leaf, fill; + uint reverse; + byte bit_num; + uint pos = 0; // The current position in the decode table + uint table_mask = (uint)1 << nbits; + uint bit_mask = table_mask >> 1; // Don't do 0 length codes + + // Fill entries for codes short enough for a direct mapping + for (bit_num = 1; bit_num <= nbits; bit_num++) + { + for (sym = 0; sym < nsyms; sym++) + { + if (length[sym] != bit_num) + continue; + + // Reverse the significant bits + fill = length[sym]; + reverse = pos >> (int)(nbits - fill); + leaf = 0; + + do + { + leaf <<= 1; + leaf |= reverse & 1; + reverse >>= 1; + } while (--fill != 0); + + if ((pos += bit_mask) > table_mask) + return false; // Table overrun + + // Fill all possible lookups of this symbol with the symbol itself + fill = bit_mask; + next_symbol = (ushort)(1 << bit_num); + + do + { + table[leaf] = sym; + leaf += next_symbol; + } while (--fill != 0); + } + + bit_mask >>= 1; + } + + // Exit with success if table is now complete + if (pos == table_mask) + return true; + + // Mark all remaining table entries as unused + for (sym = (ushort)pos; sym < table_mask; sym++) + { + reverse = sym; + leaf = 0; + fill = (uint)nbits; + + do + { + leaf <<= 1; + leaf |= reverse & 1; + reverse >>= 1; + } while (--fill != 0); + + table[leaf] = 0xFFFF; + } + + // next_symbol = base of allocation for long codes + next_symbol = ((table_mask >> 1) < nsyms) ? (ushort)nsyms : (ushort)(table_mask >> 1); + + // Give ourselves room for codes to grow by up to 16 more bits. + // codes now start at bit nbits+16 and end at (nbits+16-codelength) + pos <<= 16; + table_mask <<= 16; + bit_mask = 1 << 15; + + for (bit_num = (byte)(nbits + 1); bit_num <= HUFF_MAXBITS; bit_num++) + { + for (sym = 0; sym < nsyms; sym++) + { + if (length[sym] != bit_num) + continue; + if (pos >= table_mask) + return false; // Table overflow + + // leaf = the first nbits of the code, reversed + reverse = pos >> 16; + leaf = 0; + fill = (uint)nbits; + + do + { + leaf <<= 1; + leaf |= reverse & 1; + reverse >>= 1; + } while (--fill != 0); + + for (fill = 0; fill < (bit_num - nbits); fill++) + { + // If this path hasn't been taken yet, 'allocate' two entries + if (table[leaf] == 0xFFFF) + { + table[(next_symbol << 1)] = 0xFFFF; + table[(next_symbol << 1) + 1] = 0xFFFF; + table[leaf] = (ushort)next_symbol++; + } + + // Follow the path and select either left or right for next bit + leaf = (uint)(table[leaf] << 1); + if (((pos >> (15 - (int)fill)) & 1) != 0) + leaf++; + } + + table[leaf] = sym; + pos += bit_mask; + } + + bit_mask >>= 1; + } + + // Full table? + return pos == table_mask; + } + #endregion #endregion diff --git a/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs b/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs index 7efac2fc..b72977ea 100644 --- a/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs +++ b/BurnOutSharp/External/libmspack/Compression/LZHKWAJ.cs @@ -152,7 +152,7 @@ namespace LibMSPackSharp.Compression lzh.RESTORE_BITS(out i_ptr, out i_end, out bit_buffer, out bits_left); - if (!CompressionStream.MakeDecodeTable(maxsymbols, tablebits, lengths, table, msb: true)) + if (!CompressionStream.MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table)) return Error.MSPACK_ERR_DATAFORMAT; return Error.MSPACK_ERR_OK; diff --git a/BurnOutSharp/External/libmspack/Compression/LZX.cs b/BurnOutSharp/External/libmspack/Compression/LZX.cs index c5bd6e33..667a6c09 100644 --- a/BurnOutSharp/External/libmspack/Compression/LZX.cs +++ b/BurnOutSharp/External/libmspack/Compression/LZX.cs @@ -1039,7 +1039,7 @@ namespace LibMSPackSharp.Compression private static Error BUILD_TABLE(LZXDStream lzx, ushort[] table, byte[] lengths, int tablebits, int maxsymbols) { - if (!CompressionStream.MakeDecodeTable(maxsymbols, tablebits, lengths, table, msb: true)) + if (!CompressionStream.MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table)) { Console.WriteLine($"Failed to build table"); return lzx.Error = Error.MSPACK_ERR_DECRUNCH; @@ -1051,7 +1051,7 @@ namespace LibMSPackSharp.Compression private static Error BUILD_TABLE_MAYBE_EMPTY(LZXDStream lzx) { lzx.LENGTH_empty = 0; - if (!CompressionStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table, msb: true)) + if (!CompressionStream.MakeDecodeTableMSB(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table)) { for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) { diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs index 5ef4e4ec..6009411d 100644 --- a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs +++ b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs @@ -360,7 +360,7 @@ namespace LibMSPackSharp.Compression } // Create decoding table with an immediate lookup - if (!CompressionStream.MakeDecodeTable(19, 7, bl_len, bl_table, msb: false)) + if (!CompressionStream.MakeDecodeTableLSB(19, 7, bl_len, bl_table)) return Error.INF_ERR_BITLENTBL; // Read literal / distance code lengths @@ -565,10 +565,10 @@ namespace LibMSPackSharp.Compression // Now huffman lengths are read for either kind of block, // create huffman decoding tables - if (!CompressionStream.MakeDecodeTable(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, zip.LITERAL_table, msb: false)) + if (!CompressionStream.MakeDecodeTableLSB(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, zip.LITERAL_table)) return Error.INF_ERR_LITERALTBL; - if (!CompressionStream.MakeDecodeTable(MSZIP_DISTANCE_MAXSYMBOLS, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, zip.DISTANCE_table, msb: false)) + if (!CompressionStream.MakeDecodeTableLSB(MSZIP_DISTANCE_MAXSYMBOLS, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, zip.DISTANCE_table)) return Error.INF_ERR_DISTANCETBL; // Decode forever until end of block code