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 Small banner for links to this site: |
19 files changed:
diff --git a/SComp.cpp b/SComp.cpp
--- /dev/null
+++ b/SComp.cpp
@@ -0,0 +1,638 @@
+// SComp.cpp - Main compression/decompression and wrapper routines
+//
+// Requires Zlib for Warcraft III files (not included).
+// Get it at http://www.gzip.org/zlib/
+//
+// Converted from assembly to C++ by ShadowFlare.
+// E-mail : blakflare@hotmail.com
+// Webpage : http://sfsrealm.hopto.org/
+// License information for this code is in license.txt
+
+
+// Define NO_WINDOWS_H globally if compiling for
+// Windows to disable calling Windows functions.
+
+// Comment this out to disable Zlib compression support.
+#define USE_ZLIB
+
+#include "SComp.h"
+#include "SErr.h"
+#include "SMem.h"
+#include "wave.h"
+#include "huffman.h"
+#ifdef USE_ZLIB
+#ifndef __SYS_ZLIB
+#include "zlib.h"
+#else
+#include <zlib.h>
+#endif
+#endif
+#include "pklib.h"
+
+typedef void (__fastcall *FCOMPRESS)(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
+typedef void (__fastcall *FDECOMPRESS)(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
+
+struct CompressFunc {
+ DWORD dwFlag;
+ FCOMPRESS fnCompress;
+};
+
+struct DecompressFunc {
+ DWORD dwFlag;
+ FDECOMPRESS fnDecompress;
+};
+
+void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
+void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
+void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
+#ifdef USE_ZLIB
+void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
+#endif
+void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel);
+
+void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
+void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
+void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
+#ifdef USE_ZLIB
+void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
+#endif
+void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
+
+void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType);
+
+typedef struct {
+ LPVOID lpvDestinationMem;
+ DWORD dwDestStart;
+ DWORD dwDestLen;
+ LPVOID lpvSourceMem;
+ DWORD dwSrcStart;
+ DWORD dwSrcLen;
+} BUFFERINFO;
+
+unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
+void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param);
+
+CompressFunc CompressionFunctions[] =
+{
+ {0x40, CompressWaveMono},
+ {0x80, CompressWaveStereo},
+ {0x01, HuffmanCompress},
+#ifdef USE_ZLIB
+ {0x02, Deflate},
+#endif
+ {0x08, Implode}
+};
+
+DecompressFunc DecompressionFunctions[] =
+{
+ {0x40, DecompressWaveMono},
+ {0x80, DecompressWaveStereo},
+ {0x01, HuffmanDecompress},
+#ifdef USE_ZLIB
+ {0x02, Inflate},
+#endif
+ {0x08, Explode}
+};
+
+const DWORD nCompFunctions = sizeof(CompressionFunctions) / sizeof(CompressionFunctions[0]);
+const DWORD nDecompFunctions = sizeof(DecompressionFunctions) / sizeof(DecompressionFunctions[0]);
+
+CompressFunc *lpLastCompressMethod = &CompressionFunctions[nCompFunctions-1];
+DecompressFunc *lpLastDecompressMethod = &DecompressionFunctions[nDecompFunctions-1];
+
+BOOL WINAPI SCompCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwCompressLevel)
+{
+ DWORD dwCompressCount,dwCurFlag,dwTempFlags,dwInSize,dwOutSize;
+ LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvAllocBuffer;
+ CompressFunc *lpCFuncTable;
+
+ if (!lpdwCompressedSize) {
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (*lpdwCompressedSize < dwDecompressedSize || !lpvDestinationMem || !lpvSourceMem) {
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ dwCompressCount = 0;
+ dwTempFlags = dwCompressionType;
+ lpCFuncTable = CompressionFunctions;
+
+ do {
+ dwCurFlag = lpCFuncTable->dwFlag;
+
+ if (dwCompressionType & dwCurFlag) {
+ dwCompressCount++;
+ }
+
+ lpCFuncTable++;
+ dwTempFlags &= ~dwCurFlag;
+ } while (lpCFuncTable <= lpLastCompressMethod);
+
+ if (dwTempFlags) {
+ return FALSE;
+ }
+
+ dwInSize = dwDecompressedSize;
+ lpvAllocBuffer = 0;
+
+ if (dwCompressCount >= 2
+ || !((LPBYTE)lpvDestinationMem+dwInSize <= (LPBYTE)lpvSourceMem
+ || (LPBYTE)lpvSourceMem+dwInSize <= (LPBYTE)lpvDestinationMem
+ || !dwCompressCount))
+ {
+ lpvWorkBuffer = SMemAlloc(dwInSize);
+
+ if (!lpvWorkBuffer) {
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ lpvAllocBuffer = lpvWorkBuffer;
+ }
+
+ lpvInBuffer = lpvSourceMem;
+ lpCFuncTable = CompressionFunctions;
+
+ do {
+ dwTempFlags = dwCompressionType;
+ dwCurFlag = lpCFuncTable->dwFlag;
+
+ if (dwTempFlags & dwCurFlag) {
+ dwCompressCount--;
+
+ if (dwCompressCount & 1) {
+ lpvOutBuffer = lpvWorkBuffer;
+ }
+ else {
+ lpvOutBuffer = (LPVOID)((LPBYTE)lpvDestinationMem+1);
+ }
+
+ if ((LPBYTE)lpvOutBuffer+dwInSize > (LPBYTE)lpvInBuffer
+ && (LPBYTE)lpvInBuffer+dwInSize > (LPBYTE)lpvOutBuffer)
+ {
+ if ((LPBYTE)lpvOutBuffer+dwInSize > (LPBYTE)lpvWorkBuffer
+ && (LPBYTE)lpvWorkBuffer+dwInSize > (LPBYTE)lpvOutBuffer)
+ {
+ lpvWorkBuffer = lpvDestinationMem;
+ lpvOutBuffer = (LPVOID)((LPBYTE)lpvWorkBuffer+1);
+ }
+ else {
+ lpvOutBuffer = lpvWorkBuffer;
+ }
+ }
+
+ dwDecompressedSize = dwInSize-1;
+ lpCFuncTable->fnCompress(lpvOutBuffer,&dwDecompressedSize,lpvInBuffer,dwInSize,&dwCompressionSubType,dwCompressLevel);
+ dwOutSize = dwDecompressedSize+1;
+
+ if (dwOutSize < dwInSize) {
+ lpvInBuffer = lpvOutBuffer;
+ dwInSize = dwDecompressedSize;
+ }
+ else {
+ dwCurFlag = lpCFuncTable->dwFlag;
+ dwCompressionType = dwCompressionType & (~dwCurFlag);
+ }
+
+ lpvWorkBuffer = lpvAllocBuffer;
+ }
+
+ lpCFuncTable++;
+ } while (lpCFuncTable <= lpLastCompressMethod);
+
+ lpvOutBuffer = lpvDestinationMem;
+
+ if (lpvInBuffer != lpvOutBuffer) {
+ if ((LPBYTE)lpvInBuffer == (LPBYTE)lpvOutBuffer+1) {
+ *(LPBYTE)lpvOutBuffer = (BYTE)dwCompressionType;
+ dwInSize++;
+ }
+ else {
+ if (dwCompressionType) {
+ SMemCopy((LPBYTE)lpvOutBuffer+1,lpvInBuffer,dwInSize);
+ dwInSize++;
+ *(LPBYTE)lpvOutBuffer = (BYTE)dwCompressionType;
+ }
+ else {
+ SMemCopy(lpvOutBuffer,lpvInBuffer,dwInSize);
+ }
+
+ lpvWorkBuffer = lpvAllocBuffer;
+ }
+ }
+
+ *lpdwCompressedSize = dwInSize;
+
+ if (lpvWorkBuffer) {
+ SMemFree(lpvWorkBuffer);
+ }
+
+ return TRUE;
+}
+
+BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
+{
+ DWORD dwDecompressedSize, dwOutSize, dwCompressTypes, dwCurFlag, dwTempFlags,dwCompressCount;
+ LPVOID lpvInBuffer,lpvOutBuffer,lpvWorkBuffer,lpvTempBuffer;
+ DecompressFunc *lpCFuncTable;
+
+ if (!lpdwDecompressedSize) {
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ dwDecompressedSize = *lpdwDecompressedSize;
+
+ if (dwDecompressedSize < dwCompressedSize || !lpvDestinationMem || !lpvSourceMem || dwCompressedSize < 1) {
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if (dwCompressedSize == dwDecompressedSize) {
+ if (lpvDestinationMem == lpvSourceMem)
+ return TRUE;
+
+ SMemCopy(lpvDestinationMem,lpvSourceMem,dwCompressedSize);
+ return TRUE;
+ }
+
+ dwCompressCount = 0;
+ dwCompressTypes = *(LPBYTE)lpvSourceMem;
+ lpvInBuffer = (LPVOID)((LPBYTE)lpvSourceMem+1);
+ dwCompressedSize--;
+ dwTempFlags = dwCompressTypes;
+ lpCFuncTable = lpLastDecompressMethod;
+
+ do {
+ dwCurFlag = lpCFuncTable->dwFlag;
+
+ if (dwCompressTypes & dwCurFlag) {
+ dwCompressCount++;
+ }
+
+ dwTempFlags &= ~dwCurFlag;
+ lpCFuncTable--;;
+ } while (lpCFuncTable >= DecompressionFunctions);
+
+ if (dwTempFlags) {
+ return FALSE;
+ }
+
+ lpvWorkBuffer = 0;
+
+ if (dwCompressCount >= 2
+ || !((LPBYTE)lpvDestinationMem+dwCompressedSize <= (LPBYTE)lpvInBuffer
+ || (LPBYTE)lpvInBuffer+dwCompressedSize <= (LPBYTE)lpvDestinationMem
+ || !dwCompressCount))
+ {
+ lpvWorkBuffer = SMemAlloc(dwDecompressedSize);
+
+ if (!lpvWorkBuffer) {
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ }
+
+ lpCFuncTable = lpLastDecompressMethod;
+
+ do {
+ if (dwCompressTypes & lpCFuncTable->dwFlag) {
+ lpvOutBuffer = lpvWorkBuffer;
+ dwCompressCount--;
+
+ if (!(dwCompressCount & 1)) {
+ lpvOutBuffer = lpvDestinationMem;
+ }
+
+ if ((LPBYTE)lpvOutBuffer+dwCompressedSize > (LPBYTE)lpvInBuffer
+ && (LPBYTE)lpvInBuffer+dwCompressedSize > (LPBYTE)lpvOutBuffer)
+ {
+ if ((LPBYTE)lpvOutBuffer+dwCompressedSize <= (LPBYTE)lpvWorkBuffer) {
+ lpvOutBuffer = lpvWorkBuffer;
+ }
+ else {
+ lpvTempBuffer = lpvOutBuffer;
+ lpvOutBuffer = lpvDestinationMem;
+
+ if ((LPBYTE)lpvWorkBuffer+dwCompressedSize <= (LPBYTE)lpvTempBuffer)
+ lpvOutBuffer = lpvWorkBuffer;
+ }
+ }
+
+ dwOutSize = dwDecompressedSize;
+ lpCFuncTable->fnDecompress(lpvOutBuffer,&dwOutSize,lpvInBuffer,dwCompressedSize);
+ dwCompressedSize = dwOutSize;
+ lpvInBuffer = lpvOutBuffer;
+ }
+
+ lpCFuncTable--;
+ } while (lpCFuncTable >= DecompressionFunctions);
+
+ if (lpvInBuffer != lpvDestinationMem) {
+ SMemCopy(lpvDestinationMem,lpvInBuffer,dwCompressedSize);
+ }
+
+ *lpdwDecompressedSize = dwCompressedSize;
+
+ if (lpvWorkBuffer) {
+ SMemFree(lpvWorkBuffer);
+ }
+
+ return TRUE;
+}
+
+void __fastcall InitWaveCompress(DWORD dwCompressLevel, LPDWORD *lplpdwCompressionSubType, LPDWORD lpdwCompressionSubType)
+{
+ if (dwCompressLevel) {
+ if (dwCompressLevel <= 2) {
+ *(LPBYTE)lplpdwCompressionSubType = 4;
+ *lpdwCompressionSubType = 6;
+ return;
+ }
+ else if (dwCompressLevel == 3) {
+ *(LPBYTE)lplpdwCompressionSubType = 6;
+ *lpdwCompressionSubType = 8;
+ return;
+ }
+ }
+
+ *(LPBYTE)lplpdwCompressionSubType = 5;
+ *lpdwCompressionSubType = 7;
+}
+
+void __fastcall CompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
+{
+ InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
+ *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,1,(unsigned int)lpdwCompressionSubType & 0xFF);
+}
+
+void __fastcall CompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
+{
+ InitWaveCompress(dwCompressLevel,&lpdwCompressionSubType,lpdwCompressionSubType);
+ *lpdwCompressedSize = CompressWave((LPBYTE)lpvDestinationMem,*lpdwCompressedSize,(short *)lpvSourceMem,dwDecompressedSize,2,(unsigned int)lpdwCompressionSubType & 0xFF);
+}
+
+void __fastcall HuffmanCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
+{
+ THuffmannTree *ht; // Huffmann tree for compression
+ TOutputStream os; // Output stream
+ THTreeItem * pItem;
+ int nCount;
+
+ ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
+
+ if (!ht) {
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+
+ // Initialize output stream
+ os.pbOutBuffer = (unsigned char *)lpvDestinationMem;
+ os.dwOutSize = *lpdwCompressedSize;
+ os.pbOutPos = (unsigned char *)lpvDestinationMem;
+ os.dwBitBuff = 0;
+ os.nBits = 0;
+
+ // Clear links for all the items in the tree
+ for(pItem = ht->items0008, nCount = 0x203; nCount != 0; nCount--, pItem++)
+ pItem->ClearItemLinks();
+
+ ht->pItem3054 = NULL;
+ ht->pItem3054 = PTR_PTR(&ht->pItem3054);
+ ht->pItem3058 = PTR_NOT(&ht->pItem3054);
+
+ ht->pItem305C = NULL;
+ ht->pFirst = PTR_PTR(&ht->pFirst);
+ ht->pLast = PTR_NOT(&ht->pFirst);
+
+ ht->offs0004 = 1;
+ ht->nItems = 0;
+
+ *lpdwCompressedSize = ht->DoCompression(&os, (unsigned char *)lpvSourceMem, dwDecompressedSize, *lpdwCompressionSubType);
+/*
+ // The following code is not necessary to run, because it has no
+ // effect on the output data. It only clears the huffmann tree, but when
+ // the tree is on the stack, who cares ?
+ while(PTR_INT(ht.pLast) > 0)
+ {
+ pItem = ht.pItem305C->Call1501DB70(ht.pLast);
+ pItem->RemoveItem();
+ }
+
+ for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
+ pItem->RemoveItem();
+ PTR_PTR(&ht.pItem3054)->RemoveItem();
+
+ for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
+ {
+ pItem--;
+ pItem->RemoveItem();
+ pItem->RemoveItem();
+ }
+*/
+}
+
+#ifdef USE_ZLIB
+
+void __fastcall Deflate(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
+{
+ if (*lpdwCompressionSubType == 0) {
+ switch (dwCompressLevel) {
+ case 1:
+ dwCompressLevel = Z_BEST_COMPRESSION;
+ break;
+ case 2:
+ dwCompressLevel = Z_BEST_SPEED;
+ break;
+ default:
+ dwCompressLevel = (DWORD)Z_DEFAULT_COMPRESSION;
+ }
+ }
+
+ compress2((LPBYTE)lpvDestinationMem,lpdwCompressedSize,(LPBYTE)lpvSourceMem,dwDecompressedSize,dwCompressLevel);
+ *lpdwCompressionSubType = 0;
+}
+
+#endif
+
+void __fastcall Implode(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, LPDWORD lpdwCompressionSubType, DWORD dwCompressLevel)
+{
+ BUFFERINFO BufferInfo;
+ unsigned int dwCompType, dwDictSize;
+ LPVOID lpvWorkBuffer;
+
+ lpvWorkBuffer = SMemAlloc(CMP_BUFFER_SIZE);
+
+ if (!lpvWorkBuffer) {
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+
+ BufferInfo.lpvSourceMem = lpvSourceMem;
+ BufferInfo.dwSrcStart = 0;
+ BufferInfo.dwSrcLen = dwDecompressedSize;
+ BufferInfo.lpvDestinationMem = lpvDestinationMem;
+ BufferInfo.dwDestStart = 0;
+ BufferInfo.dwDestLen = *lpdwCompressedSize;
+
+ dwCompType = (*lpdwCompressionSubType==2)?CMP_ASCII:CMP_BINARY;
+
+ if (dwDecompressedSize >= 0xC00) {
+ dwDictSize = 0x1000;
+ }
+ else if (dwDecompressedSize < 0x600) {
+ dwDictSize = 0x400;
+ }
+ else {
+ dwDictSize = 0x800;
+ }
+
+ implode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo,&dwCompType,&dwDictSize);
+ *lpdwCompressedSize = BufferInfo.dwDestStart;
+ *lpdwCompressionSubType = 0;
+
+ SMemFree(lpvWorkBuffer);
+}
+
+void __fastcall DecompressWaveMono(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
+{
+ *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,1);
+}
+
+void __fastcall DecompressWaveStereo(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
+{
+ *lpdwDecompressedSize = DecompressWave((LPBYTE)lpvDestinationMem,*lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize,2);
+}
+
+void __fastcall HuffmanDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
+{
+ THuffmannTree *ht;
+ TInputStream is;
+ THTreeItem * pItem;
+ unsigned int nCount;
+
+ ht = (THuffmannTree *)SMemAlloc(sizeof(THuffmannTree));
+
+ if (!ht) {
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+
+ // Initialize input stream
+ is.pbInBuffer = (unsigned char *)lpvSourceMem;
+ is.dwBitBuff = *(unsigned long *)lpvSourceMem;
+ is.pbInBuffer += sizeof(unsigned long);
+ is.nBits = 32;
+
+ // Initialize the Huffman tree
+ for(pItem = ht->items0008, nCount = 0x203; nCount != 0; pItem++, nCount--)
+ pItem->ClearItemLinks();
+
+ ht->pItem3050 = NULL;
+ ht->pItem3054 = PTR_PTR(&ht->pItem3054);
+ ht->pItem3058 = PTR_NOT(ht->pItem3054);
+
+ ht->pItem305C = NULL;
+ ht->pFirst = PTR_PTR(&ht->pFirst);
+ ht->pLast = PTR_NOT(ht->pFirst);
+
+ ht->offs0004 = 1;
+ ht->nItems = 0;
+
+ // Clear all TQDecompress items
+ for(nCount = 0; nCount < sizeof(ht->qd3474) / sizeof(TQDecompress); nCount++)
+ ht->qd3474[nCount].offs00 = 0;
+
+ *lpdwDecompressedSize = ht->DoDecompression((unsigned char *)lpvDestinationMem, *lpdwDecompressedSize, &is);
+/*
+ // The following code is not necessary to run, because it has no
+ // effect on the output data. It only clears the huffmann tree, but when
+ // the tree is on the stack, who cares ?
+ while(PTR_INT(ht.pLast) > 0)
+ {
+ pItem = ht.pItem305C->Call1501DB70(ht.pLast);
+ pItem->RemoveItem();
+ }
+
+ for(pItem = ht.pFirst; PTR_INT(ht.pItem3058) > 0; pItem = ht.pItem3058)
+ pItem->RemoveItem();
+ PTR_PTR(&ht.pItem3054)->RemoveItem();
+
+ for(pItem = ht.items0008 + 0x203, nCount = 0x203; nCount != 0; nCount--)
+ {
+ pItem--;
+ pItem->RemoveItem();
+ pItem->RemoveItem();
+ }
+*/
+
+ SMemFree(ht);
+}
+
+#ifdef USE_ZLIB
+
+void __fastcall Inflate(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
+{
+ uncompress((LPBYTE)lpvDestinationMem,lpdwDecompressedSize,(LPBYTE)lpvSourceMem,dwCompressedSize);
+}
+
+#endif
+
+void __fastcall Explode(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize)
+{
+ BUFFERINFO BufferInfo;
+ LPVOID lpvWorkBuffer;
+
+ lpvWorkBuffer = SMemAlloc(EXP_BUFFER_SIZE);
+
+ if (!lpvWorkBuffer) {
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+
+ BufferInfo.lpvSourceMem = lpvSourceMem;
+ BufferInfo.dwSrcStart = 0;
+ BufferInfo.dwSrcLen = dwCompressedSize;
+ BufferInfo.lpvDestinationMem = lpvDestinationMem;
+ BufferInfo.dwDestStart = 0;
+ BufferInfo.dwDestLen = *lpdwDecompressedSize;
+
+ explode(FillInput,FillOutput,(char *)lpvWorkBuffer,&BufferInfo);
+ *lpdwDecompressedSize = BufferInfo.dwDestStart;
+
+ SMemFree(lpvWorkBuffer);
+}
+
+unsigned int FillInput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
+{
+ DWORD dwBufferSize;
+ BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
+
+ dwBufferSize = *lpdwSize;
+
+ if (dwBufferSize >= lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart) {
+ dwBufferSize = lpBufferInfo->dwSrcLen - lpBufferInfo->dwSrcStart;
+ }
+
+ SMemCopy(lpvBuffer,(LPBYTE)lpBufferInfo->lpvSourceMem+lpBufferInfo->dwSrcStart,dwBufferSize);
+ lpBufferInfo->dwSrcStart += dwBufferSize;
+ return dwBufferSize;
+}
+
+void FillOutput(char *lpvBuffer, unsigned int *lpdwSize, void *param)
+{
+ DWORD dwBufferSize;
+ BUFFERINFO *lpBufferInfo = (BUFFERINFO *)param;
+
+ dwBufferSize = *lpdwSize;
+
+ if (dwBufferSize >= lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart) {
+ dwBufferSize = lpBufferInfo->dwDestLen - lpBufferInfo->dwDestStart;
+ }
+
+ SMemCopy((LPBYTE)lpBufferInfo->lpvDestinationMem+lpBufferInfo->dwDestStart,lpvBuffer,dwBufferSize);
+ lpBufferInfo->dwDestStart += dwBufferSize;
+}
+
diff --git a/SComp.h b/SComp.h
--- /dev/null
+++ b/SComp.h
@@ -0,0 +1,25 @@
+// SComp.h - Header for main compression/decompression routines
+// License information for this code is in license.txt
+
+#ifndef S_COMP_INCLUDED
+#define S_COMP_INCLUDED
+
+#if (defined(_WIN32) || defined(WIN32)) && !defined(NO_WINDOWS_H)
+#include <windows.h>
+#else
+#include "wintypes.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BOOL WINAPI SCompCompress(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwCompressLevel);
+BOOL WINAPI SCompDecompress(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
+
+#ifdef __cplusplus
+}; // extern "C"
+#endif
+
+#endif
+
diff --git a/SErr.cpp b/SErr.cpp
--- /dev/null
+++ b/SErr.cpp
@@ -0,0 +1,35 @@
+// SErr.cpp - SetLastError routine
+//
+// Converted from assembly to C++ by ShadowFlare.
+// E-mail : blakflare@hotmail.com
+// Webpage : http://sfsrealm.hopto.org/
+// License information for this code is in license.txt
+
+
+#include "SErr.h"
+
+DWORD dwLastError;
+
+#if (defined(_WIN32) || defined(WIN32)) && !defined(NO_WINDOWS_H)
+
+DWORD WINAPI SErrSetLastError(DWORD dwErrorCode)
+{
+ dwLastError = dwErrorCode;
+ SetLastError(dwErrorCode);
+ return dwErrorCode;
+}
+
+#else
+
+DWORD WINAPI SErrSetLastError(DWORD dwErrorCode)
+{
+ return (dwLastError = dwErrorCode);
+}
+
+#endif
+
+DWORD WINAPI SErrGetLastError(VOID)
+{
+ return dwLastError;
+}
+
diff --git a/SErr.h b/SErr.h
--- /dev/null
+++ b/SErr.h
@@ -0,0 +1,25 @@
+// SErr.h - Header for SetLastError routine
+// License information for this code is in license.txt
+
+#ifndef S_ERR_INCLUDED
+#define S_ERR_INCLUDED
+
+#if (defined(_WIN32) || defined(WIN32)) && !defined(NO_WINDOWS_H)
+#include <windows.h>
+#else
+#include "wintypes.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DWORD WINAPI SErrSetLastError(DWORD dwErrorCode);
+DWORD WINAPI SErrGetLastError(VOID);
+
+#ifdef __cplusplus
+}; // extern "C"
+#endif
+
+#endif
+
diff --git a/SMem.cpp b/SMem.cpp
--- /dev/null
+++ b/SMem.cpp
@@ -0,0 +1,66 @@
+// SMem.cpp - Memory functions
+//
+// Converted from assembly to C++ by ShadowFlare.
+// E-mail : blakflare@hotmail.com
+// Webpage : http://sfsrealm.hopto.org/
+// License information for this code is in license.txt
+
+
+#include "SMem.h"
+#include <malloc.h>
+
+LPVOID WINAPI SMemAlloc(DWORD dwSize)
+{
+ LPVOID lpMemory = malloc(dwSize);
+ if (lpMemory) SMemZero(lpMemory,dwSize);
+ return lpMemory;
+}
+
+void WINAPI SMemFree(LPVOID lpvMemory)
+{
+ if (lpvMemory) free(lpvMemory);
+}
+
+DWORD WINAPI SMemCopy(LPVOID lpDestination, LPCVOID lpSource, DWORD dwLength)
+{
+ DWORD dwPrevLen = dwLength;
+ LPDWORD lpdwDestination = (LPDWORD)lpDestination,lpdwSource = (LPDWORD)lpSource;
+ LPBYTE lpbyDestination,lpbySource;
+
+ dwLength >>= 2;
+
+ while (dwLength--)
+ *lpdwDestination++ = *lpdwSource++;
+
+ lpbyDestination = (LPBYTE)lpdwDestination;
+ lpbySource = (LPBYTE)lpdwSource;
+
+ dwLength = dwPrevLen;
+ dwLength &= 3;
+
+ while (dwLength--)
+ *lpbyDestination++ = *lpbySource++;
+
+ return dwPrevLen;
+}
+
+void WINAPI SMemZero(LPVOID lpDestination, DWORD dwLength)
+{
+ DWORD dwPrevLen = dwLength;
+ LPDWORD lpdwDestination = (LPDWORD)lpDestination;
+ LPBYTE lpbyDestination;
+
+ dwLength >>= 2;
+
+ while (dwLength--)
+ *lpdwDestination++ = 0;
+
+ lpbyDestination = (LPBYTE)lpdwDestination;
+
+ dwLength = dwPrevLen;
+ dwLength &= 3;
+
+ while (dwLength--)
+ *lpbyDestination++ = 0;
+}
+
diff --git a/SMem.h b/SMem.h
--- /dev/null
+++ b/SMem.h
@@ -0,0 +1,27 @@
+// SMem.h - Header for memory functions
+// License information for this code is in license.txt
+
+#ifndef S_MEM_INCLUDED
+#define S_MEM_INCLUDED
+
+#if (defined(_WIN32) || defined(WIN32)) && !defined(NO_WINDOWS_H)
+#include <windows.h>
+#else
+#include "wintypes.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LPVOID WINAPI SMemAlloc(DWORD dwSize);
+void WINAPI SMemFree(LPVOID lpvMemory);
+DWORD WINAPI SMemCopy(LPVOID lpDestination, LPCVOID lpSource, DWORD dwLength);
+void WINAPI SMemZero(LPVOID lpDestination, DWORD dwLength);
+
+#ifdef __cplusplus
+}; // extern "C"
+#endif
+
+#endif
+
diff --git a/ZLib_Static_min.lib b/ZLib_Static_min.lib
new file mode 100644 (file)
index 0000000..dce1150 Binary files /dev/null and b/ZLib_Static_min.lib differ diff --git a/crc32.c b/crc32.c
--- /dev/null
+++ b/crc32.c
@@ -0,0 +1,72 @@
+/*****************************************************************************/
+/* crc32.c Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Pkware Data Compression Library Version 1.11 */
+/* Dissassembled method crc32 - cdecl version */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 09.04.03 1.00 Lad The first version of crc32.c */
+/* 02.05.03 1.00 Lad Stress test done */
+/*****************************************************************************/
+
+#include "pklib.h"
+
+static char CopyRight[] = "PKWARE Data Compression Library for Win32\r\n"
+ "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
+ "Patent No. 5,051,745\r\n"
+ "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
+ "Version 1.11\r\n";
+
+static unsigned long crc_table[] =
+{
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+
+unsigned long PKEXPORT crc32pk(char * buffer, unsigned int * psize, unsigned long * old_crc)
+{
+ unsigned int size = *psize;
+ unsigned long ch;
+ unsigned long crc_value = *old_crc;
+
+ while(size-- != 0)
+ {
+ ch = *buffer++ ^ (char)crc_value;
+ crc_value >>= 8;
+
+ crc_value = crc_table[ch & 0x0FF] ^ crc_value;
+ }
+ return crc_value;
+}
diff --git a/explode.c b/explode.c
--- /dev/null
+++ b/explode.c
@@ -0,0 +1,503 @@
+/*****************************************************************************/
+/* explode.c Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Explode function of PKWARE Data Compression library */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
+/* 08.04.03 1.01 Lad Renamed to explode.c to be compatible with pklib */
+/* 02.05.03 1.01 Lad Stress test done */
+/*****************************************************************************/
+
+#include "pklib.h"
+#include "SMem.h"
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+// Compression structure (Size 12596 bytes)
+typedef struct
+{
+ unsigned long offs0000; // 0000
+ unsigned long ctype; // 0004 - Compression type (CMP_BINARY or CMP_ASCII)
+ unsigned long outputPos; // 0008 - Position in output buffer
+ unsigned long dsize_bits; // 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000)
+ unsigned long dsize_mask; // 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000)
+ unsigned long bit_buff; // 0014 - 16-bit buffer for processing input data
+ unsigned long extra_bits; // 0018 - Number of extra (above 8) bits in bit buffer
+ unsigned int in_pos; // 001C - Position in in_buff
+ unsigned long in_bytes; // 0020 - Number of bytes in input buffer
+ void * param; // 0024 - Custom parameter
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 0028
+ void (*write_buf)(char *buf, unsigned int *size, void *param);// 002C
+ unsigned char out_buff[0x2000]; // 0030 - Output circle buffer. Starting position is 0x1000
+ unsigned char offs2030[0x204]; // 2030 - ???
+ unsigned char in_buff[0x800]; // 2234 - Buffer for data to be decompressed
+ unsigned char position1[0x100]; // 2A34 - Positions in buffers
+ unsigned char position2[0x100]; // 2B34 - Positions in buffers
+ unsigned char offs2C34[0x100]; // 2C34 - Buffer for
+ unsigned char offs2D34[0x100]; // 2D34 - Buffer for
+ unsigned char offs2E34[0x80]; // 2EB4 - Buffer for
+ unsigned char offs2EB4[0x100]; // 2EB4 - Buffer for
+ unsigned char ChBitsAsc[0x100]; // 2FB4 - Buffer for
+ unsigned char DistBits[0x40]; // 30B4 - Numbers of bytes to skip copied block length
+ unsigned char LenBits[0x10]; // 30F4 - Numbers of bits for skip copied block length
+ unsigned char ExLenBits[0x10]; // 3104 - Number of valid bits for copied block
+ unsigned short LenBase[0x10]; // 3114 - Buffer for
+} TDcmpStruct;
+
+//-----------------------------------------------------------------------------
+// Tables
+
+static unsigned char DistBits[] =
+{
+ 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+};
+
+static unsigned char DistCode[] =
+{
+ 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
+ 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
+ 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
+ 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
+};
+
+static unsigned char ExLenBits[] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+};
+
+static unsigned short LenBase[] =
+{
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
+};
+
+static unsigned char LenBits[] =
+{
+ 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
+};
+
+static unsigned char LenCode[] =
+{
+ 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
+};
+
+static unsigned char ChBitsAsc[] =
+{
+ 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
+ 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
+ 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
+ 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
+ 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
+ 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
+ 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
+};
+
+static unsigned short ChCodeAsc[] =
+{
+ 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
+ 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
+ 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
+ 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
+ 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
+ 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
+ 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
+ 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
+ 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
+ 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
+ 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
+ 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
+ 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
+ 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
+ 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
+ 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
+ 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
+ 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
+ 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
+ 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
+ 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
+ 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
+ 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
+ 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
+ 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
+ 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
+ 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
+ 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
+ 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
+ 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
+ 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
+ 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
+};
+
+//-----------------------------------------------------------------------------
+// Local variables
+
+static char Copyright[] = "PKWARE Data Compression Library for Win32\r\n"
+ "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
+ "Patent No. 5,051,745\r\n"
+ "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
+ "Version 1.11";
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static void GenDecodeTabs(long count, unsigned char * bits, unsigned char * pCode, unsigned char * buffer2)
+{
+ long i;
+
+ for(i = count-1; i >= 0; i--) // EBX - count
+ {
+ unsigned long idx1 = pCode[i];
+ unsigned long idx2 = 1 << bits[i];
+
+ do
+ {
+ buffer2[idx1] = (unsigned char)i;
+ idx1 += idx2;
+ }
+ while(idx1 < 0x100);
+ }
+}
+
+static void GenAscTabs(TDcmpStruct * pWork)
+{
+ unsigned short * pChCodeAsc = &ChCodeAsc[0xFF];
+ unsigned long acc, add;
+ unsigned short count;
+
+ for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--)
+ {
+ unsigned char * pChBitsAsc = pWork->ChBitsAsc + count;
+ unsigned char bits_asc = *pChBitsAsc;
+
+ if(bits_asc <= 8)
+ {
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc;
+
+ do
+ {
+ pWork->offs2C34[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x100);
+ }
+ else if((acc = (*pChCodeAsc & 0xFF)) != 0)
+ {
+ pWork->offs2C34[acc] = 0xFF;
+
+ if(*pChCodeAsc & 0x3F)
+ {
+ bits_asc -= 4;
+ *pChBitsAsc = bits_asc;
+
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc >> 4;
+ do
+ {
+ pWork->offs2D34[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x100);
+ }
+ else
+ {
+ bits_asc -= 6;
+ *pChBitsAsc = bits_asc;
+
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc >> 6;
+ do
+ {
+ pWork->offs2E34[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x80);
+ }
+ }
+ else
+ {
+ bits_asc -= 8;
+ *pChBitsAsc = bits_asc;
+
+ add = (1 << bits_asc);
+ acc = *pChCodeAsc >> 8;
+ do
+ {
+ pWork->offs2EB4[acc] = (unsigned char)count;
+ acc += add;
+ }
+ while(acc < 0x100);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Skips given number of bits in bit buffer. Result is stored in pWork->bit_buff
+// If no data in input buffer, returns true
+
+static int WasteBits(TDcmpStruct * pWork, unsigned long nBits)
+{
+ // If number of bits required is less than number of (bits in the buffer) ?
+ if(nBits <= pWork->extra_bits)
+ {
+ pWork->extra_bits -= nBits;
+ pWork->bit_buff >>= nBits;
+ return 0;
+ }
+
+ // Load input buffer if necessary
+ pWork->bit_buff >>= pWork->extra_bits;
+ if(pWork->in_pos == pWork->in_bytes)
+ {
+ pWork->in_pos = sizeof(pWork->in_buff);
+ if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0)
+ return 1;
+ pWork->in_pos = 0;
+ }
+
+ // Update bit buffer
+ pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8);
+ pWork->bit_buff >>= (nBits - pWork->extra_bits);
+ pWork->extra_bits = (pWork->extra_bits - nBits) + 8;
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Returns : 0x000 - 0x0FF : One byte from compressed file.
+// 0x100 - 0x305 : Copy previous block (0x100 = 1 byte)
+// 0x306 : Out of buffer (?)
+
+static unsigned long DecodeLit(TDcmpStruct * pWork)
+{
+ unsigned long nBits; // Number of bits to skip
+ unsigned long value; // Position in buffers
+
+ // Test the current bit in byte buffer. If is not set, simply return the next byte.
+ if(pWork->bit_buff & 1)
+ {
+ // Skip current bit in the buffer
+ if(WasteBits(pWork, 1))
+ return 0x306;
+
+ // The next bits are position in buffers
+ value = pWork->position2[(pWork->bit_buff & 0xFF)];
+
+ // Get number of bits to skip
+ if(WasteBits(pWork, pWork->LenBits[value]))
+ return 0x306;
+
+ if((nBits = pWork->ExLenBits[value]) != 0)
+ {
+ unsigned long val2 = pWork->bit_buff & ((1 << nBits) - 1);
+
+ if(WasteBits(pWork, nBits))
+ {
+ if((value + val2) != 0x10E)
+ return 0x306;
+ }
+ value = pWork->LenBase[value] + val2;
+ }
+ return value + 0x100; // Return number of bytes to repeat
+ }
+
+ // Waste one bit
+ if(WasteBits(pWork, 1))
+ return 0x306;
+
+ // If the binary compression type, read 8 bits and return them as one byte.
+ if(pWork->ctype == CMP_BINARY)
+ {
+ value = pWork->bit_buff & 0xFF;
+ if(WasteBits(pWork, 8))
+ return 0x306;
+ return value;
+ }
+
+ // When ASCII compression ...
+ if(pWork->bit_buff & 0xFF)
+ {
+ value = pWork->offs2C34[pWork->bit_buff & 0xFF];
+
+ if(value == 0xFF)
+ {
+ if(pWork->bit_buff & 0x3F)
+ {
+ if(WasteBits(pWork, 4))
+ return 0x306;
+
+ value = pWork->offs2D34[pWork->bit_buff & 0xFF];
+ }
+ else
+ {
+ if(WasteBits(pWork, 6))
+ return 0x306;
+
+ value = pWork->offs2E34[pWork->bit_buff & 0x7F];
+ }
+ }
+ }
+ else
+ {
+ if(WasteBits(pWork, 8))
+ return 0x306;
+
+ value = pWork->offs2EB4[pWork->bit_buff & 0xFF];
+ }
+
+ return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value;
+}
+
+//-----------------------------------------------------------------------------
+// Retrieves the number of bytes to move back
+
+static unsigned long DecodeDist(TDcmpStruct * pWork, unsigned long dwLength)
+{
+ unsigned long pos = pWork->position1[(pWork->bit_buff & 0xFF)];
+ unsigned long nSkip = pWork->DistBits[pos]; // Number of bits to skip
+
+ // Skip the appropriate number of bits
+ if(WasteBits(pWork, nSkip) == 1)
+ return 0;
+
+ if(dwLength == 2)
+ {
+ pos = (pos << 2) | (pWork->bit_buff & 0x03);
+
+ if(WasteBits(pWork, 2) == 1)
+ return 0;
+ }
+ else
+ {
+ pos = (pos << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask);
+
+ // Skip the bits
+ if(WasteBits(pWork, pWork->dsize_bits) == 1)
+ return 0;
+ }
+ return pos+1;
+}
+
+static unsigned long Expand(TDcmpStruct * pWork)
+{
+ unsigned int copyBytes; // Number of bytes to copy
+ unsigned long oneByte; // One byte from compressed file
+ unsigned long dwResult;
+
+ pWork->outputPos = 0x1000; // Initialize output buffer position
+
+ // If end of data or error, terminate decompress
+ while((dwResult = oneByte = DecodeLit(pWork)) < 0x305)
+ {
+ // If one byte is greater than 0x100, means "Repeat n - 0xFE bytes"
+ if(oneByte >= 0x100)
+ {
+ unsigned char * source; // ECX
+ unsigned char * target; // EDX
+ unsigned long copyLength = oneByte - 0xFE;
+ unsigned long moveBack;
+
+ // Get length of data to copy
+ if((moveBack = DecodeDist(pWork, copyLength)) == 0)
+ {
+ dwResult = 0x306;
+ break;
+ }
+
+ // Target and source pointer
+ target = &pWork->out_buff[pWork->outputPos];
+ source = target - moveBack;
+ pWork->outputPos += copyLength;
+
+ while(copyLength-- > 0)
+ *target++ = *source++;
+ }
+ else
+ pWork->out_buff[pWork->outputPos++] = (unsigned char)oneByte;
+
+ // If number of extracted bytes has reached 1/2 of output buffer,
+ // flush output buffer.
+ if(pWork->outputPos >= 0x2000)
+ {
+ // Copy decompressed data into user buffer
+ copyBytes = 0x1000;
+ pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
+
+ // If there are some data left, keep them alive
+ SMemCopy(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
+ pWork->outputPos -= 0x1000;
+ }
+ }
+
+ copyBytes = pWork->outputPos - 0x1000;
+ pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
+ return dwResult;
+}
+
+
+//-----------------------------------------------------------------------------
+// Main exploding function.
+
+unsigned int PKEXPORT explode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param)
+{
+ TDcmpStruct * pWork = (TDcmpStruct *)work_buf;
+
+ // Initialize work struct and load compressed data
+ pWork->read_buf = read_buf;
+ pWork->write_buf = write_buf;
+ pWork->param = param;
+ pWork->in_pos = sizeof(pWork->in_buff);
+ pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param);
+ if(pWork->in_bytes <= 4)
+ return CMP_BAD_DATA;
+
+ pWork->ctype = pWork->in_buff[0]; // Get the compression type
+ pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size
+ pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer
+ pWork->extra_bits = 0; // Extra (over 8) bits
+ pWork->in_pos = 3; // Position in input buffer
+
+ // Test for the valid dictionary size
+ if(4 > pWork->dsize_bits || pWork->dsize_bits > 6)
+ return CMP_INVALID_DICTSIZE;
+
+ pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction
+
+ if(pWork->ctype != CMP_BINARY)
+ {
+ if(pWork->ctype != CMP_ASCII)
+ return CMP_INVALID_MODE;
+
+ SMemCopy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc));
+ GenAscTabs(pWork);
+ }
+
+ SMemCopy(pWork->LenBits, LenBits, sizeof(pWork->LenBits));
+ GenDecodeTabs(0x10, pWork->LenBits, LenCode, pWork->position2);
+ SMemCopy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits));
+ SMemCopy(pWork->LenBase, LenBase, sizeof(pWork->LenBase));
+ SMemCopy(pWork->DistBits, DistBits, sizeof(pWork->DistBits));
+ GenDecodeTabs(0x40, pWork->DistBits, DistCode, pWork->position1);
+ if(Expand(pWork) != 0x306)
+ return CMP_NO_ERROR;
+
+ return CMP_ABORT;
+}
diff --git a/huffman.cpp b/huffman.cpp
--- /dev/null
+++ b/huffman.cpp
@@ -0,0 +1,1387 @@
+/*****************************************************************************/
+/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */
+/*---------------------------------------------------------------------------*/
+/* This module contains Huffmann (de)compression methods */
+/* */
+/* Authors : Ladislav Zezula (ladik.zezula.net) */
+/* ShadowFlare (BlakFlare@hotmail.com) */
+/* */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */
+/* 03.05.03 1.00 Lad Added compression methods */
+/*****************************************************************************/
+
+#include "huffman.h"
+#include "SMem.h"
+
+//-----------------------------------------------------------------------------
+// Methods of the THTreeItem struct
+
+// 1501DB70
+THTreeItem * THTreeItem::Call1501DB70(THTreeItem * pLast)
+{
+ if(pLast == NULL)
+ pLast = this + 1;
+ return pLast;
+}
+
+// Gets previous Huffman tree item (?)
+THTreeItem * THTreeItem::GetPrevItem(long value)
+{
+ if(PTR_INT(prev) < 0)
+ return PTR_NOT(prev);
+
+ if(value < 0)
+ value = this - next->prev;
+ return prev + value;
+
+// OLD VERSION
+// if(PTR_INT(value) < 0)
+// value = PTR_INT((item - item->next->prev));
+// return (THTreeItem *)((char *)prev + value);
+}
+
+// 1500F5E0
+void THTreeItem::ClearItemLinks()
+{
+ next = prev = NULL;
+}
+
+// 1500BC90
+void THTreeItem::RemoveItem()
+{
+ THTreeItem * pTemp; // EDX
+
+ if(next != NULL)
+ {
+ pTemp = prev;
+
+ if(PTR_INT(pTemp) <= 0)
+ pTemp = PTR_NOT(pTemp);
+ else
+ pTemp += (this - next->prev);
+
+ pTemp->next = next;
+ next->prev = prev;
+ next = prev = NULL;
+ }
+}
+
+/*
+// OLD VERSION : Removes item from the tree (?)
+static void RemoveItem(THTreeItem * item)
+{
+ THTreeItem * next = item->next; // ESI
+ THTreeItem * prev = item->prev; // EDX
+
+ if(next == NULL)
+ return;
+
+ if(PTR_INT(prev) < 0)
+ prev = PTR_NOT(prev);
+ else
+ // ??? usually item == next->prev, so what is it ?
+ prev = (THTreeItem *)((unsigned char *)prev + (unsigned long)((unsigned char *)item - (unsigned char *)(next->prev)));
+
+ // Remove HTree item from the chain
+ prev->next = next; // Sets the 'first' pointer
+ next->prev = item->prev;
+
+ // Invalidate pointers
+ item->next = NULL;
+ item->prev = NULL;
+}
+*/
+
+//-----------------------------------------------------------------------------
+// TOutputStream functions
+
+void TOutputStream::PutBits(unsigned long dwBuff, unsigned int nPutBits)
+{
+ dwBitBuff |= (dwBuff << nBits);
+ nBits += nPutBits;
+
+ // Flush completed bytes
+ while(nBits >= 8)
+ {
+ if(dwOutSize != 0)
+ {
+ *pbOutPos++ = (unsigned char)dwBitBuff;
+ dwOutSize--;
+ }
+
+ dwBitBuff >>= 8;
+ nBits -= 8;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// TInputStream functions
+
+// Gets one bit from input stream
+unsigned long TInputStream::GetBit()
+{
+ unsigned long dwBit = (dwBitBuff & 1);
+
+ dwBitBuff >>= 1;
+ if(--nBits == 0)
+ {
+ dwBitBuff = *(unsigned long *)pbInBuffer;
+ pbInBuffer += sizeof(unsigned long);
+ nBits = 32;
+ }
+ return dwBit;
+}
+
+// Gets 7 bits from the stream
+unsigned long TInputStream::Get7Bits()
+{
+ if(nBits <= 7)
+ {
+ dwBitBuff |= *(unsigned short *)pbInBuffer << nBits;
+ pbInBuffer += sizeof(unsigned short);
+ nBits += 16;
+ }
+
+ // Get 7 bits from input stream
+ return (dwBitBuff & 0x7F);
+}
+
+// Gets the whole byte from the input stream.
+unsigned long TInputStream::Get8Bits()
+{
+ unsigned long dwOneByte;
+
+ if(nBits <= 8)
+ {
+ dwBitBuff |= *(unsigned short *)pbInBuffer << nBits;
+ pbInBuffer += sizeof(unsigned short);
+ nBits += 16;
+ }
+
+ dwOneByte = (dwBitBuff & 0xFF);
+ dwBitBuff >>= 8;
+ nBits -= 8;
+ return dwOneByte;
+}
+
+//-----------------------------------------------------------------------------
+// Functions for huffmann tree items
+
+// Inserts item into the tree (?)
+static void InsertItem(THTreeItem ** itemPtr, THTreeItem * item, unsigned long where, THTreeItem * item2)
+{
+ THTreeItem * next = item->next; // EDI - next to the first item
+ THTreeItem * prev = item->prev; // ESI - prev to the first item
+ long next2; // Pointer to the next item
+ THTreeItem * prev2; // Pointer to previous item
+
+ // The same code like in RemoveItem(item);
+ if(next != 0) // If the first item already has next one
+ {
+ if(PTR_INT(prev) < 0)
+ prev = PTR_NOT(prev);
+ else
+ prev += (item - next->prev);
+
+ // 150083C1
+ // Remove the item from the tree
+ prev->next = next;
+ next->prev = prev;
+
+ // Invalidate 'prev' and 'next' pointer
+ item->next = 0;
+ item->prev = 0;
+ }
+
+ if(item2 == NULL) // EDX - If the second item is not entered,
+ item2 = PTR_PTR(&itemPtr[1]); // take the first tree item
+
+ switch(where)
+ {
+ case SWITCH_ITEMS : // Switch the two items
+ item->next = item2->next; // item2->next (Pointer to pointer to first)
+ item->prev = item2->next->prev;
+ item2->next->prev = item;
+ item2->next = item; // Set the first item
+ return;
+
+ case INSERT_ITEM: // Insert as the last item
+ item->next = item2; // Set next item (or pointer to pointer to first item)
+ item->prev = item2->prev; // Set prev item (or last item in the tree)
+
+ next2 = PTR_INT(itemPtr[0]);// Usually NULL
+ prev2 = item2->prev; // Prev item to the second (or last tree item)
+
+ if(PTR_INT(prev2) < 0)
+ {
+ prev2 = PTR_NOT(prev);
+
+ prev2->next = item;
+ item2->prev = item; // Next after last item
+ return;
+ }
+
+ if(next2 < 0)
+ next2 = item2 - item2->next->prev;
+// next2 = (THTreeItem *)(unsigned long)((unsigned char *)item2 - (unsigned char *)(item2->next->prev));
+
+// prev2 = (THTreeItem *)((char *)prev2 + (unsigned long)next2);// ???
+ prev2 += next2;
+ prev2->next = item;
+ item2->prev = item; // Set the next/last item
+ return;
+
+ default:
+ return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// THuffmannTree class functions
+
+// Builds Huffman tree. Called with the first 8 bits loaded from input stream
+void THuffmannTree::BuildTree(unsigned int nCmpType)
+{
+ unsigned long maxByte; // [ESP+10] - The greatest character found in table
+ THTreeItem ** itemPtr; // [ESP+14] - Pointer to Huffman tree item pointer array
+ unsigned char * byteArray; // [ESP+1C] - Pointer to unsigned char in Table1502A630
+ THTreeItem * child1;
+ unsigned long i; // egcs in linux doesn't like multiple for loops without an explicit i
+
+ // Loop while pointer has a negative value
+ while(PTR_INT(pLast) > 0) // ESI - Last entry
+ {
+ THTreeItem * temp; // EAX
+
+ if(pLast->next != NULL) // ESI->next
+ pLast->RemoveItem();
+ // EDI = &offs3054
+ pItem3058 = PTR_PTR(&pItem3054);// [EDI+4]
+ pLast->prev = pItem3058; // EAX
+
+ temp = PTR_PTR(&pItem3054)->GetPrevItem(PTR_INT(&pItem3050));
+
+ temp->next = pLast;
+ pItem3054 = pLast;
+ }
+
+ // Clear all pointers in HTree item array
+ SMemZero(items306C, sizeof(items306C));
+
+ maxByte = 0; // Greatest character found init to zero.
+ itemPtr = (THTreeItem **)&items306C; // Pointer to current entry in HTree item pointer array
+
+ // Ensure we have low 8 bits only
+ nCmpType &= 0xFF;
+ byteArray = Table1502A630 + nCmpType * 258; // EDI also
+
+ for(i = 0; i < 0x100; i++, itemPtr++)
+ {
+ THTreeItem * item = pItem3058; // Item to be created
+ THTreeItem * pItem3 = pItem3058;
+ unsigned char oneByte = byteArray[i];
+
+ // Skip all the bytes which are zero.
+ if(byteArray[i] == 0)
+ continue;
+
+ // If not valid pointer, take the first available item in the array
+ if(PTR_INT(item) <= 0)
+ item = &items0008[nItems++];
+
+ // Insert this item as the top of the tree
+ InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL);
+
+ item->parent = NULL; // Invalidate child and parent
+ item->child = NULL;
+ *itemPtr = item; // Store pointer into pointer array
+
+ item->dcmpByte = i; // Store counter
+ item->byteValue = oneByte; // Store byte value
+ if(oneByte >= maxByte)
+ {
+ maxByte = oneByte;
+ continue;
+ }
+
+ // Find the first item which has byte value greater than current one byte
+ if(PTR_INT((pItem3 = pLast)) > 0) // EDI - Pointer to the last item
+ {
+ // 15006AF7
+ if(pItem3 != NULL)
+ {
+ do // 15006AFB
+ {
+ if(pItem3->byteValue >= oneByte)
+ goto _15006B09;
+ pItem3 = pItem3->prev;
+ }
+ while(PTR_INT(pItem3) > 0);
+ }
+ }
+ pItem3 = NULL;
+
+ // 15006B09
+ _15006B09:
+ if(item->next != NULL)
+ item->RemoveItem();
+
+ // 15006B15
+ if(pItem3 == NULL)
+ pItem3 = PTR_PTR(&pFirst);
+
+ // 15006B1F
+ item->next = pItem3->next;
+ item->prev = pItem3->next->prev;
+ pItem3->next->prev = item;
+ pItem3->next = item;
+ }
+
+ // 15006B4A
+ for(; i < 0x102; i++)
+ {
+ THTreeItem ** itemPtr = &items306C[i]; // EDI
+
+ // 15006B59
+ THTreeItem * item = pItem3058; // ESI
+ if(PTR_INT(item) <= 0)
+ item = &items0008[nItems++];
+
+ InsertItem(&pItem305C, item, INSERT_ITEM, NULL);
+
+ // 15006B89
+ item->dcmpByte = i;
+ item->byteValue = 1;
+ item->parent = NULL;
+ item->child = NULL;
+ *itemPtr++ = item;
+ }
+
+ // 15006BAA
+ if(PTR_INT((child1 = pLast)) > 0) // EDI - last item (first child to item
+ {
+ THTreeItem * child2; // EBP
+ THTreeItem * item; // ESI
+
+ // 15006BB8
+ while(PTR_INT((child2 = child1->prev)) > 0)
+ {
+ if(PTR_INT((item = pItem3058)) <= 0)
+ item = &items0008[nItems++];
+
+ // 15006BE3
+ InsertItem(&pItem305C, item, SWITCH_ITEMS, NULL);
+
+ // 15006BF3
+ item->parent = NULL;
+ item->child = NULL;
+
+ //EDX = child2->byteValue + child1->byteValue;
+ //EAX = child1->byteValue;
+ //ECX = maxByte; // The greatest character (0xFF usually)
+
+ item->byteValue = child1->byteValue + child2->byteValue; // 0x02
+ item->child = child1; // Prev item in the
+ child1->parent = item;
+ child2->parent = item;
+
+ // EAX = item->byteValue;
+ if(item->byteValue >= maxByte)
+ maxByte = item->byteValue;
+ else
+ {
+ THTreeItem * pItem2 = child2->prev; // EDI
+
+ if(PTR_INT(pItem2) > 0)
+ {
+ // 15006C2D
+ do
+ {
+ if(pItem2->byteValue >= item->byteValue)
+ goto _15006C3B;
+ pItem2 = pItem2->prev;
+ }
+ while(PTR_INT(pItem2) > 0);
+ }
+ pItem2 = NULL;
+
+ _15006C3B:
+ if(item->next != 0)
+ {
+ THTreeItem * temp4 = item->GetPrevItem(-1);
+
+ temp4->next = item->next; // The first item changed
+ item->next->prev = item->prev; // First->prev changed to negative value
+ item->next = NULL;
+ item->prev = NULL;
+ }
+
+ // 15006C62
+ if(pItem2 == NULL)
+ pItem2 = PTR_PTR(&pFirst);
+
+ item->next = pItem2->next; // Set item with 0x100 byte value
+ item->prev = pItem2->next->prev; // Set item with 0x17 byte value
+ pItem2->next->prev = item; // Changed prev of item with
+ pItem2->next = item;
+ }
+ // 15006C7B
+ if(PTR_INT((child1 = child2->prev)) <= 0)
+ break;
+ }
+ }
+ // 15006C88
+ offs0004 = 1;
+}
+/*
+// Modifies Huffman tree. Adds new item and changes
+void THuffmannTree::ModifyTree(unsigned long dwIndex)
+{
+ THTreeItem * pItem1 = pItem3058; // ESI
+ THTreeItem * pSaveLast = (PTR_INT(pLast) <= 0) ? NULL : pLast; // EBX
+ THTreeItem * temp; // EAX
+
+ // Prepare the first item to insert to the tree
+ if(PTR_INT(pItem1) <= 0)
+ pItem1 = &items0008[nItems++];
+
+ // If item has any next item, remove it from the chain
+ if(pItem1->next != NULL)
+ {
+ THTreeItem * temp = pItem1->GetPrevItem(-1); // EAX
+
+ temp->next = pItem1->next;
+ pItem1->next->prev = pItem1->prev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ pItem1->next = PTR_PTR(&pFirst);
+ pItem1->prev = pLast;
+ temp = pItem1->next->GetPrevItem(PTR_INT(pItem305C));
+
+ // 150068E9
+ temp->next = pItem1;
+ pLast = pItem1;
+
+ pItem1->parent = NULL;
+ pItem1->child = NULL;
+
+ // 150068F6
+ pItem1->dcmpByte = pSaveLast->dcmpByte; // Copy item index
+ pItem1->byteValue = pSaveLast->byteValue; // Copy item byte value
+ pItem1->parent = pSaveLast; // Set parent to last item
+ items306C[pSaveLast->dcmpByte] = pItem1; // Insert item into item pointer array
+
+ // Prepare the second item to insert into the tree
+ if(PTR_INT((pItem1 = pItem3058)) <= 0)
+ pItem1 = &items0008[nItems++];
+
+ // 1500692E
+ if(pItem1->next != NULL)
+ {
+ temp = pItem1->GetPrevItem(-1); // EAX
+
+ temp->next = pItem1->next;
+ pItem1->next->prev = pItem1->prev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+ // 1500694C
+ pItem1->next = PTR_PTR(&pFirst);
+ pItem1->prev = pLast;
+ temp = pItem1->next->GetPrevItem(PTR_INT(pItem305C));
+
+ // 15006968
+ temp->next = pItem1;
+ pLast = pItem1;
+
+ // 1500696E
+ pItem1->child = NULL;
+ pItem1->dcmpByte = dwIndex;
+ pItem1->byteValue = 0;
+ pItem1->parent = pSaveLast;
+ pSaveLast->child = pItem1;
+ items306C[dwIndex] = pItem1;
+
+ do
+ {
+ THTreeItem * pItem2 = pItem1;
+ THTreeItem * pItem3;
+ unsigned long byteValue;
+
+ // 15006993
+ byteValue = ++pItem1->byteValue;
+
+ // Pass through all previous which have its value greater than byteValue
+ while(PTR_INT((pItem3 = pItem2->prev)) > 0) // EBX
+ {
+ if(pItem3->byteValue >= byteValue)
+ goto _150069AE;
+
+ pItem2 = pItem2->prev;
+ }
+ // 150069AC
+ pItem3 = NULL;
+
+ _150069AE:
+ if(pItem2 == pItem1)
+ continue;
+
+ // 150069B2
+ // Switch pItem2 with item
+ InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1);
+ InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3);
+
+ // 150069D0
+ // Switch parents of pItem1 and pItem2
+ temp = pItem2->parent->child;
+ if(pItem1 == pItem1->parent->child)
+ pItem1->parent->child = pItem2;
+
+ if(pItem2 == temp)
+ pItem2->parent->child = pItem1;
+
+ // 150069ED
+ // Switch parents of pItem1 and pItem3
+ temp = pItem1->parent;
+ pItem1 ->parent = pItem2->parent;
+ pItem2->parent = temp;
+ offs0004++;
+ }
+ while(PTR_INT((pItem1 = pItem1->parent)) > 0);
+}
+*/
+
+THTreeItem * THuffmannTree::Call1500E740(unsigned int nValue)
+{
+ THTreeItem * pItem1 = pItem3058; // EDX
+ THTreeItem * pItem2; // EAX
+ THTreeItem * pNext;
+ THTreeItem * pPrev;
+ THTreeItem ** ppItem;
+
+ if(PTR_INT(pItem1) <= 0 || (pItem2 = pItem1) == NULL)
+ {
+ if((pItem2 = &items0008[nItems++]) != NULL)
+ pItem1 = pItem2;
+ else
+ pItem1 = pFirst;
+ }
+ else
+ pItem1 = pItem2;
+
+ pNext = pItem1->next;
+ if(pNext != NULL)
+ {
+ pPrev = pItem1->prev;
+ if(PTR_INT(pPrev) <= 0)
+ pPrev = PTR_NOT(pPrev);
+ else
+ pPrev += (pItem1 - pItem1->next->prev);
+
+ pPrev->next = pNext;
+ pNext->prev = pPrev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ ppItem = &pFirst; // esi
+ if(nValue > 1)
+ {
+ // ecx = pFirst->next;
+ pItem1->next = *ppItem;
+ pItem1->prev = (*ppItem)->prev;
+
+ (*ppItem)->prev = pItem2;
+ *ppItem = pItem1;
+
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ else
+ {
+ pItem1->next = (THTreeItem *)ppItem;
+ pItem1->prev = ppItem[1];
+ // edi = pItem305C;
+ pPrev = ppItem[1]; // ecx
+ if(pPrev <= 0)
+ {
+ pPrev = PTR_NOT(pPrev);
+ pPrev->next = pItem1;
+ pPrev->prev = pItem2;
+
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ else
+ {
+ if(PTR_INT(pItem305C) < 0)
+ pPrev += (THTreeItem *)ppItem - (*ppItem)->prev;
+ else
+ pPrev += PTR_INT(pItem305C);
+
+ pPrev->next = pItem1;
+ ppItem[1] = pItem2;
+ pItem2->parent = NULL;
+ pItem2->child = NULL;
+ }
+ }
+ return pItem2;
+}
+
+void THuffmannTree::Call1500E820(THTreeItem * pItem)
+{
+ THTreeItem * pItem1; // edi
+ THTreeItem * pItem2 = NULL; // eax
+ THTreeItem * pItem3; // edx
+ THTreeItem * pPrev; // ebx
+
+ for(; pItem != NULL; pItem = pItem->parent)
+ {
+ pItem->byteValue++;
+
+ for(pItem1 = pItem; ; pItem1 = pPrev)
+ {
+ pPrev = pItem1->prev;
+ if(PTR_INT(pPrev) <= 0)
+ {
+ pPrev = NULL;
+ break;
+ }
+
+ if(pPrev->byteValue >= pItem->byteValue)
+ break;
+ }
+
+ if(pItem1 == pItem)
+ continue;
+
+ if(pItem1->next != NULL)
+ {
+ pItem2 = pItem1->GetPrevItem(-1);
+ pItem2->next = pItem1->next;
+ pItem1->next->prev = pItem1->prev;
+ pItem1->next = NULL;
+ pItem1->prev = NULL;
+ }
+
+ pItem2 = pItem->next;
+ pItem1->next = pItem2;
+ pItem1->prev = pItem2->prev;
+ pItem2->prev = pItem1;
+ pItem->next = pItem1;
+ if((pItem2 = pItem1) != NULL)
+ {
+ pItem2 = pItem->GetPrevItem(-1);
+ pItem2->next = pItem->next;
+ pItem->next->prev = pItem->prev;
+ pItem->next = NULL;
+ pItem->prev = NULL;
+ }
+
+ if(pPrev == NULL)
+ pPrev = PTR_PTR(&pFirst);
+
+ pItem2 = pPrev->next;
+ pItem->next = pItem2;
+ pItem->prev = pItem2->prev;
+ pItem2->prev = pItem;
+ pPrev->next = pItem;
+
+ pItem3 = pItem1->parent->child;
+ pItem2 = pItem->parent;
+ if(pItem2->child == pItem)
+ pItem2->child = pItem1;
+ if(pItem3 == pItem1)
+ pItem1->parent->child = pItem;
+
+ pItem2 = pItem->parent;
+ pItem->parent = pItem1->parent;
+ pItem1->parent = pItem2;
+ offs0004++;
+ }
+}
+
+// 1500E920
+unsigned int THuffmannTree::DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType)
+{
+ THTreeItem * pItem1;
+ THTreeItem * pItem2;
+ THTreeItem * pItem3;
+ THTreeItem * pTemp;
+ unsigned long dwBitBuff;
+ unsigned int nBits;
+ unsigned int nBit;
+
+ BuildTree(nCmpType);
+ bIsCmp0 = (nCmpType == 0);
+
+ // Store the compression type into output buffer
+ os->dwBitBuff |= (nCmpType << os->nBits);
+ os->nBits += 8;
+
+ // Flush completed bytes
+ while(os->nBits >= 8)
+ {
+ if(os->dwOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->dwOutSize--;
+ }
+
+ os->dwBitBuff >>= 8;
+ os->nBits -= 8;
+ }
+
+ for(; nInLength != 0; nInLength--)
+ {
+ unsigned char bOneByte = *pbInBuffer++;
+
+ if((pItem1 = items306C[bOneByte]) == NULL)
+ {
+ pItem2 = items306C[0x101]; // ecx
+ pItem3 = pItem2->parent; // eax
+ dwBitBuff = 0;
+ nBits = 0;
+
+ for(; pItem3 != NULL; pItem3 = pItem3->parent)
+ {
+ nBit = (pItem3->child != pItem2) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem2 = pItem3;
+ }
+ os->PutBits(dwBitBuff, nBits);
+
+ // Store the loaded byte into output stream
+ os->dwBitBuff |= (bOneByte << os->nBits);
+ os->nBits += 8;
+
+ // Flush the whole byte(s)
+ while(os->nBits >= 8)
+ {
+ if(os->dwOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->dwOutSize--;
+ }
+ os->dwBitBuff >>= 8;
+ os->nBits -= 8;
+ }
+
+ pItem1 = (PTR_INT(pLast) <= 0) ? NULL : pLast;
+ pItem2 = Call1500E740(1);
+ pItem2->dcmpByte = pItem1->dcmpByte;
+ pItem2->byteValue = pItem1->byteValue;
+ pItem2->parent = pItem1;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem2 = Call1500E740(1);
+ pItem2->dcmpByte = bOneByte;
+ pItem2->byteValue = 0;
+ pItem2->parent = pItem1;
+ items306C[pItem2->dcmpByte] = pItem2;
+ pItem1->child = pItem2;
+
+ Call1500E820(pItem2);
+
+ if(bIsCmp0 != 0)
+ {
+ Call1500E820(items306C[bOneByte]);
+ continue;
+ }
+
+ for(pItem1 = items306C[bOneByte]; pItem1 != NULL; pItem1 = pItem1->parent)
+ {
+ pItem1->byteValue++;
+ pItem2 = pItem1;
+
+ for(;;)
+ {
+ pItem3 = pItem2->prev;
+ if(PTR_INT(pItem3) <= 0)
+ {
+ pItem3 = NULL;
+ break;
+ }
+ if(pItem3->byteValue >= pItem1->byteValue)
+ break;
+ pItem2 = pItem3;
+ }
+
+ if(pItem2 != pItem1)
+ {
+ InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1);
+ InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3);
+
+ pItem3 = pItem2->parent->child;
+ if(pItem1->parent->child == pItem1)
+ pItem1->parent->child = pItem2;
+
+ if(pItem3 == pItem2)
+ pItem2->parent->child = pItem1;
+
+ pTemp = pItem1->parent;
+ pItem1->parent = pItem2->parent;
+ pItem2->parent = pTemp;
+ offs0004++;
+ }
+ }
+ }
+// 1500EB62
+ else
+ {
+ dwBitBuff = 0;
+ nBits = 0;
+ for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent)
+ {
+ nBit = (pItem2->child != pItem1) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem1 = pItem2;
+ }
+ os->PutBits(dwBitBuff, nBits);
+ }
+
+// 1500EB98
+ if(bIsCmp0 != 0)
+ Call1500E820(items306C[bOneByte]); // 1500EB9D
+// 1500EBAF
+ } // for(; nInLength != 0; nInLength--)
+
+// 1500EBB8
+ pItem1 = items306C[0x100];
+ dwBitBuff = 0;
+ nBits = 0;
+ for(pItem2 = pItem1->parent; pItem2 != NULL; pItem2 = pItem2->parent)
+ {
+ nBit = (pItem2->child != pItem1) ? 1 : 0;
+ dwBitBuff = (dwBitBuff << 1) | nBit;
+ nBits++;
+ pItem1 = pItem2;
+ }
+
+// 1500EBE6
+ os->PutBits(dwBitBuff, nBits);
+
+// 1500EBEF
+ // Flush the remaining bits
+ while(os->nBits != 0)
+ {
+ if(os->dwOutSize != 0)
+ {
+ *os->pbOutPos++ = (unsigned char)os->dwBitBuff;
+ os->dwOutSize--;
+ }
+ os->dwBitBuff >>= 8;
+ os->nBits -= ((os->nBits > 8) ? 8 : os->nBits);
+ }
+
+ return (os->pbOutPos - os->pbOutBuffer);
+}
+
+// Decompression using Huffman tree (1500E450)
+unsigned int THuffmannTree::DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is)
+{
+ TQDecompress * qd;
+ THTreeItem * pItem1;
+ THTreeItem * pItem2;
+ unsigned char * pbOutPos = pbOutBuffer;
+ unsigned long nBitCount;
+ unsigned int nDcmpByte = 0;
+ unsigned int n8Bits; // 8 bits loaded from input stream
+ unsigned int n7Bits; // 7 bits loaded from input stream
+ bool bHasQdEntry;
+
+ // Test the output length. Must not be NULL.
+ if(dwOutLength == 0)
+ return 0;
+
+ // Get the compression type from the input stream
+ n8Bits = is->Get8Bits();
+
+ // Build the Huffman tree
+ BuildTree(n8Bits);
+ bIsCmp0 = (n8Bits == 0) ? 1 : 0;
+
+ for(;;)
+ {
+ n7Bits = is->Get7Bits(); // Get 7 bits from input stream
+
+ // Try to use quick decompression. Check TQDecompress array for corresponding item.
+ // If found, ise the result byte instead.
+ qd = &qd3474[n7Bits];
+
+ // If there is a quick-pass possible (ebx)
+ bHasQdEntry = (qd->offs00 >= offs0004) ? true : false;
+
+ // If we can use quick decompress, use it.
+ if(bHasQdEntry)
+ {
+ if(qd->nBits > 7)
+ {
+ is->dwBitBuff >>= 7;
+ is->nBits -= 7;
+ pItem1 = qd->pItem;
+ goto _1500E549;
+ }
+ is->dwBitBuff >>= qd->nBits;
+ is->nBits -= qd->nBits;
+ nDcmpByte = qd->dcmpByte;
+ }
+ else
+ {
+ pItem1 = pFirst->next->prev;
+ if(PTR_INT(pItem1) <= 0)
+ pItem1 = NULL;
+_1500E549:
+ nBitCount = 0;
+ pItem2 = NULL;
+
+ do
+ {
+ pItem1 = pItem1->child; // Move down by one level
+ if(is->GetBit()) // If current bit is set, move to previous
+ pItem1 = pItem1->prev;
+
+ if(++nBitCount == 7) // If we are at 7th bit, save current HTree item.
+ pItem2 = pItem1;
+ }
+ while(pItem1->child != NULL); // Walk until tree has no deeper level
+
+ if(bHasQdEntry == false)
+ {
+ if(nBitCount > 7)
+ {
+ qd->offs00 = offs0004;
+ qd->nBits = nBitCount;
+ qd->pItem = pItem2;
+ }
+ else
+ {
+ unsigned long nIndex = n7Bits & (0xFFFFFFFF >> (32 - nBitCount));
+ unsigned long nAdd = (1 << nBitCount);
+
+ for(qd = &qd3474[nIndex]; nIndex <= 0x7F; nIndex += nAdd, qd += nAdd)
+ {
+ qd->offs00 = offs0004;
+ qd->nBits = nBitCount;
+ qd->dcmpByte = pItem1->dcmpByte;
+ }
+ }
+ }
+ nDcmpByte = pItem1->dcmpByte;
+ }
+
+ if(nDcmpByte == 0x101) // Huffman tree needs to be modified
+ {
+ n8Bits = is->Get8Bits();
+ pItem1 = (pLast <= 0) ? NULL : pLast;
+
+ pItem2 = Call1500E740(1);
+ pItem2->parent = pItem1;
+ pItem2->dcmpByte = pItem1->dcmpByte;
+ pItem2->byteValue = pItem1->byteValue;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem2 = Call1500E740(1);
+ pItem2->parent = pItem1;
+ pItem2->dcmpByte = n8Bits;
+ pItem2->byteValue = 0;
+ items306C[pItem2->dcmpByte] = pItem2;
+
+ pItem1->child = pItem2;
+ Call1500E820(pItem2);
+ if(bIsCmp0 == 0)
+ Call1500E820(items306C[n8Bits]);
+
+ nDcmpByte = n8Bits;
+ }
+
+ if(nDcmpByte == 0x100)
+ break;
+
+ *pbOutPos++ = (unsigned char)nDcmpByte;
+ if(--dwOutLength == 0)
+ break;
+
+ if(bIsCmp0)
+ Call1500E820(items306C[nDcmpByte]);
+ }
+
+ return (pbOutPos - pbOutBuffer);
+}
+
+/* OLD VERSION
+unsigned int THuffmannTree::DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is)
+{
+ THTreeItem * pItem1; // Current item if walking HTree
+ unsigned long bitCount; // Bit counter if walking HTree
+ unsigned long oneByte; // 8 bits from bit stream/Pointer to target
+ unsigned char * outPtr; // Current pointer to output buffer
+ bool hasQDEntry; // true if entry for quick decompression if filled
+ THTreeItem * itemAt7 = NULL; // HTree item found at 7th bit
+ THTreeItem * temp; // For every use
+ unsigned long dcmpByte = 0; // Decompressed byte value
+ bool bFlag = 0;
+
+ // Test the output length. Must not be NULL.
+ if(dwOutLength == 0)
+ return 0;
+
+ // If too few bits in input bit buffer, we have to load next 16 bits
+ is->EnsureHasMoreThan8Bits();
+
+ // Get 8 bits from input stream
+ oneByte = is->Get8Bits();
+
+ // Build the Huffman tree
+ BuildTree(oneByte);
+
+ bIsCmp0 = (oneByte == 0) ? 1 : 0;
+ outPtr = pbOutBuffer; // Copy pointer to output data
+
+ for(;;)
+ {
+ TQDecompress * qd; // For quick decompress
+ unsigned long sevenBits = is->Get7Bits();// 7 bits from input stream
+
+ // Try to use quick decompression. Check TQDecompress array for corresponding item.
+ // If found, ise the result byte instead.
+ qd = &qd3474[sevenBits];
+
+ // If there is a quick-pass possible
+ hasQDEntry = (qd->offs00 == offs0004) ? 1 : 0;
+
+ // Start passing the Huffman tree. Set item to tree root item
+ pItem1 = pFirst;
+
+ // If we can use quick decompress, use it.
+ bFlag = 1;
+ if(hasQDEntry == 1)
+ {
+ // Check the bit count is greater than 7, move item to 7 levels deeper
+ if((bitCount = qd->bitCount) > 7)
+ {
+ is->dwBitBuff >>= 7;
+ is->nBits -= 7;
+ pItem1 = qd->item; // Don't start with root item, but with some deeper-laying
+ }
+ else
+ {
+ // If OK, use their byte value
+ is->dwBitBuff >>= bitCount;
+ is->nBits -= bitCount;
+ dcmpByte = qd->dcmpByte;
+ bFlag = 0;
+ }
+ }
+ else
+ {
+ pItem1 = pFirst->next->prev;
+ if(PTR_INT(pItem1) <= 0)
+ pItem1 = NULL;
+ }
+
+ if(bFlag == 1)
+ {
+ // Walk through Huffman Tree
+ bitCount = 0; // Clear bit counter
+ do
+ {
+ pItem1 = pItem1->child;
+ if(is->GetBit() != 0) // If current bit is set, move to previous
+ pItem1 = pItem1->prev; // item in current level
+
+ if(++bitCount == 7) // If we are at 7th bit, store current HTree item.
+ itemAt7 = pItem1; // Store Huffman tree item
+ }
+ while(pItem1->child != NULL); // Walk until tree has no deeper level
+
+ // If quick decompress entry is not filled yet, fill it.
+ if(hasQDEntry == 0)
+ {
+ if(bitCount > 7) // If we passed more than 7 bits, store bitCount and item
+ {
+ qd->offs00 = offs0004; // Value indicates that entry is resolved
+ qd->bitCount = bitCount; // Number of bits passed
+ qd->item = itemAt7; // Store item at 7th bit
+ }
+ // If we passed less than 7 bits, fill entry and bit count multipliers
+ else
+ {
+ unsigned long index = sevenBits & (0xFFFFFFFF >> (32 - bitCount)); // Index for quick-decompress entry
+ unsigned long addIndex = (1 << bitCount); // Add value for index
+
+ qd = &qd3474[index];
+
+ do
+ {
+ qd->offs00 = offs0004;
+ qd->bitCount = bitCount;
+ qd->dcmpByte = pItem1->dcmpByte;
+
+ index += addIndex;
+ qd += addIndex;
+ }
+ while(index <= 0x7F);
+ }
+ }
+ dcmpByte = pItem1->dcmpByte;
+ }
+
+ if(dcmpByte == 0x101) // Huffman tree needs to be modified
+ {
+ // Check if there is enough bits in the buffer
+ is->EnsureHasMoreThan8Bits();
+
+ // Get 8 bits from the buffer
+ oneByte = is->Get8Bits();
+
+ // Modify Huffman tree
+ ModifyTree(oneByte);
+
+ // Get lastly added tree item
+ pItem1 = items306C[oneByte];
+
+ if(bIsCmp0 == 0 && pItem1 != NULL)
+ {
+ // 15006F15
+ do
+ {
+ THTreeItem * pItem2 = pItem1;
+ THTreeItem * pItem3;
+ unsigned long byteValue;
+
+ byteValue = ++pItem1->byteValue;
+
+ while(PTR_INT((pItem3 = pItem2->prev)) > 0)
+ {
+ if(pItem3->byteValue >= byteValue)
+ goto _15006F30;
+
+ pItem2 = pItem2->prev;
+ }
+ pItem3 = NULL;
+
+ _15006F30:
+ if(pItem2 == pItem1)
+ continue;
+
+ InsertItem(&pItem305C, pItem2, SWITCH_ITEMS, pItem1);
+ InsertItem(&pItem305C, pItem1, SWITCH_ITEMS, pItem3);
+
+ temp = pItem2->parent->child;
+ if(pItem1 == pItem1->parent->child)
+ pItem1->parent->child = pItem2;
+
+ if(pItem2 == temp)
+ pItem2->parent->child = pItem1;
+
+ // Switch parents of pItem1 and pItem3
+ temp = pItem1->parent;
+ pItem1->parent = pItem2->parent;
+ pItem2->parent = temp;
+ offs0004++;
+ }
+ while(PTR_INT((pItem1 = pItem1->parent)) > 0);
+ }
+ dcmpByte = oneByte;
+ }
+
+ if(dcmpByte != 0x100) // Not at the end of data ?
+ {
+ *outPtr++ = (unsigned char)dcmpByte;
+ if(--dwOutLength > 0)
+ {
+ if(bIsCmp0 != 0)
+ Call1500E820(items306C[pItem1->byteValue]);
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ return (unsigned long)(outPtr - pbOutBuffer);
+}
+*/
+
+// Table for (de)compression. Every compression type has 258 entries
+unsigned char THuffmannTree::Table1502A630[] =
+{
+ // Data for compression type 0x00
+ 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00,
+
+ // Data for compression type 0x01
+ 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
+ 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
+ 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
+ 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
+ 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
+ 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
+ 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
+ 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
+ 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
+ 0x00, 0x00,
+
+ // Data for compression type 0x02
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
+ 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
+ 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
+ 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x03
+ 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
+ 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
+ 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
+ 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
+ 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
+ 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
+ 0x00, 0x00,
+
+ // Data for compression type 0x04
+ 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x05
+ 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
+ 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
+ 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
+ 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x06
+ 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x07
+ 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ // Data for compression type 0x08
+ 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
+ 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
+ 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+};
diff --git a/huffman.h b/huffman.h
--- /dev/null
+++ b/huffman.h
@@ -0,0 +1,133 @@
+/*****************************************************************************/
+/* huffman.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Description : */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* xx.xx.xx 1.00 Lad The first version of huffman.h */
+/* 03.05.03 2.00 Lad Added compression */
+/*****************************************************************************/
+
+#ifndef __HUFFMAN_H__
+#define __HUFFMAN_H__
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define INSERT_ITEM 1
+#define SWITCH_ITEMS 2 // Switch the item1 and item2
+
+#define PTR_NOT(ptr) (THTreeItem *)(~(unsigned long)(ptr))
+#define PTR_PTR(ptr) ((THTreeItem *)(ptr))
+#define PTR_INT(ptr) (long)(ptr)
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+//-----------------------------------------------------------------------------
+// Structures and classes
+
+// Input stream for Huffmann decompression
+class TInputStream
+{
+ public:
+
+ unsigned long GetBit();
+ unsigned long Get7Bits();
+ unsigned long Get8Bits();
+
+ unsigned char * pbInBuffer; // 00 - Input data
+ unsigned long dwBitBuff; // 04 - Input bit buffer
+ unsigned int nBits; // 08 - Number of bits remaining in 'dwValue'
+};
+
+// Output stream for Huffmann compression
+class TOutputStream
+{
+ public:
+
+ void PutBits(unsigned long dwBuff, unsigned int nPutBits);
+
+ unsigned char * pbOutBuffer; // 00 : Output buffer
+ unsigned long dwOutSize; // 04 : Size of output buffer
+ unsigned char * pbOutPos; // 08 : Current output position
+ unsigned long dwBitBuff; // 0C : Bit buffer
+ unsigned long nBits; // 10 : Number of bits in the bit buffer
+};
+
+// Huffmann tree item (?)
+struct THTreeItem
+{
+ public:
+
+ THTreeItem * Call1501DB70(THTreeItem * pLast);
+ THTreeItem * GetPrevItem(long value);
+ void ClearItemLinks();
+ void RemoveItem();
+
+ THTreeItem * next; // 00 - Pointer to next THTreeItem
+ THTreeItem * prev; // 04 - Pointer to prev THTreeItem (< 0 if none)
+ unsigned long dcmpByte; // 08 - Index of this item in item pointer array, decompressed byte value
+ unsigned long byteValue; // 0C - Some byte value
+ THTreeItem * parent; // 10 - Pointer to parent THTreeItem (NULL if none)
+ THTreeItem * child; // 14 - Pointer to child THTreeItem
+};
+
+// Structure used for quick decompress. The 'bitCount' contains number of bits
+// and byte value contains result decompressed byte value.
+// After each walk through Huffman tree are filled all entries which are
+// multiplies of number of bits loaded from input stream. These entries
+// contain number of bits and result value. At the next 7 bits is tested this
+// structure first. If corresponding entry found, decompression routine will
+// not walk through Huffman tree and directly stores output byte to output stream.
+struct TQDecompress
+{
+ unsigned long offs00; // 00 - 1 if resolved
+ unsigned long nBits; // 04 - Bit count
+ union
+ {
+ unsigned long dcmpByte; // 08 - Byte value for decompress (if bitCount <= 7)
+ THTreeItem * pItem; // 08 - THTreeItem (if number of bits is greater than 7
+ };
+};
+
+// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert
+// for the decompression, I do not know actually if the class is really a Hufmann
+// tree. If someone knows the decompression details, please let me know
+class THuffmannTree
+{
+ public:
+
+ void BuildTree(unsigned int nCmpType);
+// void ModifyTree(unsigned long dwIndex);
+// void Call15007010(Bit32 dwInLength, THTreeItem * item);
+ THTreeItem * Call1500E740(unsigned int nValue);
+ void Call1500E820(THTreeItem * pItem);
+ unsigned int DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType);
+ unsigned int DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is);
+
+ unsigned long bIsCmp0; // 0000 - 1 if compression type 0
+ unsigned long offs0004; // 0004 - Some flag
+ THTreeItem items0008[0x203]; // 0008 - HTree items
+
+ //- Sometimes used as HTree item -----------
+ THTreeItem * pItem3050; // 3050 - Always NULL (?)
+ THTreeItem * pItem3054; // 3054 - Pointer to Huffman tree item
+ THTreeItem * pItem3058; // 3058 - Pointer to Huffman tree item (< 0 if invalid)
+
+ //- Sometimes used as HTree item -----------
+ THTreeItem * pItem305C; // 305C - Usually NULL
+ THTreeItem * pFirst; // 3060 - Pointer to top (first) Huffman tree item
+ THTreeItem * pLast; // 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid)
+ unsigned long nItems; // 3068 - Number of used HTree items
+
+ //-------------------------------------------
+ THTreeItem * items306C[0x102]; // 306C - THTreeItem pointer array
+ TQDecompress qd3474[0x80]; // 3474 - Array for quick decompression
+
+ static unsigned char Table1502A630[];// Some table
+};
+
+#endif // __HUFFMAN_H__
diff --git a/implode.c b/implode.c
--- /dev/null
+++ b/implode.c
@@ -0,0 +1,660 @@
+/*****************************************************************************/
+/* implode.c Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Implode function of PKWARE Data Compression library */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.04.03 1.00 Ladislav Zezula First version of implode.c */
+/* 02.05.03 1.00 Ladislav Zezula Stress test done */
+/* 12.06.03 1.00 ShadowFlare Fixed error in WriteCmpData that caused */
+/* different output to be produced */
+/*****************************************************************************/
+
+#include "pklib.h"
+#include "SMem.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define DICT_OFFSET 0x204
+#define UNCMP_OFFSET (pWork->dsize_bytes + DICT_OFFSET)
+
+//-----------------------------------------------------------------------------
+// Local structures
+
+// Compression structure (Size 36312 bytes)
+typedef struct
+{
+ unsigned int offs0000; // 0000 :
+ unsigned int out_bytes; // 0004 : # bytes available in out_buff
+ unsigned int out_bits; // 0008 : # of bits available in the last out byte
+ unsigned int dsize_bits; // 000C : Dict size : 4=0x400, 5=0x800, 6=0x1000
+ unsigned int dsize_mask; // 0010 : Dict size : 0x0F=0x400, 0x1F=0x800, 0x3F=0x1000
+ unsigned int ctype; // 0014 : Compression type (Ascii or binary)
+ unsigned int dsize_bytes; // 0018 : Dictionary size in bytes
+ unsigned char dist_bits[0x40]; // 001C : Distance bits
+ unsigned char dist_codes[0x40]; // 005C : Distance codes
+ unsigned char nChBits[0x306]; // 009C :
+ unsigned short nChCodes[0x306]; // 03A2 :
+ unsigned short offs09AE; // 09AE :
+
+ void * param; // 09B0 : User parameter
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 9B4
+ void (*write_buf)(char *buf, unsigned int *size, void *param); // 9B8
+
+ unsigned short offs09BC[0x204]; // 09BC :
+ unsigned long offs0DC4; // 0DC4 :
+ unsigned short offs0DC8[0x900]; // 0DC8 :
+ unsigned short offs1FC8; // 1FC8 :
+ char out_buff[0x802]; // 1FCA : Output (compressed) data
+ unsigned char work_buff[0x2204]; // 27CC : Work buffer
+ // + DICT_OFFSET => Dictionary
+ // + UNCMP_OFFSET => Uncompressed data
+ unsigned short offs49D0[0x2000]; // 49D0 :
+} TCmpStruct;
+
+//-----------------------------------------------------------------------------
+// Tables
+
+static unsigned char DistBits[] =
+{
+ 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+};
+
+static unsigned char DistCode[] =
+{
+ 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
+ 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
+ 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
+ 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
+};
+
+static unsigned char ExLenBits[] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+};
+
+static unsigned char LenBits[] =
+{
+ 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
+};
+
+static unsigned char LenCode[] =
+{
+ 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
+};
+
+static unsigned char ChBitsAsc[] =
+{
+ 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
+ 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
+ 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
+ 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
+ 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
+ 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
+ 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
+};
+
+static unsigned short ChCodeAsc[] =
+{
+ 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
+ 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
+ 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
+ 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
+ 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
+ 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
+ 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
+ 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
+ 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
+ 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
+ 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
+ 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
+ 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
+ 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
+ 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
+ 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
+ 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
+ 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
+ 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
+ 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
+ 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
+ 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
+ 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
+ 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
+ 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
+ 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
+ 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
+ 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
+ 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
+ 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
+ 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
+ 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
+};
+
+//-----------------------------------------------------------------------------
+// Local variables
+
+static char Copyright[] = "PKWARE Data Compression Library for Win32\r\n"
+ "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
+ "Patent No. 5,051,745\r\n"
+ "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
+ "Version 1.11";
+
+//-----------------------------------------------------------------------------
+// Local functions
+
+static void SortBuffer(TCmpStruct * pWork, unsigned char * uncmp_data, unsigned char * work_end)
+{
+ unsigned short * pin0DC8;
+ unsigned char * puncmp;
+ unsigned long offs1, offs2;
+ unsigned long ndwords;
+ unsigned int add;
+
+ // Fill 0x480 dwords (0x1200 bytes)
+ ndwords = (pWork->out_buff - (char *)pWork->offs0DC8 + 1) >> 2;
+ if(ndwords <= 1)
+ ndwords = 1;
+ SMemZero(pWork->offs0DC8, ndwords << 2);
+
+ for(puncmp = uncmp_data; work_end > puncmp; puncmp++)
+ pWork->offs0DC8[(puncmp[0] * 4) + (puncmp[1] * 5)]++;
+
+ add = 0;
+ for(pin0DC8 = pWork->offs0DC8; pin0DC8 < &pWork->offs1FC8; pin0DC8++)
+ {
+ add += *pin0DC8;
+ *pin0DC8 = (unsigned short)add;
+ }
+
+ for(work_end--; work_end >= uncmp_data; work_end--)
+ {
+ offs1 = (work_end[0] * 4) + (work_end[1] * 5); // EAX
+ offs2 = (work_end - pWork->work_buff); // EDI
+
+ pWork->offs0DC8[offs1]--;
+ pWork->offs49D0[pWork->offs0DC8[offs1]] = (unsigned short)offs2;
+ }
+}
+
+static void FlushBuf(TCmpStruct * pWork)
+{
+ unsigned char save_ch1;
+ unsigned char save_ch2;
+ unsigned int size = 0x800;
+
+ pWork->write_buf(pWork->out_buff, &size, pWork->param);
+
+ save_ch1 = pWork->out_buff[0x800];
+ save_ch2 = pWork->out_buff[pWork->out_bytes];
+ pWork->out_bytes -= 0x800;
+
+ SMemZero(pWork->out_buff, 0x802);
+
+ if(pWork->out_bytes != 0)
+ pWork->out_buff[0] = save_ch1;
+ if(pWork->out_bits != 0)
+ pWork->out_buff[pWork->out_bytes] = save_ch2;
+}
+
+static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
+{
+ unsigned int out_bits;
+
+ // If more than 8 bits to output, do recursion
+ if(nbits > 8)
+ {
+ OutputBits(pWork, 8, bit_buff);
+ bit_buff >>= 8;
+ nbits -= 8;
+ }
+
+ // Add bits to the last out byte in out_buff;
+ out_bits = pWork->out_bits;
+ pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits);
+ pWork->out_bits += nbits;
+
+ // If 8 or more bits, increment number of bytes
+ if(pWork->out_bits > 8)
+ {
+ pWork->out_bytes++;
+ bit_buff >>= (8 - out_bits);
+
+ pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff;
+ pWork->out_bits &= 7;
+ }
+ else
+ {
+ pWork->out_bits &= 7;
+ if(pWork->out_bits == 0)
+ pWork->out_bytes++;
+ }
+
+ // If there is enough compressed bytes, flush them
+ if(pWork->out_bytes >= 0x800)
+ FlushBuf(pWork);
+}
+
+static unsigned long FindRep(TCmpStruct * pWork, unsigned char * srcbuff)
+{
+ unsigned short esp12;
+ unsigned char * esp14;
+ unsigned short esp18;
+ unsigned char * srcbuff2;
+ unsigned char esp20;
+
+ unsigned char * srcbuff3;
+ unsigned short * pin0DC8;
+ unsigned char * pin27CC;
+ unsigned short * pin49D0;
+ unsigned long nreps = 1; // EAX
+ unsigned long ebx, esi;
+ unsigned short di;
+
+ pin0DC8 = pWork->offs0DC8 + (srcbuff[0] * 4) + (srcbuff[1] * 5);
+ esi = (srcbuff - pWork->dsize_bytes) - pWork->work_buff + 1;
+ esp18 = *pin0DC8;
+ pin49D0 = pWork->offs49D0 + esp18;
+
+ if(*pin49D0 < esi)
+ {
+ while(*pin49D0 < esi)
+ {
+ pin49D0++;
+ esp18++;
+ }
+ *pin0DC8 = esp18;
+ }
+//---------------------------------------------------------------------------
+ srcbuff2 = srcbuff - 1;
+ pin49D0 = pWork->offs49D0 + esp18;
+ pin27CC = pWork->work_buff + *pin49D0;
+ if(srcbuff2 <= pin27CC)
+ return 0;
+//---------------------------------------------------------------------------
+ srcbuff3 = srcbuff;
+ for(;;)
+ {
+ if(srcbuff3[nreps-1] == pin27CC[nreps-1] && *srcbuff3 == *pin27CC)
+ {
+ pin27CC++;
+ srcbuff3++;
+ for(ebx = 2; ebx < DICT_OFFSET; ebx++)
+ {
+ pin27CC++;
+ srcbuff3++;
+ if(*pin27CC != *srcbuff3)
+ break;
+ }
+
+ srcbuff3 = srcbuff;
+ if(ebx >= nreps)
+ {
+ pWork->offs0000 = srcbuff3 - pin27CC + ebx - 1;
+ if((nreps = ebx) > 10)
+ break;
+ }
+ }
+
+ pin49D0++;
+ esp18++;
+ pin27CC = pWork->work_buff + *pin49D0;
+
+ if(srcbuff2 > pin27CC)
+ continue;
+
+ return (nreps >= 2) ? nreps : 0;
+ }
+//---------------------------------------------------------------------------
+ if(ebx == DICT_OFFSET)
+ {
+ pWork->offs0000--;
+ return ebx;
+ }
+//---------------------------------------------------------------------------
+ pin49D0 = pWork->offs49D0 + esp18;
+ if(pWork->work_buff + pin49D0[1] >= srcbuff2)
+ return nreps;
+//---------------------------------------------------------------------------
+ di = 0;
+ pWork->offs09BC[0] = 0xFFFF;
+ pWork->offs09BC[1] = di;
+ esp12 = 1;
+
+ do
+ {
+ esi = di;
+ if(srcbuff[esp12] != srcbuff[esi])
+ {
+ di = pWork->offs09BC[esi];
+ if(di != 0xFFFF)
+ continue;
+ }
+ pWork->offs09BC[++esp12] = ++di;
+ }
+ while(esp12 < nreps);
+//---------------------------------------------------------------------------
+ esi = nreps;
+ pin27CC = pWork->work_buff + pin49D0[0] + nreps;
+ esp14 = pin27CC;
+
+ for(;;) // 0040268B
+ {
+ esi = pWork->offs09BC[esi];
+ if(esi == 0xFFFF)
+ esi = 0;
+
+ pin49D0 = pWork->offs49D0 + esp18;
+ do
+ {
+ pin49D0++;
+ esp18++;
+ pin27CC = pWork->work_buff + pin49D0[0];
+ if(pin27CC >= srcbuff2)
+ return nreps;
+ }
+ while(pin27CC + esi < esp14);
+//---------------------------------------------------------------------------
+ esp20 = srcbuff[nreps - 2];
+ if(esp20 == pin27CC[nreps - 2])
+ {
+ if(pin27CC + esi != esp14)
+ {
+ esp14 = pin27CC;
+ esi = 0;
+ }
+ }
+ else
+ {
+ pin49D0 = pWork->offs49D0 + esp18;
+ do
+ {
+ pin49D0++;
+ esp18++;
+ pin27CC = pWork->work_buff + pin49D0[0];
+ if(pin27CC >= srcbuff2)
+ return nreps;
+ }
+ while(pin27CC[nreps - 2] != esp20 || pin27CC[0] != *srcbuff);
+
+ esp14 = pin27CC + 2;
+ esi = 2;
+ }
+//---------------------------------------------------------------------------
+ for(; esp14[0] == srcbuff[esi]; esp14++)
+ {
+ if(++esi >= DICT_OFFSET)
+ break;
+ }
+
+ if(esi < nreps)
+ continue;
+ pWork->offs0000 = srcbuff - pin27CC - 1;
+ if(esi <= nreps)
+ continue;
+ nreps = esi;
+ if(esi == DICT_OFFSET)
+ return nreps;
+
+ do
+ {
+ if(srcbuff[esp12] != srcbuff[di])
+ {
+ di = pWork->offs09BC[di];
+ if(di != 0xFFFF)
+ continue;
+ }
+ pWork->offs09BC[++esp12] = ++di;
+ }
+ while(esp12 < esi);
+ }
+}
+
+static void WriteCmpData(TCmpStruct * pWork)
+{
+ unsigned int nreps = 0; // ESP+10 : Number of repeats
+ unsigned char * uncmp_end; // ESP+14 : End of uncompressed data
+ unsigned int esp18 = 0; // ESP+18 :
+ unsigned int bytes_required; // ESP+1C : Number of bytes required to read
+ unsigned int esp20 = 0; // ESP+20 :
+ unsigned char * uncmp_begin = &pWork->work_buff[UNCMP_OFFSET]; // EDI
+ unsigned long nreps1;
+ unsigned long save_offs0000 = 0;
+ int total_loaded = 0;
+
+ // Store the compression type and dictionary size
+ pWork->out_buff[0] = (char)pWork->ctype;
+ pWork->out_buff[1] = (char)pWork->dsize_bits;
+ pWork->out_bytes = 2;
+
+ // Reset output buffer to zero
+ SMemZero(&pWork->out_buff[2], sizeof(pWork->out_buff) - 2);
+ pWork->out_bits = 0;
+
+ do {
+ total_loaded = 0;
+ bytes_required = 0x1000;
+
+ do {
+ int loaded = pWork->read_buf(&pWork->work_buff[UNCMP_OFFSET + total_loaded], &bytes_required, pWork->param);
+
+ if (loaded == 0) {
+ if (total_loaded == 0 && esp20 == 0) {
+ OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
+
+ if (pWork->out_bits != 0)
+ ++pWork->out_bytes;
+
+ pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
+ return;
+ }
+
+ esp18 = 1;
+ break;
+ }
+
+ total_loaded += loaded;
+ bytes_required -= loaded;
+ } while (bytes_required);
+
+ uncmp_end = &pWork->work_buff[pWork->dsize_bytes + total_loaded];
+
+ if (esp18 != 0)
+ uncmp_end += DICT_OFFSET;
+
+ if (esp20) {
+ if (esp20 == 1) {
+ SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes + DICT_OFFSET, uncmp_end + 1);
+ ++esp20;
+ }
+ else {
+ SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes, uncmp_end + 1);
+ }
+ }
+ else {
+ SortBuffer(pWork, uncmp_begin, uncmp_end + 1);
+ ++esp20;
+
+ if (pWork->dsize_bytes != 0x1000)
+ ++esp20;
+ }
+
+ while (uncmp_end > uncmp_begin) {
+ nreps1 = FindRep(pWork, uncmp_begin);
+
+ while (nreps1) {
+ if (nreps1 == 2 && pWork->offs0000 >= 0x100)
+ break;
+
+ if (esp18 != 0 && uncmp_begin + nreps1 > uncmp_end) {
+ if ((nreps1 = uncmp_end - uncmp_begin) < 2)
+ break;
+
+ if (nreps1 != 2 || pWork->offs0000 < 0x100)
+ goto loc_15036C7F;
+
+ break;
+ }
+
+ if (nreps1 >= 8 || uncmp_begin + 1 >= uncmp_end)
+ goto loc_15036C7F;
+
+ save_offs0000 = pWork->offs0000; // ebp
+ nreps = nreps1;
+ nreps1 = FindRep(pWork, uncmp_begin + 1);
+
+ if (nreps >= nreps1)
+ goto loc_15036C79;
+
+ if (nreps + 1 >= nreps1 && save_offs0000 <= 0x80)
+ goto loc_15036C79;
+
+ OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
+ ++uncmp_begin;
+ }
+
+ OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
+ ++uncmp_begin;
+ continue;
+
+loc_15036C79:
+ nreps1 = nreps;
+ pWork->offs0000 = save_offs0000;
+
+loc_15036C7F:
+ OutputBits(pWork, pWork->nChBits[nreps1 + 0xFE], pWork->nChCodes[nreps1 + 0xFE]);
+
+ if (nreps1 == 2) {
+ OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> 2], pWork->dist_codes[pWork->offs0000 >> 2]);
+ OutputBits(pWork, 2, pWork->offs0000 & 3);
+ }
+ else {
+ OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> pWork->dsize_bits], pWork->dist_codes[pWork->offs0000 >> pWork->dsize_bits]);
+ OutputBits(pWork, pWork->dsize_bits, pWork->offs0000 & pWork->dsize_mask);
+ }
+
+ uncmp_begin += nreps1;
+ }
+
+ if (esp18 != 0) {
+ OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
+
+ if (pWork->out_bits != 0)
+ ++pWork->out_bytes;
+
+ pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
+ return;
+ }
+
+ uncmp_begin -= 0x1000;
+ SMemCopy(pWork->work_buff, &pWork->work_buff[0x1000], UNCMP_OFFSET);
+ } while (esp18 == 0);
+}
+
+//-----------------------------------------------------------------------------
+// Main imploding function
+
+unsigned int PKEXPORT implode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param,
+ unsigned int *type,
+ unsigned int *dsize)
+{
+ TCmpStruct * pWork = (TCmpStruct *)work_buf;
+ unsigned int nChCode;
+ unsigned int nCount;
+ unsigned int i;
+
+ // Fill the work buffer information
+ pWork->read_buf = read_buf;
+ pWork->write_buf = write_buf;
+ pWork->dsize_bytes = *dsize;
+ pWork->ctype = *type;
+ pWork->param = param;
+ pWork->dsize_bits = 4;
+ pWork->dsize_mask = 0x0F;
+
+ // Test dictionary size
+ switch(*dsize)
+ {
+ case 0x1000 :
+ pWork->dsize_bits++;
+ pWork->dsize_mask |= 0x20;
+ // No break here !!!
+
+ case 0x0800 :
+ pWork->dsize_bits++;
+ pWork->dsize_mask |= 0x10;
+ // No break here !!!
+
+ case 0x0400 :
+ break;
+
+ default:
+ return CMP_INVALID_DICTSIZE;
+ }
+
+ // Test the compression type
+ switch(*type)
+ {
+ case CMP_BINARY: // We will compress data with binary compression type
+ for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)
+ {
+ pWork->nChBits[nCount] = 9;
+ pWork->nChCodes[nCount] = (unsigned short)nChCode;
+ nChCode = (nChCode & 0x0000FFFF) + 2;
+ }
+ break;
+
+
+ case CMP_ASCII: // We will compress data with ASCII compression type
+ for(nCount = 0; nCount < 0x100; nCount++)
+ {
+ pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1);
+ pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);
+ }
+ break;
+
+ default:
+ return CMP_INVALID_MODE;
+ }
+
+ for(i = 0; i < 0x10; i++)
+ {
+ int nCount2 = 0; // EBX
+
+ if((1 << ExLenBits[i]) == 0)
+ continue;
+
+ do
+ {
+ pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);
+ pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);
+
+ nCount2++;
+ nCount++;
+ }
+ while((1 << ExLenBits[i]) > nCount2);
+ }
+
+ // Copy the distance codes and distance bits and perform the compression
+ SMemCopy(&pWork->dist_codes, DistCode, sizeof(DistCode));
+ SMemCopy(&pWork->dist_bits, DistBits, sizeof(DistBits));
+ WriteCmpData(pWork);
+ return CMP_NO_ERROR;
+}
diff --git a/license.txt b/license.txt
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,24 @@
+Copyright (c) 2002-2008, ShadowFlare <blakflare@hotmail.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
\ No newline at end of file
diff --git a/pklib.h b/pklib.h
--- /dev/null
+++ b/pklib.h
@@ -0,0 +1,67 @@
+/*****************************************************************************/
+/* pklib.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Header file for PKWARE Data Compression Library */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 31.03.03 1.00 Lad The first version of pkware.h */
+/*****************************************************************************/
+
+#ifndef __PKLIB_H__
+#define __PKLIB_H__
+
+//-----------------------------------------------------------------------------
+// Defines
+
+#define CMP_BUFFER_SIZE 36312 // Size of compression buffer
+#define EXP_BUFFER_SIZE 12596 // Size of decompress buffer
+
+#define CMP_BINARY 0 // Binary compression
+#define CMP_ASCII 1 // Ascii compression
+
+#define CMP_NO_ERROR 0
+#define CMP_INVALID_DICTSIZE 1
+#define CMP_INVALID_MODE 2
+#define CMP_BAD_DATA 3
+#define CMP_ABORT 4
+
+//-----------------------------------------------------------------------------
+// Define calling convention
+
+#define PKEXPORT
+//#define PKEXPORT __cdecl // Use for normal __cdecl calling
+//#define PKEXPORT __stdcall
+//#define PKEXPORT __fastcall
+
+//-----------------------------------------------------------------------------
+// Public functions
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+unsigned int PKEXPORT implode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param,
+ unsigned int *type,
+ unsigned int *dsize);
+
+
+unsigned int PKEXPORT explode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param);
+
+// The original name "crc32" was changed to "crc32pk" due
+// to compatibility with zlib
+unsigned long PKEXPORT crc32pk(char *buffer, unsigned int *size, unsigned long *old_crc);
+
+#ifdef __cplusplus
+ } // End of 'extern "C"' declaration
+#endif
+
+#endif // __PKLIB_H__
diff --git a/wave.cpp b/wave.cpp
--- /dev/null
+++ b/wave.cpp
@@ -0,0 +1,360 @@
+/*****************************************************************************/
+/* wave.cpp Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* This module contains decompression methods used by Storm.dll to decompress*/
+/* WAVe files. Thanks to Tom Amigo for releasing his sources. */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
+/* 20.05.03 2.00 Lad Added compression */
+/*****************************************************************************/
+
+#include "wave.h"
+
+//------------------------------------------------------------------------------
+// Structures
+
+union TByteAndWordPtr
+{
+ unsigned short * pw;
+ unsigned char * pb;
+};
+
+//-----------------------------------------------------------------------------
+// Tables necessary dor decompression
+
+static unsigned long Table1503F120[] =
+{
+ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
+ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
+ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
+ 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
+};
+
+static unsigned long Table1503F1A0[] =
+{
+ 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
+ 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
+ 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
+ 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
+ 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
+ 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
+ 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
+ 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
+ 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
+ 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
+ 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
+ 0x00007FFF
+};
+
+//----------------------------------------------------------------------------
+// CompressWave
+
+int CompressWave(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel)
+{
+ TByteAndWordPtr out; // Output buffer
+ long nArray3[2]; // EBP-48
+ long nArray2[2]; // EBP-40
+ long nArray1[2]; // EBP-38
+ long nWords; // EBP-30
+ unsigned EBP2C; // EBP-2C
+ long nRemains = dwOutLength; // EBP-28 : Number of bytes remaining
+ long nCmpType2; // EBP-24
+ unsigned dwStopBit; // EBP-20
+ long EBP1C; // EBP-1C
+ unsigned dwBitBuff; // EBP-18
+// char * pbOutPos = pbOutBuffer; // EBP-14 : Saved pointer to the output buffer
+ long nLength; // EBP-10 :
+ long nIndex; // EBP-0C :
+// short * pwOutPos = pwInBuffer; // EBP-08 : Current output pointer
+ // EBP-04 :
+ unsigned short wCmp; // EBP-02 :
+ unsigned dwBit; // EBP+08 : A Bit
+ long nTableValue;
+ long nOneWord;
+ long nValue;
+
+ if(dwInLength < 2)
+ return 2;
+
+ // ebx = nChannels;
+ wCmp = (unsigned char)(nCmpLevel - 1);
+ out.pb = pbOutBuffer;
+ *out.pb++ = 0;
+ *out.pb++ = (unsigned char)wCmp;
+
+ if((out.pb - pbOutBuffer + nChannels * 2) > nRemains)
+ return out.pb - pbOutBuffer + nChannels * 2;
+
+ nArray1[0] = nArray1[1] = 0x2C;
+
+ if(nChannels > 0)
+ {
+ for(int i = 0; i < nChannels; i++)
+ {
+ nOneWord = *pwInBuffer++;
+ *out.pw++ = (unsigned short)nOneWord;
+ nArray2[i] = nOneWord;
+ }
+ }
+
+ nLength = dwInLength;
+ if(nLength < 0) // mov eax, dwInLength; cdq; sub eax, edx;
+ nLength++;
+ nLength = (nLength / 2) - (out.pb - pbOutBuffer);
+ nLength = (nLength < 0) ? 0 : nLength;
+ nCmpType2 = nChannels;
+
+ nIndex = nChannels - 1; // edi
+ nWords = dwInLength / 2; // eax
+ if(nWords <= nChannels)
+ return out.pb - pbOutBuffer;
+
+ // ebx - nChannels
+ // ecx - pwOutPos
+ do // 1500F02D
+ {
+ if((out.pb - pbOutBuffer + 2) > nRemains)
+ return out.pb - pbOutBuffer + 2;
+
+ if(nChannels == 2)
+ nIndex = (nIndex == 0) ? 1 : 0;
+
+ nOneWord = *pwInBuffer++; // ecx - nOneWord
+ // esi - nArray2[nIndex]
+ nValue = nOneWord - nArray2[nIndex];
+ if(nValue < 0)
+ nValue = ~nValue + 1; // eax
+
+ unsigned ebx = (nOneWord >= nArray2[nIndex]) ? 1 : 0;
+ // esi - nArray1[nIndex]
+ // edx - Table1503F1A0[nArray1[nIndex]]
+ nArray3[nIndex] = nOneWord;
+
+ // edi - Table1503F1A0[nArray1[nIndex]] >> nCmpLevel
+ ebx = (ebx - 1) & 0x40;
+ dwStopBit = nCmpLevel;
+
+ // edi - nIndex;
+ nTableValue = Table1503F1A0[nArray1[nIndex]];
+ if(nValue < (nTableValue >> nCmpLevel))
+ {
+ if(nArray1[nIndex] != 0)
+ nArray1[nIndex]--;
+ *out.pb++ = 0x80;
+ }
+ else
+ {
+ while(nValue > nTableValue * 2)
+ { // 1500F0C0
+ if(nArray1[nIndex] >= 0x58 || nLength == 0)
+ break;
+
+ nArray1[nIndex] += 8;
+ if(nArray1[nIndex] > 0x58)
+ nArray1[nIndex] = 0x58;
+
+ nTableValue = Table1503F1A0[nArray1[nIndex]];
+ *out.pb++ = 0x81;
+ nLength--;
+ }
+
+ dwBitBuff = 0;
+ EBP2C = nTableValue >> wCmp;
+ unsigned esi = 1 << (dwStopBit - 2);
+ EBP1C = 0;
+ dwBit = 1;
+ dwStopBit = 0x20;
+
+ if(esi <= 0x20)
+ dwStopBit = esi;
+ for(;;)
+ {
+// esi = EBP1C + nTableValue;
+ if((EBP1C + nTableValue) <= nValue)
+ {
+ EBP1C += nTableValue;
+ dwBitBuff |= dwBit;
+ }
+ if(dwBit == dwStopBit)
+ break;
+
+ nTableValue >>= 1;
+ dwBit <<= 1;
+ }
+
+ nValue = nArray2[nIndex];
+ if(ebx != 0)
+ {
+ nValue -= (EBP1C + EBP2C);
+ if(nValue < (int)0xFFFF8000)
+ nValue = (int)0xFFFF8000;
+ }
+ else
+ {
+ nValue += (EBP1C + EBP2C);
+ if(nValue > 0x00007FFF)
+ nValue = 0x00007FFF;
+ }
+
+ nArray2[nIndex] = nValue;
+ *out.pb++ = (unsigned char)(dwBitBuff | ebx);
+ nTableValue = Table1503F120[dwBitBuff & 0x1F];
+ nArray1[nIndex] += nTableValue;
+ if(nArray1[nIndex] < 0)
+ nArray1[nIndex] = 0;
+ else if(nArray1[nIndex] > 0x58)
+ nArray1[nIndex] = 0x58;
+ }
+ // 1500F1D8
+ }
+ while(++nCmpType2 < nWords);
+
+ return out.pb - pbOutBuffer;
+}
+
+//----------------------------------------------------------------------------
+// DecompressWave
+
+// 1500F230
+int DecompressWave(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels)
+{
+ TByteAndWordPtr out;
+ TByteAndWordPtr in;
+ unsigned char * pbInEnd = pbInBuffer + dwInLength; // End on input buffer
+ unsigned long index;
+ long nArray1[2];
+ long nArray2[2];
+
+ out.pb = pbOutBuffer;
+ in.pb = pbInBuffer;
+ nArray1[0] = 0x2C;
+ nArray1[1] = 0x2C;
+ in.pw++;
+
+ // 15007AD7
+ if(nChannels > 0)
+ {
+ for(int count = 0; count < nChannels; count++)
+ {
+ long temp;
+
+ temp = *(short *)in.pw++;
+ nArray2[count] = temp;
+
+ if(dwOutLength < 2)
+ return out.pb - pbOutBuffer;
+
+ *out.pw++ = (unsigned short)temp;
+ dwOutLength -= 2;
+ }
+ }
+
+ index = nChannels - 1;
+ while(in.pb < pbInEnd)
+ {
+ unsigned char oneByte = *in.pb++;
+
+ if(nChannels == 2)
+ index = (index == 0) ? 1 : 0;
+
+ // Get one byte from input buffer
+ // 15007B25
+ if(oneByte & 0x80)
+ {
+ // 15007B32
+ switch(oneByte & 0x7F)
+ {
+ case 0: // 15007B8E
+ if(nArray1[index] != 0)
+ nArray1[index]--;
+
+ if(dwOutLength < 2)
+ break;
+
+ *out.pw++ = (unsigned short)nArray2[index];
+ dwOutLength -= 2;
+ continue;
+
+ case 1: // 15007B72
+ nArray1[index] += 8; // EBX also
+ if(nArray1[index] > 0x58)
+ nArray1[index] = 0x58;
+ if(nChannels == 2)
+ index = (index == 0) ? 1 : 0;
+ continue;
+
+ case 2:
+ continue;
+
+ default:
+ nArray1[index] -= 8;
+ if(nArray1[index] < 0)
+ nArray1[index] = 0;
+
+ if(nChannels != 2)
+ continue;
+
+ index = (index == 0) ? 1 : 0;
+ continue;
+ }
+ }
+ else
+ {
+ unsigned long temp1 = Table1503F1A0[nArray1[index]]; // EDI
+ unsigned long temp2 = temp1 >> pbInBuffer[1]; // ESI
+ long temp3 = nArray2[index]; // ECX
+
+ if(oneByte & 0x01) // EBX = oneByte
+ temp2 += (temp1 >> 0);
+
+ if(oneByte & 0x02)
+ temp2 += (temp1 >> 1);
+
+ if(oneByte & 0x04)
+ temp2 += (temp1 >> 2);
+
+ if(oneByte & 0x08)
+ temp2 += (temp1 >> 3);
+
+ if(oneByte & 0x10)
+ temp2 += (temp1 >> 4);
+
+ if(oneByte & 0x20)
+ temp2 += (temp1 >> 5);
+
+ if(oneByte & 0x40)
+ {
+ temp3 -= temp2;
+ if(temp3 <= (long)0xFFFF8000)
+ temp3 = (long)0xFFFF8000;
+ }
+ else
+ {
+ temp3 += temp2;
+ if(temp3 >= 0x7FFF)
+ temp3 = 0x7FFF;
+ }
+ nArray2[index] = temp3;
+ if(dwOutLength < 2)
+ break;
+
+ temp2 = nArray1[index];
+ oneByte &= 0x1F;
+
+ *out.pw++ = (unsigned short)temp3;
+ dwOutLength -= 2;
+
+ temp2 += Table1503F120[oneByte];
+ nArray1[index] = temp2;
+
+ if(nArray1[index] < 0)
+ nArray1[index] = 0;
+ else if(nArray1[index] > 0x58)
+ nArray1[index] = 0x58;
+ }
+ }
+ return (out.pb - pbOutBuffer);
+}
+
diff --git a/wave.h b/wave.h
--- /dev/null
+++ b/wave.h
@@ -0,0 +1,20 @@
+/*****************************************************************************/
+/* Wave.h Copyright (c) Ladislav Zezula 2003 */
+/*---------------------------------------------------------------------------*/
+/* Header file for WAVe unplode functions */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 31.03.03 1.00 Lad The first version of Wave.h */
+/*****************************************************************************/
+
+#ifndef __WAVE_H__
+#define __WAVE_H__
+
+//-----------------------------------------------------------------------------
+// Functions
+
+int CompressWave (unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel);
+int DecompressWave(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels);
+
+#endif // __WAVE_H__
diff --git a/wintypes.h b/wintypes.h
--- /dev/null
+++ b/wintypes.h
@@ -0,0 +1,38 @@
+// wintypes.h - Windows data types
+// (when not compiling for Windows)
+// License information for this code is in license.txt
+
+#ifndef WIN_TYPES_INCLUDED
+#define WIN_TYPES_INCLUDED
+
+#define WINAPI
+#define CDECL
+#define __fastcall
+
+#define CONST const
+
+typedef void VOID;
+typedef void *LPVOID;
+typedef CONST void *LPCVOID;
+typedef const char *LPCSTR;
+typedef unsigned char BYTE;
+typedef BYTE *LPBYTE;
+typedef unsigned short WORD;
+typedef WORD *LPWORD;
+typedef short SHORT;
+typedef unsigned long DWORD;
+typedef DWORD *LPDWORD;
+typedef long LONG;
+typedef LONG *LPLONG;
+
+typedef int BOOL;
+typedef int (WINAPI *FARPROC)();
+
+#define FALSE 0
+#define TRUE 1
+
+#define ERROR_NOT_ENOUGH_MEMORY 8L
+#define ERROR_INVALID_PARAMETER 87L
+
+#endif
+
diff --git a/zconf.h b/zconf.h
--- /dev/null
+++ b/zconf.h
@@ -0,0 +1,279 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define compress2 z_compress2
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
+# define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+# ifndef STDC
+# define STDC
+# endif
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+# define NEED_DUMMY_RETURN
+#endif
+
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+# ifndef __32BIT__
+# define SMALL_MEDIUM
+# define FAR _far
+# endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+# if defined(_WINDOWS) || defined(WINDOWS)
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR _cdecl _export
+# endif
+# endif
+# if defined (__BORLANDC__)
+# if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+# include <windows.h>
+# define ZEXPORT __declspec(dllexport) WINAPI
+# define ZEXPORTRVA __declspec(dllexport) WINAPIV
+# else
+# if defined (_Windows) && defined (__DLL__)
+# define ZEXPORT _export
+# define ZEXPORTVA _export
+# endif
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# if defined (ZLIB_DLL)
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+#endif
+
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(inflate_blocks,"INBL")
+# pragma map(inflate_blocks_new,"INBLNE")
+# pragma map(inflate_blocks_free,"INBLFR")
+# pragma map(inflate_blocks_reset,"INBLRE")
+# pragma map(inflate_codes_free,"INCOFR")
+# pragma map(inflate_codes,"INCO")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_flush,"INFLU")
+# pragma map(inflate_mask,"INMA")
+# pragma map(inflate_set_dictionary,"INSEDI2")
+# pragma map(inflate_copyright,"INCOPY")
+# pragma map(inflate_trees_bits,"INTRBI")
+# pragma map(inflate_trees_dynamic,"INTRDY")
+# pragma map(inflate_trees_fixed,"INTRFI")
+# pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/zlib.h b/zlib.h
--- /dev/null
+++ b/zlib.h
@@ -0,0 +1,893 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.1.4, March 11th, 2002
+
+ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.4"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ the compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero).
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may some
+ introduce some output latency (reading input without producing any output)
+ except when forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_SYNC_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ If a preset dictionary is needed at this point (see inflateSetDictionary
+ below), inflate sets strm-adler to the adler32 checksum of the
+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
+ it sets strm->adler to the adler32 checksum of all output produced
+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+ an error code as described below. At the end of the stream, inflate()
+ checks that its computed adler32 checksum is equal to that saved by the
+ compressor and returns Z_STREAM_END only if the checksum is correct.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect
+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+ case, the application may then call inflateSync to look for a good
+ compression block.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front.
+
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. If a compressed stream with a larger window size is given as
+ input, inflate() will return with the error code Z_DATA_ERROR instead of
+ trying to allocate a larger window.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+ memLevel). msg is set to null if there is no error message. inflateInit2
+ does not perform any decompression apart from reading the zlib header if
+ present: this will be done by inflate(). (So next_in and avail_in may be
+ modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate
+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler32 value returned by this call of
+ inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h". (See the description
+ of deflateInit2 for more information about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ const voidp buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int err));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
|