doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DemoFile.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 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.
23 
24 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.
25 
26 ===========================================================================
27 */
28 
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 idCVar idDemoFile::com_logDemos( "com_logDemos", "0", CVAR_SYSTEM | CVAR_BOOL, "Write demo.log with debug information in it" );
33 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" );
34 idCVar idDemoFile::com_preloadDemos( "com_preloadDemos", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_ARCHIVE, "Load the whole demo in to RAM before running it" );
35 
36 #define DEMO_MAGIC GAME_NAME " RDEMO"
37 
38 /*
39 ================
40 idDemoFile::idDemoFile
41 ================
42 */
44  f = NULL;
45  fLog = NULL;
46  log = false;
47  fileImage = NULL;
48  compressor = NULL;
49  writing = false;
50 }
51 
52 /*
53 ================
54 idDemoFile::~idDemoFile
55 ================
56 */
58  Close();
59 }
60 
61 /*
62 ================
63 idDemoFile::AllocCompressor
64 ================
65 */
67  switch ( type ) {
68  case 0: return idCompressor::AllocNoCompression();
69  default:
70  case 1: return idCompressor::AllocLZW();
71  case 2: return idCompressor::AllocLZSS();
72  case 3: return idCompressor::AllocHuffman();
73  }
74 }
75 
76 /*
77 ================
78 idDemoFile::OpenForReading
79 ================
80 */
81 bool idDemoFile::OpenForReading( const char *fileName ) {
82  static const int magicLen = sizeof(DEMO_MAGIC) / sizeof(DEMO_MAGIC[0]);
83  char magicBuffer[magicLen];
84  int compression;
85  int fileLength;
86 
87  Close();
88 
89  f = fileSystem->OpenFileRead( fileName );
90  if ( !f ) {
91  return false;
92  }
93 
94  fileLength = f->Length();
95 
96  if ( com_preloadDemos.GetBool() ) {
97  fileImage = (byte *)Mem_Alloc( fileLength );
98  f->Read( fileImage, fileLength );
100  f = new idFile_Memory( va( "preloaded(%s)", fileName ), (const char *)fileImage, fileLength );
101  }
102 
103  if ( com_logDemos.GetBool() ) {
104  fLog = fileSystem->OpenFileWrite( "demoread.log" );
105  }
106 
107  writing = false;
108 
109  f->Read(magicBuffer, magicLen);
110  if ( memcmp(magicBuffer, DEMO_MAGIC, magicLen) == 0 ) {
111  f->ReadInt( compression );
112  } else {
113  // Ideally we would error out if the magic string isn't there,
114  // but for backwards compatibility we are going to assume it's just an uncompressed demo file
115  compression = 0;
116  f->Rewind();
117  }
118 
119  compressor = AllocCompressor( compression );
120  compressor->Init( f, false, 8 );
121 
122  return true;
123 }
124 
125 /*
126 ================
127 idDemoFile::SetLog
128 ================
129 */
130 void idDemoFile::SetLog(bool b, const char *p) {
131  log = b;
132  if (p) {
133  logStr = p;
134  }
135 }
136 
137 /*
138 ================
139 idDemoFile::Log
140 ================
141 */
142 void idDemoFile::Log(const char *p) {
143  if ( fLog && p && *p ) {
144  fLog->Write( p, strlen(p) );
145  }
146 }
147 
148 /*
149 ================
150 idDemoFile::OpenForWriting
151 ================
152 */
153 bool idDemoFile::OpenForWriting( const char *fileName ) {
154  Close();
155 
156  f = fileSystem->OpenFileWrite( fileName );
157  if ( f == NULL ) {
158  return false;
159  }
160 
161  if ( com_logDemos.GetBool() ) {
162  fLog = fileSystem->OpenFileWrite( "demowrite.log" );
163  }
164 
165  writing = true;
166 
167  f->Write(DEMO_MAGIC, sizeof(DEMO_MAGIC));
169  f->Flush();
170 
172  compressor->Init( f, true, 8 );
173 
174  return true;
175 }
176 
177 /*
178 ================
179 idDemoFile::Close
180 ================
181 */
183  if ( writing && compressor ) {
185  }
186 
187  if ( f ) {
188  fileSystem->CloseFile( f );
189  f = NULL;
190  }
191  if ( fLog ) {
193  fLog = NULL;
194  }
195  if ( fileImage ) {
196  Mem_Free( fileImage );
197  fileImage = NULL;
198  }
199  if ( compressor ) {
200  delete compressor;
201  compressor = NULL;
202  }
203 
204  demoStrings.DeleteContents( true );
205 }
206 
207 /*
208 ================
209 idDemoFile::ReadHashString
210 ================
211 */
213  int index;
214 
215  if ( log && fLog ) {
216  const char *text = va( "%s > Reading hash string\n", logStr.c_str() );
217  fLog->Write( text, strlen( text ) );
218  }
219 
220  ReadInt( index );
221 
222  if ( index == -1 ) {
223  // read a new string for the table
224  idStr *str = new idStr;
225 
226  idStr data;
227  ReadString( data );
228  *str = data;
229 
230  demoStrings.Append( str );
231 
232  return *str;
233  }
234 
236  Close();
237  common->Error( "demo hash index out of range" );
238  }
239 
240  return demoStrings[index]->c_str();
241 }
242 
243 /*
244 ================
245 idDemoFile::WriteHashString
246 ================
247 */
248 void idDemoFile::WriteHashString( const char *str ) {
249  if ( log && fLog ) {
250  const char *text = va( "%s > Writing hash string\n", logStr.c_str() );
251  fLog->Write( text, strlen( text ) );
252  }
253  // see if it is already in the has table
254  for ( int i = 0 ; i < demoStrings.Num() ; i++ ) {
255  if ( !strcmp( demoStrings[i]->c_str(), str ) ) {
256  WriteInt( i );
257  return;
258  }
259  }
260 
261  // add it to our table and the demo table
262  idStr *copy = new idStr( str );
263 //common->Printf( "hash:%i = %s\n", demoStrings.Num(), str );
264  demoStrings.Append( copy );
265  int cmd = -1;
266  WriteInt( cmd );
267  WriteString( str );
268 }
269 
270 /*
271 ================
272 idDemoFile::ReadDict
273 ================
274 */
276  int i, c;
277  idStr key, val;
278 
279  dict.Clear();
280  ReadInt( c );
281  for ( i = 0; i < c; i++ ) {
282  key = ReadHashString();
283  val = ReadHashString();
284  dict.Set( key, val );
285  }
286 }
287 
288 /*
289 ================
290 idDemoFile::WriteDict
291 ================
292 */
293 void idDemoFile::WriteDict( const idDict &dict ) {
294  int i, c;
295 
296  c = dict.GetNumKeyVals();
297  WriteInt( c );
298  for ( i = 0; i < c; i++ ) {
299  WriteHashString( dict.GetKeyVal( i )->GetKey() );
300  WriteHashString( dict.GetKeyVal( i )->GetValue() );
301  }
302 }
303 
304 /*
305  ================
306  idDemoFile::Read
307  ================
308  */
309 int idDemoFile::Read( void *buffer, int len ) {
310  int read = compressor->Read( buffer, len );
311  if ( read == 0 && len >= 4 ) {
312  *(demoSystem_t *)buffer = DS_FINISHED;
313  }
314  return read;
315 }
316 
317 /*
318  ================
319  idDemoFile::Write
320  ================
321  */
322 int idDemoFile::Write( const void *buffer, int len ) {
323  return compressor->Write( buffer, len );
324 }
325 
326 
327 
328 
#define strcmp
Definition: Str.h:41
virtual idFile * OpenFileRead(const char *relativePath, bool allowCopyFiles=true, const char *gamedir=NULL)=0
static idCVar com_compressDemos
Definition: DemoFile.h:84
virtual int Read(void *outData, int outLength)=0
virtual int Write(const void *inData, int inLength)=0
virtual int virtual int ReadInt(int &value)
Definition: File.cpp:311
virtual void Rewind(void)
Definition: File.cpp:251
static idCompressor * AllocLZW(void)
const idStr & GetKey(void) const
Definition: Dict.h:52
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
bool OpenForWriting(const char *fileName)
Definition: DemoFile.cpp:153
idFile * fLog
Definition: DemoFile.h:79
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
GLenum GLsizei len
Definition: glext.h:3472
void Set(const char *key, const char *value)
Definition: Dict.cpp:275
demoSystem_t
Definition: DemoFile.h:40
int i
Definition: process.py:33
virtual void Init(idFile *f, bool compress, int wordLength)=0
static idCVar com_preloadDemos
Definition: DemoFile.h:85
static idCVar com_logDemos
Definition: DemoFile.h:83
idFile * f
Definition: DemoFile.h:75
virtual void Flush(void)
Definition: File.cpp:234
virtual int WriteInt(const int value)
Definition: File.cpp:468
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
virtual int WriteString(const char *string)
Definition: File.cpp:546
idCommon * common
Definition: Common.cpp:206
Definition: Dict.h:65
#define NULL
Definition: Lib.h:88
void Clear(void)
Definition: Dict.cpp:201
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
GLuint buffer
Definition: glext.h:3108
int GetInteger(void) const
Definition: CVarSystem.h:143
#define DEMO_MAGIC
Definition: DemoFile.cpp:36
virtual idFile * OpenFileWrite(const char *relativePath, const char *basePath="fs_savepath")=0
virtual int Read(void *buffer, int len)
Definition: File.cpp:179
const idStr & GetValue(void) const
Definition: Dict.h:53
void DeleteContents(bool clear)
Definition: List.h:207
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
void Log(const char *p)
Definition: DemoFile.cpp:142
bool writing
Definition: DemoFile.h:73
virtual void FinishCompress(void)=0
GLubyte GLubyte b
Definition: glext.h:4662
static idCompressor * AllocHuffman(void)
int Append(const type &obj)
Definition: List.h:646
static idCompressor * AllocNoCompression(void)
bool GetBool(void) const
Definition: CVarSystem.h:142
int Write(const void *buffer, int len)
Definition: DemoFile.cpp:322
bool OpenForReading(const char *fileName)
Definition: DemoFile.cpp:81
int Num(void) const
Definition: List.h:265
unsigned char byte
Definition: Lib.h:75
void WriteDict(const idDict &dict)
Definition: DemoFile.cpp:293
virtual int Write(const void *buffer, int len)
Definition: File.cpp:189
void SetLog(bool b, const char *p)
Definition: DemoFile.cpp:130
Definition: Str.h:116
idList< idStr * > demoStrings
Definition: DemoFile.h:78
idCompressor * compressor
Definition: DemoFile.h:76
static idCompressor * AllocLZSS(void)
void Close()
Definition: DemoFile.cpp:182
const char * c_str(void) const
Definition: Str.h:487
const idKeyValue * GetKeyVal(int index) const
Definition: Dict.h:294
const char * ReadHashString()
Definition: DemoFile.cpp:212
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
virtual int ReadString(idStr &string)
Definition: File.cpp:396
char * va(const char *fmt,...)
Definition: Str.cpp:1568
virtual void CloseFile(idFile *f)=0
virtual void Error(const char *fmt,...) id_attribute((format(printf
GLfloat GLfloat p
Definition: glext.h:4674
int GetNumKeyVals(void) const
Definition: Dict.h:290
int Read(void *buffer, int len)
Definition: DemoFile.cpp:309
virtual int Length(void)
Definition: File.cpp:199
idStr logStr
Definition: DemoFile.h:81
bool log
Definition: DemoFile.h:80
void ReadDict(idDict &dict)
Definition: DemoFile.cpp:275
byte * fileImage
Definition: DemoFile.h:74
void WriteHashString(const char *str)
Definition: DemoFile.cpp:248
static idCompressor * AllocCompressor(int type)
Definition: DemoFile.cpp:66