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 | /* 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) |
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 : |
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 | |
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 | }; |
67 | |
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 | }; |
75 | |
76 | static unsigned char ExLenBits[] = |
77 | { |
78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 |
79 | }; |
80 | |
81 | static unsigned char LenBits[] = |
82 | { |
83 | 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 |
84 | }; |
85 | |
86 | static unsigned char LenCode[] = |
87 | { |
88 | 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 |
89 | }; |
90 | |
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 | }; |
110 | |
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 | }; |
146 | |
147 | //----------------------------------------------------------------------------- |
148 | // Local variables |
149 | |
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"; |
155 | |
156 | //----------------------------------------------------------------------------- |
157 | // Local functions |
158 | |
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; |
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 | |
193 | static 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 | |
213 | static 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 | |
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; |
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 | |
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; |
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 | |
533 | loc_15036C79: |
534 | nreps1 = nreps; |
535 | pWork->offs0000 = save_offs0000; |
536 | |
537 | loc_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 | |
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; |
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 | } |
|