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




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 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         ));
114 CompressFunc CompressionFunctions[] =
116         {0x40, CompressWaveMono},
117         {0x80, CompressWaveStereo},
118         {0x01, HuffmanCompress},
119 #ifdef USE_ZLIB
120         {0x02, Deflate},
121 #endif
122         {0x08, Implode},
123 #ifdef USE_BZIP2
124         {0x10, CompressBZ2},
125 #endif
126 };
128 DecompressFunc DecompressionFunctions[] =
130         {0x40, DecompressWaveMono},
131         {0x80, DecompressWaveStereo},
132         {0x01, HuffmanDecompress},
133 #ifdef USE_ZLIB
134         {0x02, Inflate},
135 #endif
136         {0x08, Explode},
137 #ifdef USE_BZIP2
138         {0x10, DecompressBZ2},
139 #endif
140 };
142 const DWORD nCompFunctions = sizeof(CompressionFunctions) / sizeof(CompressionFunctions[0]);
143 const DWORD nDecompFunctions = sizeof(DecompressionFunctions) / sizeof(DecompressionFunctions[0]);
145 CompressFunc *lpLastCompressMethod = &CompressionFunctions[nCompFunctions-1];
146 DecompressFunc *lpLastDecompressMethod = &DecompressionFunctions[nDecompFunctions-1];
148 BOOL WINAPI SCompCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwCompressLevel)
150         DWORD dwCompressCount,dwCurFlag,dwTempFlags,dwInSize,dwOutSize;
151         LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvAllocBuffer;
152         CompressFunc *lpCFuncTable;
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         }
163         dwCompressCount = 0;
164         dwTempFlags = dwCompressionType;
165         lpCFuncTable = CompressionFunctions;
167         do {
168           dwCurFlag = lpCFuncTable->dwFlag;
170           if (dwCompressionType & dwCurFlag) {
171             dwCompressCount++;
172           }
174           lpCFuncTable++;
175           dwTempFlags &= ~dwCurFlag;
176         } while (lpCFuncTable <= lpLastCompressMethod);
178         if (dwTempFlags) {
179           return FALSE;
180         }
182         dwInSize = dwDecompressedSize;
183         lpvAllocBuffer = 0;
185         if (dwCompressCount >= 2
186           || !((LPBYTE)lpvDestinationMem+dwInSize <= (LPBYTE)lpvSourceMem
187             || (LPBYTE)lpvSourceMem+dwInSize <= (LPBYTE)lpvDestinationMem
188             || !dwCompressCount))
189         {
190           lpvWorkBuffer = SMemAlloc(dwInSize);
192           if (!lpvWorkBuffer) {
193             SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
194             return FALSE;
195           }
197           lpvAllocBuffer = lpvWorkBuffer;
198         }
200         lpvInBuffer = lpvSourceMem;
201         lpCFuncTable = CompressionFunctions;
203         do {
204           dwTempFlags = dwCompressionType;
205           dwCurFlag = lpCFuncTable->dwFlag;
207           if (dwTempFlags & dwCurFlag) {
208             dwCompressCount--;
210             if (dwCompressCount & 1) {
211               lpvOutBuffer = lpvWorkBuffer;
212             }
213             else {
214               lpvOutBuffer = (LPVOID)((LPBYTE)lpvDestinationMem+1);
215             }
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             }
231             dwDecompressedSize = dwInSize-1;
232             lpCFuncTable->fnCompress(lpvOutBuffer,&dwDecompressedSize,lpvInBuffer,dwInSize,&dwCompressionSubType,dwCompressLevel);
233             dwOutSize = dwDecompressedSize+1;
235             if (dwOutSize < dwInSize) {
236               lpvInBuffer = lpvOutBuffer;
237               dwInSize = dwDecompressedSize;
238             }
239             else {
240               dwCurFlag = lpCFuncTable->dwFlag;
241               dwCompressionType = dwCompressionType & (~dwCurFlag);
242             }
244             lpvWorkBuffer = lpvAllocBuffer;
245           }
247           lpCFuncTable++;
248         } while (lpCFuncTable <= lpLastCompressMethod);
250         lpvOutBuffer = lpvDestinationMem;
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             }
267             lpvWorkBuffer = lpvAllocBuffer;
268           }
269         }
271         *lpdwCompressedSize = dwInSize;
273         if (lpvWorkBuffer) {
274           SMemFree(lpvWorkBuffer);
275         }
277         return TRUE;
280 BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
282         DWORD dwDecompressedSize, dwOutSize, dwCompressTypes, dwCurFlag, dwTempFlags,dwCompressCount;
283         LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvTempBuffer;
284         DecompressFunc *lpCFuncTable;
286         if (!lpdwDecompressedSize) {
287           SErrSetLastError(ERROR_INVALID_PARAMETER);
288           return FALSE;
289         }
291         dwDecompressedSize = *lpdwDecompressedSize;
293         if (dwDecompressedSize < dwCompressedSize || !lpvDestinationMem || !lpvSourceMem || dwCompressedSize < 1) {
294           SErrSetLastError(ERROR_INVALID_PARAMETER);
295           return FALSE;
296         }
298         if (dwCompressedSize == dwDecompressedSize) {
299           if (lpvDestinationMem == lpvSourceMem)
300             return TRUE;
302           SMemCopy(lpvDestinationMem,lpvSourceMem,dwCompressedSize);
303           return TRUE;
304         }
306         dwCompressCount = 0;
307         dwCompressTypes = *(LPBYTE)lpvSourceMem;
308         lpvInBuffer = (LPVOID)((LPBYTE)lpvSourceMem+1);
309         dwCompressedSize--;
310         dwTempFlags = dwCompressTypes;
311         lpCFuncTable = lpLastDecompressMethod;
313         do {
314           dwCurFlag = lpCFuncTable->dwFlag;
316           if (dwCompressTypes & dwCurFlag) {
317             dwCompressCount++;
318           }
320           dwTempFlags &= ~dwCurFlag;
321           lpCFuncTable--;;
322         } while (lpCFuncTable >= DecompressionFunctions);
324         if (dwTempFlags) {
325           return FALSE;
326         }
328         lpvWorkBuffer = 0;
330         if (dwCompressCount >= 2
331           || !((LPBYTE)lpvDestinationMem+dwCompressedSize <= (LPBYTE)lpvInBuffer
332             || (LPBYTE)lpvInBuffer+dwCompressedSize <= (LPBYTE)lpvDestinationMem
333             || !dwCompressCount))
334         {
335           lpvWorkBuffer = SMemAlloc(dwDecompressedSize);
337           if (!lpvWorkBuffer) {
338             SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
339             return FALSE;
340           }
341         }
343         lpCFuncTable = lpLastDecompressMethod;
345         do {
346           if (dwCompressTypes & lpCFuncTable->dwFlag) {
347             lpvOutBuffer = lpvWorkBuffer;
348             dwCompressCount--;
350             if (!(dwCompressCount & 1)) {
351               lpvOutBuffer = lpvDestinationMem;
352             }
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;
364                 if ((LPBYTE)lpvWorkBuffer+dwCompressedSize <= (LPBYTE)lpvTempBuffer)
365                   lpvOutBuffer = lpvWorkBuffer;
366               }
367             }
369             dwOutSize = dwDecompressedSize;
370             lpCFuncTable->fnDecompress(lpvOutBuffer,&dwOutSize,lpvInBuffer,dwCompressedSize);
371             dwCompressedSize = dwOutSize;
372             lpvInBuffer = lpvOutBuffer;
373           }
375           lpCFuncTable--;
376         } while (lpCFuncTable >= DecompressionFunctions);
378         if (lpvInBuffer != lpvDestinationMem) {
379           SMemCopy(lpvDestinationMem,lpvInBuffer,dwCompressedSize);
380         }
382         *lpdwDecompressedSize = dwCompressedSize;
384         if (lpvWorkBuffer) {
385           SMemFree(lpvWorkBuffer);
386         }
388         return TRUE;
391 void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType)
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         }
406         *(LPBYTE)lplpdwCompressionSubType = 5;
407         *lpdwCompressionSubType = 7;
410 void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
412         InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
413         *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,1,(unsigned int)lpdwCompressionSubType & 0xFF);
416 void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
418         InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
419         *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,2,(unsigned int)lpdwCompressionSubType & 0xFF);
422 void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
424         THuffmannTree *ht;                  // Huffmann tree for compression
425         TOutputStream os;                   // Output stream
426         THTreeItem * pItem;
427         int nCount;
429         ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
431         if (!ht) {
432           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
433           return;
434         }
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;
443         // Clear links for all the items in the tree
444         for(pItem = ht->items0008, nCount = 0x203; nCount != 0; nCount--, pItem++)
445           pItem->ClearItemLinks();
447         ht->pItem3054 = NULL;
448         ht->pItem3054 = PTR_PTR(&ht->pItem3054);
449         ht->pItem3058 = PTR_NOT(&ht->pItem3054);
451         ht->pItem305C = NULL;
452         ht->pFirst    = PTR_PTR(&ht->pFirst);
453         ht->pLast     = PTR_NOT(&ht->pFirst);
455         ht->offs0004  = 1;
456         ht->nItems    = 0;
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         }
469         for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
470           pItem->RemoveItem();
471         PTR_PTR(&ht.pItem3054)->RemoveItem();
473         for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
474         {
475           pItem--;
476           pItem->RemoveItem();
477           pItem->RemoveItem();
478         }
479 */
482 #ifdef USE_ZLIB
484 void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
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         }
499         compress2((LPBYTE)lpvDestinationMem,(unsigned long *)lpdwCompressedSize,(LPBYTE)lpvSourceMem,dwDecompressedSize,dwCompressLevel);
500         *lpdwCompressionSubType = 0;
503 #endif
505 void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
507         BUFFERINFO BufferInfo;
508         unsigned int dwCompType, dwDictSize;
509         LPVOID lpvWorkBuffer;
511         lpvWorkBuffer = SMemAlloc(CMP_BUFFER_SIZE);
513         if (!lpvWorkBuffer) {
514           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
515           return;
516         }
518         BufferInfo.lpvSourceMem = lpvSourceMem;
519         BufferInfo.dwSrcStart = 0;
520         BufferInfo.dwSrcLen = dwDecompressedSize;
521         BufferInfo.lpvDestinationMem = lpvDestinationMem;
522         BufferInfo.dwDestStart = 0;
523         BufferInfo.dwDestLen = *lpdwCompressedSize;
525         dwCompType = (*lpdwCompressionSubType==2)?CMP_ASCII:CMP_BINARY;
527         if (dwDecompressedSize >= 0xC00) {
528           dwDictSize = 0x1000;
529         }
530         else if (dwDecompressedSize < 0x600) {
531           dwDictSize = 0x400;
532         }
533         else {
534           dwDictSize = 0x800;
535         }
537         implode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo,&dwCompType,&dwDictSize);
538         *lpdwCompressedSize = BufferInfo.dwDestStart;
539         *lpdwCompressionSubType = 0;
541         SMemFree(lpvWorkBuffer);
544 #ifdef USE_BZIP2
546 void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
548         int nBlockSize;
550         nBlockSize = 9;
551         if (lpdwCompressionSubType)
552                 if (*lpdwCompressionSubType >= 1 && *lpdwCompressionSubType <= 9)
553                         nBlockSize = *lpdwCompressionSubType;
555         BZ2_bzBuffToBuffCompress((char *)lpvDestinationMem, (unsigned int *)lpdwCompressedSize, (char *)lpvSourceMem, (unsigned int)dwDecompressedSize, nBlockSize, 0, 0);
556         *lpdwCompressionSubType = 0;
559 #endif
561 void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
563         *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1);
566 void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
568         *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2);
571 void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
573         THuffmannTree *ht;
574         TInputStream  is;
575         THTreeItem * pItem;
576         unsigned int nCount;
578         ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
580         if (!ht) {
581           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
582           return;
583         }
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;
591         // Initialize the Huffman tree
592         for(pItem  = ht->items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
593           pItem->ClearItemLinks();
595         ht->pItem3050 = NULL;
596         ht->pItem3054 = PTR_PTR(&ht->pItem3054);
597         ht->pItem3058 = PTR_NOT(ht->pItem3054);
599         ht->pItem305C = NULL;
600         ht->pFirst    = PTR_PTR(&ht->pFirst);
601         ht->pLast     = PTR_NOT(ht->pFirst);
603         ht->offs0004  = 1;
604         ht->nItems    = 0;
606         // Clear all TQDecompress items
607         for(nCount = 0; nCount < sizeof(ht->qd3474) / sizeof(TQDecompress); nCount++)
608           ht->qd3474[nCount].offs00 = 0;
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         }
621         for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
622           pItem->RemoveItem();
623         PTR_PTR(&ht.pItem3054)->RemoveItem();
625         for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
626         {
627           pItem--;
628           pItem->RemoveItem();
629           pItem->RemoveItem();
630         }
631 */
633         SMemFree(ht);
636 #ifdef USE_ZLIB
638 void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
640         uncompress((LPBYTE)lpvDestinationMem,(unsigned long *)lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize);
643 #endif
645 void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
647         BUFFERINFO BufferInfo;
648         LPVOID lpvWorkBuffer;
650         lpvWorkBuffer = SMemAlloc(EXP_BUFFER_SIZE);
652         if (!lpvWorkBuffer) {
653           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
654           return;
655         }
657         BufferInfo.lpvSourceMem = lpvSourceMem;
658         BufferInfo.dwSrcStart = 0;
659         BufferInfo.dwSrcLen = dwCompressedSize;
660         BufferInfo.lpvDestinationMem = lpvDestinationMem;
661         BufferInfo.dwDestStart = 0;
662         BufferInfo.dwDestLen = *lpdwDecompressedSize;
664         explode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo);
665         *lpdwDecompressedSize = BufferInfo.dwDestStart;
667         SMemFree(lpvWorkBuffer);
670 #ifdef USE_BZIP2
672 void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
674         BZ2_bzBuffToBuffDecompress((char *)lpvDestinationMem, (unsigned int *)lpdwDecompressedSize, (char *)lpvSourceMem, (unsigned int)dwCompressedSize, 0, 0);
677 #endif
679 unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
681         DWORD dwBufferSize;
682         BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
684         dwBufferSize = *lpdwSize;
686         if (dwBufferSize >= lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart) {
687           dwBufferSize = lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart;
688         }
690         SMemCopy(lpvBuffer,(LPBYTE)lpBufferInfo->lpvSourceMem+lpBufferInfo->dwSrcStart,dwBufferSize);
691         lpBufferInfo->dwSrcStart += dwBufferSize;
692         return dwBufferSize;
695 void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
697         DWORD dwBufferSize;
698         BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
700         dwBufferSize = *lpdwSize;
702         if (dwBufferSize >= lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart) {
703           dwBufferSize = lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart;
704         }
706         SMemCopy((LPBYTE)lpBufferInfo->lpvDestinationMem+lpBufferInfo->dwDestStart,lpvBuffer,dwBufferSize);
707         lpBufferInfo->dwDestStart += dwBufferSize;
710 #ifdef __cplusplus
711 extern "C" {
712 #endif
714 #ifdef USE_BZIP2
716 void bz_internal_error ( int errcode )
720 #endif
722 #ifdef __cplusplus
723 };  // extern "C"
724 #endif