123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- idCVar idDemoFile::com_logDemos( "com_logDemos", "0", CVAR_SYSTEM | CVAR_BOOL, "Write demo.log with debug information in it" );
- idCVar idDemoFile::com_compressDemos( "com_compressDemos", "1", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE, "Compression scheme for demo files\n0: None (Fast, large files)\n1: LZW (Fast to compress, Fast to decompress, medium/small files)\n2: LZSS (Slow to compress, Fast to decompress, small files)\n3: Huffman (Fast to compress, Slow to decompress, medium files)\nSee also: The 'CompressDemo' command" );
- idCVar idDemoFile::com_preloadDemos( "com_preloadDemos", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_ARCHIVE, "Load the whole demo in to RAM before running it" );
- #define DEMO_MAGIC GAME_NAME " RDEMO"
- /*
- ================
- idDemoFile::idDemoFile
- ================
- */
- idDemoFile::idDemoFile() {
- f = NULL;
- fLog = NULL;
- log = false;
- fileImage = NULL;
- compressor = NULL;
- writing = false;
- }
- /*
- ================
- idDemoFile::~idDemoFile
- ================
- */
- idDemoFile::~idDemoFile() {
- Close();
- }
- /*
- ================
- idDemoFile::AllocCompressor
- ================
- */
- idCompressor *idDemoFile::AllocCompressor( int type ) {
- switch ( type ) {
- case 0: return idCompressor::AllocNoCompression();
- default:
- case 1: return idCompressor::AllocLZW();
- case 2: return idCompressor::AllocLZSS();
- case 3: return idCompressor::AllocHuffman();
- }
- }
- /*
- ================
- idDemoFile::OpenForReading
- ================
- */
- bool idDemoFile::OpenForReading( const char *fileName ) {
- static const int magicLen = sizeof(DEMO_MAGIC) / sizeof(DEMO_MAGIC[0]);
- char magicBuffer[magicLen];
- int compression;
- int fileLength;
- Close();
- f = fileSystem->OpenFileRead( fileName );
- if ( !f ) {
- return false;
- }
- fileLength = f->Length();
- if ( com_preloadDemos.GetBool() ) {
- fileImage = (byte *)Mem_Alloc( fileLength, TAG_CRAP );
- f->Read( fileImage, fileLength );
- fileSystem->CloseFile( f );
- f = new (TAG_SYSTEM) idFile_Memory( va( "preloaded(%s)", fileName ), (const char *)fileImage, fileLength );
- }
- if ( com_logDemos.GetBool() ) {
- fLog = fileSystem->OpenFileWrite( "demoread.log" );
- }
- writing = false;
- f->Read(magicBuffer, magicLen);
- if ( memcmp(magicBuffer, DEMO_MAGIC, magicLen) == 0 ) {
- f->ReadInt( compression );
- } else {
- // Ideally we would error out if the magic string isn't there,
- // but for backwards compatibility we are going to assume it's just an uncompressed demo file
- compression = 0;
- f->Rewind();
- }
- compressor = AllocCompressor( compression );
- compressor->Init( f, false, 8 );
- return true;
- }
- /*
- ================
- idDemoFile::SetLog
- ================
- */
- void idDemoFile::SetLog(bool b, const char *p) {
- log = b;
- if (p) {
- logStr = p;
- }
- }
- /*
- ================
- idDemoFile::Log
- ================
- */
- void idDemoFile::Log(const char *p) {
- if ( fLog && p && *p ) {
- fLog->Write( p, strlen(p) );
- }
- }
- /*
- ================
- idDemoFile::OpenForWriting
- ================
- */
- bool idDemoFile::OpenForWriting( const char *fileName ) {
- Close();
- f = fileSystem->OpenFileWrite( fileName );
- if ( f == NULL ) {
- return false;
- }
- if ( com_logDemos.GetBool() ) {
- fLog = fileSystem->OpenFileWrite( "demowrite.log" );
- }
- writing = true;
- f->Write(DEMO_MAGIC, sizeof(DEMO_MAGIC));
- f->WriteInt( com_compressDemos.GetInteger() );
- f->Flush();
- compressor = AllocCompressor( com_compressDemos.GetInteger() );
- compressor->Init( f, true, 8 );
- return true;
- }
- /*
- ================
- idDemoFile::Close
- ================
- */
- void idDemoFile::Close() {
- if ( writing && compressor ) {
- compressor->FinishCompress();
- }
- if ( f ) {
- fileSystem->CloseFile( f );
- f = NULL;
- }
- if ( fLog ) {
- fileSystem->CloseFile( fLog );
- fLog = NULL;
- }
- if ( fileImage ) {
- Mem_Free( fileImage );
- fileImage = NULL;
- }
- if ( compressor ) {
- delete compressor;
- compressor = NULL;
- }
- demoStrings.DeleteContents( true );
- }
- /*
- ================
- idDemoFile::ReadHashString
- ================
- */
- const char *idDemoFile::ReadHashString() {
- int index;
- if ( log && fLog ) {
- const char *text = va( "%s > Reading hash string\n", logStr.c_str() );
- fLog->Write( text, strlen( text ) );
- }
- ReadInt( index );
- if ( index == -1 ) {
- // read a new string for the table
- idStr *str = new (TAG_SYSTEM) idStr;
-
- idStr data;
- ReadString( data );
- *str = data;
-
- demoStrings.Append( str );
- return *str;
- }
- if ( index < -1 || index >= demoStrings.Num() ) {
- Close();
- common->Error( "demo hash index out of range" );
- }
- return demoStrings[index]->c_str();
- }
- /*
- ================
- idDemoFile::WriteHashString
- ================
- */
- void idDemoFile::WriteHashString( const char *str ) {
- if ( log && fLog ) {
- const char *text = va( "%s > Writing hash string\n", logStr.c_str() );
- fLog->Write( text, strlen( text ) );
- }
- // see if it is already in the has table
- for ( int i = 0 ; i < demoStrings.Num() ; i++ ) {
- if ( !strcmp( demoStrings[i]->c_str(), str ) ) {
- WriteInt( i );
- return;
- }
- }
- // add it to our table and the demo table
- idStr *copy = new (TAG_SYSTEM) idStr( str );
- //common->Printf( "hash:%i = %s\n", demoStrings.Num(), str );
- demoStrings.Append( copy );
- int cmd = -1;
- WriteInt( cmd );
- WriteString( str );
- }
- /*
- ================
- idDemoFile::ReadDict
- ================
- */
- void idDemoFile::ReadDict( idDict &dict ) {
- int i, c;
- idStr key, val;
- dict.Clear();
- ReadInt( c );
- for ( i = 0; i < c; i++ ) {
- key = ReadHashString();
- val = ReadHashString();
- dict.Set( key, val );
- }
- }
- /*
- ================
- idDemoFile::WriteDict
- ================
- */
- void idDemoFile::WriteDict( const idDict &dict ) {
- int i, c;
- c = dict.GetNumKeyVals();
- WriteInt( c );
- for ( i = 0; i < c; i++ ) {
- WriteHashString( dict.GetKeyVal( i )->GetKey() );
- WriteHashString( dict.GetKeyVal( i )->GetValue() );
- }
- }
- /*
- ================
- idDemoFile::Read
- ================
- */
- int idDemoFile::Read( void *buffer, int len ) {
- int read = compressor->Read( buffer, len );
- if ( read == 0 && len >= 4 ) {
- *(demoSystem_t *)buffer = DS_FINISHED;
- }
- return read;
- }
- /*
- ================
- idDemoFile::Write
- ================
- */
- int idDemoFile::Write( const void *buffer, int len ) {
- return compressor->Write( buffer, len );
- }
|