[8423] Fixed typo in mangos.sql.
[getmangos.git] / contrib / vmap_extractor_v2 / stormlib / SCompression.cpp
blob612ef2cc262bfae84250274c9538b19e5d9a75a2
1 /*****************************************************************************/
2 /* SCompression.cpp Copyright (c) Ladislav Zezula 2003 */
3 /*---------------------------------------------------------------------------*/
4 /* This module serves as a bridge between StormLib code and (de)compression */
5 /* functions. All (de)compression calls go (and should only go) through this */
6 /* module. No system headers should be included in this module to prevent */
7 /* compile-time problems. */
8 /*---------------------------------------------------------------------------*/
9 /* Date Ver Who Comment */
10 /* -------- ---- --- ------- */
11 /* 01.04.03 1.00 Lad The first version of SCompression.cpp */
12 /* 19.11.03 1.01 Dan Big endian handling */
13 /*****************************************************************************/
15 #define __STORMLIB_SELF__
16 #include "StormLib.h"
17 #include "SCommon.h"
19 #include <string.h>
21 // Include functions from Pkware Data Compression Library
22 #include "pklib/pklib.h"
24 // Include functions from zlib
25 #ifndef __SYS_ZLIB
26 #include "zlib/zlib.h" // Include functions from zlib
27 #else
28 #include <zlib.h> // If zlib is available on system, use this instead
29 #endif
31 // Include functions from Huffmann compression
32 #include "huffman/huff.h"
34 // Include functions from WAVe compression
35 #include "wave/wave.h"
37 // Include functions from BZip2 compression library
38 #ifndef __SYS_BZLIB
39 #include "bzip2/bzlib.h" // Include functions from bzlib
40 #else
41 #include <bzlib.h> // If bzlib is available on system, use this instead
42 #endif
44 //-----------------------------------------------------------------------------
45 // Local structures
47 // Information about the input and output buffers for pklib
48 typedef struct
50 char * pInBuff; // Pointer to input data buffer
51 int nInPos; // Current offset in input data buffer
52 int nInBytes; // Number of bytes in the input buffer
53 char * pOutBuff; // Pointer to output data buffer
54 int nOutPos; // Position in the output buffer
55 int nMaxOut; // Maximum number of bytes in the output buffer
56 } TDataInfo;
58 // Table of compression functions
59 typedef int (*COMPRESS)(char *, int *, char *, int, int *, int);
60 typedef struct
62 unsigned long dwMask; // Compression mask
63 COMPRESS Compress; // Compression function
64 } TCompressTable;
66 // Table of decompression functions
67 typedef int (*DECOMPRESS)(char *, int *, char *, int);
68 typedef struct
70 unsigned long dwMask; // Decompression bit
71 DECOMPRESS Decompress; // Decompression function
72 } TDecompressTable;
75 /*****************************************************************************/
76 /* */
77 /* Support functions for Pkware Data Compression Library */
78 /* */
79 /*****************************************************************************/
81 // Function loads data from the input buffer. Used by Pklib's "implode"
82 // and "explode" function as user-defined callback
83 // Returns number of bytes loaded
84 //
85 // char * buf - Pointer to a buffer where to store loaded data
86 // unsigned int * size - Max. number of bytes to read
87 // void * param - Custom pointer, parameter of implode/explode
89 static unsigned int ReadInputData(char * buf, unsigned int * size, void * param)
91 TDataInfo * pInfo = (TDataInfo *)param;
92 unsigned int nMaxAvail = (pInfo->nInBytes - pInfo->nInPos);
93 unsigned int nToRead = *size;
95 // Check the case when not enough data available
96 if(nToRead > nMaxAvail)
97 nToRead = nMaxAvail;
99 // Load data and increment offsets
100 memcpy(buf, pInfo->pInBuff + pInfo->nInPos, nToRead);
101 pInfo->nInPos += nToRead;
103 return nToRead;
106 // Function for store output data. Used by Pklib's "implode" and "explode"
107 // as user-defined callback
109 // char * buf - Pointer to data to be written
110 // unsigned int * size - Number of bytes to write
111 // void * param - Custom pointer, parameter of implode/explode
113 static void WriteOutputData(char * buf, unsigned int * size, void * param)
115 TDataInfo * pInfo = (TDataInfo *)param;
116 unsigned int nMaxWrite = (pInfo->nMaxOut - pInfo->nOutPos);
117 unsigned int nToWrite = *size;
119 // Check the case when not enough space in the output buffer
120 if(nToWrite > nMaxWrite)
121 nToWrite = nMaxWrite;
123 // Write output data and increments offsets
124 memcpy(pInfo->pOutBuff + pInfo->nOutPos, buf, nToWrite);
125 pInfo->nOutPos += nToWrite;
128 /*****************************************************************************/
129 /* */
130 /* "80" is IMA ADPCM stereo (de)compression */
131 /* "40" is IMA ADPCM mono (de)compression */
132 /* */
133 /*****************************************************************************/
135 int Compress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
137 // Prepare the compression level for the next compression
138 // (After us, the Huffmann compression will be called)
139 if(0 < nCmpLevel && nCmpLevel <= 2)
141 nCmpLevel = 4;
142 *pCmpType = 6;
144 else if(nCmpLevel == 3)
146 nCmpLevel = 6;
147 *pCmpType = 8;
149 else
151 nCmpLevel = 5;
152 *pCmpType = 7;
154 *pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 1, nCmpLevel);
155 return 0;
158 int Decompress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
160 *pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 1);
161 return 1;
164 int Compress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
166 // Prepare the compression type for the next compression
167 // (After us, the Huffmann compression will be called)
168 if(0 < nCmpLevel && nCmpLevel <= 2)
170 nCmpLevel = 4;
171 *pCmpType = 6;
173 else if(nCmpLevel == 3)
175 nCmpLevel = 6;
176 *pCmpType = 8;
178 else
180 nCmpLevel = 5;
181 *pCmpType = 7;
183 *pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 2, nCmpLevel);
184 return 0;
187 int Decompress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
189 *pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 2);
190 return 1;
193 /*****************************************************************************/
194 /* */
195 /* The "01" (de)compression is the Huffman (de)compression */
196 /* */
197 /*****************************************************************************/
199 // 1500F4C0
200 int Compress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
202 THuffmannTree ht; // Huffmann tree for compression
203 TOutputStream os; // Output stream
205 // Initialize output stream
206 os.pbOutBuffer = (unsigned char *)pbOutBuffer;
207 os.dwOutSize = *pdwOutLength;
208 os.pbOutPos = (unsigned char *)pbOutBuffer;
209 os.dwBitBuff = 0;
210 os.nBits = 0;
212 // Initialize the Huffmann tree for compression
213 ht.InitTree(true);
215 *pdwOutLength = ht.DoCompression(&os, (unsigned char *)pbInBuffer, dwInLength, *pCmpType);
217 // The following code is not necessary to run, because it has no
218 // effect on the output data. It only clears the huffmann tree, but when
219 // the tree is on the stack, who cares ?
220 // ht.UninitTree();
221 return 0;
224 // 1500F5F0
225 int Decompress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int /* dwInLength */)
227 THuffmannTree ht;
228 TInputStream is;
230 // Initialize input stream
231 // is.pbInBuffer = (unsigned char *)pbInBuffer;
232 is.dwBitBuff = BSWAP_INT32_UNSIGNED(*(unsigned long *)pbInBuffer);
233 pbInBuffer += sizeof(unsigned long);
234 is.pbInBuffer = (unsigned char *)pbInBuffer;
235 is.nBits = 32;
237 // Initialize the Huffmann tree for compression
238 ht.InitTree(false);
239 *pdwOutLength = ht.DoDecompression((unsigned char *)pbOutBuffer, *pdwOutLength, &is);
241 // The following code is not necessary to run, because it has no
242 // effect on the output data. It only clears the huffmann tree, but when
243 // the tree is on the stack, who cares ?
244 // ht.UninitTree();
245 return 0;
248 /*****************************************************************************/
249 /* */
250 /* The "02" (de)compression is the ZLIB (de)compression */
251 /* */
252 /*****************************************************************************/
254 int Compress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * /* pCmpType */, int /* nCmpLevel */)
256 z_stream z; // Stream information for zlib
257 int nResult;
259 // Fill the stream structure for zlib
260 z.next_in = (Bytef *)pbInBuffer;
261 z.avail_in = (uInt)dwInLength;
262 z.total_in = dwInLength;
263 z.next_out = (Bytef *)pbOutBuffer;
264 z.avail_out = *pdwOutLength;
265 z.total_out = 0;
266 z.zalloc = NULL;
267 z.zfree = NULL;
269 // Initialize the compression structure. Storm.dll uses zlib version 1.1.3
270 *pdwOutLength = 0;
271 if((nResult = deflateInit(&z, Z_DEFAULT_COMPRESSION)) == 0)
273 // Call zlib to compress the data
274 nResult = deflate(&z, Z_FINISH);
276 if(nResult == Z_OK || nResult == Z_STREAM_END)
277 *pdwOutLength = z.total_out;
279 deflateEnd(&z);
281 return nResult;
284 int Decompress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
286 z_stream z; // Stream information for zlib
287 int nResult;
289 // Fill the stream structure for zlib
290 z.next_in = (Bytef *)pbInBuffer;
291 z.avail_in = (uInt)dwInLength;
292 z.total_in = dwInLength;
293 z.next_out = (Bytef *)pbOutBuffer;
294 z.avail_out = *pdwOutLength;
295 z.total_out = 0;
296 z.zalloc = NULL;
297 z.zfree = NULL;
299 // Initialize the decompression structure. Storm.dll uses zlib version 1.1.3
300 if((nResult = inflateInit(&z)) == 0)
302 // Call zlib to decompress the data
303 nResult = inflate(&z, Z_FINISH);
304 *pdwOutLength = z.total_out;
305 inflateEnd(&z);
307 return nResult;
310 /*****************************************************************************/
311 /* */
312 /* The "08" (de)compression is the Pkware DCL (de)compression */
313 /* */
314 /*****************************************************************************/
316 int Compress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
318 TDataInfo Info; // Data information
319 char * work_buf = ALLOCMEM(char, CMP_BUFFER_SIZE);// Pklib's work buffer
320 unsigned int dict_size; // Dictionary size
321 unsigned int ctype; // Compression type
323 // Fill data information structure
324 Info.pInBuff = pbInBuffer;
325 Info.nInPos = 0;
326 Info.nInBytes = dwInLength;
327 Info.pOutBuff = pbOutBuffer;
328 Info.nOutPos = 0;
329 Info.nMaxOut = *pdwOutLength;
331 // Set the compression type and dictionary size
332 ctype = (*pCmpType == 2) ? CMP_ASCII : CMP_BINARY;
333 if (dwInLength < 0x600)
334 dict_size = 0x400;
335 else if(0x600 <= dwInLength && dwInLength < 0xC00)
336 dict_size = 0x800;
337 else
338 dict_size = 0x1000;
340 // Do the compression
341 implode(ReadInputData, WriteOutputData, work_buf, &Info, &ctype, &dict_size);
342 *pdwOutLength = Info.nOutPos;
343 FREEMEM(work_buf);
344 return 0;
347 int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
349 TDataInfo Info; // Data information
350 char * work_buf = ALLOCMEM(char, EXP_BUFFER_SIZE);// Pklib's work buffer
352 // Fill data information structure
353 Info.pInBuff = pbInBuffer;
354 Info.nInPos = 0;
355 Info.nInBytes = dwInLength;
356 Info.pOutBuff = pbOutBuffer;
357 Info.nOutPos = 0;
358 Info.nMaxOut = *pdwOutLength;
360 // Do the decompression
361 explode(ReadInputData, WriteOutputData, work_buf, &Info);
363 // Fix: If PKLIB is unable to decompress the data, they are uncompressed
364 if(Info.nOutPos == 0)
366 Info.nOutPos = min(*pdwOutLength, dwInLength);
367 memcpy(pbOutBuffer, pbInBuffer, Info.nOutPos);
370 *pdwOutLength = Info.nOutPos;
371 FREEMEM(work_buf);
372 return 0;
375 /*****************************************************************************/
376 /* */
377 /* The "10" (de)compression is the Bzip2 (de)compression */
378 /* */
379 /*****************************************************************************/
381 int Compress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
383 bz_stream strm;
384 int blockSize100k;
385 int workFactor = 30;
387 // Keep compiler happy
388 nCmpLevel = nCmpLevel;
390 // Initialize the BZLIB compression
391 strm.bzalloc = NULL;
392 strm.bzfree = NULL;
394 // Adjust the block size
395 blockSize100k = *pCmpType;
396 if(blockSize100k < 1 || blockSize100k > 9)
397 blockSize100k = 9;
399 // Blizzard uses 9 as blockSize100k, (0 as workFactor)
400 if(BZ2_bzCompressInit(&strm, blockSize100k, 0, workFactor) == 0)
402 strm.next_in = pbInBuffer;
403 strm.avail_in = dwInLength;
404 strm.next_out = pbOutBuffer;
405 strm.avail_out = *pdwOutLength;
407 // Perform the compression
408 while(BZ2_bzCompress(&strm, (strm.avail_in != 0) ? BZ_RUN : BZ_FINISH) != BZ_STREAM_END);
410 // Put the stream into idle state
411 BZ2_bzCompressEnd(&strm);
412 *pdwOutLength = strm.total_out_lo32;
414 else
416 *pdwOutLength = 0;
419 return 0;
422 int Decompress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
424 bz_stream strm;
426 // Initialize the BZLIB decompression
427 strm.bzalloc = NULL;
428 strm.bzfree = NULL;
429 if(BZ2_bzDecompressInit(&strm, 0, 0) == 0)
431 strm.next_in = pbInBuffer;
432 strm.avail_in = dwInLength;
433 strm.next_out = pbOutBuffer;
434 strm.avail_out = *pdwOutLength;
436 // Perform the decompression
437 while(BZ2_bzDecompress(&strm) != BZ_STREAM_END);
439 // Put the stream into idle state
440 BZ2_bzDecompressEnd(&strm);
441 *pdwOutLength = strm.total_out_lo32;
443 else
445 // Set zero output length
446 *pdwOutLength = 0;
449 return 0;
452 /*****************************************************************************/
453 /* */
454 /* SCompCompress */
455 /* */
456 /*****************************************************************************/
458 // This table contains compress functions which can be applied to
459 // uncompressed blocks. Each bit set means the corresponding
460 // compression method/function must be applied.
462 // WAVes compression Data compression
463 // ------------------ -------------------
464 // 1st block - 0x08 0x08 (D, HF, W2, SC, D2)
465 // Rest blocks - 0x81 0x02 (W3)
467 static TCompressTable cmp_table[] =
469 {MPQ_COMPRESSION_WAVE_MONO, Compress_wave_mono}, // IMA ADPCM mono compression
470 {MPQ_COMPRESSION_WAVE_STEREO, Compress_wave_stereo}, // IMA ADPCM stereo compression
471 {MPQ_COMPRESSION_HUFFMANN, Compress_huff}, // Huffmann compression
472 {MPQ_COMPRESSION_ZLIB, Compress_zlib}, // Compression with the "zlib" library
473 {MPQ_COMPRESSION_PKWARE, Compress_pklib}, // Compression with Pkware DCL
474 {MPQ_COMPRESSION_BZIP2, Compress_bzip2} // Compression Bzip2 library
477 int WINAPI SCompCompress(char * pbCompressed, int * pdwOutLength, char * pbUncompressed, int dwInLength,
478 int uCompressions, int nCmpType, int nCmpLevel)
480 char * pbTempBuff = NULL; // Temporary storage for decompressed data
481 char * pbOutput = pbCompressed; // Current output buffer
482 char * pbInput; // Current input buffer
483 int uCompressions2;
484 int dwCompressCount = 0;
485 int dwDoneCount = 0;
486 int dwOutSize = 0;
487 int dwInSize = dwInLength;
488 int dwEntries = (sizeof(cmp_table) / sizeof(TCompressTable));
489 int nResult = 1;
490 int i;
492 // Check for valid parameters
493 if(!pdwOutLength || *pdwOutLength < dwInLength || !pbCompressed || !pbUncompressed)
495 SetLastError(ERROR_INVALID_PARAMETER);
496 return 0;
499 // Count the compressions
500 for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
502 if(uCompressions & cmp_table[i].dwMask)
503 dwCompressCount++;
505 uCompressions2 &= ~cmp_table[i].dwMask;
508 // If a compression remains, do nothing
509 if(uCompressions2 != 0)
511 SetLastError(ERROR_INVALID_PARAMETER);
512 return 0;
515 // If more that one compression, allocate intermediate buffer
516 if(dwCompressCount >= 2)
517 pbTempBuff = ALLOCMEM(char, *pdwOutLength + 1);
519 // Perform the compressions
520 pbInput = pbUncompressed;
521 dwInSize = dwInLength;
522 for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
524 if(uCompressions2 & cmp_table[i].dwMask)
526 // Set the right output buffer
527 dwCompressCount--;
528 pbOutput = (dwCompressCount & 1) ? pbTempBuff : pbCompressed;
530 // Perform the partial compression
531 dwOutSize = *pdwOutLength - 1;
533 cmp_table[i].Compress(pbOutput + 1, &dwOutSize, pbInput, dwInSize, &nCmpType, nCmpLevel);
534 if(dwOutSize == 0)
536 SetLastError(ERROR_GEN_FAILURE);
537 *pdwOutLength = 0;
538 nResult = 0;
539 break;
542 // If the compression failed, copy the block instead
543 if(dwOutSize >= dwInSize - 1)
545 if(dwDoneCount > 0)
546 pbOutput++;
548 memcpy(pbOutput, pbInput, dwInSize);
549 pbInput = pbOutput;
550 uCompressions &= ~cmp_table[i].dwMask;
551 dwOutSize = dwInSize;
553 else
555 pbInput = pbOutput + 1;
556 dwInSize = dwOutSize;
557 dwDoneCount++;
562 // Copy the compressed data to the correct output buffer
563 if(nResult != 0)
565 if(uCompressions && (dwInSize + 1) < *pdwOutLength)
567 if(pbOutput != pbCompressed && pbOutput != pbCompressed + 1)
568 memcpy(pbCompressed, pbOutput, dwInSize);
569 *pbCompressed = (char)uCompressions;
570 *pdwOutLength = dwInSize + 1;
572 else
574 memmove(pbCompressed, pbUncompressed, dwInSize);
575 *pdwOutLength = dwInSize;
579 // Cleanup and return
580 if(pbTempBuff != NULL)
581 FREEMEM(pbTempBuff);
582 return nResult;
585 /*****************************************************************************/
586 /* */
587 /* SCompDecompress */
588 /* */
589 /*****************************************************************************/
591 // This table contains decompress functions which can be applied to
592 // uncompressed blocks. The compression mask is stored in the first byte
593 // of compressed block
594 static TDecompressTable dcmp_table[] =
596 {MPQ_COMPRESSION_BZIP2, Decompress_bzip2}, // Decompression with Bzip2 library
597 {MPQ_COMPRESSION_PKWARE, Decompress_pklib}, // Decompression with Pkware Data Compression Library
598 {MPQ_COMPRESSION_ZLIB, Decompress_zlib}, // Decompression with the "zlib" library
599 {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression
600 {MPQ_COMPRESSION_WAVE_STEREO, Decompress_wave_stereo}, // IMA ADPCM stereo decompression
601 {MPQ_COMPRESSION_WAVE_MONO, Decompress_wave_mono} // IMA ADPCM mono decompression
604 int WINAPI SCompDecompress(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
606 char * pbTempBuff = NULL; // Temporary storage for decompressed data
607 char * pbWorkBuff = NULL; // Where to store decompressed data
608 int dwOutLength = *pdwOutLength; // For storage number of output bytes
609 unsigned fDecompressions1; // Decompressions applied to the block
610 unsigned fDecompressions2; // Just another copy of decompressions applied to the block
611 int dwCount = 0; // Counter for every use
612 int dwEntries = (sizeof(dcmp_table) / sizeof(TDecompressTable));
613 int nResult = 1;
614 int i;
616 // If the input length is the same as output, do nothing.
617 if(dwInLength == dwOutLength)
619 if(pbInBuffer == pbOutBuffer)
620 return 1;
622 memcpy(pbOutBuffer, pbInBuffer, dwInLength);
623 *pdwOutLength = dwInLength;
624 return 1;
627 // Get applied compression types and decrement data length
628 fDecompressions1 = fDecompressions2 = (unsigned char)*pbInBuffer++;
629 dwInLength--;
631 // Search decompression table type and get all types of compression
632 for(i = 0; i < dwEntries; i++)
634 // We have to apply this decompression ?
635 if(fDecompressions1 & dcmp_table[i].dwMask)
636 dwCount++;
638 // Clear this flag from temporary variable.
639 fDecompressions2 &= ~dcmp_table[i].dwMask;
642 // Check if there is some method unhandled
643 // (E.g. compressed by future versions)
644 if(fDecompressions2 != 0)
646 SetLastError(ERROR_INVALID_PARAMETER);
647 return 0;
650 // If there is more than only one compression, we have to allocate extra buffer
651 if(dwCount >= 2)
652 pbTempBuff = ALLOCMEM(char, dwOutLength);
654 // Apply all decompressions
655 for(i = 0, dwCount = 0; i < dwEntries; i++)
657 // If not used this kind of compression, skip the loop
658 if(fDecompressions1 & dcmp_table[i].dwMask)
660 // If odd case, use target buffer for output, otherwise use allocated tempbuffer
661 pbWorkBuff = (dwCount++ & 1) ? pbTempBuff : pbOutBuffer;
662 dwOutLength = *pdwOutLength;
664 // Decompress buffer using corresponding function
665 dcmp_table[i].Decompress(pbWorkBuff, &dwOutLength, pbInBuffer, dwInLength);
666 if(dwOutLength == 0)
668 SetLastError(ERROR_GEN_FAILURE);
669 nResult = 0;
670 break;
673 // Move output length to src length for next compression
674 dwInLength = dwOutLength;
675 pbInBuffer = pbWorkBuff;
679 // If output buffer is not the same like target buffer, we have to copy data
680 if(nResult != 0)
682 if(pbWorkBuff != pbOutBuffer)
683 memcpy(pbOutBuffer, pbInBuffer, dwOutLength);
687 // Delete temporary buffer, if necessary
688 if(pbTempBuff != NULL)
689 FREEMEM(pbTempBuff);
691 *pdwOutLength = dwOutLength;
692 return nResult;
695 /*****************************************************************************/
696 /* */
697 /* SCompSetDataCompression */
698 /* */
699 /*****************************************************************************/
701 int WINAPI SCompSetDataCompression(int nDataCompression)
703 int nValidMask = (MPQ_COMPRESSION_ZLIB | MPQ_COMPRESSION_PKWARE | MPQ_COMPRESSION_BZIP2);
705 if((nDataCompression & nValidMask) != nDataCompression)
707 SetLastError(ERROR_INVALID_PARAMETER);
708 return FALSE;
711 SetDataCompression(nDataCompression);
712 return TRUE;