1 /*****************************************************************************/
2 /* explode.c Copyright (c) Ladislav Zezula 2003 */
3 /*---------------------------------------------------------------------------*/
4 /* Implode 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 /*****************************************************************************/
18 //-----------------------------------------------------------------------------
21 static unsigned char DistBits
[] =
23 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
24 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
25 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
26 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
29 static unsigned char DistCode
[] =
31 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
32 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
33 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
34 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
37 static unsigned char ExLenBits
[] =
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
42 static unsigned short LenBase
[] =
44 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
45 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
48 static unsigned char LenBits
[] =
50 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
53 static unsigned char LenCode
[] =
55 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
58 static unsigned char ChBitsAsc
[] =
60 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
61 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
62 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
63 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
64 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
65 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
66 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
67 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
68 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
69 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
70 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
71 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
72 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
73 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
74 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
75 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
78 static unsigned short ChCodeAsc
[] =
80 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
81 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
82 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
83 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
84 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
85 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
86 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
87 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
88 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
89 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
90 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
91 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
92 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
93 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
94 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
95 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
96 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
97 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
98 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
99 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
100 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
101 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
102 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
103 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
104 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
105 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
106 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
107 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
108 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
109 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
110 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
111 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
114 //-----------------------------------------------------------------------------
117 static char Copyright
[] = "PKWARE Data Compression Library for Win32\r\n"
118 "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
119 "Patent No. 5,051,745\r\n"
120 "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
123 //-----------------------------------------------------------------------------
126 // Copies a block to another location
127 static void lmemcpy(void * trg
, const void * src
, size_t count
)
129 memcpy(trg
, src
, count
);
132 static void GenDecodeTabs(long count
, unsigned char * bits
, unsigned char * pCode
, unsigned char * buffer2
)
136 for(i
= count
-1; i
>= 0; i
--) // EBX - count
138 unsigned long idx1
= pCode
[i
];
139 unsigned long idx2
= 1 << bits
[i
];
143 buffer2
[idx1
] = (unsigned char)i
;
150 static void GenAscTabs(TDcmpStruct
* pWork
)
152 unsigned short * pChCodeAsc
= &ChCodeAsc
[0xFF];
153 unsigned long acc
, add
;
154 unsigned short count
;
156 for(count
= 0x00FF; pChCodeAsc
>= ChCodeAsc
; pChCodeAsc
--, count
--)
158 unsigned char * pChBitsAsc
= pWork
->ChBitsAsc
+ count
;
159 unsigned char bits_asc
= *pChBitsAsc
;
163 add
= (1 << bits_asc
);
168 pWork
->offs2C34
[acc
] = (unsigned char)count
;
173 else if((acc
= (*pChCodeAsc
& 0xFF)) != 0)
175 pWork
->offs2C34
[acc
] = 0xFF;
177 if(*pChCodeAsc
& 0x3F)
180 *pChBitsAsc
= bits_asc
;
182 add
= (1 << bits_asc
);
183 acc
= *pChCodeAsc
>> 4;
186 pWork
->offs2D34
[acc
] = (unsigned char)count
;
194 *pChBitsAsc
= bits_asc
;
196 add
= (1 << bits_asc
);
197 acc
= *pChCodeAsc
>> 6;
200 pWork
->offs2E34
[acc
] = (unsigned char)count
;
209 *pChBitsAsc
= bits_asc
;
211 add
= (1 << bits_asc
);
212 acc
= *pChCodeAsc
>> 8;
215 pWork
->offs2EB4
[acc
] = (unsigned char)count
;
223 //-----------------------------------------------------------------------------
224 // Skips given number of bits in bit buffer. Result is stored in pWork->bit_buff
225 // If no data in input buffer, returns true
227 static int WasteBits(TDcmpStruct
* pWork
, unsigned long nBits
)
229 // If number of bits required is less than number of (bits in the buffer) ?
230 if(nBits
<= pWork
->extra_bits
)
232 pWork
->extra_bits
-= nBits
;
233 pWork
->bit_buff
>>= nBits
;
237 // Load input buffer if necessary
238 pWork
->bit_buff
>>= pWork
->extra_bits
;
239 if(pWork
->in_pos
== pWork
->in_bytes
)
241 pWork
->in_pos
= sizeof(pWork
->in_buff
);
242 if((pWork
->in_bytes
= pWork
->read_buf((char *)pWork
->in_buff
, &pWork
->in_pos
, pWork
->param
)) == 0)
248 pWork
->bit_buff
|= (pWork
->in_buff
[pWork
->in_pos
++] << 8);
249 pWork
->bit_buff
>>= (nBits
- pWork
->extra_bits
);
250 pWork
->extra_bits
= (pWork
->extra_bits
- nBits
) + 8;
254 //-----------------------------------------------------------------------------
255 // Returns : 0x000 - 0x0FF : One byte from compressed file.
256 // 0x100 - 0x305 : Copy previous block (0x100 = 1 byte)
257 // 0x306 : Out of buffer (?)
259 static unsigned long DecodeLit(TDcmpStruct
* pWork
)
261 unsigned long nBits
; // Number of bits to skip
262 unsigned long value
; // Position in buffers
264 // Test the current bit in byte buffer. If is not set, simply return the next byte.
265 if(pWork
->bit_buff
& 1)
267 // Skip current bit in the buffer
268 if(WasteBits(pWork
, 1))
271 // The next bits are position in buffers
272 value
= pWork
->position2
[(pWork
->bit_buff
& 0xFF)];
274 // Get number of bits to skip
275 if(WasteBits(pWork
, pWork
->LenBits
[value
]))
278 if((nBits
= pWork
->ExLenBits
[value
]) != 0)
280 unsigned long val2
= pWork
->bit_buff
& ((1 << nBits
) - 1);
282 if(WasteBits(pWork
, nBits
))
284 if((value
+ val2
) != 0x10E)
287 value
= pWork
->LenBase
[value
] + val2
;
289 return value
+ 0x100; // Return number of bytes to repeat
293 if(WasteBits(pWork
, 1))
296 // If the binary compression type, read 8 bits and return them as one byte.
297 if(pWork
->ctype
== CMP_BINARY
)
299 value
= pWork
->bit_buff
& 0xFF;
300 if(WasteBits(pWork
, 8))
305 // When ASCII compression ...
306 if(pWork
->bit_buff
& 0xFF)
308 value
= pWork
->offs2C34
[pWork
->bit_buff
& 0xFF];
312 if(pWork
->bit_buff
& 0x3F)
314 if(WasteBits(pWork
, 4))
317 value
= pWork
->offs2D34
[pWork
->bit_buff
& 0xFF];
321 if(WasteBits(pWork
, 6))
324 value
= pWork
->offs2E34
[pWork
->bit_buff
& 0x7F];
330 if(WasteBits(pWork
, 8))
333 value
= pWork
->offs2EB4
[pWork
->bit_buff
& 0xFF];
336 return WasteBits(pWork
, pWork
->ChBitsAsc
[value
]) ? 0x306 : value
;
339 //-----------------------------------------------------------------------------
340 // Retrieves the number of bytes to move back
342 static unsigned long DecodeDist(TDcmpStruct
* pWork
, unsigned long dwLength
)
344 unsigned long pos
= pWork
->position1
[(pWork
->bit_buff
& 0xFF)];
345 unsigned long nSkip
= pWork
->DistBits
[pos
]; // Number of bits to skip
347 // Skip the appropriate number of bits
348 if(WasteBits(pWork
, nSkip
) == 1)
353 pos
= (pos
<< 2) | (pWork
->bit_buff
& 0x03);
355 if(WasteBits(pWork
, 2) == 1)
360 pos
= (pos
<< pWork
->dsize_bits
) | (pWork
->bit_buff
& pWork
->dsize_mask
);
363 if(WasteBits(pWork
, pWork
->dsize_bits
) == 1)
369 static unsigned long Expand(TDcmpStruct
* pWork
)
371 unsigned int copyBytes
; // Number of bytes to copy
372 unsigned long oneByte
; // One byte from compressed file
373 unsigned long dwResult
;
375 pWork
->outputPos
= 0x1000; // Initialize output buffer position
377 // If end of data or error, terminate decompress
378 while((dwResult
= oneByte
= DecodeLit(pWork
)) < 0x305)
380 // If one byte is greater than 0x100, means "Repeat n - 0xFE bytes"
383 unsigned char * source
; // ECX
384 unsigned char * target
; // EDX
385 unsigned long copyLength
= oneByte
- 0xFE;
386 unsigned long moveBack
;
388 // Get length of data to copy
389 if((moveBack
= DecodeDist(pWork
, copyLength
)) == 0)
395 // Target and source pointer
396 target
= &pWork
->out_buff
[pWork
->outputPos
];
397 source
= target
- moveBack
;
398 pWork
->outputPos
+= copyLength
;
400 while(copyLength
-- > 0)
401 *target
++ = *source
++;
404 pWork
->out_buff
[pWork
->outputPos
++] = (unsigned char)oneByte
;
406 // If number of extracted bytes has reached 1/2 of output buffer,
407 // flush output buffer.
408 if(pWork
->outputPos
>= 0x2000)
410 // Copy decompressed data into user buffer
412 pWork
->write_buf((char *)&pWork
->out_buff
[0x1000], ©Bytes
, pWork
->param
);
414 // If there are some data left, keep them alive
415 lmemcpy(pWork
->out_buff
, &pWork
->out_buff
[0x1000], pWork
->outputPos
- 0x1000);
416 pWork
->outputPos
-= 0x1000;
420 copyBytes
= pWork
->outputPos
- 0x1000;
421 pWork
->write_buf((char *)&pWork
->out_buff
[0x1000], ©Bytes
, pWork
->param
);
426 //-----------------------------------------------------------------------------
427 // Main exploding function.
429 unsigned int explode(
430 unsigned int (*read_buf
)(char *buf
, unsigned int *size
, void *param
),
431 void (*write_buf
)(char *buf
, unsigned int *size
, void *param
),
435 TDcmpStruct
* pWork
= (TDcmpStruct
*)work_buf
;
437 // Set the whole work buffer to zeros
438 memset(pWork
, 0, sizeof(TDcmpStruct
));
440 // Initialize work struct and load compressed data
441 pWork
->read_buf
= read_buf
;
442 pWork
->write_buf
= write_buf
;
443 pWork
->param
= param
;
444 pWork
->in_pos
= sizeof(pWork
->in_buff
);
445 pWork
->in_bytes
= pWork
->read_buf((char *)pWork
->in_buff
, &pWork
->in_pos
, pWork
->param
);
446 if(pWork
->in_bytes
<= 4)
449 pWork
->ctype
= pWork
->in_buff
[0]; // Get the compression type
450 pWork
->dsize_bits
= pWork
->in_buff
[1]; // Get the dictionary size
451 pWork
->bit_buff
= pWork
->in_buff
[2]; // Initialize 16-bit bit buffer
452 pWork
->extra_bits
= 0; // Extra (over 8) bits
453 pWork
->in_pos
= 3; // Position in input buffer
455 // Test for the valid dictionary size
456 if(4 > pWork
->dsize_bits
|| pWork
->dsize_bits
> 6)
457 return CMP_INVALID_DICTSIZE
;
459 pWork
->dsize_mask
= 0xFFFF >> (0x10 - pWork
->dsize_bits
); // Shifted by 'sar' instruction
461 if(pWork
->ctype
!= CMP_BINARY
)
463 if(pWork
->ctype
!= CMP_ASCII
)
464 return CMP_INVALID_MODE
;
466 lmemcpy(pWork
->ChBitsAsc
, ChBitsAsc
, sizeof(pWork
->ChBitsAsc
));
470 lmemcpy(pWork
->LenBits
, LenBits
, sizeof(pWork
->LenBits
));
471 GenDecodeTabs(0x10, pWork
->LenBits
, LenCode
, pWork
->position2
);
472 lmemcpy(pWork
->ExLenBits
, ExLenBits
, sizeof(pWork
->ExLenBits
));
473 lmemcpy(pWork
->LenBase
, LenBase
, sizeof(pWork
->LenBase
));
474 lmemcpy(pWork
->DistBits
, DistBits
, sizeof(pWork
->DistBits
));
475 GenDecodeTabs(0x40, pWork
->DistBits
, DistCode
, pWork
->position1
);
476 if(Expand(pWork
) != 0x306)