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
58da368c 18// Comment this out to disable bzip 2 compression support.
19#define USE_BZIP2
20
3e09a0ee 21#include "SComp.h"
22#include "SErr.h"
23#include "SMem.h"
24#include "wave.h"
25#include "huffman.h"
58da368c 26
3e09a0ee 27#ifdef USE_ZLIB
28#ifndef __SYS_ZLIB
58da368c 29#define ZLIB_INTERNAL
30#include "zlib/zlib.h"
3e09a0ee 31#else
32#include <zlib.h>
33#endif
34#endif
58da368c 35
3e09a0ee 36#include "pklib.h"
37
58da368c 38#ifdef USE_BZIP2
39#ifndef __SYS_BZLIB
40#include "bzip2/bzlib.h"
41#else
42#include <bzlib.h>
43#endif
44#endif
45
3e09a0ee 46typedef void (__fastcall *FCOMPRESS)(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
47typedef void (__fastcall *FDECOMPRESS)(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
48
49struct CompressFunc {
50 DWORD dwFlag;
51 FCOMPRESS fnCompress;
52};
53
54struct DecompressFunc {
55 DWORD dwFlag;
56 FDECOMPRESS fnDecompress;
57};
58
59void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
60void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
61void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
62#ifdef USE_ZLIB
63void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
64#endif
65void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
58da368c 66#ifdef USE_BZIP2
67void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
68#endif
3e09a0ee 69
70void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
71void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
72void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
73#ifdef USE_ZLIB
74void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
75#endif
76void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
58da368c 77#ifdef USE_BZIP2
78void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
79#endif
3e09a0ee 80
81void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType);
82
83typedef struct {
84 LPVOID lpvDestinationMem;
85 DWORD dwDestStart;
86 DWORD dwDestLen;
87 LPVOID lpvSourceMem;
88 DWORD dwSrcStart;
89 DWORD dwSrcLen;
90} BUFFERINFO;
91
92unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
93void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
94
95CompressFunc CompressionFunctions[] =
96{
97 {0x40, CompressWaveMono},
98 {0x80, CompressWaveStereo},
99 {0x01, HuffmanCompress},
100#ifdef USE_ZLIB
101 {0x02, Deflate},
102#endif
58da368c 103 {0x08, Implode},
104#ifdef USE_BZIP2
105 {0x10, CompressBZ2},
106#endif
3e09a0ee 107};
108
109DecompressFunc DecompressionFunctions[] =
110{
111 {0x40, DecompressWaveMono},
112 {0x80, DecompressWaveStereo},
113 {0x01, HuffmanDecompress},
114#ifdef USE_ZLIB
115 {0x02, Inflate},
116#endif
58da368c 117 {0x08, Explode},
118#ifdef USE_BZIP2
119 {0x10, DecompressBZ2},
120#endif
3e09a0ee 121};
122
123const DWORD nCompFunctions = sizeof(CompressionFunctions) / sizeof(CompressionFunctions[0]);
124const DWORD nDecompFunctions = sizeof(DecompressionFunctions) / sizeof(DecompressionFunctions[0]);
125
126CompressFunc *lpLastCompressMethod = &CompressionFunctions[nCompFunctions-1];
127DecompressFunc *lpLastDecompressMethod = &DecompressionFunctions[nDecompFunctions-1];
128
129BOOL WINAPI SCompCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwCompressLevel)
130{
131 DWORD dwCompressCount,dwCurFlag,dwTempFlags,dwInSize,dwOutSize;
132 LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvAllocBuffer;
133 CompressFunc *lpCFuncTable;
134
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 }
143
144 dwCompressCount = 0;
145 dwTempFlags = dwCompressionType;
146 lpCFuncTable = CompressionFunctions;
147
148 do {
149 dwCurFlag = lpCFuncTable->dwFlag;
150
151 if (dwCompressionType & dwCurFlag) {
152 dwCompressCount++;
153 }
154
155 lpCFuncTable++;
156 dwTempFlags &= ~dwCurFlag;
157 } while (lpCFuncTable <= lpLastCompressMethod);
158
159 if (dwTempFlags) {
160 return FALSE;
161 }
162
163 dwInSize = dwDecompressedSize;
164 lpvAllocBuffer = 0;
165
166 if (dwCompressCount >= 2
167 || !((LPBYTE)lpvDestinationMem+dwInSize <= (LPBYTE)lpvSourceMem
168 || (LPBYTE)lpvSourceMem+dwInSize <= (LPBYTE)lpvDestinationMem
169 || !dwCompressCount))
170 {
171 lpvWorkBuffer = SMemAlloc(dwInSize);
172
173 if (!lpvWorkBuffer) {
174 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
175 return FALSE;
176 }
177
178 lpvAllocBuffer = lpvWorkBuffer;
179 }
180
181 lpvInBuffer = lpvSourceMem;
182 lpCFuncTable = CompressionFunctions;
183
184 do {
185 dwTempFlags = dwCompressionType;
186 dwCurFlag = lpCFuncTable->dwFlag;
187
188 if (dwTempFlags & dwCurFlag) {
189 dwCompressCount--;
190
191 if (dwCompressCount & 1) {
192 lpvOutBuffer = lpvWorkBuffer;
193 }
194 else {
195 lpvOutBuffer = (LPVOID)((LPBYTE)lpvDestinationMem+1);
196 }
197
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 }
211
212 dwDecompressedSize = dwInSize-1;
213 lpCFuncTable->fnCompress(lpvOutBuffer,&dwDecompressedSize,lpvInBuffer,dwInSize,&dwCompressionSubType,dwCompressLevel);
214 dwOutSize = dwDecompressedSize+1;
215
216 if (dwOutSize < dwInSize) {
217 lpvInBuffer = lpvOutBuffer;
218 dwInSize = dwDecompressedSize;
219 }
220 else {
221 dwCurFlag = lpCFuncTable->dwFlag;
222 dwCompressionType = dwCompressionType & (~dwCurFlag);
223 }
224
225 lpvWorkBuffer = lpvAllocBuffer;
226 }
227
228 lpCFuncTable++;
229 } while (lpCFuncTable <= lpLastCompressMethod);
230
231 lpvOutBuffer = lpvDestinationMem;
232
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 }
247
248 lpvWorkBuffer = lpvAllocBuffer;
249 }
250 }
251
252 *lpdwCompressedSize = dwInSize;
253
254 if (lpvWorkBuffer) {
255 SMemFree(lpvWorkBuffer);
256 }
257
258 return TRUE;
259}
260
261BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
262{
263 DWORD dwDecompressedSize, dwOutSize, dwCompressTypes, dwCurFlag, dwTempFlags,dwCompressCount;
264 LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvTempBuffer;
265 DecompressFunc *lpCFuncTable;
266
267 if (!lpdwDecompressedSize) {
268 SErrSetLastError(ERROR_INVALID_PARAMETER);
269 return FALSE;
270 }
271
272 dwDecompressedSize = *lpdwDecompressedSize;
273
274 if (dwDecompressedSize < dwCompressedSize || !lpvDestinationMem || !lpvSourceMem || dwCompressedSize < 1) {
275 SErrSetLastError(ERROR_INVALID_PARAMETER);
276 return FALSE;
277 }
278
279 if (dwCompressedSize == dwDecompressedSize) {
280 if (lpvDestinationMem == lpvSourceMem)
281 return TRUE;
282
283 SMemCopy(lpvDestinationMem,lpvSourceMem,dwCompressedSize);
284 return TRUE;
285 }
286
287 dwCompressCount = 0;
288 dwCompressTypes = *(LPBYTE)lpvSourceMem;
289 lpvInBuffer = (LPVOID)((LPBYTE)lpvSourceMem+1);
290 dwCompressedSize--;
291 dwTempFlags = dwCompressTypes;
292 lpCFuncTable = lpLastDecompressMethod;
293
294 do {
295 dwCurFlag = lpCFuncTable->dwFlag;
296
297 if (dwCompressTypes & dwCurFlag) {
298 dwCompressCount++;
299 }
300
301 dwTempFlags &= ~dwCurFlag;
302 lpCFuncTable--;;
303 } while (lpCFuncTable >= DecompressionFunctions);
304
305 if (dwTempFlags) {
306 return FALSE;
307 }
308
309 lpvWorkBuffer = 0;
310
311 if (dwCompressCount >= 2
312 || !((LPBYTE)lpvDestinationMem+dwCompressedSize <= (LPBYTE)lpvInBuffer
313 || (LPBYTE)lpvInBuffer+dwCompressedSize <= (LPBYTE)lpvDestinationMem
314 || !dwCompressCount))
315 {
316 lpvWorkBuffer = SMemAlloc(dwDecompressedSize);
317
318 if (!lpvWorkBuffer) {
319 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
320 return FALSE;
321 }
322 }
323
324 lpCFuncTable = lpLastDecompressMethod;
325
326 do {
327 if (dwCompressTypes & lpCFuncTable->dwFlag) {
328 lpvOutBuffer = lpvWorkBuffer;
329 dwCompressCount--;
330
331 if (!(dwCompressCount & 1)) {
332 lpvOutBuffer = lpvDestinationMem;
333 }
334
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;
344
345 if ((LPBYTE)lpvWorkBuffer+dwCompressedSize <= (LPBYTE)lpvTempBuffer)
346 lpvOutBuffer = lpvWorkBuffer;
347 }
348 }
349
350 dwOutSize = dwDecompressedSize;
351 lpCFuncTable->fnDecompress(lpvOutBuffer,&dwOutSize,lpvInBuffer,dwCompressedSize);
352 dwCompressedSize = dwOutSize;
353 lpvInBuffer = lpvOutBuffer;
354 }
355
356 lpCFuncTable--;
357 } while (lpCFuncTable >= DecompressionFunctions);
358
359 if (lpvInBuffer != lpvDestinationMem) {
360 SMemCopy(lpvDestinationMem,lpvInBuffer,dwCompressedSize);
361 }
362
363 *lpdwDecompressedSize = dwCompressedSize;
364
365 if (lpvWorkBuffer) {
366 SMemFree(lpvWorkBuffer);
367 }
368
369 return TRUE;
370}
371
372void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType)
373{
374 if (dwCompressLevel) {
375 if (dwCompressLevel <= 2) {
376 *(LPBYTE)lplpdwCompressionSubType = 4;
377 *lpdwCompressionSubType = 6;
378 return;
379 }
380 else if (dwCompressLevel == 3) {
381 *(LPBYTE)lplpdwCompressionSubType = 6;
382 *lpdwCompressionSubType = 8;
383 return;
384 }
385 }
386
387 *(LPBYTE)lplpdwCompressionSubType = 5;
388 *lpdwCompressionSubType = 7;
389}
390
391void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
392{
393 InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
394 *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,1,(unsigned int)lpdwCompressionSubType & 0xFF);
395}
396
397void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
398{
399 InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
400 *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,2,(unsigned int)lpdwCompressionSubType & 0xFF);
401}
402
403void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
404{
405 THuffmannTree *ht; // Huffmann tree for compression
406 TOutputStream os; // Output stream
407 THTreeItem * pItem;
408 int nCount;
409
410 ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
411
412 if (!ht) {
413 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
414 return;
415 }
416
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;
423
424 // Clear links for all the items in the tree
425 for(pItem = ht->items0008, nCount = 0x203; nCount != 0; nCount--, pItem++)
426 pItem->ClearItemLinks();
427
428 ht->pItem3054 = NULL;
429 ht->pItem3054 = PTR_PTR(&ht->pItem3054);
430 ht->pItem3058 = PTR_NOT(&ht->pItem3054);
431
432 ht->pItem305C = NULL;
433 ht->pFirst = PTR_PTR(&ht->pFirst);
434 ht->pLast = PTR_NOT(&ht->pFirst);
435
436 ht->offs0004 = 1;
437 ht->nItems = 0;
438
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 }
449
450 for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
451 pItem->RemoveItem();
452 PTR_PTR(&ht.pItem3054)->RemoveItem();
453
454 for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
455 {
456 pItem--;
457 pItem->RemoveItem();
458 pItem->RemoveItem();
459 }
460*/
461}
462
463#ifdef USE_ZLIB
464
465void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
466{
467 if (*lpdwCompressionSubType == 0) {
468 switch (dwCompressLevel) {
469 case 1:
470 dwCompressLevel = Z_BEST_COMPRESSION;
471 break;
472 case 2:
473 dwCompressLevel = Z_BEST_SPEED;
474 break;
475 default:
476 dwCompressLevel = (DWORD)Z_DEFAULT_COMPRESSION;
477 }
478 }
479
480 compress2((LPBYTE)lpvDestinationMem,lpdwCompressedSize,(LPBYTE)lpvSourceMem,dwDecompressedSize,dwCompressLevel);
481 *lpdwCompressionSubType = 0;
482}
483
484#endif
485
486void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
487{
488 BUFFERINFO BufferInfo;
489 unsigned int dwCompType, dwDictSize;
490 LPVOID lpvWorkBuffer;
491
492 lpvWorkBuffer = SMemAlloc(CMP_BUFFER_SIZE);
493
494 if (!lpvWorkBuffer) {
495 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
496 return;
497 }
498
499 BufferInfo.lpvSourceMem = lpvSourceMem;
500 BufferInfo.dwSrcStart = 0;
501 BufferInfo.dwSrcLen = dwDecompressedSize;
502 BufferInfo.lpvDestinationMem = lpvDestinationMem;
503 BufferInfo.dwDestStart = 0;
504 BufferInfo.dwDestLen = *lpdwCompressedSize;
505
506 dwCompType = (*lpdwCompressionSubType==2)?CMP_ASCII:CMP_BINARY;
507
508 if (dwDecompressedSize >= 0xC00) {
509 dwDictSize = 0x1000;
510 }
511 else if (dwDecompressedSize < 0x600) {
512 dwDictSize = 0x400;
513 }
514 else {
515 dwDictSize = 0x800;
516 }
517
518 implode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo,&dwCompType,&dwDictSize);
519 *lpdwCompressedSize = BufferInfo.dwDestStart;
520 *lpdwCompressionSubType = 0;
521
522 SMemFree(lpvWorkBuffer);
523}
524
58da368c 525#ifdef USE_BZIP2
526
527void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
528{
529 int nBlockSize;
530
531 nBlockSize = 9;
532 if (lpdwCompressionSubType)
533 if (*lpdwCompressionSubType >= 1 && *lpdwCompressionSubType <= 9)
534 nBlockSize = *lpdwCompressionSubType;
535
536 BZ2_bzBuffToBuffCompress((char *)lpvDestinationMem, (unsigned int *)lpdwCompressedSize, (char *)lpvSourceMem, (unsigned int)dwDecompressedSize, nBlockSize, 0, 0);
537 *lpdwCompressionSubType = 0;
538}
539
540#endif
541
3e09a0ee 542void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
543{
544 *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1);
545}
546
547void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
548{
549 *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2);
550}
551
552void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
553{
554 THuffmannTree *ht;
555 TInputStream is;
556 THTreeItem * pItem;
557 unsigned int nCount;
558
559 ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
560
561 if (!ht) {
562 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
563 return;
564 }
565
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;
571
572 // Initialize the Huffman tree
573 for(pItem = ht->items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
574 pItem->ClearItemLinks();
575
576 ht->pItem3050 = NULL;
577 ht->pItem3054 = PTR_PTR(&ht->pItem3054);
578 ht->pItem3058 = PTR_NOT(ht->pItem3054);
579
580 ht->pItem305C = NULL;
581 ht->pFirst = PTR_PTR(&ht->pFirst);
582 ht->pLast = PTR_NOT(ht->pFirst);
583
584 ht->offs0004 = 1;
585 ht->nItems = 0;
586
587 // Clear all TQDecompress items
588 for(nCount = 0; nCount < sizeof(ht->qd3474) / sizeof(TQDecompress); nCount++)
589 ht->qd3474[nCount].offs00 = 0;
590
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 }
601
602 for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
603 pItem->RemoveItem();
604 PTR_PTR(&ht.pItem3054)->RemoveItem();
605
606 for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
607 {
608 pItem--;
609 pItem->RemoveItem();
610 pItem->RemoveItem();
611 }
612*/
613
614 SMemFree(ht);
615}
616
617#ifdef USE_ZLIB
618
619void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
620{
621 uncompress((LPBYTE)lpvDestinationMem,lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize);
622}
623
624#endif
625
626void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
627{
628 BUFFERINFO BufferInfo;
629 LPVOID lpvWorkBuffer;
630
631 lpvWorkBuffer = SMemAlloc(EXP_BUFFER_SIZE);
632
633 if (!lpvWorkBuffer) {
634 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
635 return;
636 }
637
638 BufferInfo.lpvSourceMem = lpvSourceMem;
639 BufferInfo.dwSrcStart = 0;
640 BufferInfo.dwSrcLen = dwCompressedSize;
641 BufferInfo.lpvDestinationMem = lpvDestinationMem;
642 BufferInfo.dwDestStart = 0;
643 BufferInfo.dwDestLen = *lpdwDecompressedSize;
644
645 explode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo);
646 *lpdwDecompressedSize = BufferInfo.dwDestStart;
647
648 SMemFree(lpvWorkBuffer);
649}
650
58da368c 651#ifdef USE_BZIP2
652
653void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
654{
655 BZ2_bzBuffToBuffDecompress((char *)lpvDestinationMem, (unsigned int *)lpdwDecompressedSize, (char *)lpvSourceMem, (unsigned int)dwCompressedSize, 0, 0);
656}
657
658#endif
659
3e09a0ee 660unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
661{
662 DWORD dwBufferSize;
663 BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
664
665 dwBufferSize = *lpdwSize;
666
667 if (dwBufferSize >= lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart) {
668 dwBufferSize = lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart;
669 }
670
671 SMemCopy(lpvBuffer,(LPBYTE)lpBufferInfo->lpvSourceMem+lpBufferInfo->dwSrcStart,dwBufferSize);
672 lpBufferInfo->dwSrcStart += dwBufferSize;
673 return dwBufferSize;
674}
675
676void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
677{
678 DWORD dwBufferSize;
679 BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
680
681 dwBufferSize = *lpdwSize;
682
683 if (dwBufferSize >= lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart) {
684 dwBufferSize = lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart;
685 }
686
687 SMemCopy((LPBYTE)lpBufferInfo->lpvDestinationMem+lpBufferInfo->dwDestStart,lpvBuffer,dwBufferSize);
688 lpBufferInfo->dwDestStart += dwBufferSize;
689}
690
58da368c 691#ifdef __cplusplus
692extern "C" {
693#endif
694
695#ifdef USE_BZIP2
696
697void bz_internal_error ( int errcode )
698{
699}
700
701#endif
702
703#ifdef __cplusplus
704}; // extern "C"
705#endif