#include "macunpack.h" #ifdef ZMA #define DELZH #endif /* ZMA */ #ifdef LZH #define DELZH #endif /* LZH */ #ifdef DELZH #include "globals.h" #include "../util/masks.h" #include "../fileio/wrfile.h" #include "bits_be.h" /* This code is valid for bitsused upto 15. */ #define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */ #define UCHAR_MAX 255 #define THRESHOLD 3 static int decoded; static int bitsused; static unsigned int blocksize; static unsigned int decode_c(void); static unsigned int decode_p(void); static void make_table(int nchar, unsigned char bitlen[], int tablebits, unsigned int table[]); /* lzh compression */ void de_lzh(int32_t ibytes, int32_t obytes, char **data, int bits) { unsigned int i, r, c; int remains; bit_be_inbytes = ibytes; bit_be_filestart = *data; bitsused = bits; bit_be_init_getbits(); blocksize = 0; decoded = 0; r = 0; for(;;) { c = decode_c(); if(decoded) { *data = bit_be_filestart; return; } if(c <= UCHAR_MAX) { out_ptr[r++] = c; obytes--; if(obytes == 0) { *data = bit_be_filestart; return; } } else { remains = c - (UCHAR_MAX + 1 - THRESHOLD); i = (r - decode_p() - 1); while(--remains >= 0) { out_ptr[r++] = out_ptr[i++]; obytes--; if(obytes == 0) { *data = bit_be_filestart; return; } } } } } #define MAXMATCH 256 #define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD) #define CBIT 9 #define CODE_BIT 16 #define NP (DICBIT + 1) #define NT (CODE_BIT + 3) #define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */ #define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */ #if NT > NP # define NPT NT #else # define NPT NP #endif static unsigned int left[2 * NC - 1], right[2 * NC - 1]; static unsigned char c_len[NC], pt_len[NPT]; static unsigned int c_table[4096], pt_table[256]; static void read_pt_len (int nn, int nbit, int i_special) { int i, c, n; unsigned int mask; n = bit_be_getbits(nbit); if (n == 0) { c = bit_be_getbits(nbit); for (i = 0; i < nn; i++) { pt_len[i] = 0; } for (i = 0; i < 256; i++) { pt_table[i] = c; } } else { i = 0; while (i < n) { c = bit_be_bitbuf >> (BITBUFSIZ - 3); if (c == 7) { mask = (unsigned) 1 << (BITBUFSIZ - 1 - 3); while (mask & bit_be_bitbuf) { mask >>= 1; c++; } } bit_be_fillbuf((c < 7) ? 3 : c - 3); pt_len[i++] = c; if (i == i_special) { c = bit_be_getbits(2); while (--c >= 0) { pt_len[i++] = 0; } } } while (i < nn) { pt_len[i++] = 0; } make_table(nn, pt_len, 8, pt_table); } } static void read_c_len (void) { int i, c, n; unsigned int mask; n = bit_be_getbits(CBIT); if (n == 0) { c = bit_be_getbits(CBIT); for (i = 0; i < NC; i++) { c_len[i] = 0; } for (i = 0; i < 4096; i++) { c_table[i] = c; } } else { i = 0; while (i < n) { c = pt_table[bit_be_bitbuf >> (BITBUFSIZ - 8)]; if (c >= NT) { mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8); do { if (bit_be_bitbuf & mask) { c = right[c]; } else { c = left [c]; } mask >>= 1; } while (c >= NT); } bit_be_fillbuf((int)pt_len[c]); if (c <= 2) { if (c == 0) { c = 1; } else if (c == 1) { c = bit_be_getbits(4) + 3; } else { c = bit_be_getbits(CBIT) + 20; } while (--c >= 0) { c_len[i++] = 0; } } else { c_len[i++] = c - 2; } } while (i < NC) { c_len[i++] = 0; } make_table(NC, c_len, 12, c_table); } } static unsigned int decode_c (void) { unsigned int j, mask; if (blocksize == 0) { blocksize = bit_be_getbits(16); if (blocksize == 0) { decoded = 1; return 0; } read_pt_len(NT, TBIT, 3); read_c_len(); read_pt_len(bitsused + 1, PBIT, -1); } blocksize--; j = c_table[bit_be_bitbuf >> (BITBUFSIZ - 12)]; if (j >= NC) { mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12); do { if (bit_be_bitbuf & mask) { j = right[j]; } else { j = left [j]; } mask >>= 1; } while (j >= NC); } bit_be_fillbuf((int)c_len[j]); return j; } static unsigned int decode_p (void) { unsigned int j, mask; j = pt_table[bit_be_bitbuf >> (BITBUFSIZ - 8)]; if (j > bitsused) { mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8); do { if (bit_be_bitbuf & mask) { j = right[j]; } else { j = left [j]; } mask >>= 1; } while (j > bitsused); } bit_be_fillbuf((int)pt_len[j]); if (j != 0) { j = ((unsigned) 1 << (j - 1)) + bit_be_getbits((int) (j - 1)); } return j; } static void make_table (int nchar, unsigned char bitlen[], int tablebits, unsigned int table[]) { unsigned int count[17], weight[17], start[18], *p; unsigned int i, k, len, ch, jutbits, avail, nextcode, mask; for (i = 1; i <= 16; i++) { count[i] = 0; } for (i = 0; i < nchar; i++) { count[bitlen[i]]++; } start[1] = 0; for (i = 1; i <= 16; i++) { start[i + 1] = start[i] + (count[i] << (16 - i)); } jutbits = 16 - tablebits; for (i = 1; i <= tablebits; i++) { start[i] >>= jutbits; weight[i] = (unsigned) 1 << (tablebits - i); } while (i <= 16) { weight[i] = (unsigned) 1 << (16 - i); i++; } i = start[tablebits + 1] >> jutbits; if (i != (unsigned int)((unsigned) 1 << 16)) { k = 1 << tablebits; while (i != k) { table[i++] = 0; } } avail = nchar; mask = (unsigned) 1 << (15 - tablebits); for (ch = 0; ch < nchar; ch++) { if ((len = bitlen[ch]) == 0) { continue; } nextcode = start[len] + weight[len]; if (len <= tablebits) { for (i = start[len]; i < nextcode; i++) { table[i] = ch; } } else { k = start[len]; p = &table[k >> jutbits]; i = len - tablebits; while (i != 0) { if (*p == 0) { right[avail] = left[avail] = 0; *p = avail++; } if (k & mask) { p = &right[*p]; } else { p = &left[*p]; } k <<= 1; i--; } *p = ch; } start[len] = nextcode; } } #else /* DELZH */ int delzh; /* keep lint and some compilers happy */ #endif /* DELZH */