mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2024-12-23 01:59:43 +08:00
157 lines
4.0 KiB
C
157 lines
4.0 KiB
C
// JCalg ultra small, ultra fast compression / decompression lib.
|
|
// Documentation available here: http://bitsum.com/jcalg1.htm
|
|
//
|
|
// Licence claims to be "This library may be used freely in any and for any application."
|
|
//
|
|
#ifndef __JCALG1_H__
|
|
#define __JCALG1_H__
|
|
|
|
typedef bool (__stdcall *PFNCALLBACKFUNC)(DWORD, DWORD);
|
|
typedef void * (__stdcall *PFNALLOCFUNC)(DWORD);
|
|
typedef bool (__stdcall *PFNDEALLOCFUNC)(void *);
|
|
|
|
struct _JCALG1_Info
|
|
{
|
|
DWORD majorVer;
|
|
DWORD minorVer;
|
|
DWORD nFastSize;
|
|
DWORD nSmallSize;
|
|
};
|
|
|
|
|
|
extern "C" DWORD _stdcall JCALG1_Compress(
|
|
const void *Source,
|
|
DWORD Length,
|
|
void *Destination,
|
|
DWORD WindowSize,
|
|
PFNALLOCFUNC,
|
|
PFNDEALLOCFUNC,
|
|
PFNCALLBACKFUNC,
|
|
BOOL bDisableChecksum);
|
|
|
|
extern "C" DWORD _stdcall JCALG1_Decompress_Fast(
|
|
const void *Source,
|
|
void *Destination);
|
|
|
|
extern "C" DWORD _stdcall JCALG1_Decompress_Small(
|
|
const void *Source,
|
|
void *Destination);
|
|
|
|
extern "C" DWORD _stdcall JCALG1_GetNeededBufferSize(
|
|
DWORD nSize);
|
|
|
|
extern "C" DWORD _stdcall JCALG1_GetInfo(
|
|
_JCALG1_Info *JCALG1_Info);
|
|
|
|
extern "C" DWORD _stdcall JCALG1_GetUncompressedSizeOfCompressedBlock(
|
|
const void *pBlock);
|
|
|
|
extern "C" DWORD _stdcall JCALG1_GetNeededBufferSize(
|
|
DWORD nSize);
|
|
|
|
|
|
|
|
#pragma pack(1)
|
|
struct xCompressHeader
|
|
{
|
|
enum
|
|
{
|
|
MAGIC = 'xCmp',
|
|
VERSION = 1,
|
|
|
|
};
|
|
|
|
unsigned nMagic; // = MAGIC;
|
|
unsigned nVersion; // = VERSION;
|
|
unsigned nUncompressedFileSize; // Size of the decompressed file.
|
|
unsigned nReadBlockSize; // Block size this file was optimized for reading.
|
|
unsigned nDecompressionBufferSize; // Minimum decompression buffer size needed to safely decompress this file.
|
|
unsigned nWindowSize;
|
|
};
|
|
|
|
// The 'simple' xCompress header for compressing small blobs of memory.
|
|
// Doesn't deal with alignment, block read size optimization or window size. Just decompresses the whole thing.
|
|
struct xCompressSimpleHeader
|
|
{
|
|
enum
|
|
{
|
|
MAGIC = 'xSmp',
|
|
};
|
|
|
|
unsigned nMagic; // = MAGIC
|
|
unsigned nUncompressedSize; // Size of the decompressed memory.
|
|
};
|
|
|
|
// NJS: Jcalg helper functions:
|
|
// Decompress a chunk of a buffer compressed via xCompress.
|
|
// What you want to do here is read a 2 meg chunk from the file and pass it to this function with an nMaxOutput that is at least 4x nInputLength
|
|
// the return value will be the number of bytes decompressed into the output buffer, or 0xFFFFFFFF if the output buffer overflowed.
|
|
inline unsigned JCALG1_Decompress_Formatted_Buffer( unsigned nInputLength, void* pInput, unsigned nMaxOutput, void* pOutput )
|
|
{
|
|
unsigned outputBufferLength = 0;
|
|
for( char* pInputPointer = (char*)pInput; pInputPointer < (char*)pInput+nInputLength; )
|
|
{
|
|
// Get the size of the next chunk:
|
|
unsigned short bytesThisBlock = *(unsigned short*)pInputPointer;
|
|
|
|
// A zero sized byte block indicates I've hit the end of the buffer:
|
|
if( !bytesThisBlock )
|
|
break;
|
|
|
|
pInputPointer += sizeof(unsigned short);
|
|
|
|
// Is this block compressed?
|
|
if( bytesThisBlock & 0x8000 )
|
|
{
|
|
bytesThisBlock &= ~0x8000;
|
|
|
|
// No it isn't just copy it:
|
|
memcpy((char*)pOutput + outputBufferLength, pInputPointer, bytesThisBlock );
|
|
|
|
outputBufferLength += bytesThisBlock;
|
|
pInputPointer += bytesThisBlock;
|
|
}
|
|
else
|
|
{
|
|
unsigned bytesDecompressed = JCALG1_Decompress_Fast( pInputPointer, (char*)pOutput + outputBufferLength);
|
|
|
|
outputBufferLength += bytesDecompressed;
|
|
pInputPointer += bytesThisBlock;
|
|
}
|
|
|
|
if( outputBufferLength > nMaxOutput )
|
|
{
|
|
return 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
return outputBufferLength;
|
|
}
|
|
|
|
// Decompress a 'simple' jcalg buffer.
|
|
inline unsigned JCALG1_Decompress_Simple_Buffer( void* pInput, void* pOutput )
|
|
{
|
|
if( !pInput || !pOutput )
|
|
return 0;
|
|
|
|
xCompressSimpleHeader* header = (xCompressSimpleHeader*)pInput;
|
|
|
|
if( header->nMagic != xCompressSimpleHeader::MAGIC )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return JCALG1_Decompress_Fast( (char*)pInput+sizeof(xCompressSimpleHeader), pOutput );
|
|
}
|
|
|
|
#pragma pack()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|