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




34b5dddb1d79a9e9bb8e6a7bc9a8671f4cda792c
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 #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"
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);
35 struct CompressFunc {
36         DWORD dwFlag;
37         FCOMPRESS fnCompress;
38 };
40 struct DecompressFunc {
41         DWORD dwFlag;
42         FDECOMPRESS fnDecompress;
43 };
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);
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);
61 void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType);
63 typedef struct {
64         LPVOID lpvDestinationMem;
65         DWORD dwDestStart;
66         DWORD dwDestLen;
67         LPVOID lpvSourceMem;
68         DWORD dwSrcStart;
69         DWORD dwSrcLen;
70 } BUFFERINFO;
72 unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
73 void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
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 };
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 };
97 const DWORD nCompFunctions = sizeof(CompressionFunctions) / sizeof(CompressionFunctions[0]);
98 const DWORD nDecompFunctions = sizeof(DecompressionFunctions) / sizeof(DecompressionFunctions[0]);
100 CompressFunc *lpLastCompressMethod = &CompressionFunctions[nCompFunctions-1];
101 DecompressFunc *lpLastDecompressMethod = &DecompressionFunctions[nDecompFunctions-1];
103 BOOL WINAPI SCompCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwCompressLevel)
105         DWORD dwCompressCount,dwCurFlag,dwTempFlags,dwInSize,dwOutSize;
106         LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvAllocBuffer;
107         CompressFunc *lpCFuncTable;
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         }
118         dwCompressCount = 0;
119         dwTempFlags = dwCompressionType;
120         lpCFuncTable = CompressionFunctions;
122         do {
123           dwCurFlag = lpCFuncTable->dwFlag;
125           if (dwCompressionType & dwCurFlag) {
126             dwCompressCount++;
127           }
129           lpCFuncTable++;
130           dwTempFlags &= ~dwCurFlag;
131         } while (lpCFuncTable <= lpLastCompressMethod);
133         if (dwTempFlags) {
134           return FALSE;
135         }
137         dwInSize = dwDecompressedSize;
138         lpvAllocBuffer = 0;
140         if (dwCompressCount >= 2
141           || !((LPBYTE)lpvDestinationMem+dwInSize <= (LPBYTE)lpvSourceMem
142             || (LPBYTE)lpvSourceMem+dwInSize <= (LPBYTE)lpvDestinationMem
143             || !dwCompressCount))
144         {
145           lpvWorkBuffer = SMemAlloc(dwInSize);
147           if (!lpvWorkBuffer) {
148             SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
149             return FALSE;
150           }
152           lpvAllocBuffer = lpvWorkBuffer;
153         }
155         lpvInBuffer = lpvSourceMem;
156         lpCFuncTable = CompressionFunctions;
158         do {
159           dwTempFlags = dwCompressionType;
160           dwCurFlag = lpCFuncTable->dwFlag;
162           if (dwTempFlags & dwCurFlag) {
163             dwCompressCount--;
165             if (dwCompressCount & 1) {
166               lpvOutBuffer = lpvWorkBuffer;
167             }
168             else {
169               lpvOutBuffer = (LPVOID)((LPBYTE)lpvDestinationMem+1);
170             }
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             }
186             dwDecompressedSize = dwInSize-1;
187             lpCFuncTable->fnCompress(lpvOutBuffer,&dwDecompressedSize,lpvInBuffer,dwInSize,&dwCompressionSubType,dwCompressLevel);
188             dwOutSize = dwDecompressedSize+1;
190             if (dwOutSize < dwInSize) {
191               lpvInBuffer = lpvOutBuffer;
192               dwInSize = dwDecompressedSize;
193             }
194             else {
195               dwCurFlag = lpCFuncTable->dwFlag;
196               dwCompressionType = dwCompressionType & (~dwCurFlag);
197             }
199             lpvWorkBuffer = lpvAllocBuffer;
200           }
202           lpCFuncTable++;
203         } while (lpCFuncTable <= lpLastCompressMethod);
205         lpvOutBuffer = lpvDestinationMem;
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             }
222             lpvWorkBuffer = lpvAllocBuffer;
223           }
224         }
226         *lpdwCompressedSize = dwInSize;
228         if (lpvWorkBuffer) {
229           SMemFree(lpvWorkBuffer);
230         }
232         return TRUE;
235 BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
237         DWORD dwDecompressedSize, dwOutSize, dwCompressTypes, dwCurFlag, dwTempFlags,dwCompressCount;
238         LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvTempBuffer;
239         DecompressFunc *lpCFuncTable;
241         if (!lpdwDecompressedSize) {
242           SErrSetLastError(ERROR_INVALID_PARAMETER);
243           return FALSE;
244         }
246         dwDecompressedSize = *lpdwDecompressedSize;
248         if (dwDecompressedSize < dwCompressedSize || !lpvDestinationMem || !lpvSourceMem || dwCompressedSize < 1) {
249           SErrSetLastError(ERROR_INVALID_PARAMETER);
250           return FALSE;
251         }
253         if (dwCompressedSize == dwDecompressedSize) {
254           if (lpvDestinationMem == lpvSourceMem)
255             return TRUE;
257           SMemCopy(lpvDestinationMem,lpvSourceMem,dwCompressedSize);
258           return TRUE;
259         }
261         dwCompressCount = 0;
262         dwCompressTypes = *(LPBYTE)lpvSourceMem;
263         lpvInBuffer = (LPVOID)((LPBYTE)lpvSourceMem+1);
264         dwCompressedSize--;
265         dwTempFlags = dwCompressTypes;
266         lpCFuncTable = lpLastDecompressMethod;
268         do {
269           dwCurFlag = lpCFuncTable->dwFlag;
271           if (dwCompressTypes & dwCurFlag) {
272             dwCompressCount++;
273           }
275           dwTempFlags &= ~dwCurFlag;
276           lpCFuncTable--;;
277         } while (lpCFuncTable >= DecompressionFunctions);
279         if (dwTempFlags) {
280           return FALSE;
281         }
283         lpvWorkBuffer = 0;
285         if (dwCompressCount >= 2
286           || !((LPBYTE)lpvDestinationMem+dwCompressedSize <= (LPBYTE)lpvInBuffer
287             || (LPBYTE)lpvInBuffer+dwCompressedSize <= (LPBYTE)lpvDestinationMem
288             || !dwCompressCount))
289         {
290           lpvWorkBuffer = SMemAlloc(dwDecompressedSize);
292           if (!lpvWorkBuffer) {
293             SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
294             return FALSE;
295           }
296         }
298         lpCFuncTable = lpLastDecompressMethod;
300         do {
301           if (dwCompressTypes & lpCFuncTable->dwFlag) {
302             lpvOutBuffer = lpvWorkBuffer;
303             dwCompressCount--;
305             if (!(dwCompressCount & 1)) {
306               lpvOutBuffer = lpvDestinationMem;
307             }
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;
319                 if ((LPBYTE)lpvWorkBuffer+dwCompressedSize <= (LPBYTE)lpvTempBuffer)
320                   lpvOutBuffer = lpvWorkBuffer;
321               }
322             }
324             dwOutSize = dwDecompressedSize;
325             lpCFuncTable->fnDecompress(lpvOutBuffer,&dwOutSize,lpvInBuffer,dwCompressedSize);
326             dwCompressedSize = dwOutSize;
327             lpvInBuffer = lpvOutBuffer;
328           }
330           lpCFuncTable--;
331         } while (lpCFuncTable >= DecompressionFunctions);
333         if (lpvInBuffer != lpvDestinationMem) {
334           SMemCopy(lpvDestinationMem,lpvInBuffer,dwCompressedSize);
335         }
337         *lpdwDecompressedSize = dwCompressedSize;
339         if (lpvWorkBuffer) {
340           SMemFree(lpvWorkBuffer);
341         }
343         return TRUE;
346 void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType)
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         }
361         *(LPBYTE)lplpdwCompressionSubType = 5;
362         *lpdwCompressionSubType = 7;
365 void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
367         InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
368         *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,1,(unsigned int)lpdwCompressionSubType & 0xFF);
371 void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
373         InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
374         *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,2,(unsigned int)lpdwCompressionSubType & 0xFF);
377 void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
379         THuffmannTree *ht;                  // Huffmann tree for compression
380         TOutputStream os;                   // Output stream
381         THTreeItem * pItem;
382         int nCount;
384         ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
386         if (!ht) {
387           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
388           return;
389         }
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;
398         // Clear links for all the items in the tree
399         for(pItem = ht->items0008, nCount = 0x203; nCount != 0; nCount--, pItem++)
400           pItem->ClearItemLinks();
402         ht->pItem3054 = NULL;
403         ht->pItem3054 = PTR_PTR(&ht->pItem3054);
404         ht->pItem3058 = PTR_NOT(&ht->pItem3054);
406         ht->pItem305C = NULL;
407         ht->pFirst    = PTR_PTR(&ht->pFirst);
408         ht->pLast     = PTR_NOT(&ht->pFirst);
410         ht->offs0004  = 1;
411         ht->nItems    = 0;
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         }
424         for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
425           pItem->RemoveItem();
426         PTR_PTR(&ht.pItem3054)->RemoveItem();
428         for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
429         {
430           pItem--;
431           pItem->RemoveItem();
432           pItem->RemoveItem();
433         }
434 */
437 #ifdef USE_ZLIB
439 void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
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         }
454         compress2((LPBYTE)lpvDestinationMem,lpdwCompressedSize,(LPBYTE)lpvSourceMem,dwDecompressedSize,dwCompressLevel);
455         *lpdwCompressionSubType = 0;
458 #endif
460 void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
462         BUFFERINFO BufferInfo;
463         unsigned int dwCompType, dwDictSize;
464         LPVOID lpvWorkBuffer;
466         lpvWorkBuffer = SMemAlloc(CMP_BUFFER_SIZE);
468         if (!lpvWorkBuffer) {
469           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
470           return;
471         }
473         BufferInfo.lpvSourceMem = lpvSourceMem;
474         BufferInfo.dwSrcStart = 0;
475         BufferInfo.dwSrcLen = dwDecompressedSize;
476         BufferInfo.lpvDestinationMem = lpvDestinationMem;
477         BufferInfo.dwDestStart = 0;
478         BufferInfo.dwDestLen = *lpdwCompressedSize;
480         dwCompType = (*lpdwCompressionSubType==2)?CMP_ASCII:CMP_BINARY;
482         if (dwDecompressedSize >= 0xC00) {
483           dwDictSize = 0x1000;
484         }
485         else if (dwDecompressedSize < 0x600) {
486           dwDictSize = 0x400;
487         }
488         else {
489           dwDictSize = 0x800;
490         }
492         implode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo,&dwCompType,&dwDictSize);
493         *lpdwCompressedSize = BufferInfo.dwDestStart;
494         *lpdwCompressionSubType = 0;
496         SMemFree(lpvWorkBuffer);
499 void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
501         *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1);
504 void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
506         *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2);
509 void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
511         THuffmannTree *ht;
512         TInputStream  is;
513         THTreeItem * pItem;
514         unsigned int nCount;
516         ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
518         if (!ht) {
519           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
520           return;
521         }
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;
529         // Initialize the Huffman tree
530         for(pItem  = ht->items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
531           pItem->ClearItemLinks();
533         ht->pItem3050 = NULL;
534         ht->pItem3054 = PTR_PTR(&ht->pItem3054);
535         ht->pItem3058 = PTR_NOT(ht->pItem3054);
537         ht->pItem305C = NULL;
538         ht->pFirst    = PTR_PTR(&ht->pFirst);
539         ht->pLast     = PTR_NOT(ht->pFirst);
541         ht->offs0004  = 1;
542         ht->nItems    = 0;
544         // Clear all TQDecompress items
545         for(nCount = 0; nCount < sizeof(ht->qd3474) / sizeof(TQDecompress); nCount++)
546           ht->qd3474[nCount].offs00 = 0;
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         }
559         for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
560           pItem->RemoveItem();
561         PTR_PTR(&ht.pItem3054)->RemoveItem();
563         for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
564         {
565           pItem--;
566           pItem->RemoveItem();
567           pItem->RemoveItem();
568         }
569 */
571         SMemFree(ht);
574 #ifdef USE_ZLIB
576 void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
578         uncompress((LPBYTE)lpvDestinationMem,lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize);
581 #endif
583 void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
585         BUFFERINFO BufferInfo;
586         LPVOID lpvWorkBuffer;
588         lpvWorkBuffer = SMemAlloc(EXP_BUFFER_SIZE);
590         if (!lpvWorkBuffer) {
591           SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
592           return;
593         }
595         BufferInfo.lpvSourceMem = lpvSourceMem;
596         BufferInfo.dwSrcStart = 0;
597         BufferInfo.dwSrcLen = dwCompressedSize;
598         BufferInfo.lpvDestinationMem = lpvDestinationMem;
599         BufferInfo.dwDestStart = 0;
600         BufferInfo.dwDestLen = *lpdwDecompressedSize;
602         explode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo);
603         *lpdwDecompressedSize = BufferInfo.dwDestStart;
605         SMemFree(lpvWorkBuffer);
608 unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
610         DWORD dwBufferSize;
611         BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
613         dwBufferSize = *lpdwSize;
615         if (dwBufferSize >= lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart) {
616           dwBufferSize = lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart;
617         }
619         SMemCopy(lpvBuffer,(LPBYTE)lpBufferInfo->lpvSourceMem+lpBufferInfo->dwSrcStart,dwBufferSize);
620         lpBufferInfo->dwSrcStart += dwBufferSize;
621         return dwBufferSize;
624 void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
626         DWORD dwBufferSize;
627         BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
629         dwBufferSize = *lpdwSize;
631         if (dwBufferSize >= lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart) {
632           dwBufferSize = lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart;
633         }
635         SMemCopy((LPBYTE)lpBufferInfo->lpvDestinationMem+lpBufferInfo->dwDestStart,lpvBuffer,dwBufferSize);
636         lpBufferInfo->dwDestStart += dwBufferSize;