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




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[] = 
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)
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     }
193 static void FlushBuf(TCmpStruct * pWork)
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;
213 static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
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);
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     }
246     // If there is enough compressed bytes, flush them
247     if(pWork->out_bytes >= 0x800)
248         FlushBuf(pWork);
251 static unsigned long FindRep(TCmpStruct * pWork, unsigned char * srcbuff)
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;
353     
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     }
426 static void WriteCmpData(TCmpStruct * pWork)
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);
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)
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;