diff --git a/BurnOutSharp.Compression/LZX/Bits.cs b/BurnOutSharp.Compression/LZX/Bits.cs index 89fa42f4..b5bfe65a 100644 --- a/BurnOutSharp.Compression/LZX/Bits.cs +++ b/BurnOutSharp.Compression/LZX/Bits.cs @@ -5,7 +5,7 @@ namespace BurnOutSharp.Compression.LZX { public uint BitBuffer; - public int BitLength; + public int BitsLeft; public int InitialPosition; //byte* } diff --git a/BurnOutSharp.Compression/LZX/Decompressor.cs b/BurnOutSharp.Compression/LZX/Decompressor.cs new file mode 100644 index 00000000..5c061736 --- /dev/null +++ b/BurnOutSharp.Compression/LZX/Decompressor.cs @@ -0,0 +1,150 @@ +using BurnOutSharp.Models.Compression.LZX; +using static BurnOutSharp.Models.Compression.LZX.Constants; + +namespace BurnOutSharp.Compression.LZX +{ + /// + public class Decompressor + { + /// + /// Decompress a byte array using a given State + /// + public static bool Decompress(State state, int inlen, byte[] inbuf, int outlen, byte[] outbuf) + { + + // TODO: Finish implementation + return false; + } + + /// + /// Read and build the Huffman tree from the lengths + /// + /// 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) + { + + // TODO: Finish implementation + return 0; + } + + // Bitstream reading macros (LZX / intel little-endian byte order) + #region Bitstream Reading Macros + + /* + * These bit access routines work by using the area beyond the MSB and the + * LSB as a free source of zeroes. This avoids having to mask any bits. + * So we have to know the bit width of the bitbuffer variable. + */ + + /// + /// Should be used first to set up the system + /// + private static void INIT_BITSTREAM(out int bitsleft, out uint bitbuf) + { + bitsleft = 0; + bitbuf = 0; + } + + /// + /// Ensures there are at least N bits in the bit buffer. It can guarantee + // up to 17 bits (i.e. it can read in 16 new bits when there is down to + /// 1 bit in the buffer, and it can read 32 bits when there are 0 bits in + /// the buffer). + /// + /// Quantum reads bytes in normal order; LZX is little-endian order + private static void ENSURE_BITS(int n, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf) + { + while (bitsleft < n) + { + bitbuf |= (uint)(((inbuf[inpos + 1] << 8) | inbuf[inpos + 0]) << (16 - bitsleft)); + bitsleft += 16; + inpos += 2; + } + } + + /// + /// Extracts (without removing) N bits from the bit buffer + /// + private static uint PEEK_BITS(int n, uint bitbuf) + { + return bitbuf >> (32 - n); + } + + /// + /// Removes N bits from the bit buffer + /// + private static void REMOVE_BITS(int n, ref int bitsleft, ref uint bitbuf) + { + bitbuf <<= n; + bitsleft -= n; + } + + /// + /// Takes N bits from the buffer and puts them in v. + /// + private static uint READ_BITS(int n, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf) + { + uint v = 0; + if (n > 0) + { + ENSURE_BITS(n, inbuf, ref inpos, ref bitsleft, ref bitbuf); + v = PEEK_BITS(n, bitbuf); + REMOVE_BITS(n, ref bitsleft, ref bitbuf); + } + + return v; + } + + #endregion + + // Huffman macros + #region Huffman Macros + + /// + /// Decodes one huffman symbol from the bitstream using the stated table and + /// puts it in v. + /// + 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); + if ((i = hufftbl[PEEK_BITS(tablebits, bitbuf)]) >= maxsymbols) + { + j = 1 << (32 - tablebits); + do + { + j >>= 1; + i <<= 1; + i |= (bitbuf & j) != 0 ? 1 : 0; + if (j == 0) + return null; + } while ((i = hufftbl[i]) >= maxsymbols); + } + + j = lentable[v = i]; + REMOVE_BITS(j, ref bitsleft, ref bitbuf); + return v; + } + + /// + /// Reads in code lengths for symbols first to last in the given table. The + /// code lengths are stored in their own special LZX way. + /// + private static bool READ_LENGTHS(byte[] lentable, uint first, uint last, Bits lb, State state, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf) + { + lb.BitBuffer = bitbuf; + lb.BitsLeft = bitsleft; + lb.InitialPosition = inpos; + + if (ReadLengths(lentable, first, last, lb, state, inbuf, ref inpos, ref bitsleft, ref bitbuf) != 0) + return false; + + bitbuf = lb.BitBuffer; + bitsleft = lb.BitsLeft; + inpos = lb.InitialPosition; + return true; + } + + #endregion + } +} \ No newline at end of file diff --git a/BurnOutSharp.Compression/LZX/State.cs b/BurnOutSharp.Compression/LZX/State.cs index 529d6c9f..212a83ed 100644 --- a/BurnOutSharp.Compression/LZX/State.cs +++ b/BurnOutSharp.Compression/LZX/State.cs @@ -76,8 +76,15 @@ namespace BurnOutSharp.Compression.LZX public int intel_started; public ushort[] tblPRETREE_table = new ushort[(1 << LZX_PRETREE_TABLEBITS) + (LZX_PRETREE_MAXSYMBOLS << 1)]; + public byte[] tblPRETREE_len = new byte[LZX_PRETREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; + public ushort[] tblMAINTREE_table = new ushort[(1 << LZX_MAINTREE_TABLEBITS) + (LZX_MAINTREE_MAXSYMBOLS << 1)]; + public byte[] tblMAINTREE_len = new byte[LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; + public ushort[] tblLENGTH_table = new ushort[(1 << LZX_LENGTH_TABLEBITS) + (LZX_LENGTH_MAXSYMBOLS << 1)]; + public byte[] tblLENGTH_len = new byte[LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; + public ushort[] tblALIGNED_table = new ushort[(1 << LZX_ALIGNED_TABLEBITS) + (LZX_ALIGNED_MAXSYMBOLS << 1)]; + public byte[] tblALIGNED_len = new byte[LZX_ALIGNED_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; } } \ No newline at end of file diff --git a/BurnOutSharp.Wrappers/MicrosoftCabinet.fdi.cs b/BurnOutSharp.Wrappers/MicrosoftCabinet.fdi.cs index 35295869..178728d1 100644 --- a/BurnOutSharp.Wrappers/MicrosoftCabinet.fdi.cs +++ b/BurnOutSharp.Wrappers/MicrosoftCabinet.fdi.cs @@ -1331,47 +1331,6 @@ // * and cabextract.c. // */ -// /* Bitstream reading macros (LZX / intel little-endian byte order) -// * -// * INIT_BITSTREAM should be used first to set up the system -// * READ_BITS(var,n) takes N bits from the buffer and puts them in var -// * -// * ENSURE_BITS(n) ensures there are at least N bits in the bit buffer. -// * it can guarantee up to 17 bits (i.e. it can read in -// * 16 new bits when there is down to 1 bit in the buffer, -// * and it can read 32 bits when there are 0 bits in the -// * buffer). -// * PEEK_BITS(n) extracts (without removing) N bits from the bit buffer -// * REMOVE_BITS(n) removes N bits from the bit buffer -// * -// * These bit access routines work by using the area beyond the MSB and the -// * LSB as a free source of zeroes. This avoids having to mask any bits. -// * So we have to know the bit width of the bitbuffer variable. -// */ - -// // #define INIT_BITSTREAM do { bitsleft = 0; bitbuf = 0; } while (0) - -// /* Quantum reads bytes in normal order; LZX is little-endian order */ -// // #define ENSURE_BITS(n) \ -// // while (bitsleft < (n)) { \ -// // bitbuf |= ((inpos[1]<<8)|inpos[0]) << (16 - bitsleft); \ -// // bitsleft += 16; inpos+=2; \ -// // } - -// // #define PEEK_BITS(n) (bitbuf >> (32 - (n))) -// // #define REMOVE_BITS(n) ((bitbuf <<= (n)), (bitsleft -= (n))) - -// // #define READ_BITS(v,n) do { \ -// // if (n) { \ -// // ENSURE_BITS(n); \ -// // (v) = PEEK_BITS(n); \ -// // REMOVE_BITS(n); \ -// // } \ -// // else { \ -// // (v) = 0; \ -// // } \ -// // } while (0) - // /* Huffman macros */ // // #define TABLEBITS(tbl) (LZX_##tbl##_TABLEBITS) @@ -1389,35 +1348,6 @@ // // MAXSYMBOLS(tbl), TABLEBITS(tbl), LENTABLE(tbl), SYMTABLE(tbl) \ // // )) { return DECR_ILLEGALDATA; } -// /* READ_HUFFSYM(tablename, var) decodes one huffman symbol from the -// * bitstream using the stated table and puts it in var. -// */ -// // #define READ_HUFFSYM(tbl,var) do { \ -// // ENSURE_BITS(16); \ -// // hufftbl = SYMTABLE(tbl); \ -// // if ((i = hufftbl[PEEK_BITS(TABLEBITS(tbl))]) >= MAXSYMBOLS(tbl)) { \ -// // j = 1 << (32 - TABLEBITS(tbl)); \ -// // do { \ -// // j >>= 1; i <<= 1; i |= (bitbuf & j) ? 1 : 0; \ -// // if (!j) { return DECR_ILLEGALDATA; } \ -// // } while ((i = hufftbl[i]) >= MAXSYMBOLS(tbl)); \ -// // } \ -// // j = LENTABLE(tbl)[(var) = i]; \ -// // REMOVE_BITS(j); \ -// // } while (0) - -// /* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols -// * first to last in the given table. The code lengths are stored in their -// * own special LZX way. -// */ -// // #define READ_LENGTHS(tbl,first,last,fn) do { \ -// // lb.bb = bitbuf; lb.bl = bitsleft; lb.ip = inpos; \ -// // if (fn(LENTABLE(tbl),(first),(last),&lb,decomp_state)) { \ -// // return DECR_ILLEGALDATA; \ -// // } \ -// // bitbuf = lb.bb; bitsleft = lb.bl; inpos = lb.ip; \ -// // } while (0) - // /// // internal class FILELIST // {