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