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




CommitLineData
3e09a0ee 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/*****************************************************************************/
13
14#include "pklib.h"
15#include "SMem.h"
16
17//-----------------------------------------------------------------------------
18// Defines
19
20#define DICT_OFFSET 0x204
21#define UNCMP_OFFSET (pWork->dsize_bytes + DICT_OFFSET)
22
23//-----------------------------------------------------------------------------
24// Local structures
25
26// Compression structure (Size 36312 bytes)
27typedef 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 :
41
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
45
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;
56
57//-----------------------------------------------------------------------------
58// Tables
59
60static 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};
67
68static 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};
75
76static unsigned char ExLenBits[] =
77{
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
79};
80
81static unsigned char LenBits[] =
82{
83 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
84};
85
86static unsigned char LenCode[] =
87{
88 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
89};
90
91static 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};
110
111static 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};
146
147//-----------------------------------------------------------------------------
148// Local variables
149
150static 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";
155
156//-----------------------------------------------------------------------------
157// Local functions
158
159static 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;
166
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);
172
173 for(puncmp = uncmp_data; work_end > puncmp; puncmp++)
174 pWork->offs0DC8[(puncmp[0] * 4) + (puncmp[1] * 5)]++;
175
176 add = 0;
177 for(pin0DC8 = pWork->offs0DC8; pin0DC8 < &pWork->offs1FC8; pin0DC8++)
178 {
179 add += *pin0DC8;
180 *pin0DC8 = (unsigned short)add;
181 }
182
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
187
188 pWork->offs0DC8[offs1]--;
189 pWork->offs49D0[pWork->offs0DC8[offs1]] = (unsigned short)offs2;
190 }
191}
192
193static void FlushBuf(TCmpStruct * pWork)
194{
195 unsigned char save_ch1;
196 unsigned char save_ch2;
197 unsigned int size = 0x800;
198
199 pWork->write_buf(pWork->out_buff, &size, pWork->param);
200
201 save_ch1 = pWork->out_buff[0x800];
202 save_ch2 = pWork->out_buff[pWork->out_bytes];
203 pWork->out_bytes -= 0x800;
204
205 SMemZero(pWork->out_buff, 0x802);
206
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}
212
213static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
214{
215 unsigned int out_bits;
216
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 }
224
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;
229
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);
235
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 }
245
246 // If there is enough compressed bytes, flush them
247 if(pWork->out_bytes >= 0x800)
248 FlushBuf(pWork);
249}
250
251static 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;
258
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;
266
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;
271
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 }
302
303 srcbuff3 = srcbuff;
304 if(ebx >= nreps)
305 {
306 pWork->offs0000 = srcbuff3 - pin27CC + ebx - 1;
307 if((nreps = ebx) > 10)
308 break;
309 }
310 }
311
312 pin49D0++;
313 esp18++;
314 pin27CC = pWork->work_buff + *pin49D0;
315
316 if(srcbuff2 > pin27CC)
317 continue;
318
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;
336
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;
353
354 for(;;) // 0040268B
355 {
356 esi = pWork->offs09BC[esi];
357 if(esi == 0xFFFF)
358 esi = 0;
359
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);
392
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 }
402
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;
411
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}
425
426static 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;
437
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;
442
443 // Reset output buffer to zero
444 SMemZero(&pWork->out_buff[2], sizeof(pWork->out_buff) - 2);
445 pWork->out_bits = 0;
446
447 do {
448 total_loaded = 0;
449 bytes_required = 0x1000;
450
451 do {
f71c1a8a 452 int loaded = pWork->read_buf((char *)&pWork->work_buff[UNCMP_OFFSET + total_loaded], &bytes_required, pWork->param);
3e09a0ee 453
454 if (loaded == 0) {
455 if (total_loaded == 0 && esp20 == 0) {
456 OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
457
458 if (pWork->out_bits != 0)
459 ++pWork->out_bytes;
460
461 pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
462 return;
463 }
464
465 esp18 = 1;
466 break;
467 }
468
469 total_loaded += loaded;
470 bytes_required -= loaded;
471 } while (bytes_required);
472
473 uncmp_end = &pWork->work_buff[pWork->dsize_bytes + total_loaded];
474
475 if (esp18 != 0)
476 uncmp_end += DICT_OFFSET;
477
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;
490
491 if (pWork->dsize_bytes != 0x1000)
492 ++esp20;
493 }
494
495 while (uncmp_end > uncmp_begin) {
496 nreps1 = FindRep(pWork, uncmp_begin);
497
498 while (nreps1) {
499 if (nreps1 == 2 && pWork->offs0000 >= 0x100)
500 break;
501
502 if (esp18 != 0 && uncmp_begin + nreps1 > uncmp_end) {
503 if ((nreps1 = uncmp_end - uncmp_begin) < 2)
504 break;
505
506 if (nreps1 != 2 || pWork->offs0000 < 0x100)
507 goto loc_15036C7F;
508
509 break;
510 }
511
512 if (nreps1 >= 8 || uncmp_begin + 1 >= uncmp_end)
513 goto loc_15036C7F;
514
515 save_offs0000 = pWork->offs0000; // ebp
516 nreps = nreps1;
517 nreps1 = FindRep(pWork, uncmp_begin + 1);
518
519 if (nreps >= nreps1)
520 goto loc_15036C79;
521
522 if (nreps + 1 >= nreps1 && save_offs0000 <= 0x80)
523 goto loc_15036C79;
524
525 OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
526 ++uncmp_begin;
527 }
528
529 OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
530 ++uncmp_begin;
531 continue;
532
533loc_15036C79:
534 nreps1 = nreps;
535 pWork->offs0000 = save_offs0000;
536
537loc_15036C7F:
538 OutputBits(pWork, pWork->nChBits[nreps1 + 0xFE], pWork->nChCodes[nreps1 + 0xFE]);
539
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 }
548
549 uncmp_begin += nreps1;
550 }
551
552 if (esp18 != 0) {
553 OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
554
555 if (pWork->out_bits != 0)
556 ++pWork->out_bytes;
557
558 pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
559 return;
560 }
561
562 uncmp_begin -= 0x1000;
563 SMemCopy(pWork->work_buff, &pWork->work_buff[0x1000], UNCMP_OFFSET);
564 } while (esp18 == 0);
565}
566
567//-----------------------------------------------------------------------------
568// Main imploding function
569
570unsigned 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;
582
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;
591
592 // Test dictionary size
593 switch(*dsize)
594 {
595 case 0x1000 :
596 pWork->dsize_bits++;
597 pWork->dsize_mask |= 0x20;
598 // No break here !!!
599
600 case 0x0800 :
601 pWork->dsize_bits++;
602 pWork->dsize_mask |= 0x10;
603 // No break here !!!
604
605 case 0x0400 :
606 break;
607
608 default:
609 return CMP_INVALID_DICTSIZE;
610 }
611
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;
623
624
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;
632
633 default:
634 return CMP_INVALID_MODE;
635 }
636
637 for(i = 0; i < 0x10; i++)
638 {
639 int nCount2 = 0; // EBX
640
641 if((1 << ExLenBits[i]) == 0)
642 continue;
643
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);
648
649 nCount2++;
650 nCount++;
651 }
652 while((1 << ExLenBits[i]) > nCount2);
653 }
654
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}