2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
2011-12-06 18:20:15 +00:00
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
2011-11-22 21:28:15 +00:00
2011-12-06 16:14:59 +00:00
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
2011-11-22 21:28:15 +00:00
Doom 3 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 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 Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 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 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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2011-12-16 22:28:29 +00:00
# include "sys/platform.h"
# include "idlib/geometry/JointTransform.h"
# include "framework/Licensee.h"
# include "framework/FileSystem.h"
# include "framework/DemoFile.h"
2011-11-22 21:28:15 +00:00
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
= = = = = = = = = = = = = = = =
*/
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 ) ;
f - > Read ( fileImage , fileLength ) ;
fileSystem - > CloseFile ( f ) ;
f = new 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 ) ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
ReadInt ( index ) ;
if ( index = = - 1 ) {
// read a new string for the table
idStr * str = new idStr ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
idStr data ;
ReadString ( data ) ;
* str = data ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
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 idStr ( str ) ;
//common->Printf( "hash:%i = %s\n", demoStrings.Num(), str );
demoStrings . Append ( copy ) ;
2011-12-06 18:20:15 +00:00
int cmd = - 1 ;
2011-11-22 21:28:15 +00:00
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 ) ;
}