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




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