Commit | Line | Data |
3e09a0ee |
1 | // SComp.cpp - Main compression/decompression and wrapper routines |
2 | // |
3 | // Requires Zlib for Warcraft III files (not included). |
4 | // Get it at http://www.gzip.org/zlib/ |
5 | // |
6 | // Converted from assembly to C++ by ShadowFlare. |
7 | // E-mail : blakflare@hotmail.com |
8 | // Webpage : http://sfsrealm.hopto.org/ |
9 | // License information for this code is in license.txt |
10 | |
11 | |
12 | // Define NO_WINDOWS_H globally if compiling for |
13 | // Windows to disable calling Windows functions. |
14 | |
15 | // Comment this out to disable Zlib compression support. |
16 | #define USE_ZLIB |
17 | |
58da368c |
18 | // Comment this out to disable bzip 2 compression support. |
19 | #define USE_BZIP2 |
20 | |
3e09a0ee |
21 | #include "SComp.h" |
22 | #include "SErr.h" |
23 | #include "SMem.h" |
24 | #include "wave.h" |
25 | #include "huffman.h" |
58da368c |
26 | |
3e09a0ee |
27 | #ifdef USE_ZLIB |
28 | #ifndef __SYS_ZLIB |
58da368c |
29 | #define ZLIB_INTERNAL |
30 | #include "zlib/zlib.h" |
3e09a0ee |
31 | #else |
32 | #include <zlib.h> |
33 | #endif |
34 | #endif |
58da368c |
35 | |
3e09a0ee |
36 | #include "pklib.h" |
37 | |
58da368c |
38 | #ifdef USE_BZIP2 |
39 | #ifndef __SYS_BZLIB |
40 | #include "bzip2/bzlib.h" |
41 | #else |
42 | #include <bzlib.h> |
43 | #endif |
44 | #endif |
45 | |
3e09a0ee |
46 | typedef void (__fastcall *FCOMPRESS)(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel); |
47 | typedef void (__fastcall *FDECOMPRESS)(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); |
48 | |
49 | struct CompressFunc { |
50 | DWORD dwFlag; |
51 | FCOMPRESS fnCompress; |
52 | }; |
53 | |
54 | struct DecompressFunc { |
55 | DWORD dwFlag; |
56 | FDECOMPRESS fnDecompress; |
57 | }; |
58 | |
59 | void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel); |
60 | void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel); |
61 | void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel); |
62 | #ifdef USE_ZLIB |
63 | void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel); |
64 | #endif |
65 | void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel); |
58da368c |
66 | #ifdef USE_BZIP2 |
67 | void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel); |
68 | #endif |
3e09a0ee |
69 | |
70 | void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); |
71 | void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); |
72 | void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); |
73 | #ifdef USE_ZLIB |
74 | void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); |
75 | #endif |
76 | void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); |
58da368c |
77 | #ifdef USE_BZIP2 |
78 | void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); |
79 | #endif |
3e09a0ee |
80 | |
81 | void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType); |
82 | |
83 | typedef struct { |
84 | LPVOID lpvDestinationMem; |
85 | DWORD dwDestStart; |
86 | DWORD dwDestLen; |
87 | LPVOID lpvSourceMem; |
88 | DWORD dwSrcStart; |
89 | DWORD dwSrcLen; |
90 | } BUFFERINFO; |
91 | |
92 | unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param); |
93 | void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param); |
94 | |
0379c6fe |
95 | const unsigned int UNSUPPORTED_COMPRESSION = (0xFF ^ (0x40 | 0x80 | 0x01 |
96 | #ifdef USE_ZLIB |
97 | | 0x02 |
98 | #endif |
99 | | 0x08 |
100 | #ifdef USE_BZIP2 |
101 | | 0x10 |
102 | #endif |
103 | )); |
104 | const unsigned int UNSUPPORTED_DECOMPRESSION = (0xFF ^ (0x40 | 0x80 | 0x01 |
105 | #ifdef USE_ZLIB |
106 | | 0x02 |
107 | #endif |
108 | | 0x08 |
109 | #ifdef USE_BZIP2 |
110 | | 0x10 |
111 | #endif |
112 | )); |
113 | |
3e09a0ee |
114 | CompressFunc CompressionFunctions[] = |
115 | { |
116 | {0x40, CompressWaveMono}, |
117 | {0x80, CompressWaveStereo}, |
118 | {0x01, HuffmanCompress}, |
119 | #ifdef USE_ZLIB |
120 | {0x02, Deflate}, |
121 | #endif |
58da368c |
122 | {0x08, Implode}, |
123 | #ifdef USE_BZIP2 |
124 | {0x10, CompressBZ2}, |
125 | #endif |
3e09a0ee |
126 | }; |
127 | |
128 | DecompressFunc DecompressionFunctions[] = |
129 | { |
130 | {0x40, DecompressWaveMono}, |
131 | {0x80, DecompressWaveStereo}, |
132 | {0x01, HuffmanDecompress}, |
133 | #ifdef USE_ZLIB |
134 | {0x02, Inflate}, |
135 | #endif |
58da368c |
136 | {0x08, Explode}, |
137 | #ifdef USE_BZIP2 |
138 | {0x10, DecompressBZ2}, |
139 | #endif |
3e09a0ee |
140 | }; |
141 | |
142 | const DWORD nCompFunctions = sizeof(CompressionFunctions) / sizeof(CompressionFunctions[0]); |
143 | const DWORD nDecompFunctions = sizeof(DecompressionFunctions) / sizeof(DecompressionFunctions[0]); |
144 | |
145 | CompressFunc *lpLastCompressMethod = &CompressionFunctions[nCompFunctions-1]; |
146 | DecompressFunc *lpLastDecompressMethod = &DecompressionFunctions[nDecompFunctions-1]; |
147 | |
148 | BOOL WINAPI SCompCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwCompressLevel) |
149 | { |
150 | DWORD dwCompressCount,dwCurFlag,dwTempFlags,dwInSize,dwOutSize; |
151 | LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvAllocBuffer; |
152 | CompressFunc *lpCFuncTable; |
153 | |
154 | if (!lpdwCompressedSize) { |
155 | SErrSetLastError(ERROR_INVALID_PARAMETER); |
156 | return FALSE; |
157 | } |
158 | if (*lpdwCompressedSize < dwDecompressedSize || !lpvDestinationMem || !lpvSourceMem) { |
159 | SErrSetLastError(ERROR_INVALID_PARAMETER); |
160 | return FALSE; |
161 | } |
162 | |
163 | dwCompressCount = 0; |
164 | dwTempFlags = dwCompressionType; |
165 | lpCFuncTable = CompressionFunctions; |
166 | |
167 | do { |
168 | dwCurFlag = lpCFuncTable->dwFlag; |
169 | |
170 | if (dwCompressionType & dwCurFlag) { |
171 | dwCompressCount++; |
172 | } |
173 | |
174 | lpCFuncTable++; |
175 | dwTempFlags &= ~dwCurFlag; |
176 | } while (lpCFuncTable <= lpLastCompressMethod); |
177 | |
178 | if (dwTempFlags) { |
179 | return FALSE; |
180 | } |
181 | |
182 | dwInSize = dwDecompressedSize; |
183 | lpvAllocBuffer = 0; |
184 | |
185 | if (dwCompressCount >= 2 |
186 | || !((LPBYTE)lpvDestinationMem+dwInSize <= (LPBYTE)lpvSourceMem |
187 | || (LPBYTE)lpvSourceMem+dwInSize <= (LPBYTE)lpvDestinationMem |
188 | || !dwCompressCount)) |
189 | { |
190 | lpvWorkBuffer = SMemAlloc(dwInSize); |
191 | |
192 | if (!lpvWorkBuffer) { |
193 | SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); |
194 | return FALSE; |
195 | } |
196 | |
197 | lpvAllocBuffer = lpvWorkBuffer; |
198 | } |
199 | |
200 | lpvInBuffer = lpvSourceMem; |
201 | lpCFuncTable = CompressionFunctions; |
202 | |
203 | do { |
204 | dwTempFlags = dwCompressionType; |
205 | dwCurFlag = lpCFuncTable->dwFlag; |
206 | |
207 | if (dwTempFlags & dwCurFlag) { |
208 | dwCompressCount--; |
209 | |
210 | if (dwCompressCount & 1) { |
211 | lpvOutBuffer = lpvWorkBuffer; |
212 | } |
213 | else { |
214 | lpvOutBuffer = (LPVOID)((LPBYTE)lpvDestinationMem+1); |
215 | } |
216 | |
217 | if ((LPBYTE)lpvOutBuffer+dwInSize > (LPBYTE)lpvInBuffer |
218 | && (LPBYTE)lpvInBuffer+dwInSize > (LPBYTE)lpvOutBuffer) |
219 | { |
220 | if ((LPBYTE)lpvOutBuffer+dwInSize > (LPBYTE)lpvWorkBuffer |
221 | && (LPBYTE)lpvWorkBuffer+dwInSize > (LPBYTE)lpvOutBuffer) |
222 | { |
223 | lpvWorkBuffer = lpvDestinationMem; |
224 | lpvOutBuffer = (LPVOID)((LPBYTE)lpvWorkBuffer+1); |
225 | } |
226 | else { |
227 | lpvOutBuffer = lpvWorkBuffer; |
228 | } |
229 | } |
230 | |
231 | dwDecompressedSize = dwInSize-1; |
232 | lpCFuncTable->fnCompress(lpvOutBuffer,&dwDecompressedSize,lpvInBuffer,dwInSize,&dwCompressionSubType,dwCompressLevel); |
233 | dwOutSize = dwDecompressedSize+1; |
234 | |
235 | if (dwOutSize < dwInSize) { |
236 | lpvInBuffer = lpvOutBuffer; |
237 | dwInSize = dwDecompressedSize; |
238 | } |
239 | else { |
240 | dwCurFlag = lpCFuncTable->dwFlag; |
241 | dwCompressionType = dwCompressionType & (~dwCurFlag); |
242 | } |
243 | |
244 | lpvWorkBuffer = lpvAllocBuffer; |
245 | } |
246 | |
247 | lpCFuncTable++; |
248 | } while (lpCFuncTable <= lpLastCompressMethod); |
249 | |
250 | lpvOutBuffer = lpvDestinationMem; |
251 | |
252 | if (lpvInBuffer != lpvOutBuffer) { |
253 | if ((LPBYTE)lpvInBuffer == (LPBYTE)lpvOutBuffer+1) { |
254 | *(LPBYTE)lpvOutBuffer = (BYTE)dwCompressionType; |
255 | dwInSize++; |
256 | } |
257 | else { |
258 | if (dwCompressionType) { |
259 | SMemCopy((LPBYTE)lpvOutBuffer+1,lpvInBuffer,dwInSize); |
260 | dwInSize++; |
261 | *(LPBYTE)lpvOutBuffer = (BYTE)dwCompressionType; |
262 | } |
263 | else { |
264 | SMemCopy(lpvOutBuffer,lpvInBuffer,dwInSize); |
265 | } |
266 | |
267 | lpvWorkBuffer = lpvAllocBuffer; |
268 | } |
269 | } |
270 | |
271 | *lpdwCompressedSize = dwInSize; |
272 | |
273 | if (lpvWorkBuffer) { |
274 | SMemFree(lpvWorkBuffer); |
275 | } |
276 | |
277 | return TRUE; |
278 | } |
279 | |
280 | BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize) |
281 | { |
282 | DWORD dwDecompressedSize, dwOutSize, dwCompressTypes, dwCurFlag, dwTempFlags,dwCompressCount; |
283 | LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvTempBuffer; |
284 | DecompressFunc *lpCFuncTable; |
285 | |
286 | if (!lpdwDecompressedSize) { |
287 | SErrSetLastError(ERROR_INVALID_PARAMETER); |
288 | return FALSE; |
289 | } |
290 | |
291 | dwDecompressedSize = *lpdwDecompressedSize; |
292 | |
293 | if (dwDecompressedSize < dwCompressedSize || !lpvDestinationMem || !lpvSourceMem || dwCompressedSize < 1) { |
294 | SErrSetLastError(ERROR_INVALID_PARAMETER); |
295 | return FALSE; |
296 | } |
297 | |
298 | if (dwCompressedSize == dwDecompressedSize) { |
299 | if (lpvDestinationMem == lpvSourceMem) |
300 | return TRUE; |
301 | |
302 | SMemCopy(lpvDestinationMem,lpvSourceMem,dwCompressedSize); |
303 | return TRUE; |
304 | } |
305 | |
306 | dwCompressCount = 0; |
307 | dwCompressTypes = *(LPBYTE)lpvSourceMem; |
308 | lpvInBuffer = (LPVOID)((LPBYTE)lpvSourceMem+1); |
309 | dwCompressedSize--; |
310 | dwTempFlags = dwCompressTypes; |
311 | lpCFuncTable = lpLastDecompressMethod; |
312 | |
313 | do { |
314 | dwCurFlag = lpCFuncTable->dwFlag; |
315 | |
316 | if (dwCompressTypes & dwCurFlag) { |
317 | dwCompressCount++; |
318 | } |
319 | |
320 | dwTempFlags &= ~dwCurFlag; |
321 | lpCFuncTable--;; |
322 | } while (lpCFuncTable >= DecompressionFunctions); |
323 | |
324 | if (dwTempFlags) { |
325 | return FALSE; |
326 | } |
327 | |
328 | lpvWorkBuffer = 0; |
329 | |
330 | if (dwCompressCount >= 2 |
331 | || !((LPBYTE)lpvDestinationMem+dwCompressedSize <= (LPBYTE)lpvInBuffer |
332 | || (LPBYTE)lpvInBuffer+dwCompressedSize <= (LPBYTE)lpvDestinationMem |
333 | || !dwCompressCount)) |
334 | { |
335 | lpvWorkBuffer = SMemAlloc(dwDecompressedSize); |
336 | |
337 | if (!lpvWorkBuffer) { |
338 | SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); |
339 | return FALSE; |
340 | } |
341 | } |
342 | |
343 | lpCFuncTable = lpLastDecompressMethod; |
344 | |
345 | do { |
346 | if (dwCompressTypes & lpCFuncTable->dwFlag) { |
347 | lpvOutBuffer = lpvWorkBuffer; |
348 | dwCompressCount--; |
349 | |
350 | if (!(dwCompressCount & 1)) { |
351 | lpvOutBuffer = lpvDestinationMem; |
352 | } |
353 | |
354 | if ((LPBYTE)lpvOutBuffer+dwCompressedSize > (LPBYTE)lpvInBuffer |
355 | && (LPBYTE)lpvInBuffer+dwCompressedSize > (LPBYTE)lpvOutBuffer) |
356 | { |
357 | if ((LPBYTE)lpvOutBuffer+dwCompressedSize <= (LPBYTE)lpvWorkBuffer) { |
358 | lpvOutBuffer = lpvWorkBuffer; |
359 | } |
360 | else { |
361 | lpvTempBuffer = lpvOutBuffer; |
362 | lpvOutBuffer = lpvDestinationMem; |
363 | |
364 | if ((LPBYTE)lpvWorkBuffer+dwCompressedSize <= (LPBYTE)lpvTempBuffer) |
365 | lpvOutBuffer = lpvWorkBuffer; |
366 | } |
367 | } |
368 | |
369 | dwOutSize = dwDecompressedSize; |
370 | lpCFuncTable->fnDecompress(lpvOutBuffer,&dwOutSize,lpvInBuffer,dwCompressedSize); |
371 | dwCompressedSize = dwOutSize; |
372 | lpvInBuffer = lpvOutBuffer; |
373 | } |
374 | |
375 | lpCFuncTable--; |
376 | } while (lpCFuncTable >= DecompressionFunctions); |
377 | |
378 | if (lpvInBuffer != lpvDestinationMem) { |
379 | SMemCopy(lpvDestinationMem,lpvInBuffer,dwCompressedSize); |
380 | } |
381 | |
382 | *lpdwDecompressedSize = dwCompressedSize; |
383 | |
384 | if (lpvWorkBuffer) { |
385 | SMemFree(lpvWorkBuffer); |
386 | } |
387 | |
388 | return TRUE; |
389 | } |
390 | |
391 | void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType) |
392 | { |
393 | if (dwCompressLevel) { |
394 | if (dwCompressLevel <= 2) { |
395 | *(LPBYTE)lplpdwCompressionSubType = 4; |
396 | *lpdwCompressionSubType = 6; |
397 | return; |
398 | } |
399 | else if (dwCompressLevel == 3) { |
400 | *(LPBYTE)lplpdwCompressionSubType = 6; |
401 | *lpdwCompressionSubType = 8; |
402 | return; |
403 | } |
404 | } |
405 | |
406 | *(LPBYTE)lplpdwCompressionSubType = 5; |
407 | *lpdwCompressionSubType = 7; |
408 | } |
409 | |
410 | void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel) |
411 | { |
412 | InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType); |
413 | *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,1,(unsigned int)lpdwCompressionSubType & 0xFF); |
414 | } |
415 | |
416 | void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel) |
417 | { |
418 | InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType); |
419 | *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,2,(unsigned int)lpdwCompressionSubType & 0xFF); |
420 | } |
421 | |
422 | void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel) |
423 | { |
424 | THuffmannTree *ht; // Huffmann tree for compression |
425 | TOutputStream os; // Output stream |
426 | THTreeItem * pItem; |
427 | int nCount; |
428 | |
429 | ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree)); |
430 | |
431 | if (!ht) { |
432 | SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); |
433 | return; |
434 | } |
435 | |
436 | // Initialize output stream |
437 | os.pbOutBuffer = (unsigned char *)lpvDestinationMem; |
438 | os.dwOutSize = *lpdwCompressedSize; |
439 | os.pbOutPos = (unsigned char *)lpvDestinationMem; |
440 | os.dwBitBuff = 0; |
441 | os.nBits = 0; |
442 | |
443 | // Clear links for all the items in the tree |
444 | for(pItem = ht->items0008, nCount = 0x203; nCount != 0; nCount--, pItem++) |
445 | pItem->ClearItemLinks(); |
446 | |
447 | ht->pItem3054 = NULL; |
448 | ht->pItem3054 = PTR_PTR(&ht->pItem3054); |
449 | ht->pItem3058 = PTR_NOT(&ht->pItem3054); |
450 | |
451 | ht->pItem305C = NULL; |
452 | ht->pFirst = PTR_PTR(&ht->pFirst); |
453 | ht->pLast = PTR_NOT(&ht->pFirst); |
454 | |
455 | ht->offs0004 = 1; |
456 | ht->nItems = 0; |
457 | |
458 | *lpdwCompressedSize = ht->DoCompression(&os, (unsigned char *)lpvSourceMem, dwDecompressedSize, *lpdwCompressionSubType); |
459 | /* |
460 | // The following code is not necessary to run, because it has no |
461 | // effect on the output data. It only clears the huffmann tree, but when |
462 | // the tree is on the stack, who cares ? |
463 | while(PTR_INT(ht.pLast) > 0) |
464 | { |
465 | pItem = ht.pItem305C->Call1501DB70(ht.pLast); |
466 | pItem->RemoveItem(); |
467 | } |
468 | |
469 | for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058) |
470 | pItem->RemoveItem(); |
471 | PTR_PTR(&ht.pItem3054)->RemoveItem(); |
472 | |
473 | for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--) |
474 | { |
475 | pItem--; |
476 | pItem->RemoveItem(); |
477 | pItem->RemoveItem(); |
478 | } |
479 | */ |
480 | } |
481 | |
482 | #ifdef USE_ZLIB |
483 | |
484 | void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel) |
485 | { |
486 | if (*lpdwCompressionSubType == 0) { |
487 | switch (dwCompressLevel) { |
488 | case 1: |
489 | dwCompressLevel = Z_BEST_COMPRESSION; |
490 | break; |
491 | case 2: |
492 | dwCompressLevel = Z_BEST_SPEED; |
493 | break; |
494 | default: |
495 | dwCompressLevel = (DWORD)Z_DEFAULT_COMPRESSION; |
496 | } |
497 | } |
498 | |
1eb6aee0 |
499 | compress2((LPBYTE)lpvDestinationMem,(unsigned long *)lpdwCompressedSize,(LPBYTE)lpvSourceMem,dwDecompressedSize,dwCompressLevel); |
3e09a0ee |
500 | *lpdwCompressionSubType = 0; |
501 | } |
502 | |
503 | #endif |
504 | |
505 | void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel) |
506 | { |
507 | BUFFERINFO BufferInfo; |
508 | unsigned int dwCompType, dwDictSize; |
509 | LPVOID lpvWorkBuffer; |
510 | |
511 | lpvWorkBuffer = SMemAlloc(CMP_BUFFER_SIZE); |
512 | |
513 | if (!lpvWorkBuffer) { |
514 | SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); |
515 | return; |
516 | } |
517 | |
518 | BufferInfo.lpvSourceMem = lpvSourceMem; |
519 | BufferInfo.dwSrcStart = 0; |
520 | BufferInfo.dwSrcLen = dwDecompressedSize; |
521 | BufferInfo.lpvDestinationMem = lpvDestinationMem; |
522 | BufferInfo.dwDestStart = 0; |
523 | BufferInfo.dwDestLen = *lpdwCompressedSize; |
524 | |
525 | dwCompType = (*lpdwCompressionSubType==2)?CMP_ASCII:CMP_BINARY; |
526 | |
527 | if (dwDecompressedSize >= 0xC00) { |
528 | dwDictSize = 0x1000; |
529 | } |
530 | else if (dwDecompressedSize < 0x600) { |
531 | dwDictSize = 0x400; |
532 | } |
533 | else { |
534 | dwDictSize = 0x800; |
535 | } |
536 | |
537 | implode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo,&dwCompType,&dwDictSize); |
538 | *lpdwCompressedSize = BufferInfo.dwDestStart; |
539 | *lpdwCompressionSubType = 0; |
540 | |
541 | SMemFree(lpvWorkBuffer); |
542 | } |
543 | |
58da368c |
544 | #ifdef USE_BZIP2 |
545 | |
546 | void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel) |
547 | { |
548 | int nBlockSize; |
549 | |
550 | nBlockSize = 9; |
551 | if (lpdwCompressionSubType) |
552 | if (*lpdwCompressionSubType >= 1 && *lpdwCompressionSubType <= 9) |
553 | nBlockSize = *lpdwCompressionSubType; |
554 | |
555 | BZ2_bzBuffToBuffCompress((char *)lpvDestinationMem, (unsigned int *)lpdwCompressedSize, (char *)lpvSourceMem, (unsigned int)dwDecompressedSize, nBlockSize, 0, 0); |
556 | *lpdwCompressionSubType = 0; |
557 | } |
558 | |
559 | #endif |
560 | |
3e09a0ee |
561 | void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize) |
562 | { |
563 | *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1); |
564 | } |
565 | |
566 | void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize) |
567 | { |
568 | *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2); |
569 | } |
570 | |
571 | void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize) |
572 | { |
573 | THuffmannTree *ht; |
574 | TInputStream is; |
575 | THTreeItem * pItem; |
576 | unsigned int nCount; |
577 | |
578 | ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree)); |
579 | |
580 | if (!ht) { |
581 | SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); |
582 | return; |
583 | } |
584 | |
585 | // Initialize input stream |
586 | is.pbInBuffer = (unsigned char *)lpvSourceMem; |
587 | is.dwBitBuff = *(unsigned long *)lpvSourceMem; |
588 | is.pbInBuffer += sizeof(unsigned long); |
589 | is.nBits = 32; |
590 | |
591 | // Initialize the Huffman tree |
592 | for(pItem = ht->items0008, nCount = 0x203; nCount != 0; pItem++, nCount--) |
593 | pItem->ClearItemLinks(); |
594 | |
595 | ht->pItem3050 = NULL; |
596 | ht->pItem3054 = PTR_PTR(&ht->pItem3054); |
597 | ht->pItem3058 = PTR_NOT(ht->pItem3054); |
598 | |
599 | ht->pItem305C = NULL; |
600 | ht->pFirst = PTR_PTR(&ht->pFirst); |
601 | ht->pLast = PTR_NOT(ht->pFirst); |
602 | |
603 | ht->offs0004 = 1; |
604 | ht->nItems = 0; |
605 | |
606 | // Clear all TQDecompress items |
607 | for(nCount = 0; nCount < sizeof(ht->qd3474) / sizeof(TQDecompress); nCount++) |
608 | ht->qd3474[nCount].offs00 = 0; |
609 | |
610 | *lpdwDecompressedSize = ht->DoDecompression((unsigned char *)lpvDestinationMem, *lpdwDecompressedSize, &is); |
611 | /* |
612 | // The following code is not necessary to run, because it has no |
613 | // effect on the output data. It only clears the huffmann tree, but when |
614 | // the tree is on the stack, who cares ? |
615 | while(PTR_INT(ht.pLast) > 0) |
616 | { |
617 | pItem = ht.pItem305C->Call1501DB70(ht.pLast); |
618 | pItem->RemoveItem(); |
619 | } |
620 | |
621 | for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058) |
622 | pItem->RemoveItem(); |
623 | PTR_PTR(&ht.pItem3054)->RemoveItem(); |
624 | |
625 | for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--) |
626 | { |
627 | pItem--; |
628 | pItem->RemoveItem(); |
629 | pItem->RemoveItem(); |
630 | } |
631 | */ |
632 | |
633 | SMemFree(ht); |
634 | } |
635 | |
636 | #ifdef USE_ZLIB |
637 | |
638 | void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize) |
639 | { |
1eb6aee0 |
640 | uncompress((LPBYTE)lpvDestinationMem,(unsigned long *)lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize); |
3e09a0ee |
641 | } |
642 | |
643 | #endif |
644 | |
645 | void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize) |
646 | { |
647 | BUFFERINFO BufferInfo; |
648 | LPVOID lpvWorkBuffer; |
649 | |
650 | lpvWorkBuffer = SMemAlloc(EXP_BUFFER_SIZE); |
651 | |
652 | if (!lpvWorkBuffer) { |
653 | SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); |
654 | return; |
655 | } |
656 | |
657 | BufferInfo.lpvSourceMem = lpvSourceMem; |
658 | BufferInfo.dwSrcStart = 0; |
659 | BufferInfo.dwSrcLen = dwCompressedSize; |
660 | BufferInfo.lpvDestinationMem = lpvDestinationMem; |
661 | BufferInfo.dwDestStart = 0; |
662 | BufferInfo.dwDestLen = *lpdwDecompressedSize; |
663 | |
664 | explode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo); |
665 | *lpdwDecompressedSize = BufferInfo.dwDestStart; |
666 | |
667 | SMemFree(lpvWorkBuffer); |
668 | } |
669 | |
58da368c |
670 | #ifdef USE_BZIP2 |
671 | |
672 | void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize) |
673 | { |
674 | BZ2_bzBuffToBuffDecompress((char *)lpvDestinationMem, (unsigned int *)lpdwDecompressedSize, (char *)lpvSourceMem, (unsigned int)dwCompressedSize, 0, 0); |
675 | } |
676 | |
677 | #endif |
678 | |
3e09a0ee |
679 | unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param) |
680 | { |
681 | DWORD dwBufferSize; |
682 | BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param; |
683 | |
684 | dwBufferSize = *lpdwSize; |
685 | |
686 | if (dwBufferSize >= lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart) { |
687 | dwBufferSize = lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart; |
688 | } |
689 | |
690 | SMemCopy(lpvBuffer,(LPBYTE)lpBufferInfo->lpvSourceMem+lpBufferInfo->dwSrcStart,dwBufferSize); |
691 | lpBufferInfo->dwSrcStart += dwBufferSize; |
692 | return dwBufferSize; |
693 | } |
694 | |
695 | void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param) |
696 | { |
697 | DWORD dwBufferSize; |
698 | BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param; |
699 | |
700 | dwBufferSize = *lpdwSize; |
701 | |
702 | if (dwBufferSize >= lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart) { |
703 | dwBufferSize = lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart; |
704 | } |
705 | |
706 | SMemCopy((LPBYTE)lpBufferInfo->lpvDestinationMem+lpBufferInfo->dwDestStart,lpvBuffer,dwBufferSize); |
707 | lpBufferInfo->dwDestStart += dwBufferSize; |
708 | } |
709 | |
58da368c |
710 | #ifdef __cplusplus |
711 | extern "C" { |
712 | #endif |
713 | |
714 | #ifdef USE_BZIP2 |
715 | |
716 | void bz_internal_error ( int errcode ) |
717 | { |
718 | } |
719 | |
720 | #endif |
721 | |
722 | #ifdef __cplusplus |
723 | }; // extern "C" |
724 | #endif |