📄 scompression.cpp.svn-base
字号:
/*****************************************************************************/
/* SCompression.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* This module serves as a bridge between StormLib code and (de)compression */
/* functions. All (de)compression calls go (and should only go) through this */
/* module. No system headers should be included in this module to prevent */
/* compile-time problems. */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 01.04.03 1.00 Lad The first version of SCompression.cpp */
/* 19.11.03 1.01 Dan Big endian handling */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
#include <string.h>
// Include functions from Pkware Data Compression Library
#include "pklib/pklib.h"
// Include functions from zlib
#ifndef __SYS_ZLIB
#include "zlib/zlib.h" // Include functions from zlib
#else
#include <zlib.h> // If zlib is available on system, use this instead
#endif
// Include functions from Huffmann compression
#include "huffman/huff.h"
// Include functions from WAVe compression
#include "wave/wave.h"
// Include functions from BZip2 compression library
#ifndef __SYS_BZLIB
#include "bzip2/bzlib.h" // Include functions from bzlib
#else
#include <bzlib.h> // If bzlib is available on system, use this instead
#endif
//-----------------------------------------------------------------------------
// Local structures
// Information about the input and output buffers for pklib
typedef struct
{
char * pInBuff; // Pointer to input data buffer
int nInPos; // Current offset in input data buffer
int nInBytes; // Number of bytes in the input buffer
char * pOutBuff; // Pointer to output data buffer
int nOutPos; // Position in the output buffer
int nMaxOut; // Maximum number of bytes in the output buffer
} TDataInfo;
// Table of compression functions
typedef int (*COMPRESS)(char *, int *, char *, int, int *, int);
typedef struct
{
unsigned long dwMask; // Compression mask
COMPRESS Compress; // Compression function
} TCompressTable;
// Table of decompression functions
typedef int (*DECOMPRESS)(char *, int *, char *, int);
typedef struct
{
unsigned long dwMask; // Decompression bit
DECOMPRESS Decompress; // Decompression function
} TDecompressTable;
/*****************************************************************************/
/* */
/* Support functions for Pkware Data Compression Library */
/* */
/*****************************************************************************/
// Function loads data from the input buffer. Used by Pklib's "implode"
// and "explode" function as user-defined callback
// Returns number of bytes loaded
//
// char * buf - Pointer to a buffer where to store loaded data
// unsigned int * size - Max. number of bytes to read
// void * param - Custom pointer, parameter of implode/explode
static unsigned int ReadInputData(char * buf, unsigned int * size, void * param)
{
TDataInfo * pInfo = (TDataInfo *)param;
unsigned int nMaxAvail = (pInfo->nInBytes - pInfo->nInPos);
unsigned int nToRead = *size;
// Check the case when not enough data available
if(nToRead > nMaxAvail)
nToRead = nMaxAvail;
// Load data and increment offsets
memcpy(buf, pInfo->pInBuff + pInfo->nInPos, nToRead);
pInfo->nInPos += nToRead;
return nToRead;
}
// Function for store output data. Used by Pklib's "implode" and "explode"
// as user-defined callback
//
// char * buf - Pointer to data to be written
// unsigned int * size - Number of bytes to write
// void * param - Custom pointer, parameter of implode/explode
static void WriteOutputData(char * buf, unsigned int * size, void * param)
{
TDataInfo * pInfo = (TDataInfo *)param;
unsigned int nMaxWrite = (pInfo->nMaxOut - pInfo->nOutPos);
unsigned int nToWrite = *size;
// Check the case when not enough space in the output buffer
if(nToWrite > nMaxWrite)
nToWrite = nMaxWrite;
// Write output data and increments offsets
memcpy(pInfo->pOutBuff + pInfo->nOutPos, buf, nToWrite);
pInfo->nOutPos += nToWrite;
}
/*****************************************************************************/
/* */
/* "80" is IMA ADPCM stereo (de)compression */
/* "40" is IMA ADPCM mono (de)compression */
/* */
/*****************************************************************************/
int Compress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
{
// Prepare the compression level for the next compression
// (After us, the Huffmann compression will be called)
if(0 < nCmpLevel && nCmpLevel <= 2)
{
nCmpLevel = 4;
*pCmpType = 6;
}
else if(nCmpLevel == 3)
{
nCmpLevel = 6;
*pCmpType = 8;
}
else
{
nCmpLevel = 5;
*pCmpType = 7;
}
*pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 1, nCmpLevel);
return 0;
}
int Decompress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
*pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 1);
return 1;
}
int Compress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
{
// Prepare the compression type for the next compression
// (After us, the Huffmann compression will be called)
if(0 < nCmpLevel && nCmpLevel <= 2)
{
nCmpLevel = 4;
*pCmpType = 6;
}
else if(nCmpLevel == 3)
{
nCmpLevel = 6;
*pCmpType = 8;
}
else
{
nCmpLevel = 5;
*pCmpType = 7;
}
*pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 2, nCmpLevel);
return 0;
}
int Decompress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
*pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 2);
return 1;
}
/*****************************************************************************/
/* */
/* The "01" (de)compression is the Huffman (de)compression */
/* */
/*****************************************************************************/
// 1500F4C0
int Compress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
{
THuffmannTree ht; // Huffmann tree for compression
TOutputStream os; // Output stream
// Initialize output stream
os.pbOutBuffer = (unsigned char *)pbOutBuffer;
os.dwOutSize = *pdwOutLength;
os.pbOutPos = (unsigned char *)pbOutBuffer;
os.dwBitBuff = 0;
os.nBits = 0;
// Initialize the Huffmann tree for compression
ht.InitTree(true);
*pdwOutLength = ht.DoCompression(&os, (unsigned char *)pbInBuffer, dwInLength, *pCmpType);
// 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 ?
// ht.UninitTree();
return 0;
}
// 1500F5F0
int Decompress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int /* dwInLength */)
{
THuffmannTree ht;
TInputStream is;
// Initialize input stream
// is.pbInBuffer = (unsigned char *)pbInBuffer;
is.dwBitBuff = BSWAP_INT32_UNSIGNED(*(unsigned long *)pbInBuffer);
pbInBuffer += sizeof(unsigned long);
is.pbInBuffer = (unsigned char *)pbInBuffer;
is.nBits = 32;
// Initialize the Huffmann tree for compression
ht.InitTree(false);
*pdwOutLength = ht.DoDecompression((unsigned char *)pbOutBuffer, *pdwOutLength, &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 ?
// ht.UninitTree();
return 0;
}
/*****************************************************************************/
/* */
/* The "02" (de)compression is the ZLIB (de)compression */
/* */
/*****************************************************************************/
int Compress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * /* pCmpType */, int /* nCmpLevel */)
{
z_stream z; // Stream information for zlib
int nResult;
// Fill the stream structure for zlib
z.next_in = (Bytef *)pbInBuffer;
z.avail_in = (uInt)dwInLength;
z.total_in = dwInLength;
z.next_out = (Bytef *)pbOutBuffer;
z.avail_out = *pdwOutLength;
z.total_out = 0;
z.zalloc = NULL;
z.zfree = NULL;
// Initialize the compression structure. Storm.dll uses zlib version 1.1.3
*pdwOutLength = 0;
if((nResult = deflateInit(&z, Z_DEFAULT_COMPRESSION)) == 0)
{
// Call zlib to compress the data
nResult = deflate(&z, Z_FINISH);
if(nResult == Z_OK || nResult == Z_STREAM_END)
*pdwOutLength = z.total_out;
deflateEnd(&z);
}
return nResult;
}
int Decompress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
z_stream z; // Stream information for zlib
int nResult;
// Fill the stream structure for zlib
z.next_in = (Bytef *)pbInBuffer;
z.avail_in = (uInt)dwInLength;
z.total_in = dwInLength;
z.next_out = (Bytef *)pbOutBuffer;
z.avail_out = *pdwOutLength;
z.total_out = 0;
z.zalloc = NULL;
z.zfree = NULL;
// Initialize the decompression structure. Storm.dll uses zlib version 1.1.3
if((nResult = inflateInit(&z)) == 0)
{
// Call zlib to decompress the data
nResult = inflate(&z, Z_FINISH);
*pdwOutLength = z.total_out;
inflateEnd(&z);
}
return nResult;
}
/*****************************************************************************/
/* */
/* The "08" (de)compression is the Pkware DCL (de)compression */
/* */
/*****************************************************************************/
int Compress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
{
TDataInfo Info; // Data information
char * work_buf = ALLOCMEM(char, CMP_BUFFER_SIZE);// Pklib's work buffer
unsigned int dict_size; // Dictionary size
unsigned int ctype; // Compression type
// Fill data information structure
Info.pInBuff = pbInBuffer;
Info.nInPos = 0;
Info.nInBytes = dwInLength;
Info.pOutBuff = pbOutBuffer;
Info.nOutPos = 0;
Info.nMaxOut = *pdwOutLength;
// Set the compression type and dictionary size
ctype = (*pCmpType == 2) ? CMP_ASCII : CMP_BINARY;
if (dwInLength < 0x600)
dict_size = 0x400;
else if(0x600 <= dwInLength && dwInLength < 0xC00)
dict_size = 0x800;
else
dict_size = 0x1000;
// Do the compression
implode(ReadInputData, WriteOutputData, work_buf, &Info, &ctype, &dict_size);
*pdwOutLength = Info.nOutPos;
FREEMEM(work_buf);
return 0;
}
int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
TDataInfo Info; // Data information
char * work_buf = ALLOCMEM(char, EXP_BUFFER_SIZE);// Pklib's work buffer
// Fill data information structure
Info.pInBuff = pbInBuffer;
Info.nInPos = 0;
Info.nInBytes = dwInLength;
Info.pOutBuff = pbOutBuffer;
Info.nOutPos = 0;
Info.nMaxOut = *pdwOutLength;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -