]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/d3xp/gamesys/SaveGame.cpp
hello world
[icculus/iodoom3.git] / neo / d3xp / gamesys / SaveGame.cpp
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 #include "../Game_local.h"
33
34 #include "TypeInfo.h"
35
36 /*
37 Save game related helper classes.
38
39 Save games are implemented in two classes, idSaveGame and idRestoreGame, that implement write/read functions for 
40 common types.  They're passed in to each entity and object for them to archive themselves.  Each class
41 implements save/restore functions for it's own data.  When restoring, all the objects are instantiated,
42 then the restore function is called on each, superclass first, then subclasses.
43
44 Pointers are restored by saving out an object index for each unique object pointer and adding them to a list of
45 objects that are to be saved.  Restore instantiates all the objects in the list before calling the Restore function
46 on each object so that the pointers returned are valid.  No object's restore function should rely on any other objects
47 being fully instantiated until after the restore process is complete.  Post restore fixup should be done by posting
48 events with 0 delay.
49
50 The savegame header will have the Game Name, Version, Map Name, and Player Persistent Info.
51
52 Changes in version make savegames incompatible, and the game will start from the beginning of the level with
53 the player's persistent info.
54
55 Changes to classes that don't need to break compatibilty can use the build number as the savegame version.
56 Later versions are responsible for restoring from previous versions by ignoring any unused data and initializing
57 variables that weren't in previous versions with safe information.
58
59 At the head of the save game is enough information to restore the player to the beginning of the level should the
60 file be unloadable in some way (for example, due to script changes).
61 */
62
63 /*
64 ================
65 idSaveGame::idSaveGame()
66 ================
67 */
68 idSaveGame::idSaveGame( idFile *savefile ) {
69
70         file = savefile;
71
72         // Put NULL at the start of the list so we can skip over it.
73         objects.Clear();
74         objects.Append( NULL );
75 }
76
77 /*
78 ================
79 idSaveGame::~idSaveGame()
80 ================
81 */
82 idSaveGame::~idSaveGame() {
83         if ( objects.Num() ) {
84                 Close();
85         }
86 }
87
88 /*
89 ================
90 idSaveGame::Close
91 ================
92 */
93 void idSaveGame::Close( void ) {
94         int i;
95
96         WriteSoundCommands();
97
98         // read trace models
99         idClipModel::SaveTraceModels( this );
100
101         for( i = 1; i < objects.Num(); i++ ) {
102                 CallSave_r( objects[ i ]->GetType(), objects[ i ] );
103         }
104
105         objects.Clear();
106
107 #ifdef ID_DEBUG_MEMORY
108         idStr gameState = file->GetName();
109         gameState.StripFileExtension();
110         WriteGameState_f( idCmdArgs( va( "test %s_save", gameState.c_str() ), false ) );
111 #endif
112 }
113
114 /*
115 ================
116 idSaveGame::WriteObjectList
117 ================
118 */
119 void idSaveGame::WriteObjectList( void ) {
120         int i;
121
122         WriteInt( objects.Num() - 1 );
123         for( i = 1; i < objects.Num(); i++ ) {
124                 WriteString( objects[ i ]->GetClassname() );
125         }
126 }
127
128 /*
129 ================
130 idSaveGame::CallSave_r
131 ================
132 */
133 void idSaveGame::CallSave_r( const idTypeInfo *cls, const idClass *obj ) {
134         if ( cls->super ) {
135                 CallSave_r( cls->super, obj );
136                 if ( cls->super->Save == cls->Save ) {
137                         // don't call save on this inheritance level since the function was called in the super class
138                         return;
139                 }
140         }
141         
142         ( obj->*cls->Save )( this );
143 }
144
145 /*
146 ================
147 idSaveGame::AddObject
148 ================
149 */
150 void idSaveGame::AddObject( const idClass *obj ) {
151         objects.AddUnique( obj );
152 }
153
154 /*
155 ================
156 idSaveGame::Write
157 ================
158 */
159 void idSaveGame::Write( const void *buffer, int len ) {
160         file->Write( buffer, len );
161 }
162
163 /*
164 ================
165 idSaveGame::WriteInt
166 ================
167 */
168 void idSaveGame::WriteInt( const int value ) {
169         file->WriteInt( value );
170 }
171
172 /*
173 ================
174 idSaveGame::WriteJoint
175 ================
176 */
177 void idSaveGame::WriteJoint( const jointHandle_t value ) {
178         file->WriteInt( (int&)value );
179 }
180
181 /*
182 ================
183 idSaveGame::WriteShort
184 ================
185 */
186 void idSaveGame::WriteShort( const short value ) {
187         file->WriteShort( value );
188 }
189
190 /*
191 ================
192 idSaveGame::WriteByte
193 ================
194 */
195 void idSaveGame::WriteByte( const byte value ) {
196         file->Write( &value, sizeof( value ) );
197 }
198
199 /*
200 ================
201 idSaveGame::WriteSignedChar
202 ================
203 */
204 void idSaveGame::WriteSignedChar( const signed char value ) {
205         file->Write( &value, sizeof( value ) );
206 }
207
208 /*
209 ================
210 idSaveGame::WriteFloat
211 ================
212 */
213 void idSaveGame::WriteFloat( const float value ) {
214         file->WriteFloat( value );
215 }
216
217 /*
218 ================
219 idSaveGame::WriteBool
220 ================
221 */
222 void idSaveGame::WriteBool( const bool value ) {
223         file->WriteBool( value );
224 }
225
226 /*
227 ================
228 idSaveGame::WriteString
229 ================
230 */  
231 void idSaveGame::WriteString( const char *string ) {
232         int len;
233
234         len = strlen( string );
235         WriteInt( len );
236     file->Write( string, len );
237 }
238
239 /*
240 ================
241 idSaveGame::WriteVec2
242 ================
243 */
244 void idSaveGame::WriteVec2( const idVec2 &vec ) {
245         file->WriteVec2( vec );
246 }
247
248 /*
249 ================
250 idSaveGame::WriteVec3
251 ================
252 */
253 void idSaveGame::WriteVec3( const idVec3 &vec ) {
254         file->WriteVec3( vec );
255 }
256
257 /*
258 ================
259 idSaveGame::WriteVec4
260 ================
261 */
262 void idSaveGame::WriteVec4( const idVec4 &vec ) {
263         file->WriteVec4( vec );
264 }
265
266 /*
267 ================
268 idSaveGame::WriteVec6
269 ================
270 */
271 void idSaveGame::WriteVec6( const idVec6 &vec ) {
272         file->WriteVec6( vec );
273 }
274
275 /*
276 ================
277 idSaveGame::WriteBounds
278 ================
279 */
280 void idSaveGame::WriteBounds( const idBounds &bounds ) {
281         idBounds b = bounds;
282         LittleRevBytes( &b, sizeof(float), sizeof(b)/sizeof(float) );
283         file->Write( &b, sizeof( b ) );
284 }
285
286 /*
287 ================
288 idSaveGame::WriteBounds
289 ================
290 */
291 void idSaveGame::WriteWinding( const idWinding &w )
292 {
293         int i, num;
294         num = w.GetNumPoints();
295         file->WriteInt( num );
296         for ( i = 0; i < num; i++ ) {
297                 idVec5 v = w[i];
298                 LittleRevBytes(&v, sizeof(float), sizeof(v)/sizeof(float) );
299                 file->Write( &v, sizeof(v) );
300         }
301 }
302
303
304 /*
305 ================
306 idSaveGame::WriteMat3
307 ================
308 */
309 void idSaveGame::WriteMat3( const idMat3 &mat ) {
310         file->WriteMat3( mat );
311 }
312
313 /*
314 ================
315 idSaveGame::WriteAngles
316 ================
317 */
318 void idSaveGame::WriteAngles( const idAngles &angles ) {
319         idAngles v = angles;
320         LittleRevBytes(&v, sizeof(float), sizeof(v)/sizeof(float) );
321         file->Write( &v, sizeof( v ) );
322 }
323
324 /*
325 ================
326 idSaveGame::WriteObject
327 ================
328 */
329 void idSaveGame::WriteObject( const idClass *obj ) {
330         int index;
331
332         index = objects.FindIndex( obj );
333         if ( index < 0 ) {
334                 gameLocal.DPrintf( "idSaveGame::WriteObject - WriteObject FindIndex failed\n" );
335
336                 // Use the NULL index
337                 index = 0;
338         }
339
340         WriteInt( index );
341 }
342
343 /*
344 ================
345 idSaveGame::WriteStaticObject
346 ================
347 */
348 void idSaveGame::WriteStaticObject( const idClass &obj ) {
349         CallSave_r( obj.GetType(), &obj );
350 }
351
352 /*
353 ================
354 idSaveGame::WriteDict
355 ================
356 */
357 void idSaveGame::WriteDict( const idDict *dict ) {
358         int num;
359         int i;
360         const idKeyValue *kv;
361
362         if ( !dict ) {
363                 WriteInt( -1 );
364         } else {
365                 num = dict->GetNumKeyVals();
366                 WriteInt( num );
367                 for( i = 0; i < num; i++ ) {
368                         kv = dict->GetKeyVal( i );
369                         WriteString( kv->GetKey() );
370                         WriteString( kv->GetValue() );
371                 }
372         }
373 }
374
375 /*
376 ================
377 idSaveGame::WriteMaterial
378 ================
379 */
380 void idSaveGame::WriteMaterial( const idMaterial *material ) {
381         if ( !material ) {
382                 WriteString( "" );
383         } else {
384                 WriteString( material->GetName() );
385         }
386 }
387
388 /*
389 ================
390 idSaveGame::WriteSkin
391 ================
392 */
393 void idSaveGame::WriteSkin( const idDeclSkin *skin ) {
394         if ( !skin ) {
395                 WriteString( "" );
396         } else {
397                 WriteString( skin->GetName() );
398         }
399 }
400
401 /*
402 ================
403 idSaveGame::WriteParticle
404 ================
405 */
406 void idSaveGame::WriteParticle( const idDeclParticle *particle ) {
407         if ( !particle ) {
408                 WriteString( "" );
409         } else {
410                 WriteString( particle->GetName() );
411         }
412 }
413
414 /*
415 ================
416 idSaveGame::WriteFX
417 ================
418 */
419 void idSaveGame::WriteFX( const idDeclFX *fx ) {
420         if ( !fx ) {
421                 WriteString( "" );
422         } else {
423                 WriteString( fx->GetName() );
424         }
425 }
426
427 /*
428 ================
429 idSaveGame::WriteModelDef
430 ================
431 */
432 void idSaveGame::WriteModelDef( const idDeclModelDef *modelDef ) {
433         if ( !modelDef ) {
434                 WriteString( "" );
435         } else {
436                 WriteString( modelDef->GetName() );
437         }
438 }
439
440 /*
441 ================
442 idSaveGame::WriteSoundShader
443 ================
444 */
445 void idSaveGame::WriteSoundShader( const idSoundShader *shader ) {
446         const char *name;
447
448         if ( !shader ) {
449                 WriteString( "" );
450         } else {
451                 name = shader->GetName();
452                 WriteString( name );
453         }
454 }
455
456 /*
457 ================
458 idSaveGame::WriteModel
459 ================
460 */
461 void idSaveGame::WriteModel( const idRenderModel *model ) {
462         const char *name;
463
464         if ( !model ) {
465                 WriteString( "" );
466         } else {
467                 name = model->Name();
468                 WriteString( name );
469         }
470 }
471
472 /*
473 ================
474 idSaveGame::WriteUserInterface
475 ================
476 */
477 void idSaveGame::WriteUserInterface( const idUserInterface *ui, bool unique ) {
478         const char *name;
479
480         if ( !ui ) {
481                 WriteString( "" );
482         } else {
483                 name = ui->Name();
484                 WriteString( name );
485                 WriteBool( unique );
486                 if ( ui->WriteToSaveGame( file ) == false ) {
487                         gameLocal.Error( "idSaveGame::WriteUserInterface: ui failed to write properly\n" );
488                 }
489         }
490 }
491
492 /*
493 ================
494 idSaveGame::WriteRenderEntity
495 ================
496 */
497 void idSaveGame::WriteRenderEntity( const renderEntity_t &renderEntity ) {
498         int i;
499
500         WriteModel( renderEntity.hModel );
501
502         WriteInt( renderEntity.entityNum );
503         WriteInt( renderEntity.bodyId );
504
505         WriteBounds( renderEntity.bounds );
506
507         // callback is set by class's Restore function
508
509         WriteInt( renderEntity.suppressSurfaceInViewID );
510         WriteInt( renderEntity.suppressShadowInViewID );
511         WriteInt( renderEntity.suppressShadowInLightID );
512         WriteInt( renderEntity.allowSurfaceInViewID );
513
514         WriteVec3( renderEntity.origin );
515         WriteMat3( renderEntity.axis );
516
517         WriteMaterial( renderEntity.customShader );
518         WriteMaterial( renderEntity.referenceShader );
519         WriteSkin( renderEntity.customSkin );
520
521         if ( renderEntity.referenceSound != NULL ) {
522                 WriteInt( renderEntity.referenceSound->Index() );
523         } else {
524                 WriteInt( 0 );
525         }
526
527         for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
528                 WriteFloat( renderEntity.shaderParms[ i ] );
529         }
530
531         for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
532                 WriteUserInterface( renderEntity.gui[ i ], renderEntity.gui[ i ] ? renderEntity.gui[ i ]->IsUniqued() : false );
533         }
534
535         WriteFloat( renderEntity.modelDepthHack );
536
537         WriteBool( renderEntity.noSelfShadow );
538         WriteBool( renderEntity.noShadow );
539         WriteBool( renderEntity.noDynamicInteractions );
540         WriteBool( renderEntity.weaponDepthHack );
541
542         WriteInt( renderEntity.forceUpdate );
543
544 #ifdef _D3XP
545         WriteInt( renderEntity.timeGroup );
546         WriteInt( renderEntity.xrayIndex );
547 #endif
548 }
549
550 /*
551 ================
552 idSaveGame::WriteRenderLight
553 ================
554 */
555 void idSaveGame::WriteRenderLight( const renderLight_t &renderLight ) {
556         int i;
557
558         WriteMat3( renderLight.axis );
559         WriteVec3( renderLight.origin );
560
561         WriteInt( renderLight.suppressLightInViewID );
562         WriteInt( renderLight.allowLightInViewID );
563         WriteBool( renderLight.noShadows );
564         WriteBool( renderLight.noSpecular );
565         WriteBool( renderLight.pointLight );
566         WriteBool( renderLight.parallel );
567
568         WriteVec3( renderLight.lightRadius );
569         WriteVec3( renderLight.lightCenter );
570
571         WriteVec3( renderLight.target );
572         WriteVec3( renderLight.right );
573         WriteVec3( renderLight.up );
574         WriteVec3( renderLight.start );
575         WriteVec3( renderLight.end );
576
577         // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
578         // WriteModel( renderLight.prelightModel );
579
580         WriteInt( renderLight.lightId );
581
582         WriteMaterial( renderLight.shader );
583
584         for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
585                 WriteFloat( renderLight.shaderParms[ i ] );
586         }
587
588         if ( renderLight.referenceSound != NULL ) {
589                 WriteInt( renderLight.referenceSound->Index() );
590         } else {
591                 WriteInt( 0 );
592         }
593 }
594
595 /*
596 ================
597 idSaveGame::WriteRefSound
598 ================
599 */
600 void idSaveGame::WriteRefSound( const refSound_t &refSound ) {
601         if ( refSound.referenceSound ) {
602                 WriteInt( refSound.referenceSound->Index() );
603         } else {
604                 WriteInt( 0 );
605         }
606         WriteVec3( refSound.origin );
607         WriteInt( refSound.listenerId );
608         WriteSoundShader( refSound.shader );
609         WriteFloat( refSound.diversity );
610         WriteBool( refSound.waitfortrigger );
611
612         WriteFloat( refSound.parms.minDistance );
613         WriteFloat( refSound.parms.maxDistance );
614         WriteFloat( refSound.parms.volume );
615         WriteFloat( refSound.parms.shakes );
616         WriteInt( refSound.parms.soundShaderFlags );
617         WriteInt( refSound.parms.soundClass );
618 }
619
620 /*
621 ================
622 idSaveGame::WriteRenderView
623 ================
624 */
625 void idSaveGame::WriteRenderView( const renderView_t &view ) {
626         int i;
627
628         WriteInt( view.viewID );
629         WriteInt( view.x );
630         WriteInt( view.y );
631         WriteInt( view.width );
632         WriteInt( view.height );
633
634         WriteFloat( view.fov_x );
635         WriteFloat( view.fov_y );
636         WriteVec3( view.vieworg );
637         WriteMat3( view.viewaxis );
638
639         WriteBool( view.cramZNear );
640
641         WriteInt( view.time );
642
643         for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
644                 WriteFloat( view.shaderParms[ i ] );
645         }
646 }
647
648 /*
649 ===================
650 idSaveGame::WriteUsercmd
651 ===================
652 */
653 void idSaveGame::WriteUsercmd( const usercmd_t &usercmd ) {
654         WriteInt( usercmd.gameFrame );
655         WriteInt( usercmd.gameTime );
656         WriteInt( usercmd.duplicateCount );
657         WriteByte( usercmd.buttons );
658         WriteSignedChar( usercmd.forwardmove );
659         WriteSignedChar( usercmd.rightmove );
660         WriteSignedChar( usercmd.upmove );
661         WriteShort( usercmd.angles[0] );
662         WriteShort( usercmd.angles[1] );
663         WriteShort( usercmd.angles[2] );
664         WriteShort( usercmd.mx );
665         WriteShort( usercmd.my );
666         WriteSignedChar( usercmd.impulse );
667         WriteByte( usercmd.flags );
668         WriteInt( usercmd.sequence );
669 }
670
671 /*
672 ===================
673 idSaveGame::WriteContactInfo
674 ===================
675 */
676 void idSaveGame::WriteContactInfo( const contactInfo_t &contactInfo ) {
677         WriteInt( (int)contactInfo.type );
678         WriteVec3( contactInfo.point );
679         WriteVec3( contactInfo.normal );
680         WriteFloat( contactInfo.dist );
681         WriteInt( contactInfo.contents );
682         WriteMaterial( contactInfo.material );
683         WriteInt( contactInfo.modelFeature );
684         WriteInt( contactInfo.trmFeature );
685         WriteInt( contactInfo.entityNum );
686         WriteInt( contactInfo.id );
687 }
688
689 /*
690 ===================
691 idSaveGame::WriteTrace
692 ===================
693 */
694 void idSaveGame::WriteTrace( const trace_t &trace ) {
695         WriteFloat( trace.fraction );
696         WriteVec3( trace.endpos );
697         WriteMat3( trace.endAxis );
698         WriteContactInfo( trace.c );
699 }
700
701 /*
702  ===================
703  idRestoreGame::WriteTraceModel
704  ===================
705  */
706 void idSaveGame::WriteTraceModel( const idTraceModel &trace ) {
707         int j, k;
708         
709         WriteInt( (int&)trace.type );
710         WriteInt( trace.numVerts );
711         for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
712                 WriteVec3( trace.verts[j] );
713         }
714         WriteInt( trace.numEdges );
715         for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
716                 WriteInt( trace.edges[j].v[0] );
717                 WriteInt( trace.edges[j].v[1] );
718                 WriteVec3( trace.edges[j].normal );
719         }
720         WriteInt( trace.numPolys );
721         for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
722                 WriteVec3( trace.polys[j].normal );
723                 WriteFloat( trace.polys[j].dist );
724                 WriteBounds( trace.polys[j].bounds );
725                 WriteInt( trace.polys[j].numEdges );
726                 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
727                         WriteInt( trace.polys[j].edges[k] );
728                 }
729         }
730         WriteVec3( trace.offset );
731         WriteBounds( trace.bounds );
732         WriteBool( trace.isConvex );
733         // padding win32 native structs
734         char tmp[3];
735         memset( tmp, 0, sizeof( tmp ) );
736         file->Write( tmp, 3 );
737 }
738
739 /*
740 ===================
741 idSaveGame::WriteClipModel
742 ===================
743 */
744 void idSaveGame::WriteClipModel( const idClipModel *clipModel ) {
745         if ( clipModel != NULL ) {
746                 WriteBool( true );
747                 clipModel->Save( this );
748         } else {
749                 WriteBool( false );
750         }
751 }
752
753 /*
754 ===================
755 idSaveGame::WriteSoundCommands
756 ===================
757 */
758 void idSaveGame::WriteSoundCommands( void ) {
759         gameSoundWorld->WriteToSaveGame( file );
760 }
761
762 /*
763 ======================
764 idSaveGame::WriteBuildNumber
765 ======================
766 */
767 void idSaveGame::WriteBuildNumber( const int value ) {
768         file->WriteInt( BUILD_NUMBER );
769 }
770
771 /***********************************************************************
772
773         idRestoreGame
774         
775 ***********************************************************************/
776
777 /*
778 ================
779 idRestoreGame::RestoreGame
780 ================
781 */
782 idRestoreGame::idRestoreGame( idFile *savefile ) {
783         file = savefile;
784 }
785
786 /*
787 ================
788 idRestoreGame::~idRestoreGame()
789 ================
790 */
791 idRestoreGame::~idRestoreGame() {
792 }
793
794 /*
795 ================
796 void idRestoreGame::CreateObjects
797 ================
798 */
799 void idRestoreGame::CreateObjects( void ) {
800         int i, num;
801         idStr classname;
802         idTypeInfo *type;
803
804         ReadInt( num );
805
806         // create all the objects
807         objects.SetNum( num + 1 );
808         memset( objects.Ptr(), 0, sizeof( objects[ 0 ] ) * objects.Num() );
809
810         for( i = 1; i < objects.Num(); i++ ) {
811                 ReadString( classname );
812                 type = idClass::GetClass( classname );
813                 if ( !type ) {
814                         Error( "idRestoreGame::CreateObjects: Unknown class '%s'", classname.c_str() );
815                 }
816                 objects[ i ] = type->CreateInstance();
817
818 #ifdef ID_DEBUG_MEMORY
819                 InitTypeVariables( objects[i], type->classname, 0xce );
820 #endif
821         }
822 }
823
824 /*
825 ================
826 void idRestoreGame::RestoreObjects
827 ================
828 */
829 void idRestoreGame::RestoreObjects( void ) {
830         int i;
831
832         ReadSoundCommands();
833
834         // read trace models
835         idClipModel::RestoreTraceModels( this );
836
837         // restore all the objects
838         for( i = 1; i < objects.Num(); i++ ) {
839                 CallRestore_r( objects[ i ]->GetType(), objects[ i ] );
840         }
841
842         // regenerate render entities and render lights because are not saved
843         for( i = 1; i < objects.Num(); i++ ) {
844                 if ( objects[ i ]->IsType( idEntity::Type ) ) {
845                         idEntity *ent = static_cast<idEntity *>( objects[ i ] );
846                         ent->UpdateVisuals();
847                         ent->Present();
848                 }
849         }
850
851 #ifdef ID_DEBUG_MEMORY
852         idStr gameState = file->GetName();
853         gameState.StripFileExtension();
854         WriteGameState_f( idCmdArgs( va( "test %s_restore", gameState.c_str() ), false ) );
855         //CompareGameState_f( idCmdArgs( va( "test %s_save", gameState.c_str() ) ) );
856         gameLocal.Error( "dumped game states" );
857 #endif
858 }
859
860 /*
861 ====================
862 void idRestoreGame::DeleteObjects
863 ====================
864 */
865 void idRestoreGame::DeleteObjects( void ) {
866
867         // Remove the NULL object before deleting
868         objects.RemoveIndex( 0 );
869
870         objects.DeleteContents( true );
871 }
872
873 /*
874 ================
875 idRestoreGame::Error
876 ================
877 */
878 void idRestoreGame::Error( const char *fmt, ... ) {
879         va_list argptr;
880         char    text[ 1024 ];
881
882         va_start( argptr, fmt );
883         vsprintf( text, fmt, argptr );
884         va_end( argptr );
885
886         objects.DeleteContents( true );
887
888         gameLocal.Error( "%s", text );
889 }
890
891 /*
892 ================
893 idRestoreGame::CallRestore_r
894 ================
895 */
896 void idRestoreGame::CallRestore_r( const idTypeInfo *cls, idClass *obj ) {
897         if ( cls->super ) {
898                 CallRestore_r( cls->super, obj );
899                 if ( cls->super->Restore == cls->Restore ) {
900                         // don't call save on this inheritance level since the function was called in the super class
901                         return;
902                 }
903         }
904         
905         ( obj->*cls->Restore )( this );
906 }
907
908 /*
909 ================
910 idRestoreGame::Read
911 ================
912 */
913 void idRestoreGame::Read( void *buffer, int len ) {
914         file->Read( buffer, len );
915 }
916
917 /*
918 ================
919 idRestoreGame::ReadInt
920 ================
921 */
922 void idRestoreGame::ReadInt( int &value ) {
923         file->ReadInt( value );
924 }
925
926 /*
927 ================
928 idRestoreGame::ReadJoint
929 ================
930 */
931 void idRestoreGame::ReadJoint( jointHandle_t &value ) {
932         file->ReadInt( (int&)value );
933 }
934
935 /*
936 ================
937 idRestoreGame::ReadShort
938 ================
939 */
940 void idRestoreGame::ReadShort( short &value ) {
941         file->ReadShort( value );
942 }
943
944 /*
945 ================
946 idRestoreGame::ReadByte
947 ================
948 */
949 void idRestoreGame::ReadByte( byte &value ) {
950         file->Read( &value, sizeof( value ) );
951 }
952
953 /*
954 ================
955 idRestoreGame::ReadSignedChar
956 ================
957 */
958 void idRestoreGame::ReadSignedChar( signed char &value ) {
959         file->Read( &value, sizeof( value ) );
960 }
961
962 /*
963 ================
964 idRestoreGame::ReadFloat
965 ================
966 */
967 void idRestoreGame::ReadFloat( float &value ) {
968         file->ReadFloat( value );
969 }
970
971 /*
972 ================
973 idRestoreGame::ReadBool
974 ================
975 */
976 void idRestoreGame::ReadBool( bool &value ) {
977         file->ReadBool( value );
978 }
979
980 /*
981 ================
982 idRestoreGame::ReadString
983 ================
984 */
985 void idRestoreGame::ReadString( idStr &string ) {
986         int len;
987
988         ReadInt( len );
989         if ( len < 0 ) {
990                 Error( "idRestoreGame::ReadString: invalid length" );
991         }
992
993         string.Fill( ' ', len );
994         file->Read( &string[ 0 ], len );
995 }
996
997 /*
998 ================
999 idRestoreGame::ReadVec2
1000 ================
1001 */
1002 void idRestoreGame::ReadVec2( idVec2 &vec ) {
1003         file->ReadVec2( vec );
1004 }
1005
1006 /*
1007 ================
1008 idRestoreGame::ReadVec3
1009 ================
1010 */
1011 void idRestoreGame::ReadVec3( idVec3 &vec ) {
1012         file->ReadVec3( vec );
1013 }
1014
1015 /*
1016 ================
1017 idRestoreGame::ReadVec4
1018 ================
1019 */
1020 void idRestoreGame::ReadVec4( idVec4 &vec ) {
1021         file->ReadVec4( vec );
1022 }
1023
1024 /*
1025 ================
1026 idRestoreGame::ReadVec6
1027 ================
1028 */
1029 void idRestoreGame::ReadVec6( idVec6 &vec ) {
1030         file->ReadVec6( vec );
1031 }
1032
1033 /*
1034 ================
1035 idRestoreGame::ReadBounds
1036 ================
1037 */
1038 void idRestoreGame::ReadBounds( idBounds &bounds ) {
1039         file->Read( &bounds, sizeof( bounds ) );
1040         LittleRevBytes( &bounds, sizeof(float), sizeof(bounds)/sizeof(float) );
1041 }
1042
1043 /*
1044 ================
1045 idRestoreGame::ReadWinding
1046 ================
1047 */
1048 void idRestoreGame::ReadWinding( idWinding &w )
1049 {
1050         int i, num;
1051         file->ReadInt( num );
1052         w.SetNumPoints( num );
1053         for ( i = 0; i < num; i++ ) {
1054                 file->Read( &w[i], sizeof(idVec5) );
1055                 LittleRevBytes(&w[i], sizeof(float), sizeof(idVec5)/sizeof(float) );
1056         }
1057 }
1058
1059 /*
1060 ================
1061 idRestoreGame::ReadMat3
1062 ================
1063 */
1064 void idRestoreGame::ReadMat3( idMat3 &mat ) {
1065         file->ReadMat3( mat );
1066 }
1067
1068 /*
1069 ================
1070 idRestoreGame::ReadAngles
1071 ================
1072 */
1073 void idRestoreGame::ReadAngles( idAngles &angles ) {
1074         file->Read( &angles, sizeof( angles ) );
1075         LittleRevBytes(&angles, sizeof(float), sizeof(idAngles)/sizeof(float) );
1076 }
1077
1078 /*
1079 ================
1080 idRestoreGame::ReadObject
1081 ================
1082 */
1083 void idRestoreGame::ReadObject( idClass *&obj ) {
1084         int index;
1085
1086         ReadInt( index );
1087         if ( ( index < 0 ) || ( index >= objects.Num() ) ) {
1088                 Error( "idRestoreGame::ReadObject: invalid object index" );
1089         }
1090         obj = objects[ index ];
1091 }
1092
1093 /*
1094 ================
1095 idRestoreGame::ReadStaticObject
1096 ================
1097 */
1098 void idRestoreGame::ReadStaticObject( idClass &obj ) {
1099         CallRestore_r( obj.GetType(), &obj );
1100 }
1101
1102 /*
1103 ================
1104 idRestoreGame::ReadDict
1105 ================
1106 */
1107 void idRestoreGame::ReadDict( idDict *dict ) {
1108         int num;
1109         int i;
1110         idStr key;
1111         idStr value;
1112
1113         ReadInt( num );
1114
1115         if ( num < 0 ) {
1116                 dict = NULL;
1117         } else {
1118                 dict->Clear();
1119                 for( i = 0; i < num; i++ ) {
1120                         ReadString( key );
1121                         ReadString( value );
1122                         dict->Set( key, value );
1123                 }
1124         }
1125 }
1126
1127 /*
1128 ================
1129 idRestoreGame::ReadMaterial
1130 ================
1131 */
1132 void idRestoreGame::ReadMaterial( const idMaterial *&material ) {
1133         idStr name;
1134
1135         ReadString( name );
1136         if ( !name.Length() ) {
1137                 material = NULL;
1138         } else {
1139                 material = declManager->FindMaterial( name );
1140         }
1141 }
1142
1143 /*
1144 ================
1145 idRestoreGame::ReadSkin
1146 ================
1147 */
1148 void idRestoreGame::ReadSkin( const idDeclSkin *&skin ) {
1149         idStr name;
1150
1151         ReadString( name );
1152         if ( !name.Length() ) {
1153                 skin = NULL;
1154         } else {
1155                 skin = declManager->FindSkin( name );
1156         }
1157 }
1158
1159 /*
1160 ================
1161 idRestoreGame::ReadParticle
1162 ================
1163 */
1164 void idRestoreGame::ReadParticle( const idDeclParticle *&particle ) {
1165         idStr name;
1166
1167         ReadString( name );
1168         if ( !name.Length() ) {
1169                 particle = NULL;
1170         } else {
1171                 particle = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, name ) );
1172         }
1173 }
1174
1175 /*
1176 ================
1177 idRestoreGame::ReadFX
1178 ================
1179 */
1180 void idRestoreGame::ReadFX( const idDeclFX *&fx ) {
1181         idStr name;
1182
1183         ReadString( name );
1184         if ( !name.Length() ) {
1185                 fx = NULL;
1186         } else {
1187                 fx = static_cast<const idDeclFX *>( declManager->FindType( DECL_FX, name ) );
1188         }
1189 }
1190
1191 /*
1192 ================
1193 idRestoreGame::ReadSoundShader
1194 ================
1195 */
1196 void idRestoreGame::ReadSoundShader( const idSoundShader *&shader ) {
1197         idStr name;
1198
1199         ReadString( name );
1200         if ( !name.Length() ) {
1201                 shader = NULL;
1202         } else {
1203                 shader = declManager->FindSound( name );
1204         }
1205 }
1206
1207 /*
1208 ================
1209 idRestoreGame::ReadModelDef
1210 ================
1211 */
1212 void idRestoreGame::ReadModelDef( const idDeclModelDef *&modelDef ) {
1213         idStr name;
1214
1215         ReadString( name );
1216         if ( !name.Length() ) {
1217                 modelDef = NULL;
1218         } else {
1219                 modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
1220         }
1221 }
1222
1223 /*
1224 ================
1225 idRestoreGame::ReadModel
1226 ================
1227 */
1228 void idRestoreGame::ReadModel( idRenderModel *&model ) {
1229         idStr name;
1230
1231         ReadString( name );
1232         if ( !name.Length() ) {
1233                 model = NULL;
1234         } else {
1235                 model = renderModelManager->FindModel( name );
1236         }
1237 }
1238
1239 /*
1240 ================
1241 idRestoreGame::ReadUserInterface
1242 ================
1243 */
1244 void idRestoreGame::ReadUserInterface( idUserInterface *&ui ) {
1245         idStr name;
1246
1247         ReadString( name );
1248         if ( !name.Length() ) {
1249                 ui = NULL;
1250         } else {
1251                 bool unique;
1252                 ReadBool( unique );
1253                 ui = uiManager->FindGui( name, true, unique );
1254                 if ( ui ) {
1255                         if ( ui->ReadFromSaveGame( file ) == false ) {
1256                                 Error( "idSaveGame::ReadUserInterface: ui failed to read properly\n" );
1257                         } else {
1258                                 ui->StateChanged( gameLocal.time );
1259                         }
1260                 }
1261         }
1262 }
1263
1264 /*
1265 ================
1266 idRestoreGame::ReadRenderEntity
1267 ================
1268 */
1269 void idRestoreGame::ReadRenderEntity( renderEntity_t &renderEntity ) {
1270         int i;
1271         int index;
1272
1273         ReadModel( renderEntity.hModel );
1274
1275         ReadInt( renderEntity.entityNum );
1276         ReadInt( renderEntity.bodyId );
1277
1278         ReadBounds( renderEntity.bounds );
1279
1280         // callback is set by class's Restore function
1281         renderEntity.callback = NULL;
1282         renderEntity.callbackData = NULL;
1283
1284         ReadInt( renderEntity.suppressSurfaceInViewID );
1285         ReadInt( renderEntity.suppressShadowInViewID );
1286         ReadInt( renderEntity.suppressShadowInLightID );
1287         ReadInt( renderEntity.allowSurfaceInViewID );
1288
1289         ReadVec3( renderEntity.origin );
1290         ReadMat3( renderEntity.axis );
1291
1292         ReadMaterial( renderEntity.customShader );
1293         ReadMaterial( renderEntity.referenceShader );
1294         ReadSkin( renderEntity.customSkin );
1295
1296         ReadInt( index );
1297         renderEntity.referenceSound = gameSoundWorld->EmitterForIndex( index );
1298
1299         for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1300                 ReadFloat( renderEntity.shaderParms[ i ] );
1301         }
1302
1303         for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
1304                 ReadUserInterface( renderEntity.gui[ i ] );
1305         }
1306
1307         // idEntity will restore "cameraTarget", which will be used in idEntity::Present to restore the remoteRenderView
1308         renderEntity.remoteRenderView = NULL;
1309
1310         renderEntity.joints = NULL;
1311         renderEntity.numJoints = 0;
1312
1313         ReadFloat( renderEntity.modelDepthHack );
1314
1315         ReadBool( renderEntity.noSelfShadow );
1316         ReadBool( renderEntity.noShadow );
1317         ReadBool( renderEntity.noDynamicInteractions );
1318         ReadBool( renderEntity.weaponDepthHack );
1319
1320         ReadInt( renderEntity.forceUpdate );
1321
1322 #ifdef _D3XP
1323         ReadInt( renderEntity.timeGroup );
1324         ReadInt( renderEntity.xrayIndex );
1325 #endif
1326 }
1327
1328 /*
1329 ================
1330 idRestoreGame::ReadRenderLight
1331 ================
1332 */
1333 void idRestoreGame::ReadRenderLight( renderLight_t &renderLight ) {
1334         int index;
1335         int i;
1336
1337         ReadMat3( renderLight.axis );
1338         ReadVec3( renderLight.origin );
1339
1340         ReadInt( renderLight.suppressLightInViewID );
1341         ReadInt( renderLight.allowLightInViewID );
1342         ReadBool( renderLight.noShadows );
1343         ReadBool( renderLight.noSpecular );
1344         ReadBool( renderLight.pointLight );
1345         ReadBool( renderLight.parallel );
1346
1347         ReadVec3( renderLight.lightRadius );
1348         ReadVec3( renderLight.lightCenter );
1349
1350         ReadVec3( renderLight.target );
1351         ReadVec3( renderLight.right );
1352         ReadVec3( renderLight.up );
1353         ReadVec3( renderLight.start );
1354         ReadVec3( renderLight.end );
1355
1356         // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
1357         // ReadModel( renderLight.prelightModel );
1358         renderLight.prelightModel = NULL;
1359
1360         ReadInt( renderLight.lightId );
1361
1362         ReadMaterial( renderLight.shader );
1363
1364         for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1365                 ReadFloat( renderLight.shaderParms[ i ] );
1366         }
1367
1368         ReadInt( index );
1369         renderLight.referenceSound = gameSoundWorld->EmitterForIndex( index );
1370 }
1371
1372 /*
1373 ================
1374 idRestoreGame::ReadRefSound
1375 ================
1376 */
1377 void idRestoreGame::ReadRefSound( refSound_t &refSound ) {
1378         int             index;
1379         ReadInt( index );
1380
1381         refSound.referenceSound = gameSoundWorld->EmitterForIndex( index );
1382         ReadVec3( refSound.origin );
1383         ReadInt( refSound.listenerId );
1384         ReadSoundShader( refSound.shader );
1385         ReadFloat( refSound.diversity );
1386         ReadBool( refSound.waitfortrigger );
1387
1388         ReadFloat( refSound.parms.minDistance );
1389         ReadFloat( refSound.parms.maxDistance );
1390         ReadFloat( refSound.parms.volume );
1391         ReadFloat( refSound.parms.shakes );
1392         ReadInt( refSound.parms.soundShaderFlags );
1393         ReadInt( refSound.parms.soundClass );
1394 }
1395
1396 /*
1397 ================
1398 idRestoreGame::ReadRenderView
1399 ================
1400 */
1401 void idRestoreGame::ReadRenderView( renderView_t &view ) {
1402         int i;
1403
1404         ReadInt( view.viewID );
1405         ReadInt( view.x );
1406         ReadInt( view.y );
1407         ReadInt( view.width );
1408         ReadInt( view.height );
1409
1410         ReadFloat( view.fov_x );
1411         ReadFloat( view.fov_y );
1412         ReadVec3( view.vieworg );
1413         ReadMat3( view.viewaxis );
1414
1415         ReadBool( view.cramZNear );
1416
1417         ReadInt( view.time );
1418
1419         for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
1420                 ReadFloat( view.shaderParms[ i ] );
1421         }
1422 }
1423
1424 /*
1425 =================
1426 idRestoreGame::ReadUsercmd
1427 =================
1428 */
1429 void idRestoreGame::ReadUsercmd( usercmd_t &usercmd ) {
1430         ReadInt( usercmd.gameFrame );
1431         ReadInt( usercmd.gameTime );
1432         ReadInt( usercmd.duplicateCount );
1433         ReadByte( usercmd.buttons );
1434         ReadSignedChar( usercmd.forwardmove );
1435         ReadSignedChar( usercmd.rightmove );
1436         ReadSignedChar( usercmd.upmove );
1437         ReadShort( usercmd.angles[0] );
1438         ReadShort( usercmd.angles[1] );
1439         ReadShort( usercmd.angles[2] );
1440         ReadShort( usercmd.mx );
1441         ReadShort( usercmd.my );
1442         ReadSignedChar( usercmd.impulse );
1443         ReadByte( usercmd.flags );
1444         ReadInt( usercmd.sequence );
1445 }
1446
1447 /*
1448 ===================
1449 idRestoreGame::ReadContactInfo
1450 ===================
1451 */
1452 void idRestoreGame::ReadContactInfo( contactInfo_t &contactInfo ) {
1453         ReadInt( (int &)contactInfo.type );
1454         ReadVec3( contactInfo.point );
1455         ReadVec3( contactInfo.normal );
1456         ReadFloat( contactInfo.dist );
1457         ReadInt( contactInfo.contents );
1458         ReadMaterial( contactInfo.material );
1459         ReadInt( contactInfo.modelFeature );
1460         ReadInt( contactInfo.trmFeature );
1461         ReadInt( contactInfo.entityNum );
1462         ReadInt( contactInfo.id );
1463 }
1464
1465 /*
1466 ===================
1467 idRestoreGame::ReadTrace
1468 ===================
1469 */
1470 void idRestoreGame::ReadTrace( trace_t &trace ) {
1471         ReadFloat( trace.fraction );
1472         ReadVec3( trace.endpos );
1473         ReadMat3( trace.endAxis );
1474         ReadContactInfo( trace.c );
1475 }
1476
1477 /*
1478  ===================
1479  idRestoreGame::ReadTraceModel
1480  ===================
1481  */
1482 void idRestoreGame::ReadTraceModel( idTraceModel &trace ) {
1483         int j, k;
1484         
1485         ReadInt( (int&)trace.type );
1486         ReadInt( trace.numVerts );
1487         for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
1488                 ReadVec3( trace.verts[j] );
1489         }
1490         ReadInt( trace.numEdges );
1491         for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
1492                 ReadInt( trace.edges[j].v[0] );
1493                 ReadInt( trace.edges[j].v[1] );
1494                 ReadVec3( trace.edges[j].normal );
1495         }
1496         ReadInt( trace.numPolys );
1497         for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
1498                 ReadVec3( trace.polys[j].normal );
1499                 ReadFloat( trace.polys[j].dist );
1500                 ReadBounds( trace.polys[j].bounds );
1501                 ReadInt( trace.polys[j].numEdges );
1502                 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
1503                         ReadInt( trace.polys[j].edges[k] );
1504                 }
1505         }
1506         ReadVec3( trace.offset );
1507         ReadBounds( trace.bounds );
1508         ReadBool( trace.isConvex );
1509         // padding win32 native structs
1510         char tmp[3];
1511         file->Read( tmp, 3 );
1512 }
1513
1514 /*
1515 =====================
1516 idRestoreGame::ReadClipModel
1517 =====================
1518 */
1519 void idRestoreGame::ReadClipModel( idClipModel *&clipModel ) {
1520         bool restoreClipModel;
1521
1522         ReadBool( restoreClipModel );
1523         if ( restoreClipModel ) {
1524                 clipModel = new idClipModel();
1525                 clipModel->Restore( this );
1526         } else {
1527                 clipModel = NULL;
1528         }
1529 }
1530
1531 /*
1532 =====================
1533 idRestoreGame::ReadSoundCommands
1534 =====================
1535 */
1536 void idRestoreGame::ReadSoundCommands( void ) {
1537         gameSoundWorld->StopAllSounds();
1538         gameSoundWorld->ReadFromSaveGame( file );
1539 }
1540
1541 /*
1542 =====================
1543 idRestoreGame::ReadBuildNumber
1544 =====================
1545 */
1546 void idRestoreGame::ReadBuildNumber( void ) {
1547         file->ReadInt( buildNumber );
1548 }
1549
1550 /*
1551 =====================
1552 idRestoreGame::GetBuildNumber
1553 =====================
1554 */
1555 int idRestoreGame::GetBuildNumber( void ) {
1556         return buildNumber;
1557 }