static public LZXstate LZXinit(int window) { LZXstate pState = null; uint wndsize = (uint)(1 << window); int i, posn_slots; // LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) // if a previously allocated window is big enough, keep it if (window < 15 || window > 21) { return(null); } // allocate state and associated window pState = new LZXstate(); pState.window = new byte[wndsize]; pState.actual_size = wndsize; pState.window_size = wndsize; // calculate required position slots if (window == 20) { posn_slots = 42; } else if (window == 21) { posn_slots = 50; } else { posn_slots = window << 1; } // alternatively // posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; // initialize other state pState.R0 = pState.R1 = pState.R2 = 1; pState.main_elements = (ushort)(LZX_NUM_CHARS + (posn_slots << 3)); pState.header_read = 0; pState.frames_read = 0; pState.block_remaining = 0; pState.block_type = LZX_BLOCKTYPE_INVALID; pState.intel_curpos = 0; pState.intel_started = false; pState.window_posn = 0; // initialise tables to 0 (because deltas will be applied to them) for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) { pState.MAINTREE.len[i] = 0; } for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) { pState.LENGTH.len[i] = 0; } return(pState); }
static public void LZXteardown(LZXstate pState) { /* * if (pState) * { * free(pState.window); * free(pState); * } */ }
static public void READ_LENGTHS(LZXstate pState, ref uint bitbuf, ref int bitsleft, ref byte *inpos, ref lzx_bits lb, Table tbl, uint first, uint last) { fixed(lzx_bits *lbp = &lb) { lb.bb = bitbuf; lb.bl = bitsleft; lb.ip = inpos; if (lzx_read_lens(pState, LENTABLE(tbl), (first), (last), lbp)) { throw (new InvalidDataException()); } bitbuf = lb.bb; bitsleft = lb.bl; inpos = lb.ip; } }
static public int LZXreset(LZXstate pState) { int i; pState.R0 = pState.R1 = pState.R2 = 1; pState.header_read = 0; pState.frames_read = 0; pState.block_remaining = 0; pState.block_type = LZX_BLOCKTYPE_INVALID; pState.intel_curpos = 0; pState.intel_started = false; pState.window_posn = 0; for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) { pState.MAINTREE.len[i] = 0; } for (i = 0; i < LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) { pState.LENGTH.len[i] = 0; } return(DECR_OK); }
/* 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. */ private static bool READ_LENGTHS(ULONG first, ULONG last, lzx_bits lb, ref ULONG bitbuf, ref LONG bitsleft, ref UBYTE[] ip, ref long inpos, LZXstate pState, ref UBYTE[] tablelen) { lb.bb = bitbuf; lb.bl = bitsleft; lb.ip = ip; lb.ippos = inpos; if (lzx_read_lens(pState, ref tablelen, first, last, lb) != 0) return false; bitbuf = lb.bb; bitsleft = lb.bl; inpos = lb.ippos; return true; }
private static int lzx_read_lens(LZXstate pState, ref UBYTE[] lens, ULONG first, ULONG last, lzx_bits lb) { ULONG i = 0, j = 0, x = 0, y = 0; int z = 0; ULONG bitbuf = lb.bb; int bitsleft = lb.bl; long inpos = lb.ippos; UWORD[] hufftbl = null; bool hr; for (x = 0; x < 20; x++) { READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); pState.PRETREE_len[x] = (byte)y; } if (!BUILD_TABLE(ref pState.PRETREE_table, ref pState.PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS)) return DECR_ILLEGALDATA; for (x = first; x < last; ) { hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, ref pState.PRETREE_len, ref j, ref z); if (!hr) return DECR_ILLEGALDATA; if (z == 17) { READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4; while (Convert.ToBoolean(y--)) lens[x++] = 0; } else if (z == 18) { READ_BITS(ref y, 5, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 20; while (Convert.ToBoolean(y--)) lens[x++] = 0; } else if (z == 19) { READ_BITS(ref y, 1, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4; hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, ref pState.PRETREE_len, ref j, ref z); if (!hr) return DECR_ILLEGALDATA; z = lens[x] - z; if (z < 0) z += 17; while (Convert.ToBoolean(y--)) lens[x++] = (byte)z; } else { z = lens[x] - z; if (z < 0) z += 17; lens[x++] = (byte)z; } } lb.bb = bitbuf; lb.bl = bitsleft; lb.ippos = inpos; return 0; }
public static void LZXteardown(LZXstate pState) { }
public static int LZXreset(LZXstate pState) { int i; pState.R0 = pState.R1 = pState.R2 = 1; pState.header_read = 0; pState.frames_read = 0; pState.block_remaining = 0; pState.block_type = LZX_BLOCKTYPE_INVALID; pState.intel_curpos = 0; pState.intel_started = 0; pState.window_posn = 0; for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) pState.MAINTREE_len[i] = 0; for (i = 0; i < LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) pState.LENGTH_len[i] = 0; return DECR_OK; }
public static LZXstate LZXinit(int window) { LZXstate pState = null; ULONG wndsize = (ULONG)(1 << window); int i, posn_slots; /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */ /* if a previously allocated window is big enough, keep it */ if (window < 15 || window > 21) return null; /* allocate state and associated window */ pState = new LZXstate(); pState.window = new UBYTE[wndsize]; pState.actual_size = wndsize; pState.window_size = wndsize; /* calculate required position slots */ if (window == 20) posn_slots = 42; else if (window == 21) posn_slots = 50; else posn_slots = window << 1; /** alternatively **/ /* posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; */ /* initialize other state */ pState.R0 = pState.R1 = pState.R2 = 1; pState.main_elements = (UWORD)(LZX_NUM_CHARS + (posn_slots << 3)); pState.header_read = 0; pState.frames_read = 0; pState.block_remaining = 0; pState.block_type = LZX_BLOCKTYPE_INVALID; pState.intel_curpos = 0; pState.intel_started = 0; pState.window_posn = 0; /* initialise tables to 0 (because deltas will be applied to them) */ for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) pState.MAINTREE_len[i] = 0; for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) pState.LENGTH_len[i] = 0; return pState; }
public static int LZXdecompress(LZXstate pState, ref UBYTE[] ip, long inpos, ref UBYTE[] op, ulong outpos, int inlen, int outlen) { long endinp = inpos + inlen; UBYTE[] window = pState.window; long runsrc = 0; long rundest = 0; UWORD[] hufftbl = null; /* used in READ_HUFFSYM macro as chosen decoding table */ ULONG window_posn = pState.window_posn; ULONG window_size = pState.window_size; ULONG R0 = pState.R0; ULONG R1 = pState.R1; ULONG R2 = pState.R2; ULONG bitbuf = 0; int bitsleft = 0; ULONG match_offset, i = 0, j = 0, k = 0; /* ijk used in READ_HUFFSYM macro */ lzx_bits lb = new lzx_bits(); /* used in READ_LENGTHS macro */ bool hr; int togo = outlen, this_run, main_element = 0, aligned_bits = 0; int match_length, length_footer = 0, extra; uint verbatim_bits = 0; INIT_BITSTREAM(ref bitsleft, ref bitbuf); /* read header if necessary */ if (!Convert.ToBoolean(pState.header_read)) { i = j = 0; READ_BITS(ref k, 1, ref bitbuf, ref bitsleft, ref ip, ref inpos); if (Convert.ToBoolean(k)) { READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos); READ_BITS(ref j, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos); } pState.intel_filesize = (LONG)((i << 16) | j); /* or 0 if not encoded */ pState.header_read = 1; } /* main decoding loop */ while (togo > 0) { /* last block finished, new block expected */ if (pState.block_remaining == 0) { if (pState.block_type == LZX_BLOCKTYPE_UNCOMPRESSED) { if (Convert.ToBoolean(pState.block_length & 1)) inpos++; /* realign bitstream to word */ INIT_BITSTREAM(ref bitsleft, ref bitbuf); } READ_BITS(ref pState.block_type, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos); READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos); READ_BITS(ref j, 8, ref bitbuf, ref bitsleft, ref ip, ref inpos); pState.block_remaining = pState.block_length = (i << 8) | j; switch (pState.block_type) { case LZX_BLOCKTYPE_ALIGNED: for (i = 0; i < 8; i++) { READ_BITS(ref j, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos); pState.ALIGNED_len[i] = (byte)j; } if (!BUILD_TABLE(ref pState.ALIGNED_table, ref pState.ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS)) return DECR_ILLEGALDATA; /* rest of aligned header is same as verbatim */ goto case LZX_BLOCKTYPE_VERBATIM; case LZX_BLOCKTYPE_VERBATIM: if (!READ_LENGTHS(0, 256, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos, pState, ref pState.MAINTREE_len)) return DECR_ILLEGALDATA; if (!READ_LENGTHS(256, pState.main_elements, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos, pState, ref pState.MAINTREE_len)) return DECR_ILLEGALDATA; if (!BUILD_TABLE(ref pState.MAINTREE_table, ref pState.MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS)) return DECR_ILLEGALDATA; if (pState.MAINTREE_len[0xE8] != 0) pState.intel_started = 1; if (!READ_LENGTHS(0, LZX_NUM_SECONDARY_LENGTHS, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos, pState, ref pState.LENGTH_len)) return DECR_ILLEGALDATA; if (!BUILD_TABLE(ref pState.LENGTH_table, ref pState.LENGTH_len, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS)) return DECR_ILLEGALDATA; break; case LZX_BLOCKTYPE_UNCOMPRESSED: pState.intel_started = 1; /* because we can't assume otherwise */ ENSURE_BITS(ref bitsleft, ref bitbuf, ref ip, ref inpos, 16); /* get up to 16 pad bits into the buffer */ if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */ R0 = (ULONG)(ip[inpos + 0]|(ip[inpos + 1]<<8)|(ip[inpos + 2]<<16)|(ip[inpos + 3]<<24));inpos+=4; R1 = (ULONG)(ip[inpos + 0]|(ip[inpos + 1]<<8)|(ip[inpos + 2]<<16)|(ip[inpos + 3]<<24));inpos+=4; R2 = (ULONG)(ip[inpos + 0]|(ip[inpos + 1]<<8)|(ip[inpos + 2]<<16)|(ip[inpos + 3]<<24));inpos+=4; break; default: return DECR_ILLEGALDATA; } } /* buffer exhaustion check */ if (inpos > endinp) { /* it's possible to have a file where the next run is less than * 16 bits in size. In this case, the READ_HUFFSYM() macro used * in building the tables will exhaust the buffer, so we should * allow for this, but not allow those accidentally read bits to * be used (so we check that there are at least 16 bits * remaining - in this boundary case they aren't really part of * the compressed data) */ if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA; } while ((this_run = (LONG)pState.block_remaining) > 0 && togo > 0) { if (this_run > togo) this_run = togo; togo -= this_run; pState.block_remaining -= (ULONG)this_run; /* apply 2^x-1 mask */ window_posn &= window_size - 1; /* runs can't straddle the window wraparound */ if ((window_posn + this_run) > window_size) return DECR_DATAFORMAT; switch (pState.block_type) { case LZX_BLOCKTYPE_VERBATIM: while (this_run > 0) { hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element); if (!hr) return DECR_ILLEGALDATA; if (main_element < LZX_NUM_CHARS) { /* literal: 0 to LZX_NUM_CHARS-1 */ window[window_posn++] = (UBYTE)main_element; this_run--; } else { /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ main_element -= LZX_NUM_CHARS; match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; if (match_length == LZX_NUM_PRIMARY_LENGTHS) { hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer); if (!hr) return DECR_ILLEGALDATA; match_length += length_footer; } match_length += LZX_MIN_MATCH; match_offset = (ULONG)main_element >> 3; if (match_offset > 2) { /* not repeated offset */ if (match_offset != 3) { extra = extra_bits[match_offset]; READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft, ref ip, ref inpos); match_offset = position_base[match_offset] - 2 + verbatim_bits; } else { match_offset = 1; } /* update repeated offset LRU queue */ R2 = R1; R1 = R0; R0 = match_offset; } else if (match_offset == 0) { match_offset = R0; } else if (match_offset == 1) { match_offset = R1; R1 = R0; R0 = match_offset; } else /* match_offset == 2 */ { match_offset = R2; R2 = R0; R0 = match_offset; } rundest = window_posn; runsrc = rundest - match_offset; window_posn += (ULONG)match_length; if (window_posn > window_size) return DECR_ILLEGALDATA; this_run -= match_length; /* copy any wrapped around source data */ while ((runsrc < 0) && (match_length-- > 0)) { window[rundest++] = window[runsrc + window_size]; runsrc++; } /* copy match data - no worries about destination wraps */ while (match_length-- > 0) window[rundest++] = window[runsrc++]; } } break; case LZX_BLOCKTYPE_ALIGNED: while (this_run > 0) { hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element); if (!hr) return DECR_ILLEGALDATA; if (main_element < LZX_NUM_CHARS) { /* literal: 0 to LZX_NUM_CHARS-1 */ window[window_posn++] = (UBYTE)main_element; this_run--; } else { /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ main_element -= LZX_NUM_CHARS; match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; if (match_length == LZX_NUM_PRIMARY_LENGTHS) { hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer); if (!hr) return DECR_ILLEGALDATA; match_length += length_footer; } match_length += LZX_MIN_MATCH; match_offset = (ULONG)main_element >> 3; if (match_offset > 2) { /* not repeated offset */ extra = extra_bits[match_offset]; match_offset = position_base[match_offset] - 2; if (extra > 3) { /* verbatim and aligned bits */ extra -= 3; READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft, ref ip, ref inpos); match_offset += (verbatim_bits << 3); hr = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits); if (!hr) return DECR_ILLEGALDATA; match_offset += (ULONG)aligned_bits; } else if (extra == 3) { /* aligned bits only */ hr = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits); if (!hr) return DECR_ILLEGALDATA; match_offset += (ULONG)aligned_bits; } else if (extra > 0) { /* extra==1, extra==2 */ /* verbatim bits only */ READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft, ref ip, ref inpos); match_offset += verbatim_bits; } else /* extra == 0 */ { /* ??? */ match_offset = 1; } /* update repeated offset LRU queue */ R2 = R1; R1 = R0; R0 = match_offset; } else if (match_offset == 0) { match_offset = R0; } else if (match_offset == 1) { match_offset = R1; R1 = R0; R0 = match_offset; } else /* match_offset == 2 */ { match_offset = R2; R2 = R0; R0 = match_offset; } rundest = window_posn; runsrc = rundest - match_offset; window_posn += (ULONG)match_length; if (window_posn > window_size) return DECR_ILLEGALDATA; this_run -= match_length; /* copy any wrapped around source data */ while ((runsrc < 0) && (match_length-- > 0)) { window[rundest++] = window[runsrc + window_size]; runsrc++; } /* copy match data - no worries about destination wraps */ while (match_length-- > 0) window[rundest++] = window[runsrc++]; } } break; case LZX_BLOCKTYPE_UNCOMPRESSED: if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA; Array.Copy(ip, inpos, window, window_posn, this_run); inpos += this_run; window_posn += (ULONG)this_run; break; default: return DECR_ILLEGALDATA; /* might as well */ } } } if (togo != 0) return DECR_ILLEGALDATA; Array.Copy( window, (!Convert.ToBoolean(window_posn) ? window_size : window_posn) - outlen, op, (long)outpos, outlen); pState.window_posn = window_posn; pState.R0 = R0; pState.R1 = R1; pState.R2 = R2; /* intel E8 decoding */ if ((pState.frames_read++ < 32768) && pState.intel_filesize != 0) { if (outlen <= 6 || !Convert.ToBoolean(pState.intel_started)) { pState.intel_curpos += outlen; } else { ulong data = outpos; ulong dataend = outpos + (ulong)outlen - 10; LONG curpos = pState.intel_curpos; LONG filesize = pState.intel_filesize; LONG abs_off, rel_off; pState.intel_curpos = curpos + outlen; while (data < dataend) { if (op[data++] != 0xE8) { curpos++; continue; } abs_off = op[data + 0] | (op[data + 1]<<8) | (op[data + 2]<<16) | (op[data + 3]<<24); if ((abs_off >= -curpos) && (abs_off < filesize)) { rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize; op[data + 0] = (UBYTE) rel_off; op[data + 1] = (UBYTE)(rel_off >> 8); op[data + 2] = (UBYTE)(rel_off >> 16); op[data + 3] = (UBYTE)(rel_off >> 24); } data += 4; curpos += 5; } } } return DECR_OK; }
static public int LZXdecompress(LZXstate pState, byte *inpos, byte *outpos, int inlen, int outlen) { fixed(byte *window = pState.window) { byte *endinp = inpos + inlen; byte *runsrc; byte *rundest; ushort[] hufftbl; // used in READ_HUFFSYM macro as chosen decoding table uint window_posn = pState.window_posn; uint window_size = pState.window_size; uint R0 = pState.R0; uint R1 = pState.R1; uint R2 = pState.R2; uint bitbuf; int bitsleft; uint match_offset, i = 0, j = 0, k = 0; /* ijk used in READ_HUFFSYM macro */ var lb = default(lzx_bits); /* used in READ_LENGTHS macro */ int togo = outlen, this_run, main_element, aligned_bits; int match_length, length_footer, extra, verbatim_bits = 0; int copy_length; //INIT_BITSTREAM(); bitsleft = 0; bitbuf = 0; // read header if necessary if (pState.header_read == 0) { i = j = 0; READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref k, 1); if (k != 0) { READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref i, 16); READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref j, 16); } pState.intel_filesize = (int)((i << 16) | j); // or 0 if not encoded pState.header_read = 1; } // main decoding loop while (togo > 0) { #if DEBUG_LZX_COMPRESSION Console.WriteLine("------------------------------------------------------------"); Console.WriteLine("MainLoop togo: {0}, pState.block_remaining: {1}", togo, pState.block_remaining); #endif // last block finished, new block expected if (pState.block_remaining == 0) { READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref pState.block_type, 3); READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref i, 16); READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref j, 8); pState.block_remaining = pState.block_length = (i << 8) | j; #if DEBUG_LZX_COMPRESSION Console.WriteLine("BlockSize: {0}", pState.block_length); #endif switch (pState.block_type) { case LZX_BLOCKTYPE_ALIGNED: #if DEBUG_LZX_COMPRESSION Console.WriteLine("[L]LZX_BLOCKTYPE_ALIGNED"); #endif for (i = 0; i < 8; i++) { READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref j, 3); LENTABLE(pState.ALIGNED)[i] = (byte)j; } BUILD_TABLE(pState.ALIGNED); /* rest of aligned header is same as verbatim */ goto case LZX_BLOCKTYPE_VERBATIM; case LZX_BLOCKTYPE_VERBATIM: #if DEBUG_LZX_COMPRESSION Console.WriteLine("[L]LZX_BLOCKTYPE_VERBATIM"); #endif READ_LENGTHS(pState, ref bitbuf, ref bitsleft, ref inpos, ref lb, pState.MAINTREE, 0, 256); READ_LENGTHS(pState, ref bitbuf, ref bitsleft, ref inpos, ref lb, pState.MAINTREE, 256, pState.main_elements); BUILD_TABLE(pState.MAINTREE); if (LENTABLE(pState.MAINTREE)[0xE8] != 0) { pState.intel_started = true; } READ_LENGTHS(pState, ref bitbuf, ref bitsleft, ref inpos, ref lb, pState.LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS); BUILD_TABLE(pState.LENGTH); break; case LZX_BLOCKTYPE_UNCOMPRESSED: #if DEBUG_LZX_COMPRESSION Console.WriteLine("[L]LZX_BLOCKTYPE_UNCOMPRESSED"); #endif pState.intel_started = true; /* because we can't assume otherwise */ ENSURE_BITS(ref bitsleft, ref inpos, ref bitbuf, 16); // get up to 16 pad bits into the buffer if (bitsleft > 16) { inpos -= 2; /* and align the bitstream! */ } R0 = (uint)(inpos[0] | (inpos[1] << 8) | (inpos[2] << 16) | (inpos[3] << 24)); inpos += 4; R1 = (uint)(inpos[0] | (inpos[1] << 8) | (inpos[2] << 16) | (inpos[3] << 24)); inpos += 4; R2 = (uint)(inpos[0] | (inpos[1] << 8) | (inpos[2] << 16) | (inpos[3] << 24)); inpos += 4; break; default: Console.Error.WriteLine("Invalid Block Type: {0}", pState.block_type); return(DECR_ILLEGALDATA); } } if (inpos > endinp) { if (inpos > (endinp + 2) || bitsleft < 16) { Console.Error.WriteLine("Error (inpos > endinp) && (inpos > (endinp + 2) || bitsleft < 16)"); return(DECR_ILLEGALDATA); } } while ((this_run = (int)pState.block_remaining) > 0 && togo > 0) { if (this_run > togo) { this_run = togo; } togo -= this_run; pState.block_remaining -= (uint)this_run; /* apply 2^x-1 mask */ window_posn &= window_size - 1; /* runs can't straddle the window wraparound */ if ((window_posn + this_run) > window_size) { return(DECR_DATAFORMAT); } switch (pState.block_type) { case LZX_BLOCKTYPE_VERBATIM: #if DEBUG_LZX_COMPRESSION Console.WriteLine("[B]LZX_BLOCKTYPE_VERBATIM"); #endif while (this_run > 0) { READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.MAINTREE, out main_element); if (main_element < LZX_NUM_CHARS) { /* literal: 0 to LZX_NUM_CHARS-1 */ window[window_posn++] = (byte)main_element; this_run--; } else { /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ main_element -= LZX_NUM_CHARS; match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; if (match_length == LZX_NUM_PRIMARY_LENGTHS) { READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.LENGTH, out length_footer); match_length += length_footer; } match_length += LZX_MIN_MATCH; match_offset = (uint)(main_element >> 3); if (match_offset > 2) { /* not repeated offset */ if (match_offset != 3) { extra = extra_bits[match_offset]; READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref verbatim_bits, extra); match_offset = (uint)(position_base[match_offset] - 2 + verbatim_bits); } else { match_offset = 1; } /* update repeated offset LRU queue */ R2 = R1; R1 = R0; R0 = match_offset; } else if (match_offset == 0) { match_offset = R0; } else if (match_offset == 1) { match_offset = R1; R1 = R0; R0 = match_offset; } else /* match_offset == 2 */ { match_offset = R2; R2 = R0; R0 = match_offset; } rundest = window + window_posn; this_run -= match_length; /* copy any wrapped around source data */ if (window_posn >= match_offset) { /* no wrap */ runsrc = rundest - match_offset; } else { runsrc = rundest + (window_size - match_offset); copy_length = (int)(match_offset - window_posn); if (copy_length < match_length) { match_length -= copy_length; window_posn += (uint)copy_length; while (copy_length-- > 0) { *rundest++ = *runsrc++; } runsrc = window; } } window_posn += (uint)match_length; /* copy match data - no worries about destination wraps */ while (match_length-- > 0) { *rundest++ = *runsrc++; } } } break; case LZX_BLOCKTYPE_ALIGNED: #if DEBUG_LZX_COMPRESSION Console.WriteLine("[B]LZX_BLOCKTYPE_ALIGNED"); #endif while (this_run > 0) { READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.MAINTREE, out main_element); if (main_element < LZX_NUM_CHARS) { /* literal: 0 to LZX_NUM_CHARS-1 */ window[window_posn++] = (byte)main_element; this_run--; } else { /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ main_element -= LZX_NUM_CHARS; match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; if (match_length == LZX_NUM_PRIMARY_LENGTHS) { READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.LENGTH, out length_footer); match_length += length_footer; } match_length += LZX_MIN_MATCH; match_offset = (uint)(main_element >> 3); if (match_offset > 2) { /* not repeated offset */ extra = extra_bits[match_offset]; match_offset = position_base[match_offset] - 2; if (extra > 3) { /* verbatim and aligned bits */ extra -= 3; READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref verbatim_bits, extra); match_offset += (uint)(verbatim_bits << 3); READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.ALIGNED, out aligned_bits); match_offset += (uint)aligned_bits; } else if (extra == 3) { /* aligned bits only */ READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.ALIGNED, out aligned_bits); match_offset += (uint)aligned_bits; } else if (extra > 0) { /* extra==1, extra==2 */ /* verbatim bits only */ READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref verbatim_bits, extra); match_offset += (uint)verbatim_bits; } else /* extra == 0 */ { /* ??? */ match_offset = 1; } /* update repeated offset LRU queue */ R2 = R1; R1 = R0; R0 = match_offset; } else if (match_offset == 0) { match_offset = R0; } else if (match_offset == 1) { match_offset = R1; R1 = R0; R0 = match_offset; } else /* match_offset == 2 */ { match_offset = R2; R2 = R0; R0 = match_offset; } rundest = window + window_posn; this_run -= match_length; /* copy any wrapped around source data */ if (window_posn >= match_offset) { /* no wrap */ runsrc = rundest - match_offset; } else { runsrc = rundest + (window_size - match_offset); copy_length = (int)(match_offset - window_posn); if (copy_length < match_length) { match_length -= copy_length; window_posn += (uint)copy_length; while (copy_length-- > 0) { *rundest++ = *runsrc++; } runsrc = window; } } window_posn += (uint)match_length; /* copy match data - no worries about destination wraps */ while (match_length-- > 0) { *rundest++ = *runsrc++; } } } break; case LZX_BLOCKTYPE_UNCOMPRESSED: #if DEBUG_LZX_COMPRESSION Console.WriteLine("[B]LZX_BLOCKTYPE_UNCOMPRESSED"); #endif if ((inpos + this_run) > endinp) { Console.Error.WriteLine("Error: ((inpos + this_run) > endinp)"); return(DECR_ILLEGALDATA); } PointerUtils.Memcpy(window + window_posn, inpos, (int)this_run); inpos += this_run; window_posn += (uint)this_run; break; default: return(DECR_ILLEGALDATA); /* might as well */ } } } if (togo != 0) { return(DECR_ILLEGALDATA); } PointerUtils.Memcpy(outpos, window + ((window_posn == 0) ? window_size : window_posn) - outlen, (int)outlen); pState.window_posn = window_posn; pState.R0 = R0; pState.R1 = R1; pState.R2 = R2; /* intel E8 decoding */ if ((pState.frames_read++ < 32768) && pState.intel_filesize != 0) { if (outlen <= 6 || !pState.intel_started) { pState.intel_curpos += outlen; } else { byte *data = outpos; byte *dataend = data + outlen - 10; int curpos = pState.intel_curpos; int filesize = pState.intel_filesize; int abs_off, rel_off; pState.intel_curpos = curpos + outlen; while (data < dataend) { if (*data++ != 0xE8) { curpos++; continue; } abs_off = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); if ((abs_off >= -curpos) && (abs_off < filesize)) { rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize; data[0] = (byte)rel_off; data[1] = (byte)(rel_off >> 8); data[2] = (byte)(rel_off >> 16); data[3] = (byte)(rel_off >> 24); } data += 4; curpos += 5; } } } return(DECR_OK); } }
static bool lzx_read_lens(LZXstate pState, byte[] lens, uint first, uint last, lzx_bits *lb) { uint i = 0, j = 0, x = 0, y = 0; int z = 0; uint bitbuf = lb->bb; int bitsleft = lb->bl; byte *inpos = lb->ip; ushort[] hufftbl; for (x = 0; x < 20; x++) { READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 4); LENTABLE(pState.PRETREE)[x] = (byte)y; } BUILD_TABLE(pState.PRETREE); for (x = first; x < last;) { // static public void READ_HUFFSYM( READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.PRETREE, out z); if (z == 17) { READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 4); y += 4; while (y-- > 0) { lens[x++] = 0; } } else if (z == 18) { READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 5); y += 20; while (y-- > 0) { lens[x++] = 0; } } else if (z == 19) { READ_BITS(ref bitsleft, ref inpos, ref bitbuf, ref y, 1); y += 4; READ_HUFFSYM(out hufftbl, ref bitsleft, ref inpos, ref bitbuf, ref i, ref j, pState.PRETREE, out z); z = lens[x] - z; if (z < 0) { z += 17; } while (y-- > 0) { lens[x++] = (byte)z; } } else { z = lens[x] - z; if (z < 0) { z += 17; } lens[x++] = (byte)z; } } lb->bb = bitbuf; lb->bl = bitsleft; lb->ip = inpos; return(false); }
public static int LZXdecompress(LZXstate pState, ref UBYTE[] ip, long inpos, ref UBYTE[] op, ulong outpos, int inlen, int outlen) { long endinp = inpos + inlen; UBYTE[] window = pState.window; long runsrc = 0; long rundest = 0; UWORD[] hufftbl = null; /* used in READ_HUFFSYM macro as chosen decoding table */ ULONG window_posn = pState.window_posn; ULONG window_size = pState.window_size; ULONG R0 = pState.R0; ULONG R1 = pState.R1; ULONG R2 = pState.R2; ULONG bitbuf = 0; int bitsleft = 0; ULONG match_offset, i = 0, j = 0, k = 0; /* ijk used in READ_HUFFSYM macro */ lzx_bits lb = new lzx_bits(); /* used in READ_LENGTHS macro */ bool hr; int togo = outlen, this_run, main_element = 0, aligned_bits = 0; int match_length, length_footer = 0, extra; uint verbatim_bits = 0; INIT_BITSTREAM(ref bitsleft, ref bitbuf); /* read header if necessary */ if (!Convert.ToBoolean(pState.header_read)) { i = j = 0; READ_BITS(ref k, 1, ref bitbuf, ref bitsleft, ref ip, ref inpos); if (Convert.ToBoolean(k)) { READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos); READ_BITS(ref j, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos); } pState.intel_filesize = (LONG)((i << 16) | j); /* or 0 if not encoded */ pState.header_read = 1; } /* main decoding loop */ while (togo > 0) { /* last block finished, new block expected */ if (pState.block_remaining == 0) { if (pState.block_type == LZX_BLOCKTYPE_UNCOMPRESSED) { if (Convert.ToBoolean(pState.block_length & 1)) { inpos++; /* realign bitstream to word */ } INIT_BITSTREAM(ref bitsleft, ref bitbuf); } READ_BITS(ref pState.block_type, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos); READ_BITS(ref i, 16, ref bitbuf, ref bitsleft, ref ip, ref inpos); READ_BITS(ref j, 8, ref bitbuf, ref bitsleft, ref ip, ref inpos); pState.block_remaining = pState.block_length = (i << 8) | j; switch (pState.block_type) { case LZX_BLOCKTYPE_ALIGNED: for (i = 0; i < 8; i++) { READ_BITS(ref j, 3, ref bitbuf, ref bitsleft, ref ip, ref inpos); pState.ALIGNED_len[i] = (byte)j; } if (!BUILD_TABLE(ref pState.ALIGNED_table, ref pState.ALIGNED_len, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS)) { return(DECR_ILLEGALDATA); } /* rest of aligned header is same as verbatim */ goto case LZX_BLOCKTYPE_VERBATIM; case LZX_BLOCKTYPE_VERBATIM: if (!READ_LENGTHS(0, 256, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos, pState, ref pState.MAINTREE_len)) { return(DECR_ILLEGALDATA); } if (!READ_LENGTHS(256, pState.main_elements, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos, pState, ref pState.MAINTREE_len)) { return(DECR_ILLEGALDATA); } if (!BUILD_TABLE(ref pState.MAINTREE_table, ref pState.MAINTREE_len, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS)) { return(DECR_ILLEGALDATA); } if (pState.MAINTREE_len[0xE8] != 0) { pState.intel_started = 1; } if (!READ_LENGTHS(0, LZX_NUM_SECONDARY_LENGTHS, lb, ref bitbuf, ref bitsleft, ref ip, ref inpos, pState, ref pState.LENGTH_len)) { return(DECR_ILLEGALDATA); } if (!BUILD_TABLE(ref pState.LENGTH_table, ref pState.LENGTH_len, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS)) { return(DECR_ILLEGALDATA); } break; case LZX_BLOCKTYPE_UNCOMPRESSED: pState.intel_started = 1; /* because we can't assume otherwise */ ENSURE_BITS(ref bitsleft, ref bitbuf, ref ip, ref inpos, 16); /* get up to 16 pad bits into the buffer */ if (bitsleft > 16) { inpos -= 2; /* and align the bitstream! */ } R0 = (ULONG)(ip[inpos + 0] | (ip[inpos + 1] << 8) | (ip[inpos + 2] << 16) | (ip[inpos + 3] << 24)); inpos += 4; R1 = (ULONG)(ip[inpos + 0] | (ip[inpos + 1] << 8) | (ip[inpos + 2] << 16) | (ip[inpos + 3] << 24)); inpos += 4; R2 = (ULONG)(ip[inpos + 0] | (ip[inpos + 1] << 8) | (ip[inpos + 2] << 16) | (ip[inpos + 3] << 24)); inpos += 4; break; default: return(DECR_ILLEGALDATA); } } /* buffer exhaustion check */ if (inpos > endinp) { /* it's possible to have a file where the next run is less than * 16 bits in size. In this case, the READ_HUFFSYM() macro used * in building the tables will exhaust the buffer, so we should * allow for this, but not allow those accidentally read bits to * be used (so we check that there are at least 16 bits * remaining - in this boundary case they aren't really part of * the compressed data) */ if (inpos > (endinp + 2) || bitsleft < 16) { return(DECR_ILLEGALDATA); } } while ((this_run = (LONG)pState.block_remaining) > 0 && togo > 0) { if (this_run > togo) { this_run = togo; } togo -= this_run; pState.block_remaining -= (ULONG)this_run; /* apply 2^x-1 mask */ window_posn &= window_size - 1; /* runs can't straddle the window wraparound */ if ((window_posn + this_run) > window_size) { return(DECR_DATAFORMAT); } switch (pState.block_type) { case LZX_BLOCKTYPE_VERBATIM: while (this_run > 0) { hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element); if (!hr) { return(DECR_ILLEGALDATA); } if (main_element < LZX_NUM_CHARS) { /* literal: 0 to LZX_NUM_CHARS-1 */ window[window_posn++] = (UBYTE)main_element; this_run--; } else { /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ main_element -= LZX_NUM_CHARS; match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; if (match_length == LZX_NUM_PRIMARY_LENGTHS) { hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer); if (!hr) { return(DECR_ILLEGALDATA); } match_length += length_footer; } match_length += LZX_MIN_MATCH; match_offset = (ULONG)main_element >> 3; if (match_offset > 2) { /* not repeated offset */ if (match_offset != 3) { extra = extra_bits[match_offset]; READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft, ref ip, ref inpos); match_offset = position_base[match_offset] - 2 + verbatim_bits; } else { match_offset = 1; } /* update repeated offset LRU queue */ R2 = R1; R1 = R0; R0 = match_offset; } else if (match_offset == 0) { match_offset = R0; } else if (match_offset == 1) { match_offset = R1; R1 = R0; R0 = match_offset; } else /* match_offset == 2 */ { match_offset = R2; R2 = R0; R0 = match_offset; } rundest = window_posn; runsrc = rundest - match_offset; window_posn += (ULONG)match_length; if (window_posn > window_size) { return(DECR_ILLEGALDATA); } this_run -= match_length; /* copy any wrapped around source data */ while ((runsrc < 0) && (match_length-- > 0)) { window[rundest++] = window[runsrc + window_size]; runsrc++; } /* copy match data - no worries about destination wraps */ while (match_length-- > 0) { window[rundest++] = window[runsrc++]; } } } break; case LZX_BLOCKTYPE_ALIGNED: while (this_run > 0) { hr = READ_HUFFSYM(ref pState.MAINTREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_MAINTREE_TABLEBITS, LZX_MAINTREE_MAXSYMBOLS, ref pState.MAINTREE_len, ref j, ref main_element); if (!hr) { return(DECR_ILLEGALDATA); } if (main_element < LZX_NUM_CHARS) { /* literal: 0 to LZX_NUM_CHARS-1 */ window[window_posn++] = (UBYTE)main_element; this_run--; } else { /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ main_element -= LZX_NUM_CHARS; match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; if (match_length == LZX_NUM_PRIMARY_LENGTHS) { hr = READ_HUFFSYM(ref pState.LENGTH_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_LENGTH_TABLEBITS, LZX_LENGTH_MAXSYMBOLS, ref pState.LENGTH_len, ref j, ref length_footer); if (!hr) { return(DECR_ILLEGALDATA); } match_length += length_footer; } match_length += LZX_MIN_MATCH; match_offset = (ULONG)main_element >> 3; if (match_offset > 2) { /* not repeated offset */ extra = extra_bits[match_offset]; match_offset = position_base[match_offset] - 2; if (extra > 3) { /* verbatim and aligned bits */ extra -= 3; READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft, ref ip, ref inpos); match_offset += (verbatim_bits << 3); hr = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits); if (!hr) { return(DECR_ILLEGALDATA); } match_offset += (ULONG)aligned_bits; } else if (extra == 3) { /* aligned bits only */ hr = READ_HUFFSYM(ref pState.ALIGNED_table, ref hufftbl, ref bitsleft, ref bitbuf, ref ip, ref inpos, ref i, LZX_ALIGNED_TABLEBITS, LZX_ALIGNED_MAXSYMBOLS, ref pState.ALIGNED_len, ref j, ref aligned_bits); if (!hr) { return(DECR_ILLEGALDATA); } match_offset += (ULONG)aligned_bits; } else if (extra > 0) /* extra==1, extra==2 */ /* verbatim bits only */ { READ_BITS(ref verbatim_bits, extra, ref bitbuf, ref bitsleft, ref ip, ref inpos); match_offset += verbatim_bits; } else /* extra == 0 */ { /* ??? */ match_offset = 1; } /* update repeated offset LRU queue */ R2 = R1; R1 = R0; R0 = match_offset; } else if (match_offset == 0) { match_offset = R0; } else if (match_offset == 1) { match_offset = R1; R1 = R0; R0 = match_offset; } else /* match_offset == 2 */ { match_offset = R2; R2 = R0; R0 = match_offset; } rundest = window_posn; runsrc = rundest - match_offset; window_posn += (ULONG)match_length; if (window_posn > window_size) { return(DECR_ILLEGALDATA); } this_run -= match_length; /* copy any wrapped around source data */ while ((runsrc < 0) && (match_length-- > 0)) { window[rundest++] = window[runsrc + window_size]; runsrc++; } /* copy match data - no worries about destination wraps */ while (match_length-- > 0) { window[rundest++] = window[runsrc++]; } } } break; case LZX_BLOCKTYPE_UNCOMPRESSED: if ((inpos + this_run) > endinp) { return(DECR_ILLEGALDATA); } Array.Copy(ip, inpos, window, window_posn, this_run); inpos += this_run; window_posn += (ULONG)this_run; break; default: return(DECR_ILLEGALDATA); /* might as well */ } } } if (togo != 0) { return(DECR_ILLEGALDATA); } Array.Copy( window, (!Convert.ToBoolean(window_posn) ? window_size : window_posn) - outlen, op, (long)outpos, outlen); pState.window_posn = window_posn; pState.R0 = R0; pState.R1 = R1; pState.R2 = R2; /* intel E8 decoding */ if ((pState.frames_read++ < 32768) && pState.intel_filesize != 0) { if (outlen <= 6 || !Convert.ToBoolean(pState.intel_started)) { pState.intel_curpos += outlen; } else { ulong data = outpos; ulong dataend = outpos + (ulong)outlen - 10; LONG curpos = pState.intel_curpos; LONG filesize = pState.intel_filesize; LONG abs_off, rel_off; pState.intel_curpos = curpos + outlen; while (data < dataend) { if (op[data++] != 0xE8) { curpos++; continue; } abs_off = op[data + 0] | (op[data + 1] << 8) | (op[data + 2] << 16) | (op[data + 3] << 24); if ((abs_off >= -curpos) && (abs_off < filesize)) { rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize; op[data + 0] = (UBYTE)rel_off; op[data + 1] = (UBYTE)(rel_off >> 8); op[data + 2] = (UBYTE)(rel_off >> 16); op[data + 3] = (UBYTE)(rel_off >> 24); } data += 4; curpos += 5; } } } return(DECR_OK); }
private static int lzx_read_lens(LZXstate pState, ref UBYTE[] lens, ULONG first, ULONG last, lzx_bits lb) { ULONG i = 0, j = 0, x = 0, y = 0; int z = 0; ULONG bitbuf = lb.bb; int bitsleft = lb.bl; long inpos = lb.ippos; UWORD[] hufftbl = null; bool hr; for (x = 0; x < 20; x++) { READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); pState.PRETREE_len[x] = (byte)y; } if (!BUILD_TABLE(ref pState.PRETREE_table, ref pState.PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS)) { return(DECR_ILLEGALDATA); } for (x = first; x < last;) { hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, ref pState.PRETREE_len, ref j, ref z); if (!hr) { return(DECR_ILLEGALDATA); } if (z == 17) { READ_BITS(ref y, 4, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4; while (Convert.ToBoolean(y--)) { lens[x++] = 0; } } else if (z == 18) { READ_BITS(ref y, 5, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 20; while (Convert.ToBoolean(y--)) { lens[x++] = 0; } } else if (z == 19) { READ_BITS(ref y, 1, ref bitbuf, ref bitsleft, ref lb.ip, ref inpos); y += 4; hr = READ_HUFFSYM(ref pState.PRETREE_table, ref hufftbl, ref bitsleft, ref bitbuf, ref lb.ip, ref inpos, ref i, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS, ref pState.PRETREE_len, ref j, ref z); if (!hr) { return(DECR_ILLEGALDATA); } z = lens[x] - z; if (z < 0) { z += 17; } while (Convert.ToBoolean(y--)) { lens[x++] = (byte)z; } } else { z = lens[x] - z; if (z < 0) { z += 17; } lens[x++] = (byte)z; } } lb.bb = bitbuf; lb.bl = bitsleft; lb.ippos = inpos; return(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. */ private static bool READ_LENGTHS(ULONG first, ULONG last, lzx_bits lb, ref ULONG bitbuf, ref LONG bitsleft, ref UBYTE[] ip, ref long inpos, LZXstate pState, ref UBYTE[] tablelen) { lb.bb = bitbuf; lb.bl = bitsleft; lb.ip = ip; lb.ippos = inpos; if (lzx_read_lens(pState, ref tablelen, first, last, lb) != 0) { return(false); } bitbuf = lb.bb; bitsleft = lb.bl; inpos = lb.ippos; return(true); }
public static void LZXteardown(LZXstate pState) { }