mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-09 02:16:46 +00:00
Port LZX read lengths
This commit is contained in:
@@ -7,6 +7,6 @@ namespace BurnOutSharp.Compression.LZX
|
||||
|
||||
public int BitsLeft;
|
||||
|
||||
public int InitialPosition; //byte*
|
||||
public int InputPosition; //byte*
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,73 @@ namespace BurnOutSharp.Compression.LZX
|
||||
/// <summary>
|
||||
/// Read and build the Huffman tree from the lengths
|
||||
/// </summary>
|
||||
/// INCORRECT IMPLEMENTATION TO SATISFY COMPILER FOR NOW
|
||||
private static int ReadLengths(byte[] lengths, uint first, uint last, Bits lb, State state, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf)
|
||||
private static int ReadLengths(byte[] lengths, uint first, uint last, Bits lb, State state, byte[] inbuf)
|
||||
{
|
||||
uint i, j, x, y;
|
||||
int z;
|
||||
|
||||
// TODO: Finish implementation
|
||||
uint bitbuf = lb.BitBuffer;
|
||||
int bitsleft = lb.BitsLeft;
|
||||
int inpos = lb.InputPosition;
|
||||
ushort[] hufftbl;
|
||||
|
||||
for (x = 0; x < 20; x++)
|
||||
{
|
||||
y = READ_BITS(4, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
state.tblPRETREE_len[x] = (byte)y;
|
||||
}
|
||||
|
||||
make_decode_table(LZX_PRETREE_MAXSYMBOLS, LZX_PRETREE_TABLEBITS, state.tblPRETREE_len, state.tblPRETREE_table);
|
||||
|
||||
for (x = first; x < last;)
|
||||
{
|
||||
z = READ_HUFFSYM(state.tblPRETREE_table, state.tblPRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
if (z == 17)
|
||||
{
|
||||
y = READ_BITS(4, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
y += 4;
|
||||
while (y-- > 0)
|
||||
{
|
||||
lengths[x++] = 0;
|
||||
}
|
||||
}
|
||||
else if (z == 18)
|
||||
{
|
||||
y = READ_BITS(5, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
y += 20;
|
||||
while (y-- > 0)
|
||||
{
|
||||
lengths[x++] = 0;
|
||||
}
|
||||
}
|
||||
else if (z == 19)
|
||||
{
|
||||
y = READ_BITS(1, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
y += 4;
|
||||
|
||||
z = READ_HUFFSYM(state.tblPRETREE_table, state.tblPRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
z = lengths[x] - z;
|
||||
if (z < 0)
|
||||
z += 17;
|
||||
|
||||
while (y-- > 0)
|
||||
{
|
||||
lengths[x++] = (byte)z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
z = lengths[x] - z;
|
||||
if (z < 0)
|
||||
z += 17;
|
||||
|
||||
lengths[x++] = (byte)z;
|
||||
}
|
||||
}
|
||||
|
||||
lb.BitBuffer = bitbuf;
|
||||
lb.BitsLeft = bitsleft;
|
||||
lb.InputPosition = inpos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -97,6 +159,105 @@ namespace BurnOutSharp.Compression.LZX
|
||||
|
||||
#endregion
|
||||
|
||||
#region Huffman Methods
|
||||
|
||||
/// <summary>
|
||||
/// This function was coded by David Tritscher. It builds a fast huffman
|
||||
/// decoding table out of just a canonical huffman code lengths table.
|
||||
/// </summary>
|
||||
/// <param name="nsyms">Total number of symbols in this huffman tree.</param>
|
||||
/// <param name="nbits">
|
||||
/// Any symbols with a code length of nbits or less can be decoded
|
||||
/// in one lookup of the table.
|
||||
/// </param>
|
||||
/// <param name="length">A table to get code lengths from [0 to syms-1]</param>
|
||||
/// <param name="table">The table to fill up with decoded symbols and pointers.</param>
|
||||
/// <returns>
|
||||
/// OK: 0
|
||||
/// error: 1
|
||||
/// </returns>
|
||||
private static int make_decode_table(uint nsyms, uint nbits, byte[] length, ushort[] table)
|
||||
{
|
||||
ushort sym;
|
||||
uint leaf;
|
||||
byte bit_num = 1;
|
||||
uint fill;
|
||||
uint pos = 0; /* the current position in the decode table */
|
||||
uint table_mask = (uint)(1 << (int)nbits);
|
||||
uint bit_mask = table_mask >> 1; /* don't do 0 length codes */
|
||||
uint next_symbol = bit_mask; /* base of allocation for long codes */
|
||||
|
||||
/* fill entries for codes short enough for a direct mapping */
|
||||
while (bit_num <= nbits)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] == bit_num)
|
||||
{
|
||||
leaf = pos;
|
||||
|
||||
if ((pos += bit_mask) > table_mask) return 1; /* table overrun */
|
||||
|
||||
/* fill all possible lookups of this symbol with the symbol itself */
|
||||
fill = bit_mask;
|
||||
while (fill-- > 0) table[leaf++] = sym;
|
||||
}
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
bit_num++;
|
||||
}
|
||||
|
||||
/* if there are any codes longer than nbits */
|
||||
if (pos != table_mask)
|
||||
{
|
||||
/* clear the remainder of the table */
|
||||
for (sym = (ushort)pos; sym < table_mask; sym++) table[sym] = 0;
|
||||
|
||||
/* give ourselves room for codes to grow by up to 16 more bits */
|
||||
pos <<= 16;
|
||||
table_mask <<= 16;
|
||||
bit_mask = 1 << 15;
|
||||
|
||||
while (bit_num <= 16)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] == bit_num)
|
||||
{
|
||||
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] == 0)
|
||||
{
|
||||
table[(next_symbol << 1)] = 0;
|
||||
table[(next_symbol << 1) + 1] = 0;
|
||||
table[leaf] = (ushort)next_symbol++;
|
||||
}
|
||||
/* follow the path and select either left or right for next bit */
|
||||
leaf = (uint)(table[leaf] << 1);
|
||||
if (((pos >> (int)(15 - fill)) & 1) != 0) leaf++;
|
||||
}
|
||||
table[leaf] = sym;
|
||||
|
||||
if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
|
||||
}
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
bit_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* full table? */
|
||||
if (pos == table_mask) return 0;
|
||||
|
||||
/* either erroneous table, or all elements are 0 - let's find out. */
|
||||
for (sym = 0; sym < nsyms; sym++) if (length[sym] != 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Huffman macros
|
||||
#region Huffman Macros
|
||||
|
||||
@@ -104,7 +265,7 @@ namespace BurnOutSharp.Compression.LZX
|
||||
/// Decodes one huffman symbol from the bitstream using the stated table and
|
||||
/// puts it in v.
|
||||
/// </summary>
|
||||
private static int? READ_HUFFSYM(ushort[] hufftbl, byte[] lentable, int tablebits, int maxsymbols, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf)
|
||||
private static int READ_HUFFSYM(ushort[] hufftbl, byte[] lentable, int tablebits, int maxsymbols, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf)
|
||||
{
|
||||
int v = 0, i, j = 0;
|
||||
ENSURE_BITS(16, inbuf, ref inpos, ref bitsleft, ref bitbuf);
|
||||
@@ -117,7 +278,7 @@ namespace BurnOutSharp.Compression.LZX
|
||||
i <<= 1;
|
||||
i |= (bitbuf & j) != 0 ? 1 : 0;
|
||||
if (j == 0)
|
||||
return null;
|
||||
throw new System.Exception();
|
||||
} while ((i = hufftbl[i]) >= maxsymbols);
|
||||
}
|
||||
|
||||
@@ -134,14 +295,14 @@ namespace BurnOutSharp.Compression.LZX
|
||||
{
|
||||
lb.BitBuffer = bitbuf;
|
||||
lb.BitsLeft = bitsleft;
|
||||
lb.InitialPosition = inpos;
|
||||
lb.InputPosition = inpos;
|
||||
|
||||
if (ReadLengths(lentable, first, last, lb, state, inbuf, ref inpos, ref bitsleft, ref bitbuf) != 0)
|
||||
if (ReadLengths(lentable, first, last, lb, state, inbuf) != 0)
|
||||
return false;
|
||||
|
||||
bitbuf = lb.BitBuffer;
|
||||
bitsleft = lb.BitsLeft;
|
||||
inpos = lb.InitialPosition;
|
||||
inpos = lb.InputPosition;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,55 +11,6 @@
|
||||
// {
|
||||
// internal unsafe class LZXfdi
|
||||
// {
|
||||
// /************************************************************
|
||||
// * fdi_lzx_read_lens (internal)
|
||||
// */
|
||||
// static int fdi_lzx_read_lens(cab_UBYTE* lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
|
||||
// fdi_decomp_state* decomp_state) {
|
||||
// cab_ULONG i, j, x, y;
|
||||
// int z;
|
||||
|
||||
// register cab_ULONG bitbuf = lb->bb;
|
||||
// register int bitsleft = lb->bl;
|
||||
// cab_UBYTE* inpos = lb->ip;
|
||||
// cab_UWORD* hufftbl;
|
||||
|
||||
// for (x = 0; x< 20; x++) {
|
||||
// READ_BITS(y, 4);
|
||||
// LENTABLE(PRETREE)[x] = y;
|
||||
// }
|
||||
// BUILD_TABLE(PRETREE);
|
||||
|
||||
// for (x = first; x<last; ) {
|
||||
// READ_HUFFSYM(PRETREE, z);
|
||||
// if (z == 17) {
|
||||
// READ_BITS(y, 4); y += 4;
|
||||
// while (y--) lens[x++] = 0;
|
||||
// }
|
||||
// else if (z == 18)
|
||||
// {
|
||||
// READ_BITS(y, 5); y += 20;
|
||||
// while (y--) lens[x++] = 0;
|
||||
// }
|
||||
// else if (z == 19)
|
||||
// {
|
||||
// READ_BITS(y, 1); y += 4;
|
||||
// READ_HUFFSYM(PRETREE, z);
|
||||
// z = lens[x] - z; if (z < 0) z += 17;
|
||||
// while (y--) lens[x++] = z;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// z = lens[x] - z; if (z < 0) z += 17;
|
||||
// lens[x++] = z;
|
||||
// }
|
||||
// }
|
||||
|
||||
// lb->bb = bitbuf;
|
||||
// lb->bl = bitsleft;
|
||||
// lb->ip = inpos;
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// /*******************************************************
|
||||
// * LZXfdi_decomp(internal)
|
||||
|
||||
Reference in New Issue
Block a user