/* * xDMS v1.3 - Portable DMS archive unpacker - Public Domain * Written by Andre Rodrigues de la Rocha * * Lempel-Ziv-Huffman decompression functions used in Heavy 1 & 2 * compression modes. Based on LZH decompression functions from * UNIX LHA made by Masaru Oki * */ #include "cdata.h" #include "u_heavy.h" #include "getbits.h" #include "maketbl.h" #define NC 510 #define NPT 20 #define N1 510 #define OFFSET 253 USHORT left[2 * NC - 1], right[2 * NC - 1 + 9]; static UCHAR c_len[NC], pt_len[NPT]; static USHORT c_table[4096], pt_table[256]; static USHORT lastlen, np; USHORT heavy_text_loc; static USHORT read_tree_c(void); static USHORT read_tree_p(void); INLINE USHORT decode_c(void); INLINE USHORT decode_p(void); USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){ USHORT j, i, c, bitmask; UCHAR *outend; /* Heavy 1 uses a 4Kb dictionary, Heavy 2 uses 8Kb */ if (flags & 8) { np = 15; bitmask = 0x1fff; } else { np = 14; bitmask = 0x0fff; } initbitbuf(in); if (flags & 2) { if (read_tree_c()) return 1; if (read_tree_p()) return 2; } outend = out+origsize; while (out>= 1; } while (j >= N1); DROPBITS(c_len[j] - 12); } return j; } INLINE USHORT decode_p(void){ USHORT i, j, m; j = pt_table[GETBITS(8)]; if (j < np) { DROPBITS(pt_len[j]); } else { DROPBITS(8); i = GETBITS(16); m = 0x8000; do { if (i & m) j = right[j]; else j = left [j]; m >>= 1; } while (j >= np); DROPBITS(pt_len[j] - 8); } if (j != np-1) { if (j > 0) { j = (USHORT)(GETBITS(i=(USHORT)(j-1)) | (1U << (j-1))); DROPBITS(i); } lastlen=j; } return lastlen; } static USHORT read_tree_c(void){ USHORT i,n; n = GETBITS(9); DROPBITS(9); if (n>0){ for (i=0; i0){ for (i=0; i