summaryrefslogtreecommitdiff
path: root/replay/compression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'replay/compression.cpp')
-rw-r--r--replay/compression.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/replay/compression.cpp b/replay/compression.cpp
new file mode 100644
index 0000000..1acb420
--- /dev/null
+++ b/replay/compression.cpp
@@ -0,0 +1,229 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//=======================================================================================//
+
+#include "compression.h"
+#include "replay/ienginereplay.h"
+#include "replay/replayutils.h"
+#include "convar.h"
+#include "filesystem.h"
+#include "fmtstr.h"
+#include "../utils/bzip2/bzlib.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//----------------------------------------------------------------------------------------
+
+extern IEngineReplay *g_pEngine;
+
+//----------------------------------------------------------------------------------------
+
+const char *g_pCompressorTypes[ NUM_COMPRESSOR_TYPES ] =
+{
+ "lzss",
+ "bz2",
+};
+
+//----------------------------------------------------------------------------------------
+
+class CCompressor_Lzss : public ICompressor
+{
+public:
+ virtual bool Compress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen )
+ {
+ return g_pEngine->LZSS_Compress( pDest, pDestLen, pSource, nSourceLen );
+ }
+
+ virtual bool Decompress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen )
+ {
+ return g_pEngine->LZSS_Decompress( pDest, pDestLen, pSource, nSourceLen );
+ }
+
+ virtual int GetEstimatedCompressionSize( unsigned int nSourceLen )
+ {
+ return nSourceLen;
+ }
+};
+
+//----------------------------------------------------------------------------------------
+
+#define BZ2_DEFAULT_BLOCKSIZE100k 9 // Highest compression rate, but uses the most memory
+#define BZ2_DEFAULT_WORKFACTOR 0 // Default work factor - same as using 30
+
+//----------------------------------------------------------------------------------------
+
+class CCompressor_Bz2 : public ICompressor
+{
+public:
+ CCompressor_Bz2(
+ int nBlockSize100k = BZ2_DEFAULT_BLOCKSIZE100k,
+ int nWorkFactor = BZ2_DEFAULT_WORKFACTOR
+ )
+ : m_nBlockSize100k( nBlockSize100k ),
+ m_nWorkFactor( nWorkFactor )
+ {
+ }
+
+ virtual bool Compress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen )
+ {
+ return BZ_OK == BZ2_bzBuffToBuffCompress(
+ pDest,
+ pDestLen,
+ const_cast< char *>( pSource ),
+ nSourceLen,
+ m_nBlockSize100k,
+ 0, // Silent verbosity
+ m_nWorkFactor
+ );
+ }
+
+ virtual bool Decompress( char *pDest, unsigned int *pDestLen, const char *pSource, unsigned int nSourceLen )
+ {
+ return BZ_OK == BZ2_bzBuffToBuffDecompress(
+ pDest,
+ pDestLen,
+ const_cast< char * >( pSource ),
+ nSourceLen,
+ 0, // Don't use smaller decompressor (half as fast)
+ 0 // Quiet
+ );
+ }
+
+ virtual int GetEstimatedCompressionSize( unsigned int nSourceLen )
+ {
+ return (int)( 1.1f * nSourceLen ) + 600;
+ }
+
+private:
+ int m_nBlockSize100k;
+ int m_nWorkFactor;
+};
+
+//----------------------------------------------------------------------------------------
+
+ICompressor *CreateCompressor( CompressorType_t nType )
+{
+ switch ( nType )
+ {
+ case COMPRESSORTYPE_BZ2: return new CCompressor_Bz2();
+ case COMPRESSORTYPE_LZSS: return new CCompressor_Lzss();
+ }
+
+ return NULL;
+}
+
+const char *GetCompressorNameSafe( CompressorType_t nType )
+{
+ if ( nType < 0 || nType >= NUM_COMPRESSOR_TYPES )
+ return "Unknown compressor type";
+
+ return g_pCompressorTypes[ nType ];
+}
+
+//----------------------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+CON_COMMAND( replay_testcompress, "Test compression" )
+{
+ if ( args.ArgC() < 3 )
+ {
+ Warning( "replay_testcompress <lzss|bz2> <file to compress>" );
+ return;
+ }
+
+ const char *pInFilename = args[ 2 ];
+ const char *pCompressionTypeName = args[ 1 ];
+
+ CompressorType_t nCompressorType = COMPRESSORTYPE_INVALID;
+
+ for ( int i = 0; i < (int)NUM_COMPRESSOR_TYPES; ++i )
+ {
+ if ( !V_stricmp( pCompressionTypeName, g_pCompressorTypes[ i ] ) )
+ {
+ nCompressorType = (CompressorType_t)i;
+ break;
+ }
+ }
+
+ if ( nCompressorType == COMPRESSORTYPE_INVALID )
+ {
+ Warning( "Invalid compression type specified. Use \"bz2\" or \"lzss\"\n" );
+ return;
+ }
+
+ const unsigned int nInFileSize = g_pFullFileSystem->Size( pInFilename );
+ if ( !nInFileSize )
+ {
+ Warning( "Zero length file.\n" );
+ return;
+ }
+
+ FileHandle_t hInFile = g_pFullFileSystem->Open( pInFilename, "rb" );
+ if ( !hInFile )
+ {
+ Warning( "Failed to open file, %s\n", pInFilename );
+ return;
+ }
+
+ char *pUncompressed = new char[ nInFileSize ];
+ if ( !pUncompressed )
+ {
+ Warning( "Failed to alloc %u bytes\n", nInFileSize );
+ return;
+ }
+
+ if ( g_pFullFileSystem->Read( pUncompressed, nInFileSize, hInFile ) != (int)nInFileSize )
+ {
+ Warning( "Failed to read file %s\n", pInFilename );
+ }
+ else
+ {
+ ICompressor *pCompressor = CreateCompressor( nCompressorType );
+ unsigned int nCompressedSize = pCompressor->GetEstimatedCompressionSize( nInFileSize );
+ char *pCompressed = new char[ nCompressedSize ];
+ if ( !pCompressed )
+ {
+ Warning( "Failed to allocate %u bytes for compressed buffer.\n", nCompressedSize );
+ return;
+ }
+
+ // Compress
+ if ( !pCompressor->Compress( pCompressed, &nCompressedSize, pUncompressed, nInFileSize ) )
+ {
+ Warning( "Compression failed.\n" );
+ }
+ else
+ {
+ CFmtStr fmtOutFilename( "%s.%s", pInFilename, pCompressionTypeName );
+ FileHandle_t hOutFile = g_pFullFileSystem->Open( fmtOutFilename.Access(), "wb+" );
+ if ( !hOutFile )
+ {
+ Warning( "Failed to open out file, %s\n", fmtOutFilename.Access() );
+ }
+ else
+ {
+ if ( g_pFullFileSystem->Write( pCompressed, nCompressedSize, hOutFile ) != (int)nCompressedSize )
+ {
+ Warning( "Failed to write compressed data to %s\n", fmtOutFilename.Access() );
+ }
+ else
+ {
+ const float flRatio = (float)nInFileSize / nCompressedSize;
+ Warning( "Wrote compressed file to successfully (%s) - ratio: %.2f:1\n", fmtOutFilename.Access(), flRatio );
+ }
+
+ g_pFullFileSystem->Close( hOutFile );
+ }
+ }
+
+ delete [] pCompressed;
+ }
+
+ g_pFullFileSystem->Close( hInFile );
+}
+
+#endif // _DEBUG
+
+//---------------------------------------------------------------------------------------- \ No newline at end of file