Current News
Archived News
Search News
Discussion Forum
Old Forum
Install Programs
More Downloads...
Troubleshooting
Source Code
Format Specs.
Misc. Information
Non-SF Stuff
Links
Small banner for links to this site:
|
Commit | Line | Data |
3e09a0ee |
1 | /*****************************************************************************/ |
2 | /* explode.c Copyright (c) Ladislav Zezula 2003 */ |
3 | /*---------------------------------------------------------------------------*/ |
4 | /* Explode function of PKWARE Data Compression library */ |
5 | /*---------------------------------------------------------------------------*/ |
6 | /* Date Ver Who Comment */ |
7 | /* -------- ---- --- ------- */ |
8 | /* 11.03.03 1.00 Lad Splitted from Pkware.cpp */ |
9 | /* 08.04.03 1.01 Lad Renamed to explode.c to be compatible with pklib */ |
10 | /* 02.05.03 1.01 Lad Stress test done */ |
11 | /*****************************************************************************/ |
12 | |
13 | #include "pklib.h" |
14 | #include "SMem.h" |
15 | |
16 | //----------------------------------------------------------------------------- |
17 | // Local structures |
18 | |
19 | // Compression structure (Size 12596 bytes) |
20 | typedef struct |
21 | { |
22 | unsigned long offs0000; // 0000 |
23 | unsigned long ctype; // 0004 - Compression type (CMP_BINARY or CMP_ASCII) |
24 | unsigned long outputPos; // 0008 - Position in output buffer |
25 | unsigned long dsize_bits; // 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) |
26 | unsigned long dsize_mask; // 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000) |
27 | unsigned long bit_buff; // 0014 - 16-bit buffer for processing input data |
28 | unsigned long extra_bits; // 0018 - Number of extra (above 8) bits in bit buffer |
29 | unsigned int in_pos; // 001C - Position in in_buff |
30 | unsigned long in_bytes; // 0020 - Number of bytes in input buffer |
31 | void * param; // 0024 - Custom parameter |
32 | unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 0028 |
33 | void (*write_buf)(char *buf, unsigned int *size, void *param);// 002C |
34 | unsigned char out_buff[0x2000]; // 0030 - Output circle buffer. Starting position is 0x1000 |
35 | unsigned char offs2030[0x204]; // 2030 - ??? |
36 | unsigned char in_buff[0x800]; // 2234 - Buffer for data to be decompressed |
37 | unsigned char position1[0x100]; // 2A34 - Positions in buffers |
38 | unsigned char position2[0x100]; // 2B34 - Positions in buffers |
39 | unsigned char offs2C34[0x100]; // 2C34 - Buffer for |
40 | unsigned char offs2D34[0x100]; // 2D34 - Buffer for |
41 | unsigned char offs2E34[0x80]; // 2EB4 - Buffer for |
42 | unsigned char offs2EB4[0x100]; // 2EB4 - Buffer for |
43 | unsigned char ChBitsAsc[0x100]; // 2FB4 - Buffer for |
44 | unsigned char DistBits[0x40]; // 30B4 - Numbers of bytes to skip copied block length |
45 | unsigned char LenBits[0x10]; // 30F4 - Numbers of bits for skip copied block length |
46 | unsigned char ExLenBits[0x10]; // 3104 - Number of valid bits for copied block |
47 | unsigned short LenBase[0x10]; // 3114 - Buffer for |
48 | } TDcmpStruct; |
49 | |
50 | //----------------------------------------------------------------------------- |
51 | // Tables |
52 | |
53 | static unsigned char DistBits[] = |
54 | { |
55 | 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
56 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
57 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
58 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 |
59 | }; |
60 | |
61 | static unsigned char DistCode[] = |
62 | { |
63 | 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, |
64 | 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, |
65 | 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, |
66 | 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 |
67 | }; |
68 | |
69 | static unsigned char ExLenBits[] = |
70 | { |
71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 |
72 | }; |
73 | |
74 | static unsigned short LenBase[] = |
75 | { |
76 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, |
77 | 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106 |
78 | }; |
79 | |
80 | static unsigned char LenBits[] = |
81 | { |
82 | 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 |
83 | }; |
84 | |
85 | static unsigned char LenCode[] = |
86 | { |
87 | 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 |
88 | }; |
89 | |
90 | static unsigned char ChBitsAsc[] = |
91 | { |
92 | 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, |
93 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
94 | 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, |
95 | 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, |
96 | 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, |
97 | 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, |
98 | 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, |
99 | 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, |
100 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, |
101 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, |
102 | 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, |
103 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
104 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
105 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
106 | 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, |
107 | 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D |
108 | }; |
109 | |
110 | static unsigned short ChCodeAsc[] = |
111 | { |
112 | 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, |
113 | 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0, |
114 | 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, |
115 | 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, |
116 | 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8, |
117 | 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, |
118 | 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, |
119 | 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710, |
120 | 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, |
121 | 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, |
122 | 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8, |
123 | 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, |
124 | 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, |
125 | 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D, |
126 | 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, |
127 | 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, |
128 | 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040, |
129 | 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, |
130 | 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, |
131 | 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280, |
132 | 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, |
133 | 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, |
134 | 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, |
135 | 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, |
136 | 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, |
137 | 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, |
138 | 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, |
139 | 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, |
140 | 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900, |
141 | 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, |
142 | 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, |
143 | 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000 |
144 | }; |
145 | |
146 | //----------------------------------------------------------------------------- |
147 | // Local variables |
148 | |
149 | static char Copyright[] = "PKWARE Data Compression Library for Win32\r\n" |
150 | "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" |
151 | "Patent No. 5,051,745\r\n" |
152 | "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" |
153 | "Version 1.11"; |
154 | |
155 | //----------------------------------------------------------------------------- |
156 | // Local functions |
157 | |
158 | static void GenDecodeTabs(long count, unsigned char * bits, unsigned char * pCode, unsigned char * buffer2) |
159 | { |
160 | long i; |
161 | |
162 | for(i = count-1; i >= 0; i--) // EBX - count |
163 | { |
164 | unsigned long idx1 = pCode[i]; |
165 | unsigned long idx2 = 1 << bits[i]; |
166 | |
167 | do |
168 | { |
169 | buffer2[idx1] = (unsigned char)i; |
170 | idx1 += idx2; |
171 | } |
172 | while(idx1 < 0x100); |
173 | } |
174 | } |
175 | |
176 | static void GenAscTabs(TDcmpStruct * pWork) |
177 | { |
178 | unsigned short * pChCodeAsc = &ChCodeAsc[0xFF]; |
179 | unsigned long acc, add; |
180 | unsigned short count; |
181 | |
182 | for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--) |
183 | { |
184 | unsigned char * pChBitsAsc = pWork->ChBitsAsc + count; |
185 | unsigned char bits_asc = *pChBitsAsc; |
186 | |
187 | if(bits_asc <= 8) |
188 | { |
189 | add = (1 << bits_asc); |
190 | acc = *pChCodeAsc; |
191 | |
192 | do |
193 | { |
194 | pWork->offs2C34[acc] = (unsigned char)count; |
195 | acc += add; |
196 | } |
197 | while(acc < 0x100); |
198 | } |
199 | else if((acc = (*pChCodeAsc & 0xFF)) != 0) |
200 | { |
201 | pWork->offs2C34[acc] = 0xFF; |
202 | |
203 | if(*pChCodeAsc & 0x3F) |
204 | { |
205 | bits_asc -= 4; |
206 | *pChBitsAsc = bits_asc; |
207 | |
208 | add = (1 << bits_asc); |
209 | acc = *pChCodeAsc >> 4; |
210 | do |
211 | { |
212 | pWork->offs2D34[acc] = (unsigned char)count; |
213 | acc += add; |
214 | } |
215 | while(acc < 0x100); |
216 | } |
217 | else |
218 | { |
219 | bits_asc -= 6; |
220 | *pChBitsAsc = bits_asc; |
221 | |
222 | add = (1 << bits_asc); |
223 | acc = *pChCodeAsc >> 6; |
224 | do |
225 | { |
226 | pWork->offs2E34[acc] = (unsigned char)count; |
227 | acc += add; |
228 | } |
229 | while(acc < 0x80); |
230 | } |
231 | } |
232 | else |
233 | { |
234 | bits_asc -= 8; |
235 | *pChBitsAsc = bits_asc; |
236 | |
237 | add = (1 << bits_asc); |
238 | acc = *pChCodeAsc >> 8; |
239 | do |
240 | { |
241 | pWork->offs2EB4[acc] = (unsigned char)count; |
242 | acc += add; |
243 | } |
244 | while(acc < 0x100); |
245 | } |
246 | } |
247 | } |
248 | |
249 | //----------------------------------------------------------------------------- |
250 | // Skips given number of bits in bit buffer. Result is stored in pWork->bit_buff |
251 | // If no data in input buffer, returns true |
252 | |
253 | static int WasteBits(TDcmpStruct * pWork, unsigned long nBits) |
254 | { |
255 | // If number of bits required is less than number of (bits in the buffer) ? |
256 | if(nBits <= pWork->extra_bits) |
257 | { |
258 | pWork->extra_bits -= nBits; |
259 | pWork->bit_buff >>= nBits; |
260 | return 0; |
261 | } |
262 | |
263 | // Load input buffer if necessary |
264 | pWork->bit_buff >>= pWork->extra_bits; |
265 | if(pWork->in_pos == pWork->in_bytes) |
266 | { |
267 | pWork->in_pos = sizeof(pWork->in_buff); |
268 | if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0) |
269 | return 1; |
270 | pWork->in_pos = 0; |
271 | } |
272 | |
273 | // Update bit buffer |
274 | pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8); |
275 | pWork->bit_buff >>= (nBits - pWork->extra_bits); |
276 | pWork->extra_bits = (pWork->extra_bits - nBits) + 8; |
277 | return 0; |
278 | } |
279 | |
280 | //----------------------------------------------------------------------------- |
281 | // Returns : 0x000 - 0x0FF : One byte from compressed file. |
282 | // 0x100 - 0x305 : Copy previous block (0x100 = 1 byte) |
283 | // 0x306 : Out of buffer (?) |
284 | |
285 | static unsigned long DecodeLit(TDcmpStruct * pWork) |
286 | { |
287 | unsigned long nBits; // Number of bits to skip |
288 | unsigned long value; // Position in buffers |
289 | |
290 | // Test the current bit in byte buffer. If is not set, simply return the next byte. |
291 | if(pWork->bit_buff & 1) |
292 | { |
293 | // Skip current bit in the buffer |
294 | if(WasteBits(pWork, 1)) |
295 | return 0x306; |
296 | |
297 | // The next bits are position in buffers |
298 | value = pWork->position2[(pWork->bit_buff & 0xFF)]; |
299 | |
300 | // Get number of bits to skip |
301 | if(WasteBits(pWork, pWork->LenBits[value])) |
302 | return 0x306; |
303 | |
304 | if((nBits = pWork->ExLenBits[value]) != 0) |
305 | { |
306 | unsigned long val2 = pWork->bit_buff & ((1 << nBits) - 1); |
307 | |
308 | if(WasteBits(pWork, nBits)) |
309 | { |
310 | if((value + val2) != 0x10E) |
311 | return 0x306; |
312 | } |
313 | value = pWork->LenBase[value] + val2; |
314 | } |
315 | return value + 0x100; // Return number of bytes to repeat |
316 | } |
317 | |
318 | // Waste one bit |
319 | if(WasteBits(pWork, 1)) |
320 | return 0x306; |
321 | |
322 | // If the binary compression type, read 8 bits and return them as one byte. |
323 | if(pWork->ctype == CMP_BINARY) |
324 | { |
325 | value = pWork->bit_buff & 0xFF; |
326 | if(WasteBits(pWork, 8)) |
327 | return 0x306; |
328 | return value; |
329 | } |
330 | |
331 | // When ASCII compression ... |
332 | if(pWork->bit_buff & 0xFF) |
333 | { |
334 | value = pWork->offs2C34[pWork->bit_buff & 0xFF]; |
335 | |
336 | if(value == 0xFF) |
337 | { |
338 | if(pWork->bit_buff & 0x3F) |
339 | { |
340 | if(WasteBits(pWork, 4)) |
341 | return 0x306; |
342 | |
343 | value = pWork->offs2D34[pWork->bit_buff & 0xFF]; |
344 | } |
345 | else |
346 | { |
347 | if(WasteBits(pWork, 6)) |
348 | return 0x306; |
349 | |
350 | value = pWork->offs2E34[pWork->bit_buff & 0x7F]; |
351 | } |
352 | } |
353 | } |
354 | else |
355 | { |
356 | if(WasteBits(pWork, 8)) |
357 | return 0x306; |
358 | |
359 | value = pWork->offs2EB4[pWork->bit_buff & 0xFF]; |
360 | } |
361 | |
362 | return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value; |
363 | } |
364 | |
365 | //----------------------------------------------------------------------------- |
366 | // Retrieves the number of bytes to move back |
367 | |
368 | static unsigned long DecodeDist(TDcmpStruct * pWork, unsigned long dwLength) |
369 | { |
370 | unsigned long pos = pWork->position1[(pWork->bit_buff & 0xFF)]; |
371 | unsigned long nSkip = pWork->DistBits[pos]; // Number of bits to skip |
372 | |
373 | // Skip the appropriate number of bits |
374 | if(WasteBits(pWork, nSkip) == 1) |
375 | return 0; |
376 | |
377 | if(dwLength == 2) |
378 | { |
379 | pos = (pos << 2) | (pWork->bit_buff & 0x03); |
380 | |
381 | if(WasteBits(pWork, 2) == 1) |
382 | return 0; |
383 | } |
384 | else |
385 | { |
386 | pos = (pos << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask); |
387 | |
388 | // Skip the bits |
389 | if(WasteBits(pWork, pWork->dsize_bits) == 1) |
390 | return 0; |
391 | } |
392 | return pos+1; |
393 | } |
394 | |
395 | static unsigned long Expand(TDcmpStruct * pWork) |
396 | { |
397 | unsigned int copyBytes; // Number of bytes to copy |
398 | unsigned long oneByte; // One byte from compressed file |
399 | unsigned long dwResult; |
400 | |
401 | pWork->outputPos = 0x1000; // Initialize output buffer position |
402 | |
403 | // If end of data or error, terminate decompress |
404 | while((dwResult = oneByte = DecodeLit(pWork)) < 0x305) |
405 | { |
406 | // If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" |
407 | if(oneByte >= 0x100) |
408 | { |
409 | unsigned char * source; // ECX |
410 | unsigned char * target; // EDX |
411 | unsigned long copyLength = oneByte - 0xFE; |
412 | unsigned long moveBack; |
413 | |
414 | // Get length of data to copy |
415 | if((moveBack = DecodeDist(pWork, copyLength)) == 0) |
416 | { |
417 | dwResult = 0x306; |
418 | break; |
419 | } |
420 | |
421 | // Target and source pointer |
422 | target = &pWork->out_buff[pWork->outputPos]; |
423 | source = target - moveBack; |
424 | pWork->outputPos += copyLength; |
425 | |
426 | while(copyLength-- > 0) |
427 | *target++ = *source++; |
428 | } |
429 | else |
430 | pWork->out_buff[pWork->outputPos++] = (unsigned char)oneByte; |
431 | |
432 | // If number of extracted bytes has reached 1/2 of output buffer, |
433 | // flush output buffer. |
434 | if(pWork->outputPos >= 0x2000) |
435 | { |
436 | // Copy decompressed data into user buffer |
437 | copyBytes = 0x1000; |
438 | pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param); |
439 | |
440 | // If there are some data left, keep them alive |
441 | SMemCopy(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000); |
442 | pWork->outputPos -= 0x1000; |
443 | } |
444 | } |
445 | |
446 | copyBytes = pWork->outputPos - 0x1000; |
447 | pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param); |
448 | return dwResult; |
449 | } |
450 | |
451 | |
452 | //----------------------------------------------------------------------------- |
453 | // Main exploding function. |
454 | |
455 | unsigned int PKEXPORT explode( |
456 | unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), |
457 | void (*write_buf)(char *buf, unsigned int *size, void *param), |
458 | char *work_buf, |
459 | void *param) |
460 | { |
461 | TDcmpStruct * pWork = (TDcmpStruct *)work_buf; |
462 | |
463 | // Initialize work struct and load compressed data |
464 | pWork->read_buf = read_buf; |
465 | pWork->write_buf = write_buf; |
466 | pWork->param = param; |
467 | pWork->in_pos = sizeof(pWork->in_buff); |
468 | pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param); |
469 | if(pWork->in_bytes <= 4) |
470 | return CMP_BAD_DATA; |
471 | |
472 | pWork->ctype = pWork->in_buff[0]; // Get the compression type |
473 | pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size |
474 | pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer |
475 | pWork->extra_bits = 0; // Extra (over 8) bits |
476 | pWork->in_pos = 3; // Position in input buffer |
477 | |
478 | // Test for the valid dictionary size |
479 | if(4 > pWork->dsize_bits || pWork->dsize_bits > 6) |
480 | return CMP_INVALID_DICTSIZE; |
481 | |
482 | pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction |
483 | |
484 | if(pWork->ctype != CMP_BINARY) |
485 | { |
486 | if(pWork->ctype != CMP_ASCII) |
487 | return CMP_INVALID_MODE; |
488 | |
489 | SMemCopy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc)); |
490 | GenAscTabs(pWork); |
491 | } |
492 | |
493 | SMemCopy(pWork->LenBits, LenBits, sizeof(pWork->LenBits)); |
494 | GenDecodeTabs(0x10, pWork->LenBits, LenCode, pWork->position2); |
495 | SMemCopy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits)); |
496 | SMemCopy(pWork->LenBase, LenBase, sizeof(pWork->LenBase)); |
497 | SMemCopy(pWork->DistBits, DistBits, sizeof(pWork->DistBits)); |
498 | GenDecodeTabs(0x40, pWork->DistBits, DistCode, pWork->position1); |
499 | if(Expand(pWork) != 0x306) |
500 | return CMP_NO_ERROR; |
501 | |
502 | return CMP_ABORT; |
503 | } |
|