/* This decompressor uses modified code from zlib. Below is it's original copyright notice. Copyright (C) 2003, 2012 Mark Adler version 1.2, 24 Oct 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Mark Adler madler@alumni.caltech.edu */ #include #include #include #include "mystdlib.h" #include /* uint8_t table[] = { 0x00, 0x39, 0x20, 0x15, 0x24, 0x04, 0x61, 0x80, 0xc4, 0xc0, 0x1f, 0xa4, 0x04, 0xca, 0x40, 0xb4, 0x08, 0x19, 0xe7, 0x03, 0xab, 0xe0, 0x83, 0xac, 0x12, 0x92, 0x82, 0x95, 0x10, 0x5b, 0x24, 0x0c, 0x75, 0x81, 0xaf, 0xe0, 0x3a, 0x24, 0x07, 0xc7, 0xc1, 0x09, 0x88, 0x23, 0x55, 0x84, 0xac, 0x50, 0x9d, 0xc6, 0x14, 0xc3, 0x82, 0xb9, 0x30, 0x5b, 0x54, 0x0b, 0xf1, 0x81, 0x8e, 0xbc, 0x33, 0xce, 0x86, 0xb9, 0xa0, 0xdf, 0xae, 0x1d, 0x04, 0x03, 0xc0, 0xf8, 0x7c, 0x13, 0x0f, 0xf0, 0x22, 0x0b, 0xa8, 0x43, 0x3e, 0x88, 0xa0, 0xd1, 0x1b, 0x48, 0x24, 0x61, 0x84, 0xad, 0xb0, 0x99, 0xe0, 0x13, 0xc0, 0x62, 0x87, 0xdc, 0x52, 0xba, 0x8a, 0x8f, 0x31, 0x59, 0x0e, 0x2c, 0x16, 0x85, 0xa0, 0x38, 0xb7, 0x8a, 0x17, 0x66, 0xc2, 0xfb, 0x50, 0x61, 0x3f, 0x8c, 0x5f, 0x01, 0x93, 0x76, 0x33, 0x6f, 0x46, 0x8e, 0x18, 0xd5, 0x6f, 0x1b, 0x1e, 0x83, 0x71, 0x6c, 0x6f, 0xfc, 0x0e, 0x3d, 0x91, 0xcf, 0x08, 0x3a, 0xc4, 0x87, 0x75, 0x80, 0xf2, 0x23, 0x1e, 0xb4, 0x83, 0xe4, 0xe0, 0x7e, 0x6d, 0x10, 0x06, 0x22, 0x08, 0x5a, 0x41, 0xf8, 0x48, 0x5b, 0x11, 0x0e, 0xce, 0x22, 0x46, 0x44, 0x56, 0x84, 0x8c, 0xc9, 0x91, 0xdc, 0x22, 0x44, 0x26, 0x49, 0x9f, 0x49, 0x56, 0x71, 0x2f, 0x18, 0x26, 0x6d, 0xa4, 0xde, 0xdc, 0x9e, 0x02, 0x94, 0x04, 0xc2, 0x89, 0x38, 0x52, 0x31, 0x8a, 0x68, 0x39, 0x51, 0x64, 0x2a, 0xb0, 0x45, 0x65, 0x80, 0xae, 0xbf, 0x16, 0x19, 0x12, 0xcb, 0x48, 0x5a, 0x6b, 0xcb, 0x6a, 0x11, 0x70, 0xa3, 0x2e, 0x80, 0x85, 0xdd, 0xf0, 0xbd, 0x7a, 0x97, 0xe5, 0xb3, 0x03, 0xbc, 0x61, 0x67, 0xcc, 0x49, 0xe1, 0x8d, 0x11, 0x32, 0x28, 0x66, 0x53, 0xd8, 0xcc, 0x2b, 0x19, 0xbd, 0x93, 0x3e, 0x54, 0x68, 0xae, 0x4d, 0x35, 0xe1, 0xaa, 0xbe, 0x35, 0xd5, 0x46, 0xc8, 0x30, 0xda, 0xd0, 0x9b, 0x95, 0x73, 0x7a, 0xc8, 0x70, 0x43, 0x4e, 0x23, 0x19, 0xc8, 0x41, 0x39, 0x76, 0x07, 0x3d, 0xb8, 0xe9, 0x79, 0x9d, 0x65, 0xe3, 0xb3, 0x94, 0x77, 0x47, 0xcf, 0x04, 0xf1, 0xe3, 0xfc, 0x3c, 0xf0, 0x27, 0xac, 0x30, 0xf7, 0x4b, 0x1f, 0x25, 0x03, 0xec, 0x0a, 0x7e, 0x65, 0xcf, 0xe8, 0x1a, 0x00, 0xa7, 0x40, 0x8d, 0xc8, 0x21, 0x45, 0x05, 0xf5, 0xa0, 0xf7, 0x34, 0x25, 0xd0, 0x85, 0x9a, 0x50, 0xcf, 0x02, 0x1d, 0xd2, 0x44, 0x2c, 0x28, 0x93, 0xdd, 0x14, 0x36, 0x22, 0xbf, 0x24, 0x5e, 0x86, 0x8c, 0xa9, 0x91, 0xb1, 0x8a, 0x39, 0xd3, 0x47, 0xab, 0x29, 0x03, 0x29, 0x22, 0x28, 0xa4, 0x7b, 0xc4, 0x96, 0x68, 0x93, 0xb9, 0x12, 0x92, 0xfa, 0x55, 0xd2, 0x4b, 0x2d, 0x29, 0x74, 0x05, 0x30, 0x38, 0xa6, 0x40, 0xd4, 0xcf, 0x6e, 0x9a, 0xcc, 0x13, 0x74, 0xda, 0x72, 0x0a, 0x4e, 0xb3, 0x29, 0xe4, 0xa9, 0x3e, 0x60, 0xa8, 0x04, 0xa5, 0x07, 0xce, 0xa1, 0xe7, 0xc0 }; */ #define MAXBITS 13 /* maximum code length */ #define MAXWIN 8192 /* maximum window size */ struct state { uint8_t *in; /* next input location */ uint8_t *out; /* output buffer and sliding window */ unsigned left; /* available input at in */ int bitbuf; /* bit buffer */ int bitcnt; /* number of bits in bit buffer */ unsigned next; /* index of next write location in out[] */ int first; /* true to check distances (for first 4K) */ }; static int bits(struct state *s, int need) { int val; /* bit accumulator */ /* load at least need bits into val */ val = s->bitbuf; while (s->bitcnt < need) { val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */ s->left--; s->bitcnt += 8; } /* drop need bits and update buffer, always zero to seven bits left */ s->bitbuf = val >> need; s->bitcnt -= need; /* return need bits, zeroing the bits above that */ return val & ((1 << need) - 1); } struct huffman { short *count; /* number of symbols of each length */ short *symbol; /* canonically ordered symbols */ }; static int decode(struct state *s, struct huffman *h) { int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */ int bitbuf; /* bits from stream */ int left; /* bits left in next or left to process */ short *next; /* next number of codes */ bitbuf = s->bitbuf; left = s->bitcnt; code = first = index = 0; len = 1; next = h->count + 1; while (1) { while (left--) { code |= (bitbuf & 1) ^ 1; /* invert code */ bitbuf >>= 1; count = *next++; if (code < first + count) { /* if length len, return symbol */ s->bitbuf = bitbuf; s->bitcnt = (s->bitcnt - len) & 7; return h->symbol[index + (code - first)]; } index += count; /* else update for next length */ first += count; first <<= 1; code <<= 1; len++; } left = (MAXBITS+1) - len; if (left == 0) break; bitbuf = *(s->in)++; s->left--; if (left > 8) left = 8; } return -9; /* ran out of codes */ } static int construct(struct huffman *h, const unsigned char *rep, int n) { int symbol; /* current symbol when stepping through length[] */ int len; /* current length when stepping through h->count[] */ int left; /* number of possible codes left of current length */ short offs[MAXBITS+1]; /* offsets in symbol table for each length */ short length[256]; /* code lengths */ /* convert compact repeat counts into symbol bit length list */ symbol = 0; do { len = *rep++; left = (len >> 4) + 1; len &= 15; do { length[symbol++] = len; } while (--left); } while (--n); n = symbol; /* count number of codes of each length */ for (len = 0; len <= MAXBITS; len++) h->count[len] = 0; for (symbol = 0; symbol < n; symbol++) (h->count[length[symbol]])++; /* assumes lengths are within bounds */ if (h->count[0] == n) /* no codes! */ return 0; /* complete, but decode() will fail */ /* check for an over-subscribed or incomplete set of lengths */ left = 1; /* one possible code of zero length */ for (len = 1; len <= MAXBITS; len++) { left <<= 1; /* one more bit, double codes left */ left -= h->count[len]; /* deduct count from possible codes */ if (left < 0) return left; /* over-subscribed--return negative */ } /* left > 0 means incomplete */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len]; /* * put symbols in table sorted by length, by symbol order within each * length */ for (symbol = 0; symbol < n; symbol++) if (length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol; /* return zero for complete set, positive for incomplete set */ return left; } /* * Decode PKWare Compression Library stream. * * Format notes: * * - First byte is 0 if literals are uncoded or 1 if they are coded. Second * byte is 4, 5, or 6 for the number of extra bits in the distance code. * This is the base-2 logarithm of the dictionary size minus six. * * - Compressed data is a combination of literals and length/distance pairs * terminated by an end code. Literals are either Huffman coded or * uncoded bytes. A length/distance pair is a coded length followed by a * coded distance to represent a string that occurs earlier in the * uncompressed data that occurs again at the current location. * * - A bit preceding a literal or length/distance pair indicates which comes * next, 0 for literals, 1 for length/distance. * * - If literals are uncoded, then the next eight bits are the literal, in the * normal bit order in th stream, i.e. no bit-reversal is needed. Similarly, * no bit reversal is needed for either the length extra bits or the distance * extra bits. * * - Literal bytes are simply written to the output. A length/distance pair is * an instruction to copy previously uncompressed bytes to the output. The * copy is from distance bytes back in the output stream, copying for length * bytes. * * - Distances pointing before the beginning of the output data are not * permitted. * * - Overlapped copies, where the length is greater than the distance, are * allowed and common. For example, a distance of one and a length of 518 * simply copies the last byte 518 times. A distance of four and a length of * twelve copies the last four bytes three times. A simple forward copy * ignoring whether the length is greater than the distance or not implements * this correctly. */ static int decomp(struct state *s) { int lit; /* true if literals are coded */ int dict; /* log2(dictionary size) - 6 */ int symbol; /* decoded symbol, extra bits for distance */ int len; /* length for copy */ unsigned dist; /* distance for copy */ int copy; /* copy counter */ unsigned char *from, *to; /* copy pointers */ static int virgin = 1; /* build tables once */ static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */ static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */ static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */ static struct huffman litcode = {litcnt, litsym}; /* length code */ static struct huffman lencode = {lencnt, lensym}; /* length code */ static struct huffman distcode = {distcnt, distsym};/* distance code */ /* bit lengths of literal codes */ static const unsigned char litlen[] = { 11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8, 9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5, 7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12, 8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27, 44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45, 44, 173}; /* bit lengths of length codes 0..15 */ static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23}; /* bit lengths of distance codes 0..63 */ static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248}; static const short base[16] = { /* base for length codes */ 3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264}; static const char extra[16] = { /* extra bits for length codes */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}; /* set up decoding tables (once--might not be thread-safe) */ if (virgin) { construct(&litcode, litlen, sizeof(litlen)); construct(&lencode, lenlen, sizeof(lenlen)); construct(&distcode, distlen, sizeof(distlen)); virgin = 0; } /* read header */ lit = bits(s, 8); if (lit > 1) return -1; dict = bits(s, 8); if (dict < 4 || dict > 6) return -2; /* decode literals and length/distance pairs */ do { if (bits(s, 1)) { /* get length */ symbol = decode(s, &lencode); len = base[symbol] + bits(s, extra[symbol]); if (len == 519) break; /* end code */ /* get distance */ symbol = len == 2 ? 2 : dict; dist = decode(s, &distcode) << symbol; dist += bits(s, symbol); dist++; if (s->first && dist > s->next) return -3; /* distance too far back */ /* copy length bytes from distance bytes back */ do { to = s->out + s->next; from = to - dist; copy = MAXWIN; if (s->next < dist) { from += copy; copy = dist; } copy -= s->next; if (copy > len) copy = len; len -= copy; s->next += copy; do { *to++ = *from++; } while (--copy); } while (len != 0); } else { /* get literal and write it */ symbol = lit ? decode(s, &litcode) : bits(s, 8); s->out[s->next++] = symbol; } } while (1); return 0; } static void decompress_subchunk( uint8_t * subchunk, size_t subchunk_size, int chunks, size_t outchunk_size ) { uint8_t output[ outchunk_size ]; struct state s; /* input/output state */ int err; /* return value */ memset( output, 0, outchunk_size ); /* initialize input state */ s.in = subchunk; s.left = subchunk_size; while( chunks-- ) { int i; /* (Re-)initialize output state */ s.out = output; s.next = 0; s.first = 1; s.bitbuf = 0; s.bitcnt = 0; err = decomp(&s); if( err ) { for( i=0; i<32; ++i ) fprintf( stderr, "%02X ", s.in[i] ); fprintf( stderr, "\nError: %d\n", err ); return; } /* Dump to stdout for now */ fwrite( output, outchunk_size, 1, stdout ); } } static void decode_19bit_address( uint8_t const *source, uint32_t *dest, size_t length ) { uint32_t acc_bits = 0, acc = 0; while( 1 ) { acc = acc*256+*(source++); acc_bits+=8; if( acc_bits >= 19 ) { uint32_t tmp = acc >> (acc_bits-19); *(dest++) = (tmp & 0x7ffff) << 11; acc_bits -= 19; if( !length-- ) return; } } } int main( int args, char **argv ) { MAP file; uint32_t offsets[256]; uint16_t num_subchunks, subchunk_rest_count, subchunk_one_count; uint8_t *fp, *subchunk; int i; if( args < 2 ) { fprintf( stderr, "Syntax: %s FILENAME\n", argv[0] ); exit(1); } file = map_file( argv[1], 1 ); if( !file ) exit( 1 ); fp = file->addr; num_subchunks = *(uint16_t*)(fp+0x14); subchunk_rest_count = *(uint16_t*)(fp+0x1c); subchunk_one_count = *(uint16_t*)(fp+0x1e); subchunk = fp + 0x20 + ( 19*num_subchunks +7 )/ 8; decode_19bit_address ( fp + 0x20, offsets, num_subchunks ); offsets[num_subchunks] = file->size; decompress_subchunk( subchunk, offsets[i], subchunk_one_count, MAXWIN ); for( i=0; i< num_subchunks; ++i ) if( offsets[i] + 0x800 < file->size ) decompress_subchunk( fp + offsets[i] + 0x800, offsets[i+1] - offsets[i], subchunk_rest_count, MAXWIN ); return 0; }