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 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[] =
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)
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;
261 BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
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;
372 void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType)
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;
391 void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
393         InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
394         *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,1,(unsigned int)lpdwCompressionSubType & 0xFF);
397 void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
399         InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
400         *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,2,(unsigned int)lpdwCompressionSubType & 0xFF);
403 void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
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 */
463 #ifdef USE_ZLIB
465 void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
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;
484 #endif
486 void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
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);
525 #ifdef USE_BZIP2
527 void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
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;
540 #endif
542 void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
544         *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1);
547 void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
549         *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2);
552 void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
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);
617 #ifdef USE_ZLIB
619 void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
621         uncompress((LPBYTE)lpvDestinationMem,lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize);
624 #endif
626 void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
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);
651 #ifdef USE_BZIP2
653 void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
655         BZ2_bzBuffToBuffDecompress((char *)lpvDestinationMem, (unsigned int *)lpdwDecompressedSize, (char *)lpvSourceMem, (unsigned int)dwCompressedSize, 0, 0);
658 #endif
660 unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
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;
676 void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
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;
691 #ifdef __cplusplus
692 extern "C" {
693 #endif
695 #ifdef USE_BZIP2
697 void bz_internal_error ( int errcode )
701 #endif
703 #ifdef __cplusplus
704 };  // extern "C"
705 #endif