2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# 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 \n 0: None (Fast, large files) \n 1: LZW (Fast to compress, Fast to decompress, medium/small files) \n 2: LZSS (Slow to compress, Fast to decompress, small files) \n 3: Huffman (Fast to compress, Slow to decompress, medium files) \n See 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
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDemoFile : : idDemoFile ( )
{
2012-11-26 18:58:24 +00:00
f = NULL ;
fLog = NULL ;
log = false ;
fileImage = NULL ;
compressor = NULL ;
writing = false ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : ~ idDemoFile
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDemoFile : : ~ idDemoFile ( )
{
2012-11-26 18:58:24 +00:00
Close ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : AllocCompressor
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
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 ( ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : OpenForReading
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDemoFile : : OpenForReading ( const char * fileName )
{
static const int magicLen = sizeof ( DEMO_MAGIC ) / sizeof ( DEMO_MAGIC [ 0 ] ) ;
2012-11-26 18:58:24 +00:00
char magicBuffer [ magicLen ] ;
int compression ;
int fileLength ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Close ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
f = fileSystem - > OpenFileRead ( fileName ) ;
2012-11-28 15:47:07 +00:00
if ( ! f )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fileLength = f - > Length ( ) ;
2012-11-28 15:47:07 +00:00
if ( com_preloadDemos . GetBool ( ) )
{
fileImage = ( byte * ) Mem_Alloc ( fileLength , TAG_CRAP ) ;
2012-11-26 18:58:24 +00:00
f - > Read ( fileImage , fileLength ) ;
fileSystem - > CloseFile ( f ) ;
2012-11-28 15:47:07 +00:00
f = new ( TAG_SYSTEM ) idFile_Memory ( va ( " preloaded(%s) " , fileName ) , ( const char * ) fileImage , fileLength ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( com_logDemos . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
fLog = fileSystem - > OpenFileWrite ( " demoread.log " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
writing = false ;
2012-11-28 15:47:07 +00:00
f - > Read ( magicBuffer , magicLen ) ;
if ( memcmp ( magicBuffer , DEMO_MAGIC , magicLen ) = = 0 )
{
2012-11-26 18:58:24 +00:00
f - > ReadInt ( compression ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// 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 ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
compressor = AllocCompressor ( compression ) ;
compressor - > Init ( f , false , 8 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : SetLog
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDemoFile : : SetLog ( bool b , const char * p )
{
2012-11-26 18:58:24 +00:00
log = b ;
2012-11-28 15:47:07 +00:00
if ( p )
{
2012-11-26 18:58:24 +00:00
logStr = p ;
}
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : Log
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDemoFile : : Log ( const char * p )
{
if ( fLog & & p & & * p )
{
fLog - > Write ( p , strlen ( p ) ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : OpenForWriting
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDemoFile : : OpenForWriting ( const char * fileName )
{
2012-11-26 18:58:24 +00:00
Close ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
f = fileSystem - > OpenFileWrite ( fileName ) ;
2012-11-28 15:47:07 +00:00
if ( f = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( com_logDemos . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
fLog = fileSystem - > OpenFileWrite ( " demowrite.log " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
writing = true ;
2012-11-28 15:47:07 +00:00
f - > Write ( DEMO_MAGIC , sizeof ( DEMO_MAGIC ) ) ;
2012-11-26 18:58:24 +00:00
f - > WriteInt ( com_compressDemos . GetInteger ( ) ) ;
f - > Flush ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
compressor = AllocCompressor ( com_compressDemos . GetInteger ( ) ) ;
compressor - > Init ( f , true , 8 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : Close
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDemoFile : : Close ( )
{
if ( writing & & compressor )
{
2012-11-26 18:58:24 +00:00
compressor - > FinishCompress ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( f )
{
2012-11-26 18:58:24 +00:00
fileSystem - > CloseFile ( f ) ;
f = NULL ;
}
2012-11-28 15:47:07 +00:00
if ( fLog )
{
2012-11-26 18:58:24 +00:00
fileSystem - > CloseFile ( fLog ) ;
fLog = NULL ;
}
2012-11-28 15:47:07 +00:00
if ( fileImage )
{
2012-11-26 18:58:24 +00:00
Mem_Free ( fileImage ) ;
fileImage = NULL ;
}
2012-11-28 15:47:07 +00:00
if ( compressor )
{
2012-11-26 18:58:24 +00:00
delete compressor ;
compressor = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
demoStrings . DeleteContents ( true ) ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : ReadHashString
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idDemoFile : : ReadHashString ( )
{
2012-11-26 18:58:24 +00:00
int index ;
2012-11-28 15:47:07 +00:00
if ( log & & fLog )
{
const char * text = va ( " %s > Reading hash string \n " , logStr . c_str ( ) ) ;
2012-11-26 18:58:24 +00:00
fLog - > Write ( text , strlen ( text ) ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
ReadInt ( index ) ;
2012-11-28 15:47:07 +00:00
if ( index = = - 1 )
{
2012-11-26 18:58:24 +00:00
// read a new string for the table
2012-11-28 15:47:07 +00:00
idStr * str = new ( TAG_SYSTEM ) idStr ;
2012-11-26 18:58:24 +00:00
idStr data ;
ReadString ( data ) ;
* str = data ;
demoStrings . Append ( str ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return * str ;
}
2012-11-28 15:47:07 +00:00
if ( index < - 1 | | index > = demoStrings . Num ( ) )
{
2012-11-26 18:58:24 +00:00
Close ( ) ;
common - > Error ( " demo hash index out of range " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return demoStrings [ index ] - > c_str ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : WriteHashString
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDemoFile : : WriteHashString ( const char * str )
{
if ( log & & fLog )
{
const char * text = va ( " %s > Writing hash string \n " , logStr . c_str ( ) ) ;
2012-11-26 18:58:24 +00:00
fLog - > Write ( text , strlen ( text ) ) ;
}
// see if it is already in the has table
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < demoStrings . Num ( ) ; i + + )
{
if ( ! strcmp ( demoStrings [ i ] - > c_str ( ) , str ) )
{
2012-11-26 18:58:24 +00:00
WriteInt ( i ) ;
return ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add it to our table and the demo table
2012-11-28 15:47:07 +00:00
idStr * copy = new ( TAG_SYSTEM ) idStr ( str ) ;
2012-11-26 18:58:24 +00:00
//common->Printf( "hash:%i = %s\n", demoStrings.Num(), str );
demoStrings . Append ( copy ) ;
2012-11-28 15:47:07 +00:00
int cmd = - 1 ;
2012-11-26 18:58:24 +00:00
WriteInt ( cmd ) ;
WriteString ( str ) ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : ReadDict
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDemoFile : : ReadDict ( idDict & dict )
{
2012-11-26 18:58:24 +00:00
int i , c ;
idStr key , val ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dict . Clear ( ) ;
ReadInt ( c ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < c ; i + + )
{
2012-11-26 18:58:24 +00:00
key = ReadHashString ( ) ;
val = ReadHashString ( ) ;
dict . Set ( key , val ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : WriteDict
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDemoFile : : WriteDict ( const idDict & dict )
{
2012-11-26 18:58:24 +00:00
int i , c ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
c = dict . GetNumKeyVals ( ) ;
WriteInt ( c ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < c ; i + + )
{
2012-11-26 18:58:24 +00:00
WriteHashString ( dict . GetKeyVal ( i ) - > GetKey ( ) ) ;
WriteHashString ( dict . GetKeyVal ( i ) - > GetValue ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : Read
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDemoFile : : Read ( void * buffer , int len )
{
2012-11-26 18:58:24 +00:00
int read = compressor - > Read ( buffer , len ) ;
2012-11-28 15:47:07 +00:00
if ( read = = 0 & & len > = 4 )
{
* ( demoSystem_t * ) buffer = DS_FINISHED ;
2012-11-26 18:58:24 +00:00
}
return read ;
}
/*
= = = = = = = = = = = = = = = =
idDemoFile : : Write
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDemoFile : : Write ( const void * buffer , int len )
{
2012-11-26 18:58:24 +00:00
return compressor - > Write ( buffer , len ) ;
}