]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/game/gamesys/SaveGame.cpp
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / game / 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
545 /*
546 ================
547 idSaveGame::WriteRenderLight
548 ================
549 */
550 void idSaveGame::WriteRenderLight( const renderLight_t &renderLight ) {
551         int i;
552
553         WriteMat3( renderLight.axis );
554         WriteVec3( renderLight.origin );
555
556         WriteInt( renderLight.suppressLightInViewID );
557         WriteInt( renderLight.allowLightInViewID );
558         WriteBool( renderLight.noShadows );
559         WriteBool( renderLight.noSpecular );
560         WriteBool( renderLight.pointLight );
561         WriteBool( renderLight.parallel );
562
563         WriteVec3( renderLight.lightRadius );
564         WriteVec3( renderLight.lightCenter );
565
566         WriteVec3( renderLight.target );
567         WriteVec3( renderLight.right );
568         WriteVec3( renderLight.up );
569         WriteVec3( renderLight.start );
570         WriteVec3( renderLight.end );
571
572         // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
573         // WriteModel( renderLight.prelightModel );
574
575         WriteInt( renderLight.lightId );
576
577         WriteMaterial( renderLight.shader );
578
579         for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
580                 WriteFloat( renderLight.shaderParms[ i ] );
581         }
582
583         if ( renderLight.referenceSound != NULL ) {
584                 WriteInt( renderLight.referenceSound->Index() );
585         } else {
586                 WriteInt( 0 );
587         }
588 }
589
590 /*
591 ================
592 idSaveGame::WriteRefSound
593 ================
594 */
595 void idSaveGame::WriteRefSound( const refSound_t &refSound ) {
596         if ( refSound.referenceSound ) {
597                 WriteInt( refSound.referenceSound->Index() );
598         } else {
599                 WriteInt( 0 );
600         }
601         WriteVec3( refSound.origin );
602         WriteInt( refSound.listenerId );
603         WriteSoundShader( refSound.shader );
604         WriteFloat( refSound.diversity );
605         WriteBool( refSound.waitfortrigger );
606
607         WriteFloat( refSound.parms.minDistance );
608         WriteFloat( refSound.parms.maxDistance );
609         WriteFloat( refSound.parms.volume );
610         WriteFloat( refSound.parms.shakes );
611         WriteInt( refSound.parms.soundShaderFlags );
612         WriteInt( refSound.parms.soundClass );
613 }
614
615 /*
616 ================
617 idSaveGame::WriteRenderView
618 ================
619 */
620 void idSaveGame::WriteRenderView( const renderView_t &view ) {
621         int i;
622
623         WriteInt( view.viewID );
624         WriteInt( view.x );
625         WriteInt( view.y );
626         WriteInt( view.width );
627         WriteInt( view.height );
628
629         WriteFloat( view.fov_x );
630         WriteFloat( view.fov_y );
631         WriteVec3( view.vieworg );
632         WriteMat3( view.viewaxis );
633
634         WriteBool( view.cramZNear );
635
636         WriteInt( view.time );
637
638         for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
639                 WriteFloat( view.shaderParms[ i ] );
640         }
641 }
642
643 /*
644 ===================
645 idSaveGame::WriteUsercmd
646 ===================
647 */
648 void idSaveGame::WriteUsercmd( const usercmd_t &usercmd ) {
649         WriteInt( usercmd.gameFrame );
650         WriteInt( usercmd.gameTime );
651         WriteInt( usercmd.duplicateCount );
652         WriteByte( usercmd.buttons );
653         WriteSignedChar( usercmd.forwardmove );
654         WriteSignedChar( usercmd.rightmove );
655         WriteSignedChar( usercmd.upmove );
656         WriteShort( usercmd.angles[0] );
657         WriteShort( usercmd.angles[1] );
658         WriteShort( usercmd.angles[2] );
659         WriteShort( usercmd.mx );
660         WriteShort( usercmd.my );
661         WriteSignedChar( usercmd.impulse );
662         WriteByte( usercmd.flags );
663         WriteInt( usercmd.sequence );
664 }
665
666 /*
667 ===================
668 idSaveGame::WriteContactInfo
669 ===================
670 */
671 void idSaveGame::WriteContactInfo( const contactInfo_t &contactInfo ) {
672         WriteInt( (int)contactInfo.type );
673         WriteVec3( contactInfo.point );
674         WriteVec3( contactInfo.normal );
675         WriteFloat( contactInfo.dist );
676         WriteInt( contactInfo.contents );
677         WriteMaterial( contactInfo.material );
678         WriteInt( contactInfo.modelFeature );
679         WriteInt( contactInfo.trmFeature );
680         WriteInt( contactInfo.entityNum );
681         WriteInt( contactInfo.id );
682 }
683
684 /*
685 ===================
686 idSaveGame::WriteTrace
687 ===================
688 */
689 void idSaveGame::WriteTrace( const trace_t &trace ) {
690         WriteFloat( trace.fraction );
691         WriteVec3( trace.endpos );
692         WriteMat3( trace.endAxis );
693         WriteContactInfo( trace.c );
694 }
695
696 /*
697  ===================
698  idRestoreGame::WriteTraceModel
699  ===================
700  */
701 void idSaveGame::WriteTraceModel( const idTraceModel &trace ) {
702         int j, k;
703         
704         WriteInt( (int&)trace.type );
705         WriteInt( trace.numVerts );
706         for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
707                 WriteVec3( trace.verts[j] );
708         }
709         WriteInt( trace.numEdges );
710         for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
711                 WriteInt( trace.edges[j].v[0] );
712                 WriteInt( trace.edges[j].v[1] );
713                 WriteVec3( trace.edges[j].normal );
714         }
715         WriteInt( trace.numPolys );
716         for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
717                 WriteVec3( trace.polys[j].normal );
718                 WriteFloat( trace.polys[j].dist );
719                 WriteBounds( trace.polys[j].bounds );
720                 WriteInt( trace.polys[j].numEdges );
721                 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
722                         WriteInt( trace.polys[j].edges[k] );
723                 }
724         }
725         WriteVec3( trace.offset );
726         WriteBounds( trace.bounds );
727         WriteBool( trace.isConvex );
728         // padding win32 native structs
729         char tmp[3];
730         memset( tmp, 0, sizeof( tmp ) );
731         file->Write( tmp, 3 );
732 }
733
734 /*
735 ===================
736 idSaveGame::WriteClipModel
737 ===================
738 */
739 void idSaveGame::WriteClipModel( const idClipModel *clipModel ) {
740         if ( clipModel != NULL ) {
741                 WriteBool( true );
742                 clipModel->Save( this );
743         } else {
744                 WriteBool( false );
745         }
746 }
747
748 /*
749 ===================
750 idSaveGame::WriteSoundCommands
751 ===================
752 */
753 void idSaveGame::WriteSoundCommands( void ) {
754         gameSoundWorld->WriteToSaveGame( file );
755 }
756
757 /*
758 ======================
759 idSaveGame::WriteBuildNumber
760 ======================
761 */
762 void idSaveGame::WriteBuildNumber( const int value ) {
763         file->WriteInt( BUILD_NUMBER );
764 }
765
766 /***********************************************************************
767
768         idRestoreGame
769         
770 ***********************************************************************/
771
772 /*
773 ================
774 idRestoreGame::RestoreGame
775 ================
776 */
777 idRestoreGame::idRestoreGame( idFile *savefile ) {
778         file = savefile;
779 }
780
781 /*
782 ================
783 idRestoreGame::~idRestoreGame()
784 ================
785 */
786 idRestoreGame::~idRestoreGame() {
787 }
788
789 /*
790 ================
791 void idRestoreGame::CreateObjects
792 ================
793 */
794 void idRestoreGame::CreateObjects( void ) {
795         int i, num;
796         idStr classname;
797         idTypeInfo *type;
798
799         ReadInt( num );
800
801         // create all the objects
802         objects.SetNum( num + 1 );
803         memset( objects.Ptr(), 0, sizeof( objects[ 0 ] ) * objects.Num() );
804
805         for( i = 1; i < objects.Num(); i++ ) {
806                 ReadString( classname );
807                 type = idClass::GetClass( classname );
808                 if ( !type ) {
809                         Error( "idRestoreGame::CreateObjects: Unknown class '%s'", classname.c_str() );
810                 }
811                 objects[ i ] = type->CreateInstance();
812
813 #ifdef ID_DEBUG_MEMORY
814                 InitTypeVariables( objects[i], type->classname, 0xce );
815 #endif
816         }
817 }
818
819 /*
820 ================
821 void idRestoreGame::RestoreObjects
822 ================
823 */
824 void idRestoreGame::RestoreObjects( void ) {
825         int i;
826
827         ReadSoundCommands();
828
829         // read trace models
830         idClipModel::RestoreTraceModels( this );
831
832         // restore all the objects
833         for( i = 1; i < objects.Num(); i++ ) {
834                 CallRestore_r( objects[ i ]->GetType(), objects[ i ] );
835         }
836
837         // regenerate render entities and render lights because are not saved
838         for( i = 1; i < objects.Num(); i++ ) {
839                 if ( objects[ i ]->IsType( idEntity::Type ) ) {
840                         idEntity *ent = static_cast<idEntity *>( objects[ i ] );
841                         ent->UpdateVisuals();
842                         ent->Present();
843                 }
844         }
845
846 #ifdef ID_DEBUG_MEMORY
847         idStr gameState = file->GetName();
848         gameState.StripFileExtension();
849         WriteGameState_f( idCmdArgs( va( "test %s_restore", gameState.c_str() ), false ) );
850         //CompareGameState_f( idCmdArgs( va( "test %s_save", gameState.c_str() ) ) );
851         gameLocal.Error( "dumped game states" );
852 #endif
853 }
854
855 /*
856 ====================
857 void idRestoreGame::DeleteObjects
858 ====================
859 */
860 void idRestoreGame::DeleteObjects( void ) {
861
862         // Remove the NULL object before deleting
863         objects.RemoveIndex( 0 );
864
865         objects.DeleteContents( true );
866 }
867
868 /*
869 ================
870 idRestoreGame::Error
871 ================
872 */
873 void idRestoreGame::Error( const char *fmt, ... ) {
874         va_list argptr;
875         char    text[ 1024 ];
876
877         va_start( argptr, fmt );
878         vsprintf( text, fmt, argptr );
879         va_end( argptr );
880
881         objects.DeleteContents( true );
882
883         gameLocal.Error( "%s", text );
884 }
885
886 /*
887 ================
888 idRestoreGame::CallRestore_r
889 ================
890 */
891 void idRestoreGame::CallRestore_r( const idTypeInfo *cls, idClass *obj ) {
892         if ( cls->super ) {
893                 CallRestore_r( cls->super, obj );
894                 if ( cls->super->Restore == cls->Restore ) {
895                         // don't call save on this inheritance level since the function was called in the super class
896                         return;
897                 }
898         }
899         
900         ( obj->*cls->Restore )( this );
901 }
902
903 /*
904 ================
905 idRestoreGame::Read
906 ================
907 */
908 void idRestoreGame::Read( void *buffer, int len ) {
909         file->Read( buffer, len );
910 }
911
912 /*
913 ================
914 idRestoreGame::ReadInt
915 ================
916 */
917 void idRestoreGame::ReadInt( int &value ) {
918         file->ReadInt( value );
919 }
920
921 /*
922 ================
923 idRestoreGame::ReadJoint
924 ================
925 */
926 void idRestoreGame::ReadJoint( jointHandle_t &value ) {
927         file->ReadInt( (int&)value );
928 }
929
930 /*
931 ================
932 idRestoreGame::ReadShort
933 ================
934 */
935 void idRestoreGame::ReadShort( short &value ) {
936         file->ReadShort( value );
937 }
938
939 /*
940 ================
941 idRestoreGame::ReadByte
942 ================
943 */
944 void idRestoreGame::ReadByte( byte &value ) {
945         file->Read( &value, sizeof( value ) );
946 }
947
948 /*
949 ================
950 idRestoreGame::ReadSignedChar
951 ================
952 */
953 void idRestoreGame::ReadSignedChar( signed char &value ) {
954         file->Read( &value, sizeof( value ) );
955 }
956
957 /*
958 ================
959 idRestoreGame::ReadFloat
960 ================
961 */
962 void idRestoreGame::ReadFloat( float &value ) {
963         file->ReadFloat( value );
964 }
965
966 /*
967 ================
968 idRestoreGame::ReadBool
969 ================
970 */
971 void idRestoreGame::ReadBool( bool &value ) {
972         file->ReadBool( value );
973 }
974
975 /*
976 ================
977 idRestoreGame::ReadString
978 ================
979 */
980 void idRestoreGame::ReadString( idStr &string ) {
981         int len;
982
983         ReadInt( len );
984         if ( len < 0 ) {
985                 Error( "idRestoreGame::ReadString: invalid length" );
986         }
987
988         string.Fill( ' ', len );
989         file->Read( &string[ 0 ], len );
990 }
991
992 /*
993 ================
994 idRestoreGame::ReadVec2
995 ================
996 */
997 void idRestoreGame::ReadVec2( idVec2 &vec ) {
998         file->ReadVec2( vec );
999 }
1000
1001 /*
1002 ================
1003 idRestoreGame::ReadVec3
1004 ================
1005 */
1006 void idRestoreGame::ReadVec3( idVec3 &vec ) {
1007         file->ReadVec3( vec );
1008 }
1009
1010 /*
1011 ================
1012 idRestoreGame::ReadVec4
1013 ================
1014 */
1015 void idRestoreGame::ReadVec4( idVec4 &vec ) {
1016         file->ReadVec4( vec );
1017 }
1018
1019 /*
1020 ================
1021 idRestoreGame::ReadVec6
1022 ================
1023 */
1024 void idRestoreGame::ReadVec6( idVec6 &vec ) {
1025         file->ReadVec6( vec );
1026 }
1027
1028 /*
1029 ================
1030 idRestoreGame::ReadBounds
1031 ================
1032 */
1033 void idRestoreGame::ReadBounds( idBounds &bounds ) {
1034         file->Read( &bounds, sizeof( bounds ) );
1035         LittleRevBytes( &bounds, sizeof(float), sizeof(bounds)/sizeof(float) );
1036 }
1037
1038 /*
1039 ================
1040 idRestoreGame::ReadWinding
1041 ================
1042 */
1043 void idRestoreGame::ReadWinding( idWinding &w )
1044 {
1045         int i, num;
1046         file->ReadInt( num );
1047         w.SetNumPoints( num );
1048         for ( i = 0; i < num; i++ ) {
1049                 file->Read( &w[i], sizeof(idVec5) );
1050                 LittleRevBytes(&w[i], sizeof(float), sizeof(idVec5)/sizeof(float) );
1051         }
1052 }
1053
1054 /*
1055 ================
1056 idRestoreGame::ReadMat3
1057 ================
1058 */
1059 void idRestoreGame::ReadMat3( idMat3 &mat ) {
1060         file->ReadMat3( mat );
1061 }
1062
1063 /*
1064 ================
1065 idRestoreGame::ReadAngles
1066 ================
1067 */
1068 void idRestoreGame::ReadAngles( idAngles &angles ) {
1069         file->Read( &angles, sizeof( angles ) );
1070         LittleRevBytes(&angles, sizeof(float), sizeof(idAngles)/sizeof(float) );
1071 }
1072
1073 /*
1074 ================
1075 idRestoreGame::ReadObject
1076 ================
1077 */
1078 void idRestoreGame::ReadObject( idClass *&obj ) {
1079         int index;
1080
1081         ReadInt( index );
1082         if ( ( index < 0 ) || ( index >= objects.Num() ) ) {
1083                 Error( "idRestoreGame::ReadObject: invalid object index" );
1084         }
1085         obj = objects[ index ];
1086 }
1087
1088 /*
1089 ================
1090 idRestoreGame::ReadStaticObject
1091 ================
1092 */
1093 void idRestoreGame::ReadStaticObject( idClass &obj ) {
1094         CallRestore_r( obj.GetType(), &obj );
1095 }
1096
1097 /*
1098 ================
1099 idRestoreGame::ReadDict
1100 ================
1101 */
1102 void idRestoreGame::ReadDict( idDict *dict ) {
1103         int num;
1104         int i;
1105         idStr key;
1106         idStr value;
1107
1108         ReadInt( num );
1109
1110         if ( num < 0 ) {
1111                 dict = NULL;
1112         } else {
1113                 dict->Clear();
1114                 for( i = 0; i < num; i++ ) {
1115                         ReadString( key );
1116                         ReadString( value );
1117                         dict->Set( key, value );
1118                 }
1119         }
1120 }
1121
1122 /*
1123 ================
1124 idRestoreGame::ReadMaterial
1125 ================
1126 */
1127 void idRestoreGame::ReadMaterial( const idMaterial *&material ) {
1128         idStr name;
1129
1130         ReadString( name );
1131         if ( !name.Length() ) {
1132                 material = NULL;
1133         } else {
1134                 material = declManager->FindMaterial( name );
1135         }
1136 }
1137
1138 /*
1139 ================
1140 idRestoreGame::ReadSkin
1141 ================
1142 */
1143 void idRestoreGame::ReadSkin( const idDeclSkin *&skin ) {
1144         idStr name;
1145
1146         ReadString( name );
1147         if ( !name.Length() ) {
1148                 skin = NULL;
1149         } else {
1150                 skin = declManager->FindSkin( name );
1151         }
1152 }
1153
1154 /*
1155 ================
1156 idRestoreGame::ReadParticle
1157 ================
1158 */
1159 void idRestoreGame::ReadParticle( const idDeclParticle *&particle ) {
1160         idStr name;
1161
1162         ReadString( name );
1163         if ( !name.Length() ) {
1164                 particle = NULL;
1165         } else {
1166                 particle = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, name ) );
1167         }
1168 }
1169
1170 /*
1171 ================
1172 idRestoreGame::ReadFX
1173 ================
1174 */
1175 void idRestoreGame::ReadFX( const idDeclFX *&fx ) {
1176         idStr name;
1177
1178         ReadString( name );
1179         if ( !name.Length() ) {
1180                 fx = NULL;
1181         } else {
1182                 fx = static_cast<const idDeclFX *>( declManager->FindType( DECL_FX, name ) );
1183         }
1184 }
1185
1186 /*
1187 ================
1188 idRestoreGame::ReadSoundShader
1189 ================
1190 */
1191 void idRestoreGame::ReadSoundShader( const idSoundShader *&shader ) {
1192         idStr name;
1193
1194         ReadString( name );
1195         if ( !name.Length() ) {
1196                 shader = NULL;
1197         } else {
1198                 shader = declManager->FindSound( name );
1199         }
1200 }
1201
1202 /*
1203 ================
1204 idRestoreGame::ReadModelDef
1205 ================
1206 */
1207 void idRestoreGame::ReadModelDef( const idDeclModelDef *&modelDef ) {
1208         idStr name;
1209
1210         ReadString( name );
1211         if ( !name.Length() ) {
1212                 modelDef = NULL;
1213         } else {
1214                 modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
1215         }
1216 }
1217
1218 /*
1219 ================
1220 idRestoreGame::ReadModel
1221 ================
1222 */
1223 void idRestoreGame::ReadModel( idRenderModel *&model ) {
1224         idStr name;
1225
1226         ReadString( name );
1227         if ( !name.Length() ) {
1228                 model = NULL;
1229         } else {
1230                 model = renderModelManager->FindModel( name );
1231         }
1232 }
1233
1234 /*
1235 ================
1236 idRestoreGame::ReadUserInterface
1237 ================
1238 */
1239 void idRestoreGame::ReadUserInterface( idUserInterface *&ui ) {
1240         idStr name;
1241
1242         ReadString( name );
1243         if ( !name.Length() ) {
1244                 ui = NULL;
1245         } else {
1246                 bool unique;
1247                 ReadBool( unique );
1248                 ui = uiManager->FindGui( name, true, unique );
1249                 if ( ui ) {
1250                         if ( ui->ReadFromSaveGame( file ) == false ) {
1251                                 Error( "idSaveGame::ReadUserInterface: ui failed to read properly\n" );
1252                         } else {
1253                                 ui->StateChanged( gameLocal.time );
1254                         }
1255                 }
1256         }
1257 }
1258
1259 /*
1260 ================
1261 idRestoreGame::ReadRenderEntity
1262 ================
1263 */
1264 void idRestoreGame::ReadRenderEntity( renderEntity_t &renderEntity ) {
1265         int i;
1266         int index;
1267
1268         ReadModel( renderEntity.hModel );
1269
1270         ReadInt( renderEntity.entityNum );
1271         ReadInt( renderEntity.bodyId );
1272
1273         ReadBounds( renderEntity.bounds );
1274
1275         // callback is set by class's Restore function
1276         renderEntity.callback = NULL;
1277         renderEntity.callbackData = NULL;
1278
1279         ReadInt( renderEntity.suppressSurfaceInViewID );
1280         ReadInt( renderEntity.suppressShadowInViewID );
1281         ReadInt( renderEntity.suppressShadowInLightID );
1282         ReadInt( renderEntity.allowSurfaceInViewID );
1283
1284         ReadVec3( renderEntity.origin );
1285         ReadMat3( renderEntity.axis );
1286
1287         ReadMaterial( renderEntity.customShader );
1288         ReadMaterial( renderEntity.referenceShader );
1289         ReadSkin( renderEntity.customSkin );
1290
1291         ReadInt( index );
1292         renderEntity.referenceSound = gameSoundWorld->EmitterForIndex( index );
1293
1294         for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1295                 ReadFloat( renderEntity.shaderParms[ i ] );
1296         }
1297
1298         for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
1299                 ReadUserInterface( renderEntity.gui[ i ] );
1300         }
1301
1302         // idEntity will restore "cameraTarget", which will be used in idEntity::Present to restore the remoteRenderView
1303         renderEntity.remoteRenderView = NULL;
1304
1305         renderEntity.joints = NULL;
1306         renderEntity.numJoints = 0;
1307
1308         ReadFloat( renderEntity.modelDepthHack );
1309
1310         ReadBool( renderEntity.noSelfShadow );
1311         ReadBool( renderEntity.noShadow );
1312         ReadBool( renderEntity.noDynamicInteractions );
1313         ReadBool( renderEntity.weaponDepthHack );
1314
1315         ReadInt( renderEntity.forceUpdate );
1316 }
1317
1318 /*
1319 ================
1320 idRestoreGame::ReadRenderLight
1321 ================
1322 */
1323 void idRestoreGame::ReadRenderLight( renderLight_t &renderLight ) {
1324         int index;
1325         int i;
1326
1327         ReadMat3( renderLight.axis );
1328         ReadVec3( renderLight.origin );
1329
1330         ReadInt( renderLight.suppressLightInViewID );
1331         ReadInt( renderLight.allowLightInViewID );
1332         ReadBool( renderLight.noShadows );
1333         ReadBool( renderLight.noSpecular );
1334         ReadBool( renderLight.pointLight );
1335         ReadBool( renderLight.parallel );
1336
1337         ReadVec3( renderLight.lightRadius );
1338         ReadVec3( renderLight.lightCenter );
1339
1340         ReadVec3( renderLight.target );
1341         ReadVec3( renderLight.right );
1342         ReadVec3( renderLight.up );
1343         ReadVec3( renderLight.start );
1344         ReadVec3( renderLight.end );
1345
1346         // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
1347         // ReadModel( renderLight.prelightModel );
1348         renderLight.prelightModel = NULL;
1349
1350         ReadInt( renderLight.lightId );
1351
1352         ReadMaterial( renderLight.shader );
1353
1354         for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1355                 ReadFloat( renderLight.shaderParms[ i ] );
1356         }
1357
1358         ReadInt( index );
1359         renderLight.referenceSound = gameSoundWorld->EmitterForIndex( index );
1360 }
1361
1362 /*
1363 ================
1364 idRestoreGame::ReadRefSound
1365 ================
1366 */
1367 void idRestoreGame::ReadRefSound( refSound_t &refSound ) {
1368         int             index;
1369         ReadInt( index );
1370
1371         refSound.referenceSound = gameSoundWorld->EmitterForIndex( index );
1372         ReadVec3( refSound.origin );
1373         ReadInt( refSound.listenerId );
1374         ReadSoundShader( refSound.shader );
1375         ReadFloat( refSound.diversity );
1376         ReadBool( refSound.waitfortrigger );
1377
1378         ReadFloat( refSound.parms.minDistance );
1379         ReadFloat( refSound.parms.maxDistance );
1380         ReadFloat( refSound.parms.volume );
1381         ReadFloat( refSound.parms.shakes );
1382         ReadInt( refSound.parms.soundShaderFlags );
1383         ReadInt( refSound.parms.soundClass );
1384 }
1385
1386 /*
1387 ================
1388 idRestoreGame::ReadRenderView
1389 ================
1390 */
1391 void idRestoreGame::ReadRenderView( renderView_t &view ) {
1392         int i;
1393
1394         ReadInt( view.viewID );
1395         ReadInt( view.x );
1396         ReadInt( view.y );
1397         ReadInt( view.width );
1398         ReadInt( view.height );
1399
1400         ReadFloat( view.fov_x );
1401         ReadFloat( view.fov_y );
1402         ReadVec3( view.vieworg );
1403         ReadMat3( view.viewaxis );
1404
1405         ReadBool( view.cramZNear );
1406
1407         ReadInt( view.time );
1408
1409         for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
1410                 ReadFloat( view.shaderParms[ i ] );
1411         }
1412 }
1413
1414 /*
1415 =================
1416 idRestoreGame::ReadUsercmd
1417 =================
1418 */
1419 void idRestoreGame::ReadUsercmd( usercmd_t &usercmd ) {
1420         ReadInt( usercmd.gameFrame );
1421         ReadInt( usercmd.gameTime );
1422         ReadInt( usercmd.duplicateCount );
1423         ReadByte( usercmd.buttons );
1424         ReadSignedChar( usercmd.forwardmove );
1425         ReadSignedChar( usercmd.rightmove );
1426         ReadSignedChar( usercmd.upmove );
1427         ReadShort( usercmd.angles[0] );
1428         ReadShort( usercmd.angles[1] );
1429         ReadShort( usercmd.angles[2] );
1430         ReadShort( usercmd.mx );
1431         ReadShort( usercmd.my );
1432         ReadSignedChar( usercmd.impulse );
1433         ReadByte( usercmd.flags );
1434         ReadInt( usercmd.sequence );
1435 }
1436
1437 /*
1438 ===================
1439 idRestoreGame::ReadContactInfo
1440 ===================
1441 */
1442 void idRestoreGame::ReadContactInfo( contactInfo_t &contactInfo ) {
1443         ReadInt( (int &)contactInfo.type );
1444         ReadVec3( contactInfo.point );
1445         ReadVec3( contactInfo.normal );
1446         ReadFloat( contactInfo.dist );
1447         ReadInt( contactInfo.contents );
1448         ReadMaterial( contactInfo.material );
1449         ReadInt( contactInfo.modelFeature );
1450         ReadInt( contactInfo.trmFeature );
1451         ReadInt( contactInfo.entityNum );
1452         ReadInt( contactInfo.id );
1453 }
1454
1455 /*
1456 ===================
1457 idRestoreGame::ReadTrace
1458 ===================
1459 */
1460 void idRestoreGame::ReadTrace( trace_t &trace ) {
1461         ReadFloat( trace.fraction );
1462         ReadVec3( trace.endpos );
1463         ReadMat3( trace.endAxis );
1464         ReadContactInfo( trace.c );
1465 }
1466
1467 /*
1468  ===================
1469  idRestoreGame::ReadTraceModel
1470  ===================
1471  */
1472 void idRestoreGame::ReadTraceModel( idTraceModel &trace ) {
1473         int j, k;
1474         
1475         ReadInt( (int&)trace.type );
1476         ReadInt( trace.numVerts );
1477         for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
1478                 ReadVec3( trace.verts[j] );
1479         }
1480         ReadInt( trace.numEdges );
1481         for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
1482                 ReadInt( trace.edges[j].v[0] );
1483                 ReadInt( trace.edges[j].v[1] );
1484                 ReadVec3( trace.edges[j].normal );
1485         }
1486         ReadInt( trace.numPolys );
1487         for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
1488                 ReadVec3( trace.polys[j].normal );
1489                 ReadFloat( trace.polys[j].dist );
1490                 ReadBounds( trace.polys[j].bounds );
1491                 ReadInt( trace.polys[j].numEdges );
1492                 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
1493                         ReadInt( trace.polys[j].edges[k] );
1494                 }
1495         }
1496         ReadVec3( trace.offset );
1497         ReadBounds( trace.bounds );
1498         ReadBool( trace.isConvex );
1499         // padding win32 native structs
1500         char tmp[3];
1501         file->Read( tmp, 3 );
1502 }
1503
1504 /*
1505 =====================
1506 idRestoreGame::ReadClipModel
1507 =====================
1508 */
1509 void idRestoreGame::ReadClipModel( idClipModel *&clipModel ) {
1510         bool restoreClipModel;
1511
1512         ReadBool( restoreClipModel );
1513         if ( restoreClipModel ) {
1514                 clipModel = new idClipModel();
1515                 clipModel->Restore( this );
1516         } else {
1517                 clipModel = NULL;
1518         }
1519 }
1520
1521 /*
1522 =====================
1523 idRestoreGame::ReadSoundCommands
1524 =====================
1525 */
1526 void idRestoreGame::ReadSoundCommands( void ) {
1527         gameSoundWorld->StopAllSounds();
1528         gameSoundWorld->ReadFromSaveGame( file );
1529 }
1530
1531 /*
1532 =====================
1533 idRestoreGame::ReadBuildNumber
1534 =====================
1535 */
1536 void idRestoreGame::ReadBuildNumber( void ) {
1537         file->ReadInt( buildNumber );
1538 }
1539
1540 /*
1541 =====================
1542 idRestoreGame::GetBuildNumber
1543 =====================
1544 */
1545 int idRestoreGame::GetBuildNumber( void ) {
1546         return buildNumber;
1547 }