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: |
1 /*****************************************************************************/
2 /* implode.c Copyright (c) Ladislav Zezula 2003 */
3 /*---------------------------------------------------------------------------*/
4 /* Implode function of PKWARE Data Compression library */
5 /*---------------------------------------------------------------------------*/
6 /* Date Ver Who Comment */
7 /* -------- ---- --- ------- */
8 /* 11.04.03 1.00 Ladislav Zezula First version of implode.c */
9 /* 02.05.03 1.00 Ladislav Zezula Stress test done */
10 /* 12.06.03 1.00 ShadowFlare Fixed error in WriteCmpData that caused */
11 /* different output to be produced */
12 /*****************************************************************************/
14 #include "pklib.h"
15 #include "SMem.h"
17 //-----------------------------------------------------------------------------
18 // Defines
20 #define DICT_OFFSET 0x204
21 #define UNCMP_OFFSET (pWork->dsize_bytes + DICT_OFFSET)
23 //-----------------------------------------------------------------------------
24 // Local structures
26 // Compression structure (Size 36312 bytes)
27 typedef struct
28 {
29 unsigned int offs0000; // 0000 :
30 unsigned int out_bytes; // 0004 : # bytes available in out_buff
31 unsigned int out_bits; // 0008 : # of bits available in the last out byte
32 unsigned int dsize_bits; // 000C : Dict size : 4=0x400, 5=0x800, 6=0x1000
33 unsigned int dsize_mask; // 0010 : Dict size : 0x0F=0x400, 0x1F=0x800, 0x3F=0x1000
34 unsigned int ctype; // 0014 : Compression type (Ascii or binary)
35 unsigned int dsize_bytes; // 0018 : Dictionary size in bytes
36 unsigned char dist_bits[0x40]; // 001C : Distance bits
37 unsigned char dist_codes[0x40]; // 005C : Distance codes
38 unsigned char nChBits[0x306]; // 009C :
39 unsigned short nChCodes[0x306]; // 03A2 :
40 unsigned short offs09AE; // 09AE :
42 void * param; // 09B0 : User parameter
43 unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 9B4
44 void (*write_buf)(char *buf, unsigned int *size, void *param); // 9B8
46 unsigned short offs09BC[0x204]; // 09BC :
47 unsigned long offs0DC4; // 0DC4 :
48 unsigned short offs0DC8[0x900]; // 0DC8 :
49 unsigned short offs1FC8; // 1FC8 :
50 char out_buff[0x802]; // 1FCA : Output (compressed) data
51 unsigned char work_buff[0x2204]; // 27CC : Work buffer
52 // + DICT_OFFSET => Dictionary
53 // + UNCMP_OFFSET => Uncompressed data
54 unsigned short offs49D0[0x2000]; // 49D0 :
55 } TCmpStruct;
57 //-----------------------------------------------------------------------------
58 // Tables
60 static unsigned char DistBits[] =
61 {
62 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
63 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
64 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
65 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
66 };
68 static unsigned char DistCode[] =
69 {
70 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
71 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
72 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
73 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
74 };
76 static unsigned char ExLenBits[] =
77 {
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
79 };
81 static unsigned char LenBits[] =
82 {
83 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
84 };
86 static unsigned char LenCode[] =
87 {
88 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
89 };
91 static unsigned char ChBitsAsc[] =
92 {
93 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
94 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
95 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
96 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
97 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
98 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
99 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
100 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
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 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
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 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
107 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
108 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
109 };
111 static unsigned short ChCodeAsc[] =
112 {
113 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
114 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
115 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
116 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
117 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
118 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
119 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
120 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
121 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
122 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
123 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
124 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
125 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
126 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
127 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
128 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
129 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
130 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
131 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
132 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
133 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
134 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
135 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
136 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
137 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
138 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
139 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
140 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
141 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
142 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
143 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
144 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
145 };
147 //-----------------------------------------------------------------------------
148 // Local variables
150 static char Copyright[] = "PKWARE Data Compression Library for Win32\r\n"
151 "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
152 "Patent No. 5,051,745\r\n"
153 "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
154 "Version 1.11";
156 //-----------------------------------------------------------------------------
157 // Local functions
159 static void SortBuffer(TCmpStruct * pWork, unsigned char * uncmp_data, unsigned char * work_end)
160 {
161 unsigned short * pin0DC8;
162 unsigned char * puncmp;
163 unsigned long offs1, offs2;
164 unsigned long ndwords;
165 unsigned int add;
167 // Fill 0x480 dwords (0x1200 bytes)
168 ndwords = (pWork->out_buff - (char *)pWork->offs0DC8 + 1) >> 2;
169 if(ndwords <= 1)
170 ndwords = 1;
171 SMemZero(pWork->offs0DC8, ndwords << 2);
173 for(puncmp = uncmp_data; work_end > puncmp; puncmp++)
174 pWork->offs0DC8[(puncmp[0] * 4) + (puncmp[1] * 5)]++;
176 add = 0;
177 for(pin0DC8 = pWork->offs0DC8; pin0DC8 < &pWork->offs1FC8; pin0DC8++)
178 {
179 add += *pin0DC8;
180 *pin0DC8 = (unsigned short)add;
181 }
183 for(work_end--; work_end >= uncmp_data; work_end--)
184 {
185 offs1 = (work_end[0] * 4) + (work_end[1] * 5); // EAX
186 offs2 = (work_end - pWork->work_buff); // EDI
188 pWork->offs0DC8[offs1]--;
189 pWork->offs49D0[pWork->offs0DC8[offs1]] = (unsigned short)offs2;
190 }
191 }
193 static void FlushBuf(TCmpStruct * pWork)
194 {
195 unsigned char save_ch1;
196 unsigned char save_ch2;
197 unsigned int size = 0x800;
199 pWork->write_buf(pWork->out_buff, &size, pWork->param);
201 save_ch1 = pWork->out_buff[0x800];
202 save_ch2 = pWork->out_buff[pWork->out_bytes];
203 pWork->out_bytes -= 0x800;
205 SMemZero(pWork->out_buff, 0x802);
207 if(pWork->out_bytes != 0)
208 pWork->out_buff[0] = save_ch1;
209 if(pWork->out_bits != 0)
210 pWork->out_buff[pWork->out_bytes] = save_ch2;
211 }
213 static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
214 {
215 unsigned int out_bits;
217 // If more than 8 bits to output, do recursion
218 if(nbits > 8)
219 {
220 OutputBits(pWork, 8, bit_buff);
221 bit_buff >>= 8;
222 nbits -= 8;
223 }
225 // Add bits to the last out byte in out_buff;
226 out_bits = pWork->out_bits;
227 pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits);
228 pWork->out_bits += nbits;
230 // If 8 or more bits, increment number of bytes
231 if(pWork->out_bits > 8)
232 {
233 pWork->out_bytes++;
234 bit_buff >>= (8 - out_bits);
236 pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff;
237 pWork->out_bits &= 7;
238 }
239 else
240 {
241 pWork->out_bits &= 7;
242 if(pWork->out_bits == 0)
243 pWork->out_bytes++;
244 }
246 // If there is enough compressed bytes, flush them
247 if(pWork->out_bytes >= 0x800)
248 FlushBuf(pWork);
249 }
251 static unsigned long FindRep(TCmpStruct * pWork, unsigned char * srcbuff)
252 {
253 unsigned short esp12;
254 unsigned char * esp14;
255 unsigned short esp18;
256 unsigned char * srcbuff2;
257 unsigned char esp20;
259 unsigned char * srcbuff3;
260 unsigned short * pin0DC8;
261 unsigned char * pin27CC;
262 unsigned short * pin49D0;
263 unsigned long nreps = 1; // EAX
264 unsigned long ebx, esi;
265 unsigned short di;
267 pin0DC8 = pWork->offs0DC8 + (srcbuff[0] * 4) + (srcbuff[1] * 5);
268 esi = (srcbuff - pWork->dsize_bytes) - pWork->work_buff + 1;
269 esp18 = *pin0DC8;
270 pin49D0 = pWork->offs49D0 + esp18;
272 if(*pin49D0 < esi)
273 {
274 while(*pin49D0 < esi)
275 {
276 pin49D0++;
277 esp18++;
278 }
279 *pin0DC8 = esp18;
280 }
281 //---------------------------------------------------------------------------
282 srcbuff2 = srcbuff - 1;
283 pin49D0 = pWork->offs49D0 + esp18;
284 pin27CC = pWork->work_buff + *pin49D0;
285 if(srcbuff2 <= pin27CC)
286 return 0;
287 //---------------------------------------------------------------------------
288 srcbuff3 = srcbuff;
289 for(;;)
290 {
291 if(srcbuff3[nreps-1] == pin27CC[nreps-1] && *srcbuff3 == *pin27CC)
292 {
293 pin27CC++;
294 srcbuff3++;
295 for(ebx = 2; ebx < DICT_OFFSET; ebx++)
296 {
297 pin27CC++;
298 srcbuff3++;
299 if(*pin27CC != *srcbuff3)
300 break;
301 }
303 srcbuff3 = srcbuff;
304 if(ebx >= nreps)
305 {
306 pWork->offs0000 = srcbuff3 - pin27CC + ebx - 1;
307 if((nreps = ebx) > 10)
308 break;
309 }
310 }
312 pin49D0++;
313 esp18++;
314 pin27CC = pWork->work_buff + *pin49D0;
316 if(srcbuff2 > pin27CC)
317 continue;
319 return (nreps >= 2) ? nreps : 0;
320 }
321 //---------------------------------------------------------------------------
322 if(ebx == DICT_OFFSET)
323 {
324 pWork->offs0000--;
325 return ebx;
326 }
327 //---------------------------------------------------------------------------
328 pin49D0 = pWork->offs49D0 + esp18;
329 if(pWork->work_buff + pin49D0[1] >= srcbuff2)
330 return nreps;
331 //---------------------------------------------------------------------------
332 di = 0;
333 pWork->offs09BC[0] = 0xFFFF;
334 pWork->offs09BC[1] = di;
335 esp12 = 1;
337 do
338 {
339 esi = di;
340 if(srcbuff[esp12] != srcbuff[esi])
341 {
342 di = pWork->offs09BC[esi];
343 if(di != 0xFFFF)
344 continue;
345 }
346 pWork->offs09BC[++esp12] = ++di;
347 }
348 while(esp12 < nreps);
349 //---------------------------------------------------------------------------
350 esi = nreps;
351 pin27CC = pWork->work_buff + pin49D0[0] + nreps;
352 esp14 = pin27CC;
354 for(;;) // 0040268B
355 {
356 esi = pWork->offs09BC[esi];
357 if(esi == 0xFFFF)
358 esi = 0;
360 pin49D0 = pWork->offs49D0 + esp18;
361 do
362 {
363 pin49D0++;
364 esp18++;
365 pin27CC = pWork->work_buff + pin49D0[0];
366 if(pin27CC >= srcbuff2)
367 return nreps;
368 }
369 while(pin27CC + esi < esp14);
370 //---------------------------------------------------------------------------
371 esp20 = srcbuff[nreps - 2];
372 if(esp20 == pin27CC[nreps - 2])
373 {
374 if(pin27CC + esi != esp14)
375 {
376 esp14 = pin27CC;
377 esi = 0;
378 }
379 }
380 else
381 {
382 pin49D0 = pWork->offs49D0 + esp18;
383 do
384 {
385 pin49D0++;
386 esp18++;
387 pin27CC = pWork->work_buff + pin49D0[0];
388 if(pin27CC >= srcbuff2)
389 return nreps;
390 }
391 while(pin27CC[nreps - 2] != esp20 || pin27CC[0] != *srcbuff);
393 esp14 = pin27CC + 2;
394 esi = 2;
395 }
396 //---------------------------------------------------------------------------
397 for(; esp14[0] == srcbuff[esi]; esp14++)
398 {
399 if(++esi >= DICT_OFFSET)
400 break;
401 }
403 if(esi < nreps)
404 continue;
405 pWork->offs0000 = srcbuff - pin27CC - 1;
406 if(esi <= nreps)
407 continue;
408 nreps = esi;
409 if(esi == DICT_OFFSET)
410 return nreps;
412 do
413 {
414 if(srcbuff[esp12] != srcbuff[di])
415 {
416 di = pWork->offs09BC[di];
417 if(di != 0xFFFF)
418 continue;
419 }
420 pWork->offs09BC[++esp12] = ++di;
421 }
422 while(esp12 < esi);
423 }
424 }
426 static void WriteCmpData(TCmpStruct * pWork)
427 {
428 unsigned int nreps = 0; // ESP+10 : Number of repeats
429 unsigned char * uncmp_end; // ESP+14 : End of uncompressed data
430 unsigned int esp18 = 0; // ESP+18 :
431 unsigned int bytes_required; // ESP+1C : Number of bytes required to read
432 unsigned int esp20 = 0; // ESP+20 :
433 unsigned char * uncmp_begin = &pWork->work_buff[UNCMP_OFFSET]; // EDI
434 unsigned long nreps1;
435 unsigned long save_offs0000 = 0;
436 int total_loaded = 0;
438 // Store the compression type and dictionary size
439 pWork->out_buff[0] = (char)pWork->ctype;
440 pWork->out_buff[1] = (char)pWork->dsize_bits;
441 pWork->out_bytes = 2;
443 // Reset output buffer to zero
444 SMemZero(&pWork->out_buff[2], sizeof(pWork->out_buff) - 2);
445 pWork->out_bits = 0;
447 do {
448 total_loaded = 0;
449 bytes_required = 0x1000;
451 do {
452 int loaded = pWork->read_buf((char *)&pWork->work_buff[UNCMP_OFFSET + total_loaded], &bytes_required, pWork->param);
454 if (loaded == 0) {
455 if (total_loaded == 0 && esp20 == 0) {
456 OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
458 if (pWork->out_bits != 0)
459 ++pWork->out_bytes;
461 pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
462 return;
463 }
465 esp18 = 1;
466 break;
467 }
469 total_loaded += loaded;
470 bytes_required -= loaded;
471 } while (bytes_required);
473 uncmp_end = &pWork->work_buff[pWork->dsize_bytes + total_loaded];
475 if (esp18 != 0)
476 uncmp_end += DICT_OFFSET;
478 if (esp20) {
479 if (esp20 == 1) {
480 SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes + DICT_OFFSET, uncmp_end + 1);
481 ++esp20;
482 }
483 else {
484 SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes, uncmp_end + 1);
485 }
486 }
487 else {
488 SortBuffer(pWork, uncmp_begin, uncmp_end + 1);
489 ++esp20;
491 if (pWork->dsize_bytes != 0x1000)
492 ++esp20;
493 }
495 while (uncmp_end > uncmp_begin) {
496 nreps1 = FindRep(pWork, uncmp_begin);
498 while (nreps1) {
499 if (nreps1 == 2 && pWork->offs0000 >= 0x100)
500 break;
502 if (esp18 != 0 && uncmp_begin + nreps1 > uncmp_end) {
503 if ((nreps1 = uncmp_end - uncmp_begin) < 2)
504 break;
506 if (nreps1 != 2 || pWork->offs0000 < 0x100)
507 goto loc_15036C7F;
509 break;
510 }
512 if (nreps1 >= 8 || uncmp_begin + 1 >= uncmp_end)
513 goto loc_15036C7F;
515 save_offs0000 = pWork->offs0000; // ebp
516 nreps = nreps1;
517 nreps1 = FindRep(pWork, uncmp_begin + 1);
519 if (nreps >= nreps1)
520 goto loc_15036C79;
522 if (nreps + 1 >= nreps1 && save_offs0000 <= 0x80)
523 goto loc_15036C79;
525 OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
526 ++uncmp_begin;
527 }
529 OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
530 ++uncmp_begin;
531 continue;
533 loc_15036C79:
534 nreps1 = nreps;
535 pWork->offs0000 = save_offs0000;
537 loc_15036C7F:
538 OutputBits(pWork, pWork->nChBits[nreps1 + 0xFE], pWork->nChCodes[nreps1 + 0xFE]);
540 if (nreps1 == 2) {
541 OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> 2], pWork->dist_codes[pWork->offs0000 >> 2]);
542 OutputBits(pWork, 2, pWork->offs0000 & 3);
543 }
544 else {
545 OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> pWork->dsize_bits], pWork->dist_codes[pWork->offs0000 >> pWork->dsize_bits]);
546 OutputBits(pWork, pWork->dsize_bits, pWork->offs0000 & pWork->dsize_mask);
547 }
549 uncmp_begin += nreps1;
550 }
552 if (esp18 != 0) {
553 OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
555 if (pWork->out_bits != 0)
556 ++pWork->out_bytes;
558 pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
559 return;
560 }
562 uncmp_begin -= 0x1000;
563 SMemCopy(pWork->work_buff, &pWork->work_buff[0x1000], UNCMP_OFFSET);
564 } while (esp18 == 0);
565 }
567 //-----------------------------------------------------------------------------
568 // Main imploding function
570 unsigned int PKEXPORT implode(
571 unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
572 void (*write_buf)(char *buf, unsigned int *size, void *param),
573 char *work_buf,
574 void *param,
575 unsigned int *type,
576 unsigned int *dsize)
577 {
578 TCmpStruct * pWork = (TCmpStruct *)work_buf;
579 unsigned int nChCode;
580 unsigned int nCount;
581 unsigned int i;
583 // Fill the work buffer information
584 pWork->read_buf = read_buf;
585 pWork->write_buf = write_buf;
586 pWork->dsize_bytes = *dsize;
587 pWork->ctype = *type;
588 pWork->param = param;
589 pWork->dsize_bits = 4;
590 pWork->dsize_mask = 0x0F;
592 // Test dictionary size
593 switch(*dsize)
594 {
595 case 0x1000 :
596 pWork->dsize_bits++;
597 pWork->dsize_mask |= 0x20;
598 // No break here !!!
600 case 0x0800 :
601 pWork->dsize_bits++;
602 pWork->dsize_mask |= 0x10;
603 // No break here !!!
605 case 0x0400 :
606 break;
608 default:
609 return CMP_INVALID_DICTSIZE;
610 }
612 // Test the compression type
613 switch(*type)
614 {
615 case CMP_BINARY: // We will compress data with binary compression type
616 for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)
617 {
618 pWork->nChBits[nCount] = 9;
619 pWork->nChCodes[nCount] = (unsigned short)nChCode;
620 nChCode = (nChCode & 0x0000FFFF) + 2;
621 }
622 break;
625 case CMP_ASCII: // We will compress data with ASCII compression type
626 for(nCount = 0; nCount < 0x100; nCount++)
627 {
628 pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1);
629 pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);
630 }
631 break;
633 default:
634 return CMP_INVALID_MODE;
635 }
637 for(i = 0; i < 0x10; i++)
638 {
639 int nCount2 = 0; // EBX
641 if((1 << ExLenBits[i]) == 0)
642 continue;
644 do
645 {
646 pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);
647 pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);
649 nCount2++;
650 nCount++;
651 }
652 while((1 << ExLenBits[i]) > nCount2);
653 }
655 // Copy the distance codes and distance bits and perform the compression
656 SMemCopy(&pWork->dist_codes, DistCode, sizeof(DistCode));
657 SMemCopy(&pWork->dist_bits, DistBits, sizeof(DistBits));
658 WriteCmpData(pWork);
659 return CMP_NO_ERROR;
660 }
|