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: |
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
12 // Define NO_WINDOWS_H globally if compiling for
13 // Windows to disable calling Windows functions.
15 // Comment this out to disable Zlib compression support.
16 #define USE_ZLIB
18 // Comment this out to disable bzip 2 compression support.
19 #define USE_BZIP2
21 #include "SComp.h"
22 #include "SErr.h"
23 #include "SMem.h"
24 #include "wave.h"
25 #include "huffman.h"
27 #ifdef USE_ZLIB
28 #ifndef __SYS_ZLIB
29 #define ZLIB_INTERNAL
30 #include "zlib/zlib.h"
31 #else
32 #include <zlib.h>
33 #endif
34 #endif
36 #include "pklib.h"
38 #ifdef USE_BZIP2
39 #ifndef __SYS_BZLIB
40 #include "bzip2/bzlib.h"
41 #else
42 #include <bzlib.h>
43 #endif
44 #endif
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);
49 struct CompressFunc {
50 DWORD dwFlag;
51 FCOMPRESS fnCompress;
52 };
54 struct DecompressFunc {
55 DWORD dwFlag;
56 FDECOMPRESS fnDecompress;
57 };
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);
66 #ifdef USE_BZIP2
67 void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
68 #endif
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);
77 #ifdef USE_BZIP2
78 void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
79 #endif
81 void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType);
83 typedef struct {
84 LPVOID lpvDestinationMem;
85 DWORD dwDestStart;
86 DWORD dwDestLen;
87 LPVOID lpvSourceMem;
88 DWORD dwSrcStart;
89 DWORD dwSrcLen;
90 } BUFFERINFO;
92 unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
93 void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
95 CompressFunc CompressionFunctions[] =
96 {
97 {0x40, CompressWaveMono},
98 {0x80, CompressWaveStereo},
99 {0x01, HuffmanCompress},
100 #ifdef USE_ZLIB
101 {0x02, Deflate},
102 #endif
103 {0x08, Implode},
104 #ifdef USE_BZIP2
105 {0x10, CompressBZ2},
106 #endif
107 };
109 DecompressFunc DecompressionFunctions[] =
110 {
111 {0x40, DecompressWaveMono},
112 {0x80, DecompressWaveStereo},
113 {0x01, HuffmanDecompress},
114 #ifdef USE_ZLIB
115 {0x02, Inflate},
116 #endif
117 {0x08, Explode},
118 #ifdef USE_BZIP2
119 {0x10, DecompressBZ2},
120 #endif
121 };
123 const DWORD nCompFunctions = sizeof(CompressionFunctions) / sizeof(CompressionFunctions[0]);
124 const DWORD nDecompFunctions = sizeof(DecompressionFunctions) / sizeof(DecompressionFunctions[0]);
126 CompressFunc *lpLastCompressMethod = &CompressionFunctions[nCompFunctions-1];
127 DecompressFunc *lpLastDecompressMethod = &DecompressionFunctions[nDecompFunctions-1];
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;
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 }
144 dwCompressCount = 0;
145 dwTempFlags = dwCompressionType;
146 lpCFuncTable = CompressionFunctions;
148 do {
149 dwCurFlag = lpCFuncTable->dwFlag;
151 if (dwCompressionType & dwCurFlag) {
152 dwCompressCount++;
153 }
155 lpCFuncTable++;
156 dwTempFlags &= ~dwCurFlag;
157 } while (lpCFuncTable <= lpLastCompressMethod);
159 if (dwTempFlags) {
160 return FALSE;
161 }
163 dwInSize = dwDecompressedSize;
164 lpvAllocBuffer = 0;
166 if (dwCompressCount >= 2
167 || !((LPBYTE)lpvDestinationMem+dwInSize <= (LPBYTE)lpvSourceMem
168 || (LPBYTE)lpvSourceMem+dwInSize <= (LPBYTE)lpvDestinationMem
169 || !dwCompressCount))
170 {
171 lpvWorkBuffer = SMemAlloc(dwInSize);
173 if (!lpvWorkBuffer) {
174 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
175 return FALSE;
176 }
178 lpvAllocBuffer = lpvWorkBuffer;
179 }
181 lpvInBuffer = lpvSourceMem;
182 lpCFuncTable = CompressionFunctions;
184 do {
185 dwTempFlags = dwCompressionType;
186 dwCurFlag = lpCFuncTable->dwFlag;
188 if (dwTempFlags & dwCurFlag) {
189 dwCompressCount--;
191 if (dwCompressCount & 1) {
192 lpvOutBuffer = lpvWorkBuffer;
193 }
194 else {
195 lpvOutBuffer = (LPVOID)((LPBYTE)lpvDestinationMem+1);
196 }
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 }
212 dwDecompressedSize = dwInSize-1;
213 lpCFuncTable->fnCompress(lpvOutBuffer,&dwDecompressedSize,lpvInBuffer,dwInSize,&dwCompressionSubType,dwCompressLevel);
214 dwOutSize = dwDecompressedSize+1;
216 if (dwOutSize < dwInSize) {
217 lpvInBuffer = lpvOutBuffer;
218 dwInSize = dwDecompressedSize;
219 }
220 else {
221 dwCurFlag = lpCFuncTable->dwFlag;
222 dwCompressionType = dwCompressionType & (~dwCurFlag);
223 }
225 lpvWorkBuffer = lpvAllocBuffer;
226 }
228 lpCFuncTable++;
229 } while (lpCFuncTable <= lpLastCompressMethod);
231 lpvOutBuffer = lpvDestinationMem;
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 }
248 lpvWorkBuffer = lpvAllocBuffer;
249 }
250 }
252 *lpdwCompressedSize = dwInSize;
254 if (lpvWorkBuffer) {
255 SMemFree(lpvWorkBuffer);
256 }
258 return TRUE;
259 }
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;
267 if (!lpdwDecompressedSize) {
268 SErrSetLastError(ERROR_INVALID_PARAMETER);
269 return FALSE;
270 }
272 dwDecompressedSize = *lpdwDecompressedSize;
274 if (dwDecompressedSize < dwCompressedSize || !lpvDestinationMem || !lpvSourceMem || dwCompressedSize < 1) {
275 SErrSetLastError(ERROR_INVALID_PARAMETER);
276 return FALSE;
277 }
279 if (dwCompressedSize == dwDecompressedSize) {
280 if (lpvDestinationMem == lpvSourceMem)
281 return TRUE;
283 SMemCopy(lpvDestinationMem,lpvSourceMem,dwCompressedSize);
284 return TRUE;
285 }
287 dwCompressCount = 0;
288 dwCompressTypes = *(LPBYTE)lpvSourceMem;
289 lpvInBuffer = (LPVOID)((LPBYTE)lpvSourceMem+1);
290 dwCompressedSize--;
291 dwTempFlags = dwCompressTypes;
292 lpCFuncTable = lpLastDecompressMethod;
294 do {
295 dwCurFlag = lpCFuncTable->dwFlag;
297 if (dwCompressTypes & dwCurFlag) {
298 dwCompressCount++;
299 }
301 dwTempFlags &= ~dwCurFlag;
302 lpCFuncTable--;;
303 } while (lpCFuncTable >= DecompressionFunctions);
305 if (dwTempFlags) {
306 return FALSE;
307 }
309 lpvWorkBuffer = 0;
311 if (dwCompressCount >= 2
312 || !((LPBYTE)lpvDestinationMem+dwCompressedSize <= (LPBYTE)lpvInBuffer
313 || (LPBYTE)lpvInBuffer+dwCompressedSize <= (LPBYTE)lpvDestinationMem
314 || !dwCompressCount))
315 {
316 lpvWorkBuffer = SMemAlloc(dwDecompressedSize);
318 if (!lpvWorkBuffer) {
319 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
320 return FALSE;
321 }
322 }
324 lpCFuncTable = lpLastDecompressMethod;
326 do {
327 if (dwCompressTypes & lpCFuncTable->dwFlag) {
328 lpvOutBuffer = lpvWorkBuffer;
329 dwCompressCount--;
331 if (!(dwCompressCount & 1)) {
332 lpvOutBuffer = lpvDestinationMem;
333 }
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;
345 if ((LPBYTE)lpvWorkBuffer+dwCompressedSize <= (LPBYTE)lpvTempBuffer)
346 lpvOutBuffer = lpvWorkBuffer;
347 }
348 }
350 dwOutSize = dwDecompressedSize;
351 lpCFuncTable->fnDecompress(lpvOutBuffer,&dwOutSize,lpvInBuffer,dwCompressedSize);
352 dwCompressedSize = dwOutSize;
353 lpvInBuffer = lpvOutBuffer;
354 }
356 lpCFuncTable--;
357 } while (lpCFuncTable >= DecompressionFunctions);
359 if (lpvInBuffer != lpvDestinationMem) {
360 SMemCopy(lpvDestinationMem,lpvInBuffer,dwCompressedSize);
361 }
363 *lpdwDecompressedSize = dwCompressedSize;
365 if (lpvWorkBuffer) {
366 SMemFree(lpvWorkBuffer);
367 }
369 return TRUE;
370 }
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 }
387 *(LPBYTE)lplpdwCompressionSubType = 5;
388 *lpdwCompressionSubType = 7;
389 }
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 }
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 }
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;
410 ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
412 if (!ht) {
413 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
414 return;
415 }
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;
424 // Clear links for all the items in the tree
425 for(pItem = ht->items0008, nCount = 0x203; nCount != 0; nCount--, pItem++)
426 pItem->ClearItemLinks();
428 ht->pItem3054 = NULL;
429 ht->pItem3054 = PTR_PTR(&ht->pItem3054);
430 ht->pItem3058 = PTR_NOT(&ht->pItem3054);
432 ht->pItem305C = NULL;
433 ht->pFirst = PTR_PTR(&ht->pFirst);
434 ht->pLast = PTR_NOT(&ht->pFirst);
436 ht->offs0004 = 1;
437 ht->nItems = 0;
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 }
450 for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
451 pItem->RemoveItem();
452 PTR_PTR(&ht.pItem3054)->RemoveItem();
454 for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
455 {
456 pItem--;
457 pItem->RemoveItem();
458 pItem->RemoveItem();
459 }
460 */
461 }
463 #ifdef USE_ZLIB
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 }
480 compress2((LPBYTE)lpvDestinationMem,lpdwCompressedSize,(LPBYTE)lpvSourceMem,dwDecompressedSize,dwCompressLevel);
481 *lpdwCompressionSubType = 0;
482 }
484 #endif
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;
492 lpvWorkBuffer = SMemAlloc(CMP_BUFFER_SIZE);
494 if (!lpvWorkBuffer) {
495 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
496 return;
497 }
499 BufferInfo.lpvSourceMem = lpvSourceMem;
500 BufferInfo.dwSrcStart = 0;
501 BufferInfo.dwSrcLen = dwDecompressedSize;
502 BufferInfo.lpvDestinationMem = lpvDestinationMem;
503 BufferInfo.dwDestStart = 0;
504 BufferInfo.dwDestLen = *lpdwCompressedSize;
506 dwCompType = (*lpdwCompressionSubType==2)?CMP_ASCII:CMP_BINARY;
508 if (dwDecompressedSize >= 0xC00) {
509 dwDictSize = 0x1000;
510 }
511 else if (dwDecompressedSize < 0x600) {
512 dwDictSize = 0x400;
513 }
514 else {
515 dwDictSize = 0x800;
516 }
518 implode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo,&dwCompType,&dwDictSize);
519 *lpdwCompressedSize = BufferInfo.dwDestStart;
520 *lpdwCompressionSubType = 0;
522 SMemFree(lpvWorkBuffer);
523 }
525 #ifdef USE_BZIP2
527 void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
528 {
529 int nBlockSize;
531 nBlockSize = 9;
532 if (lpdwCompressionSubType)
533 if (*lpdwCompressionSubType >= 1 && *lpdwCompressionSubType <= 9)
534 nBlockSize = *lpdwCompressionSubType;
536 BZ2_bzBuffToBuffCompress((char *)lpvDestinationMem, (unsigned int *)lpdwCompressedSize, (char *)lpvSourceMem, (unsigned int)dwDecompressedSize, nBlockSize, 0, 0);
537 *lpdwCompressionSubType = 0;
538 }
540 #endif
542 void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
543 {
544 *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1);
545 }
547 void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
548 {
549 *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2);
550 }
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;
559 ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
561 if (!ht) {
562 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
563 return;
564 }
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;
572 // Initialize the Huffman tree
573 for(pItem = ht->items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
574 pItem->ClearItemLinks();
576 ht->pItem3050 = NULL;
577 ht->pItem3054 = PTR_PTR(&ht->pItem3054);
578 ht->pItem3058 = PTR_NOT(ht->pItem3054);
580 ht->pItem305C = NULL;
581 ht->pFirst = PTR_PTR(&ht->pFirst);
582 ht->pLast = PTR_NOT(ht->pFirst);
584 ht->offs0004 = 1;
585 ht->nItems = 0;
587 // Clear all TQDecompress items
588 for(nCount = 0; nCount < sizeof(ht->qd3474) / sizeof(TQDecompress); nCount++)
589 ht->qd3474[nCount].offs00 = 0;
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 }
602 for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
603 pItem->RemoveItem();
604 PTR_PTR(&ht.pItem3054)->RemoveItem();
606 for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
607 {
608 pItem--;
609 pItem->RemoveItem();
610 pItem->RemoveItem();
611 }
612 */
614 SMemFree(ht);
615 }
617 #ifdef USE_ZLIB
619 void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
620 {
621 uncompress((LPBYTE)lpvDestinationMem,lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize);
622 }
624 #endif
626 void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
627 {
628 BUFFERINFO BufferInfo;
629 LPVOID lpvWorkBuffer;
631 lpvWorkBuffer = SMemAlloc(EXP_BUFFER_SIZE);
633 if (!lpvWorkBuffer) {
634 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
635 return;
636 }
638 BufferInfo.lpvSourceMem = lpvSourceMem;
639 BufferInfo.dwSrcStart = 0;
640 BufferInfo.dwSrcLen = dwCompressedSize;
641 BufferInfo.lpvDestinationMem = lpvDestinationMem;
642 BufferInfo.dwDestStart = 0;
643 BufferInfo.dwDestLen = *lpdwDecompressedSize;
645 explode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo);
646 *lpdwDecompressedSize = BufferInfo.dwDestStart;
648 SMemFree(lpvWorkBuffer);
649 }
651 #ifdef USE_BZIP2
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 }
658 #endif
660 unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
661 {
662 DWORD dwBufferSize;
663 BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
665 dwBufferSize = *lpdwSize;
667 if (dwBufferSize >= lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart) {
668 dwBufferSize = lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart;
669 }
671 SMemCopy(lpvBuffer,(LPBYTE)lpBufferInfo->lpvSourceMem+lpBufferInfo->dwSrcStart,dwBufferSize);
672 lpBufferInfo->dwSrcStart += dwBufferSize;
673 return dwBufferSize;
674 }
676 void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
677 {
678 DWORD dwBufferSize;
679 BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
681 dwBufferSize = *lpdwSize;
683 if (dwBufferSize >= lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart) {
684 dwBufferSize = lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart;
685 }
687 SMemCopy((LPBYTE)lpBufferInfo->lpvDestinationMem+lpBufferInfo->dwDestStart,lpvBuffer,dwBufferSize);
688 lpBufferInfo->dwDestStart += dwBufferSize;
689 }
691 #ifdef __cplusplus
692 extern "C" {
693 #endif
695 #ifdef USE_BZIP2
697 void bz_internal_error ( int errcode )
698 {
699 }
701 #endif
703 #ifdef __cplusplus
704 }; // extern "C"
705 #endif
|