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