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
0379c6fe 95const unsigned int UNSUPPORTED_COMPRESSION = (0xFF ^ (0x40 | 0x80 | 0x01
96#ifdef USE_ZLIB
97 | 0x02
98#endif
99 | 0x08
100#ifdef USE_BZIP2
101 | 0x10
102#endif
103 ));
104const unsigned int UNSUPPORTED_DECOMPRESSION = (0xFF ^ (0x40 | 0x80 | 0x01
105#ifdef USE_ZLIB
106 | 0x02
107#endif
108 | 0x08
109#ifdef USE_BZIP2
110 | 0x10
111#endif
112 ));
113
3e09a0ee 114CompressFunc CompressionFunctions[] =
115{
116 {0x40, CompressWaveMono},
117 {0x80, CompressWaveStereo},
118 {0x01, HuffmanCompress},
119#ifdef USE_ZLIB
120 {0x02, Deflate},
121#endif
58da368c 122 {0x08, Implode},
123#ifdef USE_BZIP2
124 {0x10, CompressBZ2},
125#endif
3e09a0ee 126};
127
128DecompressFunc DecompressionFunctions[] =
129{
130 {0x40, DecompressWaveMono},
131 {0x80, DecompressWaveStereo},
132 {0x01, HuffmanDecompress},
133#ifdef USE_ZLIB
134 {0x02, Inflate},
135#endif
58da368c 136 {0x08, Explode},
137#ifdef USE_BZIP2
138 {0x10, DecompressBZ2},
139#endif
3e09a0ee 140};
141
142const DWORD nCompFunctions = sizeof(CompressionFunctions) / sizeof(CompressionFunctions[0]);
143const DWORD nDecompFunctions = sizeof(DecompressionFunctions) / sizeof(DecompressionFunctions[0]);
144
145CompressFunc *lpLastCompressMethod = &CompressionFunctions[nCompFunctions-1];
146DecompressFunc *lpLastDecompressMethod = &DecompressionFunctions[nDecompFunctions-1];
147
148BOOL WINAPI SCompCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwCompressLevel)
149{
150 DWORD dwCompressCount,dwCurFlag,dwTempFlags,dwInSize,dwOutSize;
151 LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvAllocBuffer;
152 CompressFunc *lpCFuncTable;
153
154 if (!lpdwCompressedSize) {
155 SErrSetLastError(ERROR_INVALID_PARAMETER);
156 return FALSE;
157 }
158 if (*lpdwCompressedSize < dwDecompressedSize || !lpvDestinationMem || !lpvSourceMem) {
159 SErrSetLastError(ERROR_INVALID_PARAMETER);
160 return FALSE;
161 }
162
163 dwCompressCount = 0;
164 dwTempFlags = dwCompressionType;
165 lpCFuncTable = CompressionFunctions;
166
167 do {
168 dwCurFlag = lpCFuncTable->dwFlag;
169
170 if (dwCompressionType & dwCurFlag) {
171 dwCompressCount++;
172 }
173
174 lpCFuncTable++;
175 dwTempFlags &= ~dwCurFlag;
176 } while (lpCFuncTable <= lpLastCompressMethod);
177
178 if (dwTempFlags) {
179 return FALSE;
180 }
181
182 dwInSize = dwDecompressedSize;
183 lpvAllocBuffer = 0;
184
185 if (dwCompressCount >= 2
186 || !((LPBYTE)lpvDestinationMem+dwInSize <= (LPBYTE)lpvSourceMem
187 || (LPBYTE)lpvSourceMem+dwInSize <= (LPBYTE)lpvDestinationMem
188 || !dwCompressCount))
189 {
190 lpvWorkBuffer = SMemAlloc(dwInSize);
191
192 if (!lpvWorkBuffer) {
193 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
194 return FALSE;
195 }
196
197 lpvAllocBuffer = lpvWorkBuffer;
198 }
199
200 lpvInBuffer = lpvSourceMem;
201 lpCFuncTable = CompressionFunctions;
202
203 do {
204 dwTempFlags = dwCompressionType;
205 dwCurFlag = lpCFuncTable->dwFlag;
206
207 if (dwTempFlags & dwCurFlag) {
208 dwCompressCount--;
209
210 if (dwCompressCount & 1) {
211 lpvOutBuffer = lpvWorkBuffer;
212 }
213 else {
214 lpvOutBuffer = (LPVOID)((LPBYTE)lpvDestinationMem+1);
215 }
216
217 if ((LPBYTE)lpvOutBuffer+dwInSize > (LPBYTE)lpvInBuffer
218 && (LPBYTE)lpvInBuffer+dwInSize > (LPBYTE)lpvOutBuffer)
219 {
220 if ((LPBYTE)lpvOutBuffer+dwInSize > (LPBYTE)lpvWorkBuffer
221 && (LPBYTE)lpvWorkBuffer+dwInSize > (LPBYTE)lpvOutBuffer)
222 {
223 lpvWorkBuffer = lpvDestinationMem;
224 lpvOutBuffer = (LPVOID)((LPBYTE)lpvWorkBuffer+1);
225 }
226 else {
227 lpvOutBuffer = lpvWorkBuffer;
228 }
229 }
230
231 dwDecompressedSize = dwInSize-1;
232 lpCFuncTable->fnCompress(lpvOutBuffer,&dwDecompressedSize,lpvInBuffer,dwInSize,&dwCompressionSubType,dwCompressLevel);
233 dwOutSize = dwDecompressedSize+1;
234
235 if (dwOutSize < dwInSize) {
236 lpvInBuffer = lpvOutBuffer;
237 dwInSize = dwDecompressedSize;
238 }
239 else {
240 dwCurFlag = lpCFuncTable->dwFlag;
241 dwCompressionType = dwCompressionType & (~dwCurFlag);
242 }
243
244 lpvWorkBuffer = lpvAllocBuffer;
245 }
246
247 lpCFuncTable++;
248 } while (lpCFuncTable <= lpLastCompressMethod);
249
250 lpvOutBuffer = lpvDestinationMem;
251
252 if (lpvInBuffer != lpvOutBuffer) {
253 if ((LPBYTE)lpvInBuffer == (LPBYTE)lpvOutBuffer+1) {
254 *(LPBYTE)lpvOutBuffer = (BYTE)dwCompressionType;
255 dwInSize++;
256 }
257 else {
258 if (dwCompressionType) {
259 SMemCopy((LPBYTE)lpvOutBuffer+1,lpvInBuffer,dwInSize);
260 dwInSize++;
261 *(LPBYTE)lpvOutBuffer = (BYTE)dwCompressionType;
262 }
263 else {
264 SMemCopy(lpvOutBuffer,lpvInBuffer,dwInSize);
265 }
266
267 lpvWorkBuffer = lpvAllocBuffer;
268 }
269 }
270
271 *lpdwCompressedSize = dwInSize;
272
273 if (lpvWorkBuffer) {
274 SMemFree(lpvWorkBuffer);
275 }
276
277 return TRUE;
278}
279
280BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
281{
282 DWORD dwDecompressedSize, dwOutSize, dwCompressTypes, dwCurFlag, dwTempFlags,dwCompressCount;
283 LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvTempBuffer;
284 DecompressFunc *lpCFuncTable;
285
286 if (!lpdwDecompressedSize) {
287 SErrSetLastError(ERROR_INVALID_PARAMETER);
288 return FALSE;
289 }
290
291 dwDecompressedSize = *lpdwDecompressedSize;
292
293 if (dwDecompressedSize < dwCompressedSize || !lpvDestinationMem || !lpvSourceMem || dwCompressedSize < 1) {
294 SErrSetLastError(ERROR_INVALID_PARAMETER);
295 return FALSE;
296 }
297
298 if (dwCompressedSize == dwDecompressedSize) {
299 if (lpvDestinationMem == lpvSourceMem)
300 return TRUE;
301
302 SMemCopy(lpvDestinationMem,lpvSourceMem,dwCompressedSize);
303 return TRUE;
304 }
305
306 dwCompressCount = 0;
307 dwCompressTypes = *(LPBYTE)lpvSourceMem;
308 lpvInBuffer = (LPVOID)((LPBYTE)lpvSourceMem+1);
309 dwCompressedSize--;
310 dwTempFlags = dwCompressTypes;
311 lpCFuncTable = lpLastDecompressMethod;
312
313 do {
314 dwCurFlag = lpCFuncTable->dwFlag;
315
316 if (dwCompressTypes & dwCurFlag) {
317 dwCompressCount++;
318 }
319
320 dwTempFlags &= ~dwCurFlag;
321 lpCFuncTable--;;
322 } while (lpCFuncTable >= DecompressionFunctions);
323
324 if (dwTempFlags) {
325 return FALSE;
326 }
327
328 lpvWorkBuffer = 0;
329
330 if (dwCompressCount >= 2
331 || !((LPBYTE)lpvDestinationMem+dwCompressedSize <= (LPBYTE)lpvInBuffer
332 || (LPBYTE)lpvInBuffer+dwCompressedSize <= (LPBYTE)lpvDestinationMem
333 || !dwCompressCount))
334 {
335 lpvWorkBuffer = SMemAlloc(dwDecompressedSize);
336
337 if (!lpvWorkBuffer) {
338 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
339 return FALSE;
340 }
341 }
342
343 lpCFuncTable = lpLastDecompressMethod;
344
345 do {
346 if (dwCompressTypes & lpCFuncTable->dwFlag) {
347 lpvOutBuffer = lpvWorkBuffer;
348 dwCompressCount--;
349
350 if (!(dwCompressCount & 1)) {
351 lpvOutBuffer = lpvDestinationMem;
352 }
353
354 if ((LPBYTE)lpvOutBuffer+dwCompressedSize > (LPBYTE)lpvInBuffer
355 && (LPBYTE)lpvInBuffer+dwCompressedSize > (LPBYTE)lpvOutBuffer)
356 {
357 if ((LPBYTE)lpvOutBuffer+dwCompressedSize <= (LPBYTE)lpvWorkBuffer) {
358 lpvOutBuffer = lpvWorkBuffer;
359 }
360 else {
361 lpvTempBuffer = lpvOutBuffer;
362 lpvOutBuffer = lpvDestinationMem;
363
364 if ((LPBYTE)lpvWorkBuffer+dwCompressedSize <= (LPBYTE)lpvTempBuffer)
365 lpvOutBuffer = lpvWorkBuffer;
366 }
367 }
368
369 dwOutSize = dwDecompressedSize;
370 lpCFuncTable->fnDecompress(lpvOutBuffer,&dwOutSize,lpvInBuffer,dwCompressedSize);
371 dwCompressedSize = dwOutSize;
372 lpvInBuffer = lpvOutBuffer;
373 }
374
375 lpCFuncTable--;
376 } while (lpCFuncTable >= DecompressionFunctions);
377
378 if (lpvInBuffer != lpvDestinationMem) {
379 SMemCopy(lpvDestinationMem,lpvInBuffer,dwCompressedSize);
380 }
381
382 *lpdwDecompressedSize = dwCompressedSize;
383
384 if (lpvWorkBuffer) {
385 SMemFree(lpvWorkBuffer);
386 }
387
388 return TRUE;
389}
390
391void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType)
392{
393 if (dwCompressLevel) {
394 if (dwCompressLevel <= 2) {
395 *(LPBYTE)lplpdwCompressionSubType = 4;
396 *lpdwCompressionSubType = 6;
397 return;
398 }
399 else if (dwCompressLevel == 3) {
400 *(LPBYTE)lplpdwCompressionSubType = 6;
401 *lpdwCompressionSubType = 8;
402 return;
403 }
404 }
405
406 *(LPBYTE)lplpdwCompressionSubType = 5;
407 *lpdwCompressionSubType = 7;
408}
409
410void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
411{
412 InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
413 *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,1,(unsigned int)lpdwCompressionSubType & 0xFF);
414}
415
416void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
417{
418 InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
419 *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,2,(unsigned int)lpdwCompressionSubType & 0xFF);
420}
421
422void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
423{
424 THuffmannTree *ht; // Huffmann tree for compression
425 TOutputStream os; // Output stream
426 THTreeItem * pItem;
427 int nCount;
428
429 ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
430
431 if (!ht) {
432 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
433 return;
434 }
435
436 // Initialize output stream
437 os.pbOutBuffer = (unsigned char *)lpvDestinationMem;
438 os.dwOutSize = *lpdwCompressedSize;
439 os.pbOutPos = (unsigned char *)lpvDestinationMem;
440 os.dwBitBuff = 0;
441 os.nBits = 0;
442
443 // Clear links for all the items in the tree
444 for(pItem = ht->items0008, nCount = 0x203; nCount != 0; nCount--, pItem++)
445 pItem->ClearItemLinks();
446
447 ht->pItem3054 = NULL;
448 ht->pItem3054 = PTR_PTR(&ht->pItem3054);
449 ht->pItem3058 = PTR_NOT(&ht->pItem3054);
450
451 ht->pItem305C = NULL;
452 ht->pFirst = PTR_PTR(&ht->pFirst);
453 ht->pLast = PTR_NOT(&ht->pFirst);
454
455 ht->offs0004 = 1;
456 ht->nItems = 0;
457
458 *lpdwCompressedSize = ht->DoCompression(&os, (unsigned char *)lpvSourceMem, dwDecompressedSize, *lpdwCompressionSubType);
459/*
460 // The following code is not necessary to run, because it has no
461 // effect on the output data. It only clears the huffmann tree, but when
462 // the tree is on the stack, who cares ?
463 while(PTR_INT(ht.pLast) > 0)
464 {
465 pItem = ht.pItem305C->Call1501DB70(ht.pLast);
466 pItem->RemoveItem();
467 }
468
469 for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
470 pItem->RemoveItem();
471 PTR_PTR(&ht.pItem3054)->RemoveItem();
472
473 for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
474 {
475 pItem--;
476 pItem->RemoveItem();
477 pItem->RemoveItem();
478 }
479*/
480}
481
482#ifdef USE_ZLIB
483
484void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
485{
486 if (*lpdwCompressionSubType == 0) {
487 switch (dwCompressLevel) {
488 case 1:
489 dwCompressLevel = Z_BEST_COMPRESSION;
490 break;
491 case 2:
492 dwCompressLevel = Z_BEST_SPEED;
493 break;
494 default:
495 dwCompressLevel = (DWORD)Z_DEFAULT_COMPRESSION;
496 }
497 }
498
1eb6aee0 499 compress2((LPBYTE)lpvDestinationMem,(unsigned long *)lpdwCompressedSize,(LPBYTE)lpvSourceMem,dwDecompressedSize,dwCompressLevel);
3e09a0ee 500 *lpdwCompressionSubType = 0;
501}
502
503#endif
504
505void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
506{
507 BUFFERINFO BufferInfo;
508 unsigned int dwCompType, dwDictSize;
509 LPVOID lpvWorkBuffer;
510
511 lpvWorkBuffer = SMemAlloc(CMP_BUFFER_SIZE);
512
513 if (!lpvWorkBuffer) {
514 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
515 return;
516 }
517
518 BufferInfo.lpvSourceMem = lpvSourceMem;
519 BufferInfo.dwSrcStart = 0;
520 BufferInfo.dwSrcLen = dwDecompressedSize;
521 BufferInfo.lpvDestinationMem = lpvDestinationMem;
522 BufferInfo.dwDestStart = 0;
523 BufferInfo.dwDestLen = *lpdwCompressedSize;
524
525 dwCompType = (*lpdwCompressionSubType==2)?CMP_ASCII:CMP_BINARY;
526
527 if (dwDecompressedSize >= 0xC00) {
528 dwDictSize = 0x1000;
529 }
530 else if (dwDecompressedSize < 0x600) {
531 dwDictSize = 0x400;
532 }
533 else {
534 dwDictSize = 0x800;
535 }
536
537 implode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo,&dwCompType,&dwDictSize);
538 *lpdwCompressedSize = BufferInfo.dwDestStart;
539 *lpdwCompressionSubType = 0;
540
541 SMemFree(lpvWorkBuffer);
542}
543
58da368c 544#ifdef USE_BZIP2
545
546void __fastcall CompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
547{
548 int nBlockSize;
549
550 nBlockSize = 9;
551 if (lpdwCompressionSubType)
552 if (*lpdwCompressionSubType >= 1 && *lpdwCompressionSubType <= 9)
553 nBlockSize = *lpdwCompressionSubType;
554
555 BZ2_bzBuffToBuffCompress((char *)lpvDestinationMem, (unsigned int *)lpdwCompressedSize, (char *)lpvSourceMem, (unsigned int)dwDecompressedSize, nBlockSize, 0, 0);
556 *lpdwCompressionSubType = 0;
557}
558
559#endif
560
3e09a0ee 561void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
562{
563 *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1);
564}
565
566void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
567{
568 *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2);
569}
570
571void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
572{
573 THuffmannTree *ht;
574 TInputStream is;
575 THTreeItem * pItem;
576 unsigned int nCount;
577
578 ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
579
580 if (!ht) {
581 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
582 return;
583 }
584
585 // Initialize input stream
586 is.pbInBuffer = (unsigned char *)lpvSourceMem;
587 is.dwBitBuff = *(unsigned long *)lpvSourceMem;
588 is.pbInBuffer += sizeof(unsigned long);
589 is.nBits = 32;
590
591 // Initialize the Huffman tree
592 for(pItem = ht->items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
593 pItem->ClearItemLinks();
594
595 ht->pItem3050 = NULL;
596 ht->pItem3054 = PTR_PTR(&ht->pItem3054);
597 ht->pItem3058 = PTR_NOT(ht->pItem3054);
598
599 ht->pItem305C = NULL;
600 ht->pFirst = PTR_PTR(&ht->pFirst);
601 ht->pLast = PTR_NOT(ht->pFirst);
602
603 ht->offs0004 = 1;
604 ht->nItems = 0;
605
606 // Clear all TQDecompress items
607 for(nCount = 0; nCount < sizeof(ht->qd3474) / sizeof(TQDecompress); nCount++)
608 ht->qd3474[nCount].offs00 = 0;
609
610 *lpdwDecompressedSize = ht->DoDecompression((unsigned char *)lpvDestinationMem, *lpdwDecompressedSize, &is);
611/*
612 // The following code is not necessary to run, because it has no
613 // effect on the output data. It only clears the huffmann tree, but when
614 // the tree is on the stack, who cares ?
615 while(PTR_INT(ht.pLast) > 0)
616 {
617 pItem = ht.pItem305C->Call1501DB70(ht.pLast);
618 pItem->RemoveItem();
619 }
620
621 for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
622 pItem->RemoveItem();
623 PTR_PTR(&ht.pItem3054)->RemoveItem();
624
625 for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
626 {
627 pItem--;
628 pItem->RemoveItem();
629 pItem->RemoveItem();
630 }
631*/
632
633 SMemFree(ht);
634}
635
636#ifdef USE_ZLIB
637
638void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
639{
1eb6aee0 640 uncompress((LPBYTE)lpvDestinationMem,(unsigned long *)lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize);
3e09a0ee 641}
642
643#endif
644
645void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
646{
647 BUFFERINFO BufferInfo;
648 LPVOID lpvWorkBuffer;
649
650 lpvWorkBuffer = SMemAlloc(EXP_BUFFER_SIZE);
651
652 if (!lpvWorkBuffer) {
653 SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
654 return;
655 }
656
657 BufferInfo.lpvSourceMem = lpvSourceMem;
658 BufferInfo.dwSrcStart = 0;
659 BufferInfo.dwSrcLen = dwCompressedSize;
660 BufferInfo.lpvDestinationMem = lpvDestinationMem;
661 BufferInfo.dwDestStart = 0;
662 BufferInfo.dwDestLen = *lpdwDecompressedSize;
663
664 explode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo);
665 *lpdwDecompressedSize = BufferInfo.dwDestStart;
666
667 SMemFree(lpvWorkBuffer);
668}
669
58da368c 670#ifdef USE_BZIP2
671
672void __fastcall DecompressBZ2(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
673{
674 BZ2_bzBuffToBuffDecompress((char *)lpvDestinationMem, (unsigned int *)lpdwDecompressedSize, (char *)lpvSourceMem, (unsigned int)dwCompressedSize, 0, 0);
675}
676
677#endif
678
3e09a0ee 679unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
680{
681 DWORD dwBufferSize;
682 BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
683
684 dwBufferSize = *lpdwSize;
685
686 if (dwBufferSize >= lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart) {
687 dwBufferSize = lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart;
688 }
689
690 SMemCopy(lpvBuffer,(LPBYTE)lpBufferInfo->lpvSourceMem+lpBufferInfo->dwSrcStart,dwBufferSize);
691 lpBufferInfo->dwSrcStart += dwBufferSize;
692 return dwBufferSize;
693}
694
695void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
696{
697 DWORD dwBufferSize;
698 BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
699
700 dwBufferSize = *lpdwSize;
701
702 if (dwBufferSize >= lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart) {
703 dwBufferSize = lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart;
704 }
705
706 SMemCopy((LPBYTE)lpBufferInfo->lpvDestinationMem+lpBufferInfo->dwDestStart,lpvBuffer,dwBufferSize);
707 lpBufferInfo->dwDestStart += dwBufferSize;
708}
709
58da368c 710#ifdef __cplusplus
711extern "C" {
712#endif
713
714#ifdef USE_BZIP2
715
716void bz_internal_error ( int errcode )
717{
718}
719
720#endif
721
722#ifdef __cplusplus
723}; // extern "C"
724#endif