/* * extract.c -- global extracting function for all known file compressions * in a MPQ archive. * * Copyright (C) 2003 Maik Broemme * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Ripped from libmpq and compacted into this one large file. */ #include #include #include #include #include "extract.h" #define FALSE 0 #define TRUE !FALSE typedef int (*DECOMPRESS) (char *, int *, const char *, int); typedef struct { unsigned long mask; /* Decompression bit */ DECOMPRESS decompress; /* Decompression function */ } decompress_table; static int pkzip_decompress(char *out_buf, int *out_length, const char *in_buf, int in_length); static int zlib_decompress(char *out_buf, int *out_length, const char *in_buf, int in_length); static int huff_decompress(char *out_buf, int *out_length, const char *in_buf, int in_length); static int adpcm_decompress_mono(char *out_buf, int *out_length, const char *in_buf, int in_length); static int adpcm_decompress_stereo(char *out_buf, int *out_length, const char *in_buf, int in_length); static decompress_table dcmp_table[] = { {0x08, pkzip_decompress}, /* Decompression with Pkware Data Compression Library */ {0x02, zlib_decompress}, /* Decompression with the "zlib" library */ {0x01, huff_decompress}, /* Huffmann decompression */ {0x80, adpcm_decompress_stereo}, /* adpcm decompression for stereo adpcms */ {0x40, adpcm_decompress_mono} /* adpcm decompression for mono adpcms */ }; /* * ADPCM decompression */ typedef union { unsigned short *pw; unsigned char *pb; } byte_and_short; /* * Tables necessary for decompression */ static unsigned long adpcm_step_changes[] = { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008 }; static unsigned long adpcm_steps[] = { 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F, 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042, 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F, 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133, 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292, 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583, 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0, 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954, 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B, 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462, 0x00007FFF }; /* * Decompress a adpcm file, mono or stereo * * Offset: 1500F230 */ static int adpcm_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels) { byte_and_short out; byte_and_short in; unsigned char *in_end = in_buf + in_length; /* End on input buffer */ unsigned long index; long nr_array1[2]; long nr_array2[2]; int count = 0; out.pb = out_buf; in.pb = in_buf; nr_array1[0] = 0x2C; nr_array1[1] = 0x2C; in.pw++; /* * 15007AD7 */ for (count = 0; count < channels; count++) { long temp; temp = *(short *) in.pw++; nr_array2[count] = temp; if (out_length < 2) { return out.pb - out_buf; } *out.pw++ = (unsigned short) temp; out_length -= 2; } index = channels - 1; while (in.pb < in_end) { unsigned char one_byte = *in.pb++; if (channels == 2) { index = (index == 0) ? 1 : 0; } /* * Get one byte from input buffer * 15007B25 */ if (one_byte & 0x80) { /* * 15007B32 */ switch (one_byte & 0x7F) { case 0: /* 15007B8E */ if (nr_array1[index] != 0) { nr_array1[index]--; } if (out_length < 2) { break; } *out.pw++ = (unsigned short) nr_array2[index]; out_length -= 2; continue; case 1: /* 15007B72 */ nr_array1[index] += 8; /* EBX also */ if (nr_array1[index] > 0x58) { nr_array1[index] = 0x58; } if (channels == 2) { index = (index == 0) ? 1 : 0; } continue; case 2: continue; default: nr_array1[index] -= 8; if (nr_array1[index] < 0) { nr_array1[index] = 0; } if (channels != 2) { continue; } index = (index == 0) ? 1 : 0; continue; } } else { unsigned long temp1 = adpcm_steps[nr_array1[index]]; /* EDI */ unsigned long temp2 = temp1 >> in_buf[1]; /* ESI */ long temp3 = nr_array2[index]; /* ECX */ if (one_byte & 0x01) { /* EBX = one_byte */ temp2 += (temp1 >> 0); } if (one_byte & 0x02) { temp2 += (temp1 >> 1); } if (one_byte & 0x04) { temp2 += (temp1 >> 2); } if (one_byte & 0x08) { temp2 += (temp1 >> 3); } if (one_byte & 0x10) { temp2 += (temp1 >> 4); } if (one_byte & 0x20) { temp2 += (temp1 >> 5); } if (one_byte & 0x40) { temp3 -= temp2; if (temp3 <= (long) 0xFFFF8000) { temp3 = (long) 0xFFFF8000; } } else { temp3 += temp2; if (temp3 >= 0x7FFF) { temp3 = 0x7FFF; } } nr_array2[index] = temp3; if (out_length < 2) { break; } temp2 = nr_array1[index]; one_byte &= 0x1F; *out.pw++ = (unsigned short) temp3; out_length -= 2; temp2 += adpcm_step_changes[one_byte]; nr_array1[index] = temp2; if (nr_array1[index] < 0) { nr_array1[index] = 0; } else { if (nr_array1[index] > 0x58) { nr_array1[index] = 0x58; } } } } return (out.pb - out_buf); } /* * Huffman decompression */ #define PTR_NOT(ptr) (struct huffman_tree_item *)(~(unsigned long)(ptr)) #define PTR_PTR(ptr) ((struct huffman_tree_item *)(ptr)) #define PTR_INT(ptr) (long)(ptr) #define INSERT_ITEM 1 #define SWITCH_ITEMS 2 /* Switch the item1 and item2 */ /* * Input stream for Huffmann decompression */ struct huffman_input_stream { unsigned char *in_buf; /* 00 - Input data */ unsigned long bit_buf; /* 04 - Input bit buffer */ unsigned int bits; /* 08 - Number of bits remaining in 'byte' */ }; /* * Huffmann tree item. */ struct huffman_tree_item { struct huffman_tree_item *next; /* 00 - Pointer to next huffman_tree_item */ struct huffman_tree_item *prev; /* 04 - Pointer to prev huffman_tree_item (< 0 if none) */ unsigned long dcmp_byte; /* 08 - Index of this item in item pointer array, decompressed byte * value */ unsigned long byte_value; /* 0C - Some byte value */ struct huffman_tree_item *parent; /* 10 - Pointer to parent huffman_tree_item (NULL if none) */ struct huffman_tree_item *child; /* 14 - Pointer to child huffman_tree_item */ }; /* * Structure used for quick decompress. The 'bits' contains * number of bits and dcmp_byte contains result decompressed byte * value. After each walk through Huffman tree are filled all entries * which are multiplies of number of bits loaded from input stream. * These entries contain number of bits and result value. At the next * 7 bits is tested this structure first. If corresponding entry found, * decompression routine will not walk through Huffman tree and * directly stores output byte to output stream. */ struct huffman_decompress { unsigned long offs00; /* 00 - 1 if resolved */ unsigned long bits; /* 04 - Bit count */ union { unsigned long dcmp_byte; /* 08 - Byte value for decompress (if bitCount <= 7) */ struct huffman_tree_item *p_item; /* 08 - THTreeItem (if number of bits is greater * than 7 */ }; }; /* * Structure for Huffman tree. */ struct huffman_tree { unsigned long cmp0; /* 0000 - 1 if compression type 0 */ unsigned long offs0004; /* 0004 - Some flag */ struct huffman_tree_item items0008[0x203]; /* 0008 - huffman tree items */ /* * Sometimes used as huffman tree item */ struct huffman_tree_item *item3050; /* 3050 - Always NULL (?) */ struct huffman_tree_item *item3054; /* 3054 - Pointer to huffman_tree_item */ struct huffman_tree_item *item3058; /* 3058 - Pointer to huffman_tree_item (< 0 if invalid) */ /* * Sometimes used as huffman tree item */ struct huffman_tree_item *item305C; /* 305C - Usually NULL */ struct huffman_tree_item *first; /* 3060 - Pointer to top (first) Huffman tree item */ struct huffman_tree_item *last; /* 3064 - Pointer to bottom (last) Huffman tree item (< 0 * if invalid) */ unsigned long items; /* 3068 - Number of used huffman tree items */ struct huffman_tree_item *items306C[0x102]; /* 306C - huffman_tree_item pointer array */ struct huffman_decompress qd3474[0x80]; /* 3474 - Array for quick decompression */ unsigned char table1502A630[]; /* Some table to make struct size flexible */ }; static unsigned char table1502A630[] = { /* * Data for compression type 0x00 */ 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* * Data for compression type 0x01 */ 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05, 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B, 0x00, 0x00, /* * Data for compression type 0x02 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04, 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02, 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A, 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Data for compression type 0x03 */ 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03, 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03, 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03, 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01, 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, 0x00, 0x00, /* * Data for compression type 0x04 */ 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Data for compression type 0x05 */ 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82, 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37, 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D, 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Data for compression type 0x06 */ 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Data for compression type 0x07 */ 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Data for compression type 0x08 */ 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10, 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11, 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* * Gets previous Huffman tree item (?) */ static struct huffman_tree_item *huff_get_prev_item(struct huffman_tree_item *hi, long value) { if (PTR_INT(hi->prev) < 0) { return PTR_NOT(hi->prev); } if (value < 0) { value = hi - hi->next->prev; } return hi->prev + value; } /* * 1500BC90 */ static void huff_remove_item(struct huffman_tree_item *hi) { struct huffman_tree_item *temp; /* EDX */ if (hi->next != NULL) { temp = hi->prev; if (PTR_INT(temp) <= 0) { temp = PTR_NOT(temp); } else { temp += (hi - hi->next->prev); } temp->next = hi->next; hi->next->prev = hi->prev; hi->next = hi->prev = NULL; } } static void huff_insert_item(struct huffman_tree_item **p_item, struct huffman_tree_item *item, unsigned long where, struct huffman_tree_item *item2) { struct huffman_tree_item *next = item->next; /* EDI - next to the first item */ struct huffman_tree_item *prev = item->prev; /* ESI - prev to the first item */ struct huffman_tree_item *prev2; /* Pointer to previous item */ long next2; /* Pointer to the next item */ /* * The same code like in mpq_huff_remove_item(); */ if (next != 0) { /* If the first item already has next one */ if (PTR_INT(prev) < 0) { prev = PTR_NOT(prev); } else { prev += (item - next->prev); } /* * 150083C1 * Remove the item from the tree */ prev->next = next; next->prev = prev; /* * Invalidate 'prev' and 'next' pointer */ item->next = 0; item->prev = 0; } if (item2 == NULL) { /* EDX - If the second item is not entered, */ item2 = PTR_PTR(&p_item[1]); /* take the first tree item */ } switch (where) { case SWITCH_ITEMS: /* Switch the two items */ item->next = item2->next; /* item2->next (Pointer to pointer to first) */ item->prev = item2->next->prev; item2->next->prev = item; item2->next = item; /* Set the first item */ return; case INSERT_ITEM: /* Insert as the last item */ item->next = item2; /* Set next item (or pointer to pointer to first item) */ item->prev = item2->prev; /* Set prev item (or last item in the tree) */ next2 = PTR_INT(p_item[0]); /* Usually NULL */ prev2 = item2->prev; /* Prev item to the second (or last tree item) */ if (PTR_INT(prev2) < 0) { prev2 = PTR_NOT(prev); prev2->next = item; item2->prev = item; /* Next after last item */ return; } if (next2 < 0) { next2 = item2 - item2->next->prev; } prev2 += next2; prev2->next = item; item2->prev = item; /* Set the next/last item */ return; default: return; } } /* * Builds Huffman tree. Called with the first 8 bits loaded from input stream. */ static void huff_build_tree(struct huffman_tree *ht, unsigned int cmp_type) { unsigned long max_byte; /* [ESP+10] - The greatest character found in table */ unsigned char *byte_array; /* [ESP+1C] - Pointer to unsigned char in table1502A630 */ unsigned long i; /* egcs in linux doesn't like multiple for loops without an * explicit i */ unsigned int found; /* Thats needed to replace the goto stuff from original source :) */ struct huffman_tree_item **p_item; /* [ESP+14] - Pointer to Huffman tree item pointer array */ struct huffman_tree_item *child1; /* * Loop while pointer has a negative value. */ while (PTR_INT(ht->last) > 0) { /* ESI - Last entry */ struct huffman_tree_item *temp; /* EAX */ if (ht->last->next != NULL) { /* ESI->next */ huff_remove_item(ht->last); } ht->item3058 = PTR_PTR(&ht->item3054); /* [EDI+4] */ ht->last->prev = ht->item3058; /* EAX */ temp = huff_get_prev_item(PTR_PTR(&ht->item3054), PTR_INT(&ht->item3050)); temp->next = ht->last; ht->item3054 = ht->last; } /* * Clear all pointers in huffman tree item array. */ memset(ht->items306C, 0, sizeof(ht->items306C)); max_byte = 0; /* Greatest character found init to zero. */ p_item = (struct huffman_tree_item **) &ht->items306C; /* Pointer to current entry in * huffman tree item pointer array */ /* * Ensure we have low 8 bits only */ cmp_type &= 0xFF; byte_array = table1502A630 + cmp_type * 258; /* EDI also */ for (i = 0; i < 0x100; i++, p_item++) { struct huffman_tree_item *item = ht->item3058; /* Item to be created */ struct huffman_tree_item *p_item3 = ht->item3058; unsigned char one_byte = byte_array[i]; /* * Skip all the bytes which are zero. */ if (byte_array[i] == 0) { continue; } /* * If not valid pointer, take the first available item in the array. */ if (PTR_INT(item) <= 0) { item = &ht->items0008[ht->items++]; } /* * Insert this item as the top of the tree. */ huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL); item->parent = NULL; /* Invalidate child and parent */ item->child = NULL; *p_item = item; /* Store pointer into pointer array */ item->dcmp_byte = i; /* Store counter */ item->byte_value = one_byte; /* Store byte value */ if (one_byte >= max_byte) { max_byte = one_byte; continue; } /* * Find the first item which has byte value greater than current one byte */ found = 0; if (PTR_INT((p_item3 = ht->last)) > 0) { /* EDI - Pointer to the last item */ /* * 15006AF7 */ if (p_item3 != NULL) { do { /* 15006AFB */ if (p_item3->byte_value >= one_byte) { found = 1; break; } p_item3 = p_item3->prev; } while (PTR_INT(p_item3) > 0); } } if (found == 0) { p_item3 = NULL; } /* * 15006B09 */ if (item->next != NULL) { huff_remove_item(item); } /* * 15006B15 */ if (p_item3 == NULL) { p_item3 = PTR_PTR(&ht->first); } /* * 15006B1F */ item->next = p_item3->next; item->prev = p_item3->next->prev; p_item3->next->prev = item; p_item3->next = item; } /* * 15006B4A */ for (; i < 0x102; i++) { struct huffman_tree_item **p_item2 = &ht->items306C[i]; /* EDI */ /* * 15006B59 */ struct huffman_tree_item *item2 = ht->item3058; /* ESI */ if (PTR_INT(item2) <= 0) { item2 = &ht->items0008[ht->items++]; } huff_insert_item(&ht->item305C, item2, INSERT_ITEM, NULL); /* * 15006B89 */ item2->dcmp_byte = i; item2->byte_value = 1; item2->parent = NULL; item2->child = NULL; *p_item2++ = item2; } /* * 15006BAA */ if (PTR_INT((child1 = ht->last)) > 0) { /* EDI - last item (first child to item */ struct huffman_tree_item *child2; /* EBP */ struct huffman_tree_item *item; /* ESI */ /* * 15006BB8 */ while (PTR_INT((child2 = child1->prev)) > 0) { if (PTR_INT((item = ht->item3058)) <= 0) { item = &ht->items0008[ht->items++]; } /* * 15006BE3 */ huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL); /* * 15006BF3 */ item->parent = NULL; item->child = NULL; /* * EDX = child2->byte_value + child1->byte_value; * EAX = child1->byte_value; * ECX = max_byte; The greatest character (0xFF usually) */ item->byte_value = child1->byte_value + child2->byte_value; /* 0x02 */ item->child = child1; /* Prev item in the */ child1->parent = item; child2->parent = item; /* * EAX = item->byte_value; */ if (item->byte_value >= max_byte) { max_byte = item->byte_value; } else { struct huffman_tree_item *p_item2 = child2->prev; /* EDI */ found = 0; if (PTR_INT(p_item2) > 0) { /* * 15006C2D */ do { if (p_item2->byte_value >= item->byte_value) { found = 1; break; } p_item2 = p_item2->prev; } while (PTR_INT(p_item2) > 0); } if (found == 0) { p_item2 = NULL; } if (item->next != 0) { struct huffman_tree_item *temp4 = huff_get_prev_item(item, -1); temp4->next = item->next; /* The first item changed */ item->next->prev = item->prev; /* First->prev changed to negative value */ item->next = NULL; item->prev = NULL; } /* * 15006C62 */ if (p_item2 == NULL) { p_item2 = PTR_PTR(&ht->first); } item->next = p_item2->next; /* Set item with 0x100 byte value */ item->prev = p_item2->next->prev; /* Set item with 0x17 byte value */ p_item2->next->prev = item; /* Changed prev of item with */ p_item2->next = item; } /* * 15006C7B */ if (PTR_INT((child1 = child2->prev)) <= 0) { break; } } } /* * 15006C88 */ ht->offs0004 = 1; } /* * Gets the whole byte from the input stream. */ static unsigned long huff_get_8bits(struct huffman_input_stream *is) { unsigned long one_byte; if (is->bits <= 8) { is->bit_buf |= *(unsigned short *) is->in_buf << is->bits; is->in_buf += sizeof(unsigned short); is->bits += 16; } one_byte = (is->bit_buf & 0xFF); is->bit_buf >>= 8; is->bits -= 8; return one_byte; } /* * Gets 7 bits from the stream. */ static unsigned long huff_get_7bits(struct huffman_input_stream *is) { if (is->bits <= 7) { is->bit_buf |= *(unsigned short *) is->in_buf << is->bits; is->in_buf += sizeof(unsigned short); is->bits += 16; } /* * Get 7 bits from input stream. */ return (is->bit_buf & 0x7F); } /* * Gets one bit from input stream. */ static unsigned long huff_get_bit(struct huffman_input_stream *is) { unsigned long bit = (is->bit_buf & 1); is->bit_buf >>= 1; if (--is->bits == 0) { is->bit_buf = *(unsigned long *) is->in_buf; is->in_buf += sizeof(unsigned long); is->bits = 32; } return bit; } static struct huffman_tree_item *huff_call1500E740(struct huffman_tree *ht, unsigned int value) { struct huffman_tree_item *p_item1 = ht->item3058; /* EDX */ struct huffman_tree_item *p_item2; /* EAX */ struct huffman_tree_item *p_next; struct huffman_tree_item *p_prev; struct huffman_tree_item **pp_item; if (PTR_INT(p_item1) <= 0 || (p_item2 = p_item1) == NULL) { if ((p_item2 = &ht->items0008[ht->items++]) != NULL) { p_item1 = p_item2; } else { p_item1 = ht->first; } } else { p_item1 = p_item2; } p_next = p_item1->next; if (p_next != NULL) { p_prev = p_item1->prev; if (PTR_INT(p_prev) <= 0) { p_prev = PTR_NOT(p_prev); } else { p_prev += (p_item1 - p_item1->next->prev); } p_prev->next = p_next; p_next->prev = p_prev; p_item1->next = NULL; p_item1->prev = NULL; } pp_item = &ht->first; /* ESI */ if (value > 1) { /* * ECX = ht->first->next; */ p_item1->next = *pp_item; p_item1->prev = (*pp_item)->prev; (*pp_item)->prev = p_item2; *pp_item = p_item1; p_item2->parent = NULL; p_item2->child = NULL; } else { p_item1->next = (struct huffman_tree_item *) pp_item; p_item1->prev = pp_item[1]; /* * EDI = ht->item305C; */ p_prev = pp_item[1]; /* ECX */ if (p_prev <= 0) { p_prev = PTR_NOT(p_prev); p_prev->next = p_item1; p_prev->prev = p_item2; p_item2->parent = NULL; p_item2->child = NULL; } else { if (PTR_INT(ht->item305C) < 0) { p_prev += (struct huffman_tree_item *) pp_item - (*pp_item)->prev; } else { p_prev += PTR_INT(ht->item305C); } p_prev->next = p_item1; pp_item[1] = p_item2; p_item2->parent = NULL; p_item2->child = NULL; } } return p_item2; } static void huff_call1500E820(struct huffman_tree *ht, struct huffman_tree_item *p_item) { struct huffman_tree_item *p_item1; /* EDI */ struct huffman_tree_item *p_item2 = NULL; /* EAX */ struct huffman_tree_item *p_item3; /* EDX */ struct huffman_tree_item *p_prev; /* EBX */ for (; p_item != NULL; p_item = p_item->parent) { p_item->byte_value++; for (p_item1 = p_item;; p_item1 = p_prev) { p_prev = p_item1->prev; if (PTR_INT(p_prev) <= 0) { p_prev = NULL; break; } if (p_prev->byte_value >= p_item->byte_value) { break; } } if (p_item1 == p_item) { continue; } if (p_item1->next != NULL) { p_item2 = huff_get_prev_item(p_item1, -1); p_item2->next = p_item1->next; p_item1->next->prev = p_item1->prev; p_item1->next = NULL; p_item1->prev = NULL; } p_item2 = p_item->next; p_item1->next = p_item2; p_item1->prev = p_item2->prev; p_item2->prev = p_item1; p_item->next = p_item1; if ((p_item2 = p_item1) != NULL) { p_item2 = huff_get_prev_item(p_item, -1); p_item2->next = p_item->next; p_item->next->prev = p_item->prev; p_item->next = NULL; p_item->prev = NULL; } if (p_prev == NULL) { p_prev = PTR_PTR(&ht->first); } p_item2 = p_prev->next; p_item->next = p_item2; p_item->prev = p_item2->prev; p_item2->prev = p_item; p_prev->next = p_item; p_item3 = p_item1->parent->child; p_item2 = p_item->parent; if (p_item2->child == p_item) { p_item2->child = p_item1; } if (p_item3 == p_item1) { p_item1->parent->child = p_item; } p_item2 = p_item->parent; p_item->parent = p_item1->parent; p_item1->parent = p_item2; ht->offs0004++; } } static int huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length) { unsigned int n8bits; /* 8 bits loaded from input stream */ unsigned int n7bits; /* 7 bits loaded from input stream */ unsigned int found; /* Thats needed to replace the goto stuff from original source :) */ unsigned int dcmp_byte = 0; unsigned long bit_count; struct huffman_decompress *qd; unsigned int has_qd; /* Can we use quick decompression? */ struct huffman_tree_item *p_item1; struct huffman_tree_item *p_item2; unsigned char *out_pos = out_buf; /* * Test the output length. Must not be non zero. */ if (out_length == 0) { return 0; } /* * Get the compression type from the input stream. */ n8bits = huff_get_8bits(is); /* * Build the Huffman tree */ huff_build_tree(ht, n8bits); ht->cmp0 = (n8bits == 0) ? TRUE : FALSE; for (;;) { n7bits = huff_get_7bits(is); /* Get 7 bits from input stream */ /* * Try to use quick decompression. Check huffman_decompress array for corresponding item. * If found, use the result byte instead. */ qd = &ht->qd3474[n7bits]; /* * If there is a quick-pass possible (ebx) */ has_qd = (qd->offs00 >= ht->offs0004) ? TRUE : FALSE; /* * If we can use quick decompress, use it. */ if (has_qd) { found = 0; if (qd->bits > 7) { is->bit_buf >>= 7; is->bits -= 7; p_item1 = qd->p_item; found = 1; } if (found == 0) { is->bit_buf >>= qd->bits; is->bits -= qd->bits; dcmp_byte = qd->dcmp_byte; } } else { found = 1; p_item1 = ht->first->next->prev; if (PTR_INT(p_item1) <= 0) { p_item1 = NULL; } } if (found == 1) { bit_count = 0; p_item2 = NULL; do { p_item1 = p_item1->child; /* Move down by one level */ if (huff_get_bit(is)) { /* If current bit is set, move to previous */ p_item1 = p_item1->prev; } if (++bit_count == 7) { /* If we are at 7th bit, save current huffman tree item. */ p_item2 = p_item1; } } while (p_item1->child != NULL); /* Walk until tree has no deeper level */ if (has_qd == FALSE) { if (bit_count > 7) { qd->offs00 = ht->offs0004; qd->bits = bit_count; qd->p_item = p_item2; } else { unsigned long index = n7bits & (0xFFFFFFFF >> (32 - bit_count)); unsigned long add = (1 << bit_count); for (qd = &ht->qd3474[index]; index <= 0x7F; index += add, qd += add) { qd->offs00 = ht->offs0004; qd->bits = bit_count; qd->dcmp_byte = p_item1->dcmp_byte; } } } dcmp_byte = p_item1->dcmp_byte; } if (dcmp_byte == 0x101) { /* Huffman tree needs to be modified */ n8bits = huff_get_8bits(is); p_item1 = (ht->last <= 0) ? NULL : ht->last; p_item2 = huff_call1500E740(ht, 1); p_item2->parent = p_item1; p_item2->dcmp_byte = p_item1->dcmp_byte; p_item2->byte_value = p_item1->byte_value; ht->items306C[p_item2->dcmp_byte] = p_item2; p_item2 = huff_call1500E740(ht, 1); p_item2->parent = p_item1; p_item2->dcmp_byte = n8bits; p_item2->byte_value = 0; ht->items306C[p_item2->dcmp_byte] = p_item2; p_item1->child = p_item2; huff_call1500E820(ht, p_item2); if (ht->cmp0 == 0) { huff_call1500E820(ht, ht->items306C[n8bits]); } dcmp_byte = n8bits; } if (dcmp_byte == 0x100) { break; } *out_pos++ = (unsigned char) dcmp_byte; if (--out_length == 0) { break; } if (ht->cmp0) { huff_call1500E820(ht, ht->items306C[dcmp_byte]); } } return (out_pos - out_buf); } static void huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi) { int count; /* * Clear links for all the items in the tree */ for (hi = ht->items0008, count = 0x203; count != 0; hi++, count--) { hi->next = hi->prev = NULL; } ht->item3050 = NULL; ht->item3054 = PTR_PTR(&ht->item3054); ht->item3058 = PTR_NOT(ht->item3054); ht->item305C = NULL; ht->first = PTR_PTR(&ht->first); ht->last = PTR_NOT(ht->first); ht->offs0004 = 1; ht->items = 0; /* * Clear all huffman_decompress items. Do this only if preparing for decompression */ for (count = 0; count < sizeof(ht->qd3474) / sizeof(struct huffman_decompress); count++) { ht->qd3474[count].offs00 = 0; } } /* * PKWARE's compression. */ #define PKZIP_EXP_BUFFER_SIZE 12596 /* Size of decompress buffer */ #define PKZIP_CMP_BINARY 0 /* Binary compression */ #define PKZIP_CMP_ASCII 1 /* Ascii compression */ #define PKZIP_CMP_NO_ERROR 0 #define PKZIP_CMP_INV_DICTSIZE 1 #define PKZIP_CMP_INV_MODE 2 #define PKZIP_CMP_BAD_DATA 3 #define PKZIP_CMP_ABORT 4 /* * Compression structure (size: 12596 bytes on x86-32) */ #ifdef _MSC_VER #pragma pack(1) #endif typedef struct { unsigned long offs0000; /* 0000 */ unsigned long cmp_type; /* 0004 - Compression type (PZIP_CMP_BINARY or * PKZIP_CMP_ASCII) */ unsigned long out_pos; /* 0008 - Position in output buffer */ unsigned long dsize_bits; /* 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) */ unsigned long dsize_mask; /* 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, * 0x1000) */ unsigned long bit_buf; /* 0014 - 16-bit buffer for processing input data */ unsigned long extra_bits; /* 0018 - Number of extra (above 8) bits in bit buffer */ unsigned int in_pos; /* 001C - Position in in_buf */ unsigned long in_bytes; /* 0020 - Number of bytes in input buffer */ void *param; /* 0024 - Custom parameter */ unsigned int (*read_buf) (char *buf, unsigned int *size, void *param); /* 0028 */ void (*write_buf) (const char *buf, unsigned int *size, void *param); /* 002C */ unsigned char out_buf[0x2000]; /* 0030 - Output circle buffer. Starting position is 0x1000 */ unsigned char offs_2030[0x204]; /* 2030 - ??? */ unsigned char in_buf[0x800]; /* 2234 - Buffer for data to be decompressed */ unsigned char pos1[0x100]; /* 2A34 - Positions in buffers */ unsigned char pos2[0x100]; /* 2B34 - Positions in buffers */ unsigned char offs_2c34[0x100]; /* 2C34 - Buffer for */ unsigned char offs_2d34[0x100]; /* 2D34 - Buffer for */ unsigned char offs_2e34[0x80]; /* 2EB4 - Buffer for */ unsigned char offs_2eb4[0x100]; /* 2EB4 - Buffer for */ unsigned char bits_asc[0x100]; /* 2FB4 - Buffer for */ unsigned char dist_bits[0x40]; /* 30B4 - Numbers of bytes to skip copied block length */ unsigned char slen_bits[0x10]; /* 30F4 - Numbers of bits for skip copied block length */ unsigned char clen_bits[0x10]; /* 3104 - Number of valid bits for copied block */ unsigned short len_base[0x10]; /* 3114 - Buffer for */ } #ifndef _MSC_VER __attribute__ ((packed)) #endif pkzip_data_cmp; typedef struct { const char *in_buf; /* Pointer to input data buffer */ unsigned int in_pos; /* Current offset in input data buffer */ int in_bytes; /* Number of bytes in the input buffer */ char *out_buf; /* Pointer to output data buffer */ unsigned int out_pos; /* Position in the output buffer */ int max_out; /* Maximum number of bytes in the output buffer */ } pkzip_data; /* * Tables */ static unsigned char pkzip_dist_bits[] = { 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }; static unsigned char pkzip_dist_code[] = { 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 }; static unsigned char pkzip_clen_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; static unsigned short pkzip_len_base[] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106 }; static unsigned char pkzip_slen_bits[] = { 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 }; static unsigned char pkzip_len_code[] = { 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 }; static unsigned char pkzip_bits_asc[] = { 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D }; static unsigned short pkzip_code_asc[] = { 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0, 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8, 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710, 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8, 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D, 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040, 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280, 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900, 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000 }; /* * Local functions */ static void pkzip_gen_decode_tabs(long count, unsigned char *bits, unsigned char *code, unsigned char *buf2) { long i; for (i = count - 1; i >= 0; i--) { /* EBX - count */ unsigned long idx1 = code[i]; unsigned long idx2 = 1 << bits[i]; do { buf2[idx1] = (unsigned char) i; idx1 += idx2; } while (idx1 < 0x100); } } static void pkzip_gen_asc_tabs(pkzip_data_cmp * mpq_pkzip) { unsigned short *code_asc = &pkzip_code_asc[0xFF]; unsigned long acc, add; unsigned short count; for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) { unsigned char *bits_asc = mpq_pkzip->bits_asc + count; unsigned char bits_tmp = *bits_asc; if (bits_tmp <= 8) { add = (1 << bits_tmp); acc = *code_asc; do { mpq_pkzip->offs_2c34[acc] = (unsigned char) count; acc += add; } while (acc < 0x100); } else { if ((acc = (*code_asc & 0xFF)) != 0) { mpq_pkzip->offs_2c34[acc] = 0xFF; if (*code_asc & 0x3F) { bits_tmp -= 4; *bits_asc = bits_tmp; add = (1 << bits_tmp); acc = *code_asc >> 4; do { mpq_pkzip->offs_2d34[acc] = (unsigned char) count; acc += add; } while (acc < 0x100); } else { bits_tmp -= 6; *bits_asc = bits_tmp; add = (1 << bits_tmp); acc = *code_asc >> 6; do { mpq_pkzip->offs_2e34[acc] = (unsigned char) count; acc += add; } while (acc < 0x80); } } else { bits_tmp -= 8; *bits_asc = bits_tmp; add = (1 << bits_tmp); acc = *code_asc >> 8; do { mpq_pkzip->offs_2eb4[acc] = (unsigned char) count; acc += add; } while (acc < 0x100); } } } } /* * Skips given number of bits in bit buffer. Result is stored in mpq_pkzip->bit_buf * If no data in input buffer, returns true */ static int pkzip_skip_bits(pkzip_data_cmp * mpq_pkzip, unsigned long bits) { /* * If number of bits required is less than number of (bits in the buffer) ? */ if (bits <= mpq_pkzip->extra_bits) { mpq_pkzip->extra_bits -= bits; mpq_pkzip->bit_buf >>= bits; return 0; } /* * Load input buffer if necessary */ mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits; if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) { mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf); if ((mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *) mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param)) == 0) { return 1; } mpq_pkzip->in_pos = 0; } /* * Update bit buffer */ mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8); mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits); mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8; return 0; } /* * Decompress the imploded data using coded literals. * Returns: 0x000 - 0x0FF : One byte from compressed file. * 0x100 - 0x305 : Copy previous block (0x100 = 1 byte) * 0x306 : Out of buffer (?) */ static unsigned long pkzip_explode_lit(pkzip_data_cmp * mpq_pkzip) { unsigned long bits; /* Number of bits to skip */ unsigned long value; /* Position in buffers */ /* * Test the current bit in byte buffer. If is not set, simply return the next byte. */ if (mpq_pkzip->bit_buf & 1) { /* * Skip current bit in the buffer. */ if (pkzip_skip_bits(mpq_pkzip, 1)) { return 0x306; } /* * The next bits are position in buffers. */ value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)]; /* * Get number of bits to skip */ if (pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) { return 0x306; } if ((bits = mpq_pkzip->clen_bits[value]) != 0) { unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1); if (pkzip_skip_bits(mpq_pkzip, bits)) { if ((value + val2) != 0x10E) { return 0x306; } } value = mpq_pkzip->len_base[value] + val2; } return value + 0x100; /* Return number of bytes to repeat */ } /* * Skip one bit */ if (pkzip_skip_bits(mpq_pkzip, 1)) { return 0x306; } /* * If the binary compression type, read 8 bits and return them as one byte. */ if (mpq_pkzip->cmp_type == PKZIP_CMP_BINARY) { value = mpq_pkzip->bit_buf & 0xFF; if (pkzip_skip_bits(mpq_pkzip, 8)) { return 0x306; } return value; } /* * When ASCII compression ... */ if (mpq_pkzip->bit_buf & 0xFF) { value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF]; if (value == 0xFF) { if (mpq_pkzip->bit_buf & 0x3F) { if (pkzip_skip_bits(mpq_pkzip, 4)) { return 0x306; } value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF]; } else { if (pkzip_skip_bits(mpq_pkzip, 6)) { return 0x306; } value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F]; } } } else { if (pkzip_skip_bits(mpq_pkzip, 8)) { return 0x306; } value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF]; } return pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value; } /* * Retrieves the number of bytes to move back. */ static unsigned long pkzip_explode_dist(pkzip_data_cmp * mpq_pkzip, unsigned long length) { unsigned long pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)]; unsigned long skip = mpq_pkzip->dist_bits[pos]; /* Number of bits to skip */ /* * Skip the appropriate number of bits */ if (pkzip_skip_bits(mpq_pkzip, skip) == 1) { return 0; } if (length == 2) { pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03); if (pkzip_skip_bits(mpq_pkzip, 2) == 1) { return 0; } } else { pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask); /* * Skip the bits */ if (pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) { return 0; } } return pos + 1; } static unsigned long pkzip_expand(pkzip_data_cmp * mpq_pkzip) { unsigned int copy_bytes; /* Number of bytes to copy */ unsigned long one_byte; /* One byte from compressed file */ unsigned long result; mpq_pkzip->out_pos = 0x1000; /* Initialize output buffer position */ /* * If end of data or error, terminate decompress */ while ((result = one_byte = pkzip_explode_lit(mpq_pkzip)) < 0x305) { /* * If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */ if (one_byte >= 0x100) { unsigned char *source; /* ECX */ unsigned char *target; /* EDX */ unsigned long copy_length = one_byte - 0xFE; unsigned long move_back; /* * Get length of data to copy */ if ((move_back = pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) { result = 0x306; break; } /* * Target and source pointer */ target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos]; source = target - move_back; mpq_pkzip->out_pos += copy_length; while (copy_length-- > 0) { *target++ = *source++; } } else { mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char) one_byte; } /* * If number of extracted bytes has reached 1/2 of output buffer, * flush output buffer. */ if (mpq_pkzip->out_pos >= 0x2000) { /* * Copy decompressed data into user buffer. */ copy_bytes = 0x1000; mpq_pkzip->write_buf((char *) &mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); /* * If there are some data left, keep them alive */ memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000); mpq_pkzip->out_pos -= 0x1000; } } copy_bytes = mpq_pkzip->out_pos - 0x1000; mpq_pkzip->write_buf((char *) &mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); return result; } /* * Main exploding function. */ static unsigned int pkzip_explode(unsigned int (*read_buf) (char *buf, unsigned int *size, void *param), void (*write_buf) (const char *buf, unsigned int *size, void *param), char *work_buf, void *param) { pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *) work_buf; /* * Set the whole work buffer to zeros */ memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp)); /* * Initialize work struct and load compressed data */ mpq_pkzip->read_buf = read_buf; mpq_pkzip->write_buf = write_buf; mpq_pkzip->param = param; mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf); mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *) mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param); if (mpq_pkzip->in_bytes <= 4) { return PKZIP_CMP_BAD_DATA; } mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; /* Get the compression type */ mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; /* Get the dictionary size */ mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; /* Initialize 16-bit bit buffer */ mpq_pkzip->extra_bits = 0; /* Extra (over 8) bits */ mpq_pkzip->in_pos = 3; /* Position in input buffer */ /* * Test for the valid dictionary size */ if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) { return PKZIP_CMP_INV_DICTSIZE; } mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); /* Shifted by 'sar' * instruction */ if (mpq_pkzip->cmp_type != PKZIP_CMP_BINARY) { if (mpq_pkzip->cmp_type != PKZIP_CMP_ASCII) { return PKZIP_CMP_INV_MODE; } memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc)); pkzip_gen_asc_tabs(mpq_pkzip); } memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits)); pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2); memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits)); memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base)); memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits)); pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1); if (pkzip_expand(mpq_pkzip) != 0x306) { return PKZIP_CMP_NO_ERROR; } return PKZIP_CMP_ABORT; } /* * Support functions for PKWARE data compression library. * * Function loads data from the input buffer. Used by mpq_pkzip * "implode" and "explode" function as user-defined callback. * Returns number of bytes loaded. * * char * buf - Pointer to a buffer where to store loaded data * unsigned int * size - Max. number of bytes to read * void * param - Custom pointer, parameter of implode/explode */ static unsigned int pkzip_read_input_data(char *buf, unsigned int *size, void *param) { pkzip_data *info = (pkzip_data *) param; unsigned int max_avail = (info->in_bytes - info->in_pos); unsigned int to_read = *size; /* * Check the case when not enough data available */ if (to_read > max_avail) { to_read = max_avail; } /* * Load data and increment offsets */ memcpy(buf, info->in_buf + info->in_pos, to_read); info->in_pos += to_read; return to_read; } /* * Support functions for PKWARE data compression library. * * Function for store output data. Used by mpq_pkzip "implode" and * "explode" as user-defined callback. * * char * buf - Pointer to data to be written * unsigned int * size - Number of bytes to write * void * param - Custom pointer, parameter of implode/explode */ static void pkzip_write_output_data(const char *buf, unsigned int *size, void *param) { pkzip_data *info = (pkzip_data *) param; unsigned int max_write = (info->max_out - info->out_pos); unsigned int to_write = *size; /* * Check the case when not enough space in the output buffer */ if (to_write > max_write) { to_write = max_write; } /* * Write output data and increments offsets */ memcpy(info->out_buf + info->out_pos, buf, to_write); info->out_pos += to_write; } static int pkzip_decompress(char *out_buf, int *out_length, const char *in_buf, int in_length) { pkzip_data info; /* Data information */ char *work_buf = malloc(PKZIP_EXP_BUFFER_SIZE); /* mpq_pkzip work buffer */ /* * Fill data information structure */ info.in_buf = in_buf; info.in_pos = 0; info.in_bytes = in_length; info.out_buf = out_buf; info.out_pos = 0; info.max_out = *out_length; /* * Do the decompression */ pkzip_explode(pkzip_read_input_data, pkzip_write_output_data, work_buf, &info); *out_length = info.out_pos; free(work_buf); return 0; } static int adpcm_decompress_mono(char *out_buf, int *out_length, const char *in_buf, int in_length) { *out_length = adpcm_decompress((unsigned char *) out_buf, *out_length, (unsigned char *) in_buf, in_length, 1); return 1; } static int adpcm_decompress_stereo(char *out_buf, int *out_length, const char *in_buf, int in_length) { *out_length = adpcm_decompress((unsigned char *) out_buf, *out_length, (unsigned char *) in_buf, in_length, 2); return 1; } static int zlib_decompress(char *out_buf, int *out_length, const char *in_buf, int in_length) { z_stream z; /* Stream information for zlib */ int result; /* * Fill the stream structure for zlib */ z.next_in = (Bytef *) in_buf; z.avail_in = (uInt) in_length; z.total_in = in_length; z.next_out = (Bytef *) out_buf; z.avail_out = *out_length; z.total_out = 0; z.zalloc = NULL; z.zfree = NULL; /* * Initialize the decompression structure. Storm.dll uses zlib version 1.1.3 */ if ((result = inflateInit(&z)) == 0) { /* * Call zlib to decompress the data */ result = inflate(&z, Z_FINISH); *out_length = z.total_out; inflateEnd(&z); } return result; } /* * Huffmann decompression routine. The in_length parameter is not used, but needs * to be specified due to compatibility reasons. * * 1500F5F0 */ static int huff_decompress(char *out_buf, int *out_length, const char *in_buf, int in_length) { struct huffman_tree *ht = malloc(sizeof(struct huffman_tree)); struct huffman_input_stream *is = malloc(sizeof(struct huffman_input_stream)); struct huffman_tree_item *hi = malloc(sizeof(struct huffman_tree_item)); memset(ht, 0, sizeof(struct huffman_tree)); memset(is, 0, sizeof(struct huffman_input_stream)); memset(hi, 0, sizeof(struct huffman_tree_item)); /* * Initialize input stream */ is->bit_buf = *(unsigned long *) in_buf; in_buf += sizeof(unsigned long); is->in_buf = (unsigned char *) in_buf; is->bits = 32; /* * Initialize the Huffmann tree for decompression */ huff_init_tree(ht, hi); *out_length = huff_do_decompress(ht, is, (unsigned char *) out_buf, *out_length); free(hi); free(is); free(ht); return 0; } int __mpqlib_multi_decompress(char *out_buf, int *pout_length, const char *in_buf, int in_length) { char *temp_buf = NULL; /* Temporary storage for decompressed data */ char *work_buf = NULL; /* Where to store decompressed data */ int out_length = *pout_length; /* For storage number of output bytes */ unsigned fDecompressions1; /* Decompressions applied to the block */ unsigned fDecompressions2; /* Just another copy of decompressions applied to the block */ int count = 0; /* Counter for every use */ int entries = (sizeof(dcmp_table) / sizeof(decompress_table)); int i; /* * If the input length is the same as output, do nothing. */ if (in_length == out_length) { if (in_buf == out_buf) { return 1; } memcpy(out_buf, in_buf, in_length); return 1; } /* * Get applied compression types and decrement data length */ fDecompressions1 = fDecompressions2 = (unsigned char) *in_buf++; in_length--; /* * Search decompression table type and get all types of compression */ for (i = 0; i < entries; i++) { /* * We have to apply this decompression? */ if (fDecompressions1 & dcmp_table[i].mask) { count++; } /* * Clear this flag from temporary variable. */ fDecompressions2 &= ~dcmp_table[i].mask; } /* * Check if there is some method unhandled * (E.g. compressed by future versions) */ if (fDecompressions2 != 0) { printf("Unknown Compression - bitfield = %08x\n", fDecompressions2); return 0; } /* * If there is more than only one compression, we have to allocate extra buffer */ if (count >= 2) { temp_buf = malloc(out_length); } /* * Apply all decompressions */ for (i = 0, count = 0; i < entries; i++) { /* * If not used this kind of compression, skip the loop */ if (fDecompressions1 & dcmp_table[i].mask) { /* * If odd case, use target buffer for output, otherwise use allocated tempbuf */ work_buf = (count++ & 1) ? temp_buf : out_buf; out_length = *pout_length; /* * Decompress buffer using corresponding function */ dcmp_table[i].decompress(work_buf, &out_length, in_buf, in_length); /* * Move output length to src length for next compression */ in_length = out_length; in_buf = work_buf; } } /* * If output buffer is not the same like target buffer, we have to copy data */ if (work_buf != out_buf) { memcpy(out_buf, in_buf, out_length); } *pout_length = out_length; /* * Delete temporary buffer, if necessary */ if (temp_buf != NULL) { free(temp_buf); } return 1; } int __mpqlib_pkzip_decompress(char *out_buf, int *pout_length, const char *in_buf, int in_length) { return pkzip_decompress(out_buf, pout_length, in_buf, in_length); }