#include "de_lzah.h" #include "macunpack.h" #ifdef SIT #define DELZAH #endif /* SIT */ #ifdef LZH #define DELZAH #endif /* LZH */ #ifdef DELZAH #include "globals.h" #include "../util/masks.h" #include "../fileio/wrfile.h" /* Note: compare with LZSS decoding in lharc! */ #define N 314 #define T (2*N-1) /* Huffman table used for first 6 bits of offset: #bits codes 3 0x000 4 0x040-0x080 5 0x100-0x2c0 6 0x300-0x5c0 7 0x600-0xbc0 8 0xc00-0xfc0 */ static unsigned short HuffCode[] = { 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x040, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x080, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x180, 0x180, 0x180, 0x180, 0x180, 0x180, 0x180, 0x180, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x240, 0x240, 0x240, 0x240, 0x240, 0x240, 0x240, 0x240, 0x280, 0x280, 0x280, 0x280, 0x280, 0x280, 0x280, 0x280, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x2c0, 0x300, 0x300, 0x300, 0x300, 0x340, 0x340, 0x340, 0x340, 0x380, 0x380, 0x380, 0x380, 0x3c0, 0x3c0, 0x3c0, 0x3c0, 0x400, 0x400, 0x400, 0x400, 0x440, 0x440, 0x440, 0x440, 0x480, 0x480, 0x480, 0x480, 0x4c0, 0x4c0, 0x4c0, 0x4c0, 0x500, 0x500, 0x500, 0x500, 0x540, 0x540, 0x540, 0x540, 0x580, 0x580, 0x580, 0x580, 0x5c0, 0x5c0, 0x5c0, 0x5c0, 0x600, 0x600, 0x640, 0x640, 0x680, 0x680, 0x6c0, 0x6c0, 0x700, 0x700, 0x740, 0x740, 0x780, 0x780, 0x7c0, 0x7c0, 0x800, 0x800, 0x840, 0x840, 0x880, 0x880, 0x8c0, 0x8c0, 0x900, 0x900, 0x940, 0x940, 0x980, 0x980, 0x9c0, 0x9c0, 0xa00, 0xa00, 0xa40, 0xa40, 0xa80, 0xa80, 0xac0, 0xac0, 0xb00, 0xb00, 0xb40, 0xb40, 0xb80, 0xb80, 0xbc0, 0xbc0, 0xc00, 0xc40, 0xc80, 0xcc0, 0xd00, 0xd40, 0xd80, 0xdc0, 0xe00, 0xe40, 0xe80, 0xec0, 0xf00, 0xf40, 0xf80, 0xfc0}; static short HuffLength[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; unsigned char (*lzah_getbyte)(void); static void lzah_inithuf(void); static void lzah_reorder(void); static void lzah_move(int *p, int *q, int n); static void lzah_getbit(void); static void lzah_outchar(int ch); static char lzah_buf[4096]; static int lzah_bufptr; static int lzah_bitsavail; static int lzah_bits; static int Frequ[1000]; static int ForwTree[1000]; static int BackTree[1000]; void de_lzah(uint32_t obytes) { int i, i1, j, ch, byte, offs, skip; lzah_inithuf(); lzah_bitsavail = 0; for(i = 0; i < 4036; i++) { lzah_buf[i] = ' '; } lzah_bufptr = 4036; while(obytes != 0) { ch = ForwTree[T - 1]; while(ch < T) { lzah_getbit(); if(lzah_bits & 0x80) { ch = ch + 1; } ch = ForwTree[ch]; } ch -= T; if(Frequ[T - 1] >= 0x8000) { lzah_reorder(); } i = BackTree[ch + T]; do { j = ++Frequ[i]; i1 = i + 1; if(Frequ[i1] < j) { while(Frequ[++i1] < j) ; i1--; Frequ[i] = Frequ[i1]; Frequ[i1] = j; j = ForwTree[i]; BackTree[j] = i1; if(j < T) { BackTree[j + 1] = i1; } ForwTree[i] = ForwTree[i1]; ForwTree[i1] = j; j = ForwTree[i]; BackTree[j] = i; if(j < T) { BackTree[j + 1] = i; } i = i1; } i = BackTree[i]; } while(i != 0); if(ch < 256) { lzah_outchar((char)ch); obytes--; } else { if(lzah_bitsavail != 0) { byte = (lzah_bits << 1) & BYTEMASK; lzah_bits = (*lzah_getbyte)() & BYTEMASK; byte |= (lzah_bits >> lzah_bitsavail); lzah_bits = lzah_bits << (7 - lzah_bitsavail); } else { byte = (*lzah_getbyte)() & BYTEMASK; } offs = HuffCode[byte]; skip = HuffLength[byte] - 2; while(skip-- != 0) { byte = byte + byte; lzah_getbit(); if(lzah_bits & 0x80) { byte++; } } offs |= (byte & 0x3f); offs = ((lzah_bufptr - offs - 1) & 0xfff); ch = ch - 253; while(ch-- > 0) { lzah_outchar(lzah_buf[offs++ & 0xfff]); obytes--; if(obytes == 0) { break; } } } } } static void lzah_inithuf (void) { int i, j; for(i = 0; i < N; i++) { Frequ[i] = 1; ForwTree[i] = i + T; BackTree[i + T] = i; } for(i = 0, j = N; j < T; i += 2, j++) { Frequ[j] = Frequ[i] + Frequ[i + 1]; ForwTree[j] = i; BackTree[i] = j; BackTree[i + 1] = j; } Frequ[T] = 0xffff; BackTree[T - 1] = 0; } static void lzah_reorder (void) { int i, j, k, l; j = 0; for(i = 0; i < T; i++) { if(ForwTree[i] >= T) { Frequ[j] = ((Frequ[i] + 1) >> 1); ForwTree[j] = ForwTree[i]; j++; } } for(i = 0, j = N; i < T; i += 2, j++) { k = i + 1; l = Frequ[i] + Frequ[k]; Frequ[j] = l; k = j - 1; while(l < Frequ[k]) { k--; } k = k + 1; lzah_move(Frequ + k, Frequ + k + 1, j - k); Frequ[k] = l; lzah_move(ForwTree + k, ForwTree + k + 1, j - k); ForwTree[k] = i; } for(i = 0; i < T; i++) { k = ForwTree[i]; if(k >= T) { BackTree[k] = i; } else { BackTree[k] = i; BackTree[k + 1] = i; } } } static void lzah_move(int *p, int *q, int n) { if(p > q) { while(n-- > 0) { *q++ = *p++; } } else { p += n; q += n; while(n-- > 0) { *--q = *--p; } } } static void lzah_getbit (void) { if(lzah_bitsavail != 0) { lzah_bits = lzah_bits + lzah_bits; lzah_bitsavail--; } else { lzah_bits = (*lzah_getbyte)() & BYTEMASK; lzah_bitsavail = 7; } } static void lzah_outchar (int ch) { *out_ptr++ = ch; lzah_buf[lzah_bufptr++] = ch; lzah_bufptr &= 0xfff; } #else /* DELZAH */ int delzah; /* keep lint and some compilers happy */ #endif /* DELZAH */