CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

SAVELOAD.CPP (59713B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\saveload.cpv   2.18   16 Oct 1995 16:48:44   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : SAVELOAD.CPP                                                 *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : August 23, 1994                                              *
     28  *                                                                                             *
     29  *                  Last Update : June 24, 1995 [JLB]                                          *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Code_All_Pointers -- Code all pointers.                                                   *
     34  *   Decode_All_Pointers -- Decodes all pointers.                                              *
     35  *   Get_Savefile_Info -- gets description, scenario #, house                                  *
     36  *   Load_Game -- loads a saved game                                                           *
     37  *   Load_Misc_Values -- Loads miscellaneous variables.                                        *
     38  *   Load_Misc_Values -- loads miscellaneous variables                                         *
     39  *   Read_Object -- reads an object from disk, in a safe way                                   *
     40  *   Save_Game -- saves a game to disk                                                         *
     41  *   Save_Misc_Values -- saves miscellaneous variables                                         *
     42  *   Target_To_TechnoType -- converts TARGET to TechnoTypeClass                                *
     43  *   TechnoType_To_Target -- converts TechnoTypeClass to TARGET                                *
     44  *   Write_Object -- reads an object from disk, in a safe way                                  *
     45  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     46 
     47 #include	"function.h"
     48 
     49 extern bool DLLSave(FileClass &file);
     50 extern bool DLLLoad(FileClass &file);
     51 
     52 		
     53 /*
     54 ********************************** Defines **********************************
     55 */
     56 #define	SAVEGAME_VERSION		(DESCRIP_MAX +						\
     57 										0x01000003 + ( 					\
     58 										sizeof(AircraftClass) + 		\
     59 										sizeof(AircraftTypeClass) + 	\
     60 										sizeof(AnimClass) + 				\
     61 										sizeof(AnimTypeClass) + 		\
     62 										sizeof(BuildingClass) + 		\
     63 										sizeof(BuildingTypeClass) + 	\
     64 										sizeof(BulletClass) + 			\
     65 										sizeof(BulletTypeClass) + 		\
     66 										sizeof(HouseClass) + 			\
     67 										sizeof(HouseTypeClass) + 		\
     68 										sizeof(InfantryClass) + 		\
     69 										sizeof(InfantryTypeClass) + 	\
     70 										sizeof(OverlayClass) + 			\
     71 										sizeof(OverlayTypeClass) + 	\
     72 										sizeof(SmudgeClass) + 			\
     73 										sizeof(SmudgeTypeClass) + 		\
     74 										sizeof(TeamClass) + 				\
     75 										sizeof(TeamTypeClass) + 		\
     76 										sizeof(TemplateClass) + 		\
     77 										sizeof(TemplateTypeClass) + 	\
     78 										sizeof(TerrainClass) + 			\
     79 										sizeof(TerrainTypeClass) + 	\
     80 										sizeof(UnitClass) + 				\
     81 										sizeof(UnitTypeClass) + 		\
     82 										sizeof(MouseClass) + 			\
     83 										sizeof(CellClass) + 				\
     84 										sizeof(FactoryClass) + 			\
     85 										sizeof(BaseClass) + 				\
     86 										sizeof(LayerClass) +				\
     87 										sizeof(BriefingText) + \
     88 										sizeof(Waypoint)))
     89 
     90 
     91 /***************************************************************************
     92  * Save_Game -- saves a game to disk                                       *
     93  *                                                                         *
     94  * Saving the Map:                                                         *
     95  *     DisplayClass::Save() invokes CellClass's Write() for every cell     *
     96  *     that needs to be saved.  A cell needs to be saved if it contains    *
     97  *     any special data at all, such as a TIcon, or an Occupier.           *
     98  *   The cell saves its own CellTrigger pointer, converted to a TARGET.    *
     99  *                                                                         *
    100  * Saving game objects:                                                    *
    101  *   - Any object stored in an ArrayOf class needs to be saved.  The ArrayOf*
    102  *     Save() routine invokes each object's Write() routine, if that       *
    103  *     object's IsActive is set.                                           *
    104  *                                                                         *
    105  * Saving the layers:                                                      *
    106  *   The Map's Layers (Ground, Air, etc) of things that are on the map,    *
    107  *     and the Logic's Layer of things to process both need to be saved.   *
    108  *     LayerClass::Save() writes the entire layer array to disk            *
    109  *                                                                         *
    110  * Saving the houses:                                                      *
    111  *   Each house needs to be saved, to record its Credits, Power, etc.      *
    112  *                                                                         *
    113  * Saving miscellaneous data:                                              *
    114  *   There are a lot of miscellaneous variables to save, such as the       *
    115  *     map's dimensions, the player's house, etc.                          *
    116  *                                                                         *
    117  * INPUT:                                                                  *
    118  *      id      numerical ID, for the file extension                       *
    119  *                                                                         *
    120  * OUTPUT:                                                                 *
    121  *      true = OK, false = error                                           *
    122  *                                                                         *
    123  * WARNINGS:                                                               *
    124  *      none.                                                              *
    125  *                                                                         *
    126  * HISTORY:                                                                *
    127  *   12/28/1994 BR : Created.                                              *
    128  *=========================================================================*/
    129 bool Save_Game(int id,char *descr)
    130 {
    131 	char name[_MAX_FNAME+_MAX_EXT];
    132 
    133 	/*
    134 	**	Generate the filename to save
    135 	*/
    136 	sprintf(name, "SAVEGAME.%03d", id);
    137 
    138 	return Save_Game(name, descr);
    139 }
    140 
    141 
    142 /*
    143 ** Version that takes file name. ST - 9/9/2019 11:10AM
    144 */
    145 bool Save_Game(const char *file_name, const char *descr)
    146 {
    147 	RawFileClass file;
    148 	int i;
    149 	unsigned long version;
    150 	unsigned scenario;
    151 	HousesType house;
    152 	char descr_buf[DESCRIP_MAX];
    153 
    154 	scenario = Scenario;								// get current scenario #
    155 	house = PlayerPtr->Class->House;				// get current house
    156 
    157 	/*
    158 	**	Code everybody's pointers
    159 	*/
    160 	Code_All_Pointers();
    161 
    162 	/*
    163 	**	Open the file
    164 	*/
    165 	if (!file.Open(file_name, WRITE)) {
    166 		Decode_All_Pointers();
    167 		return(false);
    168 	}
    169 
    170 	/*
    171 	** Save the DLLs variables first, so we can do a version check in the DLL when we begin the load
    172 	*/
    173 	if (RunningAsDLL) {
    174 		if (!DLLSave(file)) {
    175 			file.Close();
    176 			Decode_All_Pointers();
    177 			return false;
    178 		}
    179 	}
    180 
    181 	/*
    182 	**	Save the description, scenario #, and house
    183 	**	(scenario # & house are saved separately from the actual Scenario &
    184 	**	PlayerPtr globals for convenience; we can quickly find out which
    185 	**	house & scenario this save-game file is for by reading these values.
    186 	**	Also, PlayerPtr is stored in a coded form in Save_Misc_Values(),
    187 	**	which may or may not be a HousesType number; so, saving 'house'
    188 	**	here ensures we can always pull out the house for this file.)
    189 	*/
    190 	sprintf(descr_buf, "%s\r\n",descr);			// put CR-LF after text
    191 	descr_buf[strlen(descr_buf) + 1] = 26;		// put CTRL-Z after NULL
    192 
    193 	if (file.Write(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
    194 		file.Close();
    195 		return(false);
    196 	}
    197 
    198 	if (file.Write(&scenario, sizeof(scenario)) != sizeof(scenario)) {
    199 		file.Close();
    200 		return(false);
    201 	}
    202 
    203 	if (file.Write(&house, sizeof(house)) != sizeof(house)) {
    204 		file.Close();
    205 		return(false);
    206 	}
    207 
    208 	/*
    209 	**	Save the save-game version, for loading verification
    210 	*/
    211 	version = SAVEGAME_VERSION;
    212 
    213 	if (file.Write(&version, sizeof(version)) != sizeof(version)) {
    214 		file.Close();
    215 		return(false);
    216 	}
    217 
    218 	Call_Back();
    219 	/*
    220 	**	Save the map.  The map must be saved first, since it saves the Theater.
    221 	*/
    222 	Map.Save(file);
    223 
    224 	Call_Back();
    225 	/*
    226 	**	Save all game objects.  This code saves every object that's stored in a
    227 	**	TFixedIHeap class.
    228 	*/
    229 	if (!Houses.Save(file)			||
    230 		!TeamTypes.Save(file)		||
    231 		!Teams.Save(file)				||
    232 		!Triggers.Save(file)			||
    233 		!Aircraft.Save(file)			||
    234 		!Anims.Save(file)				||
    235 		!Buildings.Save(file)		||
    236 		!Bullets.Save(file)			||
    237 		!Infantry.Save(file)			||
    238 		!Overlays.Save(file)			||
    239 		!Smudges.Save(file)			||
    240 		!Templates.Save(file)		||
    241 		!Terrains.Save(file)			||
    242 		!Units.Save(file)				||
    243 		!Factories.Save(file)) {
    244 		file.Close();
    245 
    246 		Decode_All_Pointers();
    247 
    248 		return(false);
    249 	}
    250 
    251 	Call_Back();
    252 	/*
    253 	**	Save the Logic & Map layers
    254 	*/
    255 	if (!Logic.Save(file)) {
    256 		file.Close();
    257 		Decode_All_Pointers();
    258 		return(false);
    259 	}
    260 
    261 	for (i = 0; i < LAYER_COUNT; i++) {
    262 		if (!Map.Layer[i].Save(file)) {
    263 			file.Close();
    264 			Decode_All_Pointers();
    265 			return(false);
    266 		}
    267 	}
    268 
    269 	/*
    270 	**	Save the Score
    271 	*/
    272 	if (!Score.Save(file)) {
    273 		file.Close();
    274 		Decode_All_Pointers();
    275 		return(false);
    276 	}
    277 
    278 	/*
    279 	**	Save the AI Base
    280 	*/
    281 	if (!Base.Save(file)) {
    282 		file.Close();
    283 		Decode_All_Pointers();
    284 		return(false);
    285 	}
    286 
    287 	/*
    288 	**	Save miscellaneous variables.
    289 	*/
    290 	if (!Save_Misc_Values(file)) {
    291 		file.Close();
    292 		Decode_All_Pointers();
    293 		return(false);
    294 	}
    295 
    296 	Call_Back();
    297 
    298 	/*
    299 	**	Close the file; we're done
    300 	*/
    301 	file.Close();
    302 	Decode_All_Pointers();
    303 
    304 	return(true);
    305 }
    306 
    307 
    308 /***************************************************************************
    309  * Load_Game -- loads a saved game                                         *
    310  *                                                                         *
    311  * This routine loads the data in the same way it was saved out.           *
    312  *                                                                         *
    313  * Loading the Map:                                                        *
    314  *   - DisplayClass::Load() invokes CellClass's Load() for every cell      *
    315  *     that was saved.                                                     *
    316  * - The cell loads its own CellTrigger pointer.                           *
    317  *                                                                         *
    318  * Loading game objects:                                                   *
    319  * - IHeap's Load() routine loads the # of objects stored, and loads       *
    320  *   each object.                                                          *
    321  * - Triggers: Add themselves to the HouseTriggers if they're associated   *
    322  *   with a house                                                          *
    323  *                                                                         *
    324  * Loading the layers:                                                     *
    325  *     LayerClass::Load() reads the entire layer array to disk             *
    326  *                                                                         *
    327  * Loading the houses:                                                     *
    328  *   Each house is loaded in its entirety.                                 *
    329  *                                                                         *
    330  * Loading miscellaneous data:                                             *
    331  *   There are a lot of miscellaneous variables to load, such as the       *
    332  *     map's dimensions, the player's house, etc.                          *
    333  *                                                                         *
    334  * INPUT:                                                                  *
    335  *      id         numerical ID, for the file extension                    *
    336  *                                                                         *
    337  * OUTPUT:                                                                 *
    338  *      true = OK, false = error                                           *
    339  *                                                                         *
    340  * WARNINGS:                                                               *
    341  *      If this routine returns false, the entire game will be in an       *
    342  *      unknown state, so the scenario will have to be re-initialized.     *
    343  *                                                                         *
    344  * HISTORY:                                                                *
    345  *   12/28/1994 BR : Created.                                              *
    346  *=========================================================================*/
    347 bool Load_Game(int id)
    348 {
    349 	char name[_MAX_FNAME+_MAX_EXT];
    350 	
    351 	/*
    352 	**	Generate the filename to load
    353 	*/
    354 	sprintf(name, "SAVEGAME.%03d", id);
    355 	
    356 	return Load_Game(name);
    357 }
    358 
    359 /*
    360 ** Version that takes a file name instead. ST - 9/9/2019 11:13AM
    361 */
    362 bool Load_Game(const char *file_name)
    363 {
    364 	RawFileClass file;
    365 	int i;
    366 	unsigned long version;
    367 	unsigned scenario;
    368 	HousesType house;
    369 	char descr_buf[DESCRIP_MAX];
    370 
    371 	/*
    372 	**	Open the file
    373 	*/
    374 	if (!file.Open(file_name, READ)) {
    375 		return(false);
    376 	}
    377 
    378 	/*
    379 	** Load the DLLs variables first, in case we need to do something different based on version
    380 	*/
    381 	if (RunningAsDLL) {
    382 		if (!DLLLoad(file)) {
    383 			file.Close();
    384 			return false;
    385 		}
    386 	}
    387 
    388 	/*
    389 	**	Read & discard the save-game's header info
    390 	*/
    391 	if (file.Read(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
    392 		file.Close();
    393 		return(false);
    394 	}
    395 
    396 	if (file.Read(&scenario, sizeof(scenario)) != sizeof(scenario)) {
    397 		file.Close();
    398 		return(false);
    399 	}
    400 
    401 	if (file.Read(&house, sizeof(house)) != sizeof(house)) {
    402 		file.Close();
    403 		return(false);
    404 	}
    405 
    406 	Call_Back();
    407 	/*
    408 	**	Clear the scenario so we start fresh; this calls the Init_Clear() routine
    409 	**	for the Map, and all object arrays.  It has the following important
    410 	**	effects:
    411 	**	- Every cell is cleared to 0's, via MapClass::Init_Clear()
    412 	**	- All heap elements' are cleared
    413 	**	- The Houses are Initialized, which also clears their HouseTriggers
    414 	**	  array
    415 	**	- The map's Layers & Logic Layer are cleared to empty
    416 	**	- The list of currently-selected objects is cleared
    417 	*/
    418 	Clear_Scenario();
    419 
    420 	/*
    421 	**	Read in & verify the save-game ID code
    422 	*/
    423 	if (file.Read(&version,sizeof(version)) != sizeof(version)) {
    424 		file.Close();
    425 		return(false);
    426 	}
    427 
    428 	if (version != SAVEGAME_VERSION) {
    429 		file.Close();
    430 		return(false);
    431 	}
    432 
    433 	Call_Back();
    434 	/*
    435 	**	Set the required CD to be in the drive according to the scenario
    436 	**	loaded.
    437 	*/
    438 	if (RequiredCD != -2) {
    439 		if (scenario >= 20 && scenario <60 && GameToPlay == GAME_NORMAL) {
    440 			RequiredCD = 2;
    441 		} else {
    442 			if (scenario >= 60){
    443 				/*
    444 				** This is a gateway bonus scenario
    445 				*/
    446 				RequiredCD = -1;
    447 			}else{
    448 				if (house == HOUSE_GOOD) {
    449 					RequiredCD = 0;
    450 				} else {
    451 					RequiredCD = 1;
    452 				}
    453 			}
    454 		}
    455 	}
    456 	if(!Force_CD_Available(RequiredCD)) {
    457 		Prog_End("Load_Game - CD not found", true);
    458 		if (!RunningAsDLL) {
    459 			exit(EXIT_FAILURE);
    460 		}
    461 		return false;
    462 	}
    463 
    464 	Call_Back();
    465 
    466 	/*
    467 	**	Load the map.  The map comes first, since it loads the Theater & init's
    468 	**	mixfiles.  The map calls all the type-class's Init routines, telling them
    469 	**	what the Theater is; this must be done before any objects are created, so
    470 	**	they'll be properly created.
    471 	*/
    472 	Map.Load(file);
    473 
    474 	Call_Back();
    475 	/*
    476 	**	Load the object data.
    477 	*/
    478 	if (!Houses.Load(file)			||
    479 		!TeamTypes.Load(file)		||
    480 		!Teams.Load(file)				||
    481 		!Triggers.Load(file)			||
    482 		!Aircraft.Load(file)			||
    483 		!Anims.Load(file)				||
    484 		!Buildings.Load(file)		||
    485 		!Bullets.Load(file)			||
    486 		!Infantry.Load(file)			||
    487 		!Overlays.Load(file)			||
    488 		!Smudges.Load(file)			||
    489 		!Templates.Load(file)		||
    490 		!Terrains.Load(file)			||
    491 		!Units.Load(file)				||
    492 		!Factories.Load(file)) {
    493 		file.Close();
    494 		return(false);
    495 	}
    496 
    497 	Call_Back();
    498 	/*
    499 	**	Load the Logic & Map Layers
    500 	*/
    501 	if (!Logic.Load(file)) {
    502 		file.Close();
    503 		return(false);
    504 	}
    505 	for (i = 0; i < LAYER_COUNT; i++) {
    506 		if (!Map.Layer[i].Load(file)) {
    507 			file.Close();
    508 			return(false);
    509 		}
    510 	}
    511 
    512 	Call_Back();
    513 	/*
    514 	**	Load the Score
    515 	*/
    516 	if (!Score.Load(file)) {
    517 		file.Close();
    518 		return(false);
    519 	}
    520 
    521 	/*
    522 	**	Load the AI Base
    523 	*/
    524 	if (!Base.Load(file)) {
    525 		file.Close();
    526 		return(false);
    527 	}
    528 
    529 	/*
    530 	**	Load miscellaneous variables, including the map size & the Theater
    531 	*/
    532 	if (!Load_Misc_Values(file)) {
    533 		file.Close();
    534 		return(false);
    535 	}
    536 
    537 	file.Close();
    538 	Decode_All_Pointers();
    539 	Map.Init_IO();
    540 	Map.Flag_To_Redraw(true);
    541 
    542 	Fixup_Scenario();
    543 
    544 	ScenarioInit = 0;
    545 
    546 	/*
    547 	** Fixup remap tables. ST - 2/28/2020 1:50PM
    548 	*/
    549 	for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
    550 		HouseClass * hptr = HouseClass::As_Pointer(house);
    551 		if (hptr && hptr->IsActive) {
    552 			hptr->Init_Data(hptr->RemapColor, hptr->ActLike, hptr->Credits);
    553 		}
    554 	}
    555 
    556 	/*
    557 	** Re-init unit trackers. They will be garbage pointers after the load
    558 	*/
    559 	for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
    560 		HouseClass * hptr = HouseClass::As_Pointer(house);
    561 		if (hptr && hptr->IsActive) {
    562 			hptr->Init_Unit_Trackers();
    563 		}
    564 	}
    565 
    566 #ifdef DEMO
    567 	if (Scenario != 10 && Scenario != 1 && Scenario != 6) {
    568 		Clear_Scenario();
    569 		return(false);
    570 	}
    571 #endif
    572 
    573 	Call_Back();
    574 	return(true);
    575 }
    576 
    577 
    578 /***************************************************************************
    579  * Save_Misc_Values -- saves miscellaneous variables                       *
    580  *                                                                         *
    581  * INPUT:                                                                  *
    582  *      file      file to use for writing                                  *
    583  *                                                                         *
    584  * OUTPUT:                                                                 *
    585  *      true = success, false = failure                                    *
    586  *                                                                         *
    587  * WARNINGS:                                                               *
    588  *      none.                                                              *
    589  *                                                                         *
    590  * HISTORY:                                                                *
    591  *   12/29/1994 BR : Created.                                              *
    592  *=========================================================================*/
    593 bool Save_Misc_Values(FileClass &file)
    594 {
    595 	int i, j;
    596 	int count;								// # ptrs in 'CurrentObject'
    597 	ObjectClass * ptr;					// for saving 'CurrentObject' ptrs
    598 
    599 	/*
    600 	**	Player's House.
    601 	*/
    602 	if (file.Write(&PlayerPtr, sizeof(PlayerPtr)) != sizeof(PlayerPtr)) {
    603 		return(false);
    604 	}
    605 
    606 	/*
    607 	**	Save this scenario number.
    608 	*/
    609 	if (file.Write(&Scenario, sizeof(Scenario)) != sizeof(Scenario)) {
    610 		return(false);
    611 	}
    612 
    613 	/*
    614 	**	Save frame #.
    615 	*/
    616 	if (file.Write(&Frame, sizeof(Frame)) != sizeof(Frame)) {
    617 		return(false);
    618 	}
    619 
    620 	/*
    621 	**	Save VQ Movie names.
    622 	*/
    623 	if (file.Write(WinMovie, sizeof(WinMovie)) != sizeof(WinMovie)) {
    624 		return(false);
    625 	}
    626 
    627 	if (file.Write(LoseMovie, sizeof(LoseMovie)) != sizeof(LoseMovie)) {
    628 		return(false);
    629 	}
    630 
    631 	/*
    632 	**	Save currently-selected objects list.
    633 	**	Save the # of ptrs in the list.
    634 	*/
    635 	for (i = 0; i < SelectedObjectsType::COUNT; i++) {
    636 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
    637 		count = selection.Count();
    638 		if (file.Write(&count, sizeof(count)) != sizeof(count)) {
    639 			return(false);
    640 		}
    641 
    642 		/*
    643 		**	Save the pointers.
    644 		*/
    645 		for (j = 0; j < count; j++) {
    646 			ptr = selection[j];
    647 			if (file.Write(&ptr, sizeof(ptr)) != sizeof(ptr)) {
    648 				return(false);
    649 			}
    650 		}
    651 	}
    652 
    653 	/*
    654 	**	Save the list of waypoints.
    655 	*/
    656 	if (file.Write(Waypoint, sizeof(Waypoint)) != sizeof(Waypoint)) {
    657 		return(false);
    658 	}
    659 
    660 	file.Write(&ScenDir, sizeof(ScenDir));
    661 	file.Write(&ScenVar, sizeof(ScenVar));
    662 	file.Write(&CarryOverMoney, sizeof(CarryOverMoney));
    663 	file.Write(&CarryOverPercent, sizeof(CarryOverPercent));
    664 	file.Write(&BuildLevel, sizeof(BuildLevel));
    665 	file.Write(BriefMovie, sizeof(BriefMovie));
    666 	file.Write(Views, sizeof(Views));
    667 	file.Write(&EndCountDown, sizeof(EndCountDown));
    668 	file.Write(BriefingText, sizeof(BriefingText));
    669 
    670 	// This is new...
    671 	file.Write(ActionMovie, sizeof(ActionMovie));
    672 
    673 	return(true);
    674 }
    675 
    676 
    677 /***********************************************************************************************
    678  * Load_Misc_Values -- Loads miscellaneous variables.                                          *
    679  *                                                                                             *
    680  * INPUT:   file  -- The file to load the misc values from.                                    *
    681  *                                                                                             *
    682  * OUTPUT:  Was the misc load process successful?                                              *
    683  *                                                                                             *
    684  * WARNINGS:   none                                                                            *
    685  *                                                                                             *
    686  * HISTORY:                                                                                    *
    687  *   06/24/1995 BRR : Created.                                                                 *
    688  *=============================================================================================*/
    689 bool Load_Misc_Values(FileClass &file)
    690 {
    691 	int i, j;
    692 	int count;								// # ptrs in 'CurrentObject'
    693 	ObjectClass * ptr;					// for loading 'CurrentObject' ptrs
    694 
    695 	/*
    696 	**	Player's House.
    697 	*/
    698 	if (file.Read(&PlayerPtr, sizeof(PlayerPtr)) != sizeof(PlayerPtr)) {
    699 		return(false);
    700 	}
    701 
    702 	/*
    703 	**	Read this scenario number.
    704 	*/
    705 	if (file.Read(&Scenario,sizeof(Scenario)) != sizeof(Scenario)) {
    706 		return(false);
    707 	}
    708 
    709 	/*
    710 	**	Load frame #.
    711 	*/
    712 	if (file.Read(&Frame, sizeof(Frame)) != sizeof(Frame)) {
    713 		return(false);
    714 	}
    715 
    716 	/*
    717 	**	Load VQ Movie names.
    718 	*/
    719 	if (file.Read(WinMovie, sizeof(WinMovie)) != sizeof(WinMovie)) {
    720 		return(false);
    721 	}
    722 
    723 	if (file.Read(LoseMovie, sizeof(LoseMovie)) != sizeof(LoseMovie)) {
    724 		return(false);
    725 	}
    726 
    727 	for (i = 0; i < SelectedObjectsType::COUNT; i++) {
    728 		/*
    729 		**	Load currently-selected objects list.
    730 		**	Load the # of ptrs in the list.
    731 		*/
    732 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
    733 		if (file.Read(&count, sizeof(count)) != sizeof(count)) {
    734 			return(false);
    735 		}
    736 
    737 		/*
    738 		**	Load the pointers.
    739 		*/
    740 		for (j = 0; j < count; j++) {
    741 			if (file.Read(&ptr, sizeof(ptr)) != sizeof(ptr)) {
    742 				return(false);
    743 			}
    744 			selection.Add(ptr);	// add to the list
    745 		}
    746 	}
    747 
    748 	/*
    749 	**	Save the list of waypoints.
    750 	*/
    751 	if (file.Read(Waypoint, sizeof(Waypoint)) != sizeof(Waypoint)) {
    752 		return(false);
    753 	}
    754 
    755 	file.Read(&ScenDir, sizeof(ScenDir));
    756 	file.Read(&ScenVar, sizeof(ScenVar));
    757 	file.Read(&CarryOverMoney, sizeof(CarryOverMoney));
    758 	file.Read(&CarryOverPercent, sizeof(CarryOverPercent));
    759 	file.Read(&BuildLevel, sizeof(BuildLevel));
    760 	file.Read(BriefMovie, sizeof(BriefMovie));
    761 	file.Read(Views, sizeof(Views));
    762 	file.Read(&EndCountDown, sizeof(EndCountDown));
    763 	file.Read(BriefingText, sizeof(BriefingText));
    764 
    765 	if (file.Seek(0, SEEK_CUR) < file.Size()) {
    766 		file.Read(ActionMovie, sizeof(ActionMovie));
    767 	}
    768 
    769 	return(true);
    770 }
    771 
    772 
    773 /*
    774 ** ST - 9/26/2019 11:43AM
    775 */
    776 extern void DLL_Code_Pointers(void);
    777 extern void DLL_Decode_Pointers(void);
    778 
    779 
    780 /***********************************************************************************************
    781  * Code_All_Pointers -- Code all pointers.                                                     *
    782  *                                                                                             *
    783  * INPUT:   none                                                                               *
    784  *                                                                                             *
    785  * OUTPUT:  none                                                                               *
    786  *                                                                                             *
    787  * WARNINGS:   none                                                                            *
    788  *                                                                                             *
    789  * HISTORY:                                                                                    *
    790  *   06/24/1995 BRR : Created.                                                                 *
    791  *=============================================================================================*/
    792 void Code_All_Pointers(void)
    793 {
    794 	int i, j;
    795 
    796 	/*
    797 	**	The Map.
    798 	*/
    799 	Map.Code_Pointers();
    800 
    801 	/*
    802 	**	The ArrayOf's.
    803 	*/
    804 	TeamTypes.Code_Pointers();
    805 	Teams.Code_Pointers();
    806 	Triggers.Code_Pointers();
    807 	Aircraft.Code_Pointers();
    808 	Anims.Code_Pointers();
    809 	Buildings.Code_Pointers();
    810 	Bullets.Code_Pointers();
    811 	Infantry.Code_Pointers();
    812 	Overlays.Code_Pointers();
    813 	Smudges.Code_Pointers();
    814 	Templates.Code_Pointers();
    815 	Terrains.Code_Pointers();
    816 	Units.Code_Pointers();
    817 	Factories.Code_Pointers();
    818 
    819 	/*
    820 	**	The Layers.
    821 	*/
    822 	Logic.Code_Pointers();
    823 	for (i = 0; i < LAYER_COUNT; i++) {
    824 		Map.Layer[i].Code_Pointers();
    825 	}
    826 
    827 	/*
    828 	**	The Score.
    829 	*/
    830 	Score.Code_Pointers();
    831 
    832 	/*
    833 	**	The Base.
    834 	*/
    835 	Base.Code_Pointers();
    836 
    837 	/*
    838 	**	PlayerPtr.
    839 	*/
    840 	PlayerPtr = (HouseClass *)(PlayerPtr->Class->House);
    841 
    842 	/*
    843 	**	Currently-selected objects.
    844 	*/
    845 	for (i = 0; i < SelectedObjectsType::COUNT; i++) {
    846 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
    847 		for (j = 0; j < selection.Count(); j++) {
    848 			selection[j] = (ObjectClass *)selection[j]->As_Target();
    849 		}
    850 	}
    851 
    852 	/*
    853 	** DLL data
    854 	*/
    855 	DLL_Code_Pointers();
    856 
    857 	/*
    858 	** Houses must be coded last, because the Class->House member of the HouseClass
    859 	** is used to code HouseClass pointers for all other objects, and if Class is
    860 	** coded, it will point to a meaningless value.
    861 	*/
    862 	Houses.Code_Pointers();
    863 }
    864 
    865 
    866 /***********************************************************************************************
    867  * Decode_All_Pointers -- Decodes all pointers.                                                *
    868  *                                                                                             *
    869  * INPUT:   none                                                                               *
    870  *                                                                                             *
    871  * OUTPUT:  none                                                                               *
    872  *                                                                                             *
    873  * WARNINGS:   none                                                                            *
    874  *                                                                                             *
    875  * HISTORY:                                                                                    *
    876  *   06/24/1995 BRR : Created.                                                                 *
    877  *=============================================================================================*/
    878 void Decode_All_Pointers(void)
    879 {
    880 	int i, j;
    881 
    882 	/*
    883 	**	The Map.
    884 	*/
    885 	Map.Decode_Pointers();
    886 
    887 	/*
    888 	** Decode houses first, so we can properly decode all other objects'
    889 	** House pointers
    890 	*/
    891 	Houses.Decode_Pointers();
    892 
    893 	/*
    894 	** DLL data
    895 	*/
    896 	DLL_Decode_Pointers();
    897 
    898 	/*
    899 	**	The ArrayOf's.
    900 	*/
    901 	TeamTypes.Decode_Pointers();
    902 	Teams.Decode_Pointers();
    903 	Triggers.Decode_Pointers();
    904 	Aircraft.Decode_Pointers();
    905 	Anims.Decode_Pointers();
    906 	Buildings.Decode_Pointers();
    907 	Bullets.Decode_Pointers();
    908 	Infantry.Decode_Pointers();
    909 	Overlays.Decode_Pointers();
    910 	Smudges.Decode_Pointers();
    911 	Templates.Decode_Pointers();
    912 	Terrains.Decode_Pointers();
    913 	Units.Decode_Pointers();
    914 	Factories.Decode_Pointers();
    915 
    916 	/*
    917 	**	The Layers.
    918 	*/
    919 	Logic.Decode_Pointers();
    920 	for (i = 0; i < LAYER_COUNT; i++) {
    921 		Map.Layer[i].Decode_Pointers();
    922 	}
    923 
    924 	/*
    925 	**	The Score.
    926 	*/
    927 	Score.Decode_Pointers();
    928 
    929 	/*
    930 	**	The Base.
    931 	*/
    932 	Base.Decode_Pointers();
    933 
    934 	/*
    935 	**	PlayerPtr.
    936 	*/
    937 	PlayerPtr = HouseClass::As_Pointer(*((HousesType*)&PlayerPtr));
    938 	Whom = PlayerPtr->Class->House;
    939 	switch (PlayerPtr->Class->House) {
    940 		case HOUSE_GOOD:
    941 			ScenPlayer = SCEN_PLAYER_GDI;
    942 			break;
    943 
    944 		case HOUSE_BAD:
    945 			ScenPlayer = SCEN_PLAYER_NOD;
    946 			break;
    947 
    948 		case HOUSE_JP:
    949 			ScenPlayer = SCEN_PLAYER_JP;
    950 			break;
    951 	}
    952 	Check_Ptr(PlayerPtr,__FILE__,__LINE__);
    953 	
    954 	if (PlayerPtr->ActLike == HOUSE_JP) {
    955 		ScenPlayer = SCEN_PLAYER_JP;
    956 	}
    957 	Set_Scenario_Name(ScenarioName, Scenario, ScenPlayer, ScenDir, ScenVar);
    958 
    959 	/*
    960 	**	Currently-selected objects.
    961 	*/
    962 	for (i = 0; i < SelectedObjectsType::COUNT; i++) {
    963 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
    964 		for (j = 0; j < selection.Count(); j++) {
    965 			unsigned long target_as_object_ptr = reinterpret_cast<unsigned long>(selection[j]);
    966 			TARGET target = (TARGET)target_as_object_ptr;
    967 			selection[j] = As_Object(target);
    968 			Check_Ptr(selection[j],__FILE__,__LINE__);
    969 		}
    970 	}
    971 
    972 	/*
    973 	**	Last-Minute Fixups; to resolve these pointers properly requires all other
    974 	**	pointers to be loaded & decoded.
    975 	*/
    976 	if (Map.PendingObjectPtr) {
    977 		Map.PendingObject = &Map.PendingObjectPtr->Class_Of();
    978 		Check_Ptr((void *)Map.PendingObject, __FILE__, __LINE__);
    979 		Map.Set_Cursor_Shape(Map.PendingObject->Occupy_List(true));
    980 	} else {
    981 		Map.PendingObject = 0;
    982 		Map.Set_Cursor_Shape(0);
    983 	}
    984 }
    985 
    986 
    987 /***********************************************************************************************
    988  * Read_Object -- reads an object from a file                                                  *
    989  *                                                                                             *
    990  *    Replacement for the original code below, which doesn't work with MSVC                    *
    991  *    We now assume that the vtable is 4 bytes, and is at the beginning of the class           *
    992  *    It's the caller's responsibility to make sure the VTable is correct                      *
    993  *                                                                                             *
    994  * INPUT:   none                                                                               *
    995  *                                                                                             *
    996  * OUTPUT:  none                                                                               *
    997  *                                                                                             *
    998  * WARNINGS:   none                                                                            *
    999  *                                                                                             *
   1000  * HISTORY:                                                                                    *
   1001  *   01/10/1995 BR : Created.                                                                  *
   1002  *   9/10/2019 12:34PM ST : Updated for MS compiler                                            *
   1003  *=============================================================================================*/
   1004 bool Read_Object(void *ptr, int class_size, FileClass & file, bool has_vtable)
   1005 {
   1006 	int size;
   1007 
   1008 	/*
   1009 	**	Read size of this chunk.
   1010 	*/
   1011 	if (file.Read(&size,sizeof(size)) != sizeof(size)) {
   1012 		return(false);
   1013 	}
   1014 	
   1015 	/*
   1016 	**	Error if incorrect size.
   1017 	*/
   1018 	if (size != class_size) {
   1019 		return false;
   1020 	}
   1021 	
   1022 	int vtable_adjust = has_vtable ? 4 : 0;
   1023 	unsigned char *object_ptr = static_cast<unsigned char *>(ptr);
   1024 
   1025 	if (has_vtable) {
   1026 		/*
   1027 		** Need to skip the vtable read.
   1028 		*/
   1029 		int dummy;
   1030 		file.Read(&dummy, vtable_adjust);
   1031 	}
   1032 
   1033 	/*
   1034 	**	Read object data.
   1035 	*/
   1036 	if (file.Read(object_ptr + vtable_adjust, class_size - vtable_adjust) != (class_size - vtable_adjust)) {
   1037 		return(false);
   1038 	}
   1039 
   1040 	return true;
   1041 }	
   1042 		
   1043 		
   1044 #if (0)
   1045 /***********************************************************************************************
   1046  * Write_Object -- writes an object to a file                                                  *
   1047  *                                                                                             *
   1048  * This routine writes an object, skipping the embedded virtual function table pointer.        *
   1049  *                                                                                             *
   1050  * INPUT:                                                                                      *
   1051  *      ptr            pointer to object to write                                              *
   1052  *      class_size      size of the class itself                                               *
   1053  *      file            file to use for I/O                                                    *
   1054  *                                                                                             *
   1055  * OUTPUT:                                                                                     *
   1056  *      true = OK, false = error                                                               *
   1057  *                                                                                             *
   1058  * WARNINGS:                                                                                   *
   1059  *      This routine ASSUMES the program modules are compiled with:                            *
   1060  *      -Vb-      Always make the virtual function table ptr 2 bytes long                      *
   1061  *      -Vt      Put the virtual function table after the 1st class's data                     *
   1062  *                                                                                             *
   1063  *    Also see warnings for Read_Object().                                                     *
   1064  *                                                                                             *
   1065  * HISTORY:                                                                                    *
   1066  *   01/10/1995 BR : Created.                                                                  *
   1067  *   9/10/2019 12:34PM ST : Updated for MS compiler                                            *
   1068  *=============================================================================================*/
   1069 bool Write_Object(void *ptr, int class_size, FileClass & file)
   1070 {
   1071 	/*
   1072 	** Test assumptions about class size.
   1073 	*/
   1074 	class TestClass {
   1075 		virtual void Test(void) = 0;
   1076 	};	
   1077 
   1078 	if (sizeof(TestClass) != 4) {
   1079 		/*
   1080 		** Crash.
   1081 		*/
   1082 		*((int*)0) = 0;
   1083 	}
   1084 	
   1085 	/*
   1086 	**	Save size of this chunk.
   1087 	*/
   1088 	if (file.Write(&class_size,sizeof(class_size)) != sizeof(class_size)) {
   1089 		return(false);
   1090 	}
   1091 
   1092 	/*
   1093 	**	Save object data.
   1094 	*/
   1095 	if (file.Write(ptr, class_size) != (class_size)) {
   1096 		return(false);
   1097 	}
   1098 
   1099 	return(true);
   1100 }
   1101 
   1102 
   1103 #endif
   1104 		
   1105 		
   1106 #if (0)		//ST - 9/10/2019 12:43PM
   1107 		  
   1108 /***********************************************************************************************
   1109  * Read_Object -- reads an object from disk                                                    *
   1110  *                                                                                             *
   1111  * This routine reads in an object and fills in the virtual function table pointer.            *
   1112  *                                                                                             *
   1113  * INPUT:                                                                                      *
   1114  *      ptr            pointer to object to read                                               *
   1115  *      base_size      size of object's absolute base class                                    *
   1116  *      class_size      size of the class itself                                               *
   1117  *      file            file to use for I/O                                                    *
   1118  *      vtable         virtual function table pointer value, NULL if none                      *
   1119  *                                                                                             *
   1120  * OUTPUT:                                                                                     *
   1121  *      true = OK, false = error                                                               *
   1122  *                                                                                             *
   1123  * WARNINGS:                                                                                   *
   1124  *      This routine ASSUMES the program modules are compiled with:                            *
   1125  *      -Vb-      Always make the virtual function table ptr 2 bytes long                      *
   1126  *      -Vt      Put the virtual function table after the 1st class's data                     *
   1127  *                                                                                             *
   1128  *      ALSO, the class used to compute 'base_size' must come first in a multiple-inheritence  *
   1129  *      hierarchy.  AND, if your class multiply-inherits from other classes, only ONE of those *
   1130  *      classes can contain virtual functions!  If you include virtual functions in the other  *
   1131  *      classes, the compiler will generate multiple virtual function tables, and this load/save *
   1132  *      technique will fail.                                                                   *
   1133  *                                                                                             *
   1134  *      Each class hierarchy is stored in memory as a chain: first the data for the base-est   *
   1135  *      class, then the virtual function table pointer for this hierarchy, then the data for   *
   1136  *      all derived classes.  If any of these derived classes multiply-inherit, the base class *
   1137  *      for the multiple inheritance is stored as a separate chain following this chain.  The  *
   1138  *      new chain will contain its own virtual function table pointer, if the multiply-        *
   1139  *      inherited hierarchy contains any virtual functions.  Thus, the declaration             *
   1140  *         class A                                                                             *
   1141  *         class B: public A                                                                   *
   1142  *         class C: public B, X                                                                *
   1143  *      is stored as:                                                                          *
   1144  *         A data                                                                              *
   1145  *         A's Virtual Table Pointer                                                           *
   1146  *         B data                                                                              *
   1147  *         X data                                                                              *
   1148  *         [X's Virtual Table Pointer]                                                         *
   1149  *         C data                                                                              *
   1150  *                                                                                             *
   1151  *      and                                                                                    *
   1152  *         class A                                                                             *
   1153  *         class B: public A                                                                   *
   1154  *         class C: public X, B                                                                *
   1155  *      is stored in memory as:                                                                *
   1156  *         X data                                                                              *
   1157  *         [X's Virtual Table Pointer]                                                         *
   1158  *         A data                                                                              *
   1159  *         A's Virtual Table Pointer                                                           *
   1160  *         B data                                                                              *
   1161  *         C data                                                                              *
   1162  *                                                                                             *
   1163  *                                                                                             *
   1164  * HISTORY:                                                                                    *
   1165  *   01/10/1995 BR : Created.                                                                  *
   1166  *=============================================================================================*/
   1167 bool Read_Object(void *ptr, int base_size, int class_size, FileClass & file, void * vtable)
   1168 {
   1169 	int size;					// object size in bytes
   1170 
   1171 	/*
   1172 	**	Read size of this chunk.
   1173 	*/
   1174 	if (file.Read(&size,sizeof(size)) != sizeof(size)) {
   1175 		return(false);
   1176 	}
   1177 
   1178 	/*
   1179 	**	Error if incorrect size.
   1180 	*/
   1181 	if (size != class_size) {
   1182 		return(false);
   1183 	}
   1184 
   1185 	/*
   1186 	**	Read object data.
   1187 	*/
   1188 	if (file.Read(ptr, class_size) != (class_size)) {
   1189 		return(false);
   1190 	}
   1191 
   1192 	/*
   1193 	**	Fill in VTable.
   1194 	*/
   1195 	if (vtable) {
   1196 		((void **)(((char *)ptr) + base_size - 4))[0] = vtable;
   1197 	}
   1198 
   1199 	return(true);
   1200 }
   1201 
   1202 #endif
   1203 
   1204 
   1205 
   1206 /***********************************************************************************************
   1207  * Write_Object -- reads an object from disk, in a safe way                                    *
   1208  *                                                                                             *
   1209  * This routine writes an object in 2 pieces, skipping the embedded                            *
   1210  * virtual function table pointer.                                                             *
   1211  *                                                                                             *
   1212  * INPUT:                                                                                      *
   1213  *      ptr            pointer to object to write                                              *
   1214  *      class_size      size of the class itself                                               *
   1215  *      file            file to use for I/O                                                    *
   1216  *                                                                                             *
   1217  * OUTPUT:                                                                                     *
   1218  *      true = OK, false = error                                                               *
   1219  *                                                                                             *
   1220  * WARNINGS:                                                                                   *
   1221  *      This routine ASSUMES the program modules are compiled with:                            *
   1222  *      -Vb-      Always make the virtual function table ptr 2 bytes long                      *
   1223  *      -Vt      Put the virtual function table after the 1st class's data                     *
   1224  *                                                                                             *
   1225  *    Also see warnings for Read_Object().                                                     *
   1226  *                                                                                             *
   1227  * HISTORY:                                                                                    *
   1228  *   01/10/1995 BR : Created.                                                                  *
   1229  *=============================================================================================*/
   1230 bool Write_Object(void *ptr, int class_size, FileClass & file)
   1231 {
   1232 	/*
   1233 	**	Save size of this chunk.
   1234 	*/
   1235 	if (file.Write(&class_size,sizeof(class_size)) != sizeof(class_size)) {
   1236 		return(false);
   1237 	}
   1238 
   1239 	/*
   1240 	**	Save object data.
   1241 	*/
   1242 	if (file.Write(ptr, class_size) != (class_size)) {
   1243 		return(false);
   1244 	}
   1245 
   1246 	return(true);
   1247 }
   1248 
   1249 
   1250 /***************************************************************************
   1251  * Get_Savefile_Info -- gets description, scenario #, house                *
   1252  *                                                                         *
   1253  * INPUT:                                                                  *
   1254  *      id         numerical ID, for the file extension                    *
   1255  *      buf      buffer to store description in                            *
   1256  *      scenp      ptr to variable to hold scenario                        *
   1257  *      housep   ptr to variable to hold house                             *
   1258  *                                                                         *
   1259  * OUTPUT:                                                                 *
   1260  *      true = OK, false = error (save-game file invalid)                  *
   1261  *                                                                         *
   1262  * WARNINGS:                                                               *
   1263  *      none.                                                              *
   1264  *                                                                         *
   1265  * HISTORY:                                                                *
   1266  *   01/12/1995 BR : Created.                                              *
   1267  *=========================================================================*/
   1268 bool Get_Savefile_Info(int id, char *buf, unsigned *scenp, HousesType *housep)
   1269 {
   1270 	RawFileClass file;
   1271 	char name[_MAX_FNAME+_MAX_EXT];
   1272 	unsigned long version;
   1273 	char descr_buf[DESCRIP_MAX];
   1274 
   1275 	/*
   1276 	**	Generate the filename to load
   1277 	*/
   1278 	sprintf(name, "SAVEGAME.%03d", id);
   1279 
   1280 	/*
   1281 	**	If the file opens OK, read the file
   1282 	*/
   1283 	if (file.Open(name, READ)) {
   1284 
   1285 		/*
   1286 		**	Read in the description, scenario #, and the house
   1287 		*/
   1288 		if (file.Read(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
   1289 			file.Close();
   1290 			return(false);
   1291 		}
   1292 
   1293 		descr_buf[strlen(descr_buf) - 2] = '\0';	// trim off CR/LF
   1294 		strcpy(buf, descr_buf);
   1295 
   1296 		if (file.Read(scenp, sizeof(unsigned)) != sizeof(unsigned)) {
   1297 			file.Close();
   1298 			return(false);
   1299 		}
   1300 
   1301 		if (file.Read(housep, sizeof(HousesType)) != sizeof(HousesType)) {
   1302 			file.Close();
   1303 			return(false);
   1304 		}
   1305 
   1306 		/*
   1307 		**	Read & verify the save-game version #
   1308 		*/
   1309 		if (file.Read(&version,sizeof(version)) != sizeof(version)) {
   1310 			file.Close();
   1311 			return(false);
   1312 		}
   1313 
   1314 		if (version!=SAVEGAME_VERSION) {
   1315 			file.Close();
   1316 			return(false);
   1317 		}
   1318 
   1319 		file.Close();
   1320 
   1321 		return(true);
   1322 	}
   1323 	return(false);
   1324 }
   1325 
   1326 
   1327 /***************************************************************************
   1328  * TechnoType_To_Target -- converts TechnoTypeClass to TARGET              *
   1329  *                                                                         *
   1330  * INPUT:                                                                  *
   1331  *      ptr      pointer to convert                                        *
   1332  *                                                                         *
   1333  * OUTPUT:                                                                 *
   1334  *      target value                                                       *
   1335  *                                                                         *
   1336  * WARNINGS:                                                               *
   1337  *      Be certain that you only use the returned target value by passing  *
   1338  *      it to Target_To_TechnoType; do NOT call As_Techno, or you'll get   *
   1339  *      a totally invalid pointer.                                         *
   1340  *                                                                         *
   1341  * HISTORY:                                                                *
   1342  *   01/12/1995 BR : Created.                                              *
   1343  *=========================================================================*/
   1344 TARGET TechnoType_To_Target(TechnoTypeClass const * ptr)
   1345 {
   1346 	TARGET target;
   1347 
   1348 	switch (ptr->What_Am_I()) {
   1349 		case RTTI_INFANTRYTYPE:
   1350 			target = Build_Target(KIND_INFANTRY, ((InfantryTypeClass const *)ptr)->Type);
   1351 			break;
   1352 
   1353 		case RTTI_UNITTYPE:
   1354 			target = Build_Target(KIND_UNIT, ((UnitTypeClass const *)ptr)->Type);
   1355 			break;
   1356 
   1357 		case RTTI_AIRCRAFTTYPE:
   1358 			target = Build_Target(KIND_AIRCRAFT, ((AircraftTypeClass const *)ptr)->Type);
   1359 			break;
   1360 
   1361 		case RTTI_BUILDINGTYPE:
   1362 			target = Build_Target(KIND_BUILDING, ((BuildingTypeClass const *)ptr)->Type);
   1363 			break;
   1364 
   1365 		default:
   1366 			target = 0;
   1367 			break;
   1368 	}
   1369 
   1370 	return(target);
   1371 }
   1372 
   1373 
   1374 /***************************************************************************
   1375  * Target_To_TechnoType -- converts TARGET to TechnoTypeClass              *
   1376  *                                                                         *
   1377  * INPUT:                                                                  *
   1378  *      target      TARGET value to convert                                *
   1379  *                                                                         *
   1380  * OUTPUT:                                                                 *
   1381  *      pointer to the TechnoTypeClass for this target value               *
   1382  *                                                                         *
   1383  * WARNINGS:                                                               *
   1384  *      The TARGET value MUST have been generated with TechnoType_To_Target;*
   1385  *      If you give this routine a target generated by an As_Target()      *
   1386  *      routine, it will return a bogus pointer.                           *
   1387  *                                                                         *
   1388  * HISTORY:                                                                *
   1389  *   01/12/1995 BR : Created.                                              *
   1390  *=========================================================================*/
   1391 TechnoTypeClass const * Target_To_TechnoType(TARGET target)
   1392 {
   1393 	switch (Target_Kind(target)) {
   1394 		case KIND_INFANTRY:
   1395 			return(&InfantryTypeClass::As_Reference((InfantryType)Target_Value(target)));
   1396 
   1397 		case KIND_UNIT:
   1398 			return(&UnitTypeClass::As_Reference((UnitType)Target_Value(target)));
   1399 
   1400 		case KIND_AIRCRAFT:
   1401 			return(&AircraftTypeClass::As_Reference((AircraftType)Target_Value(target)));
   1402 
   1403 		case KIND_BUILDING:
   1404 			return(&BuildingTypeClass::As_Reference((StructType)Target_Value(target)));
   1405 	}
   1406 	return(NULL);
   1407 }
   1408 
   1409 
   1410 /***************************************************************************
   1411  * Get_VTable -- gets the VTable pointer for the given object              *
   1412  *                                                                         *
   1413  * INPUT:                                                                  *
   1414  *      ptr      pointer to check                                          *
   1415  *                                                                         *
   1416  * OUTPUT:                                                                 *
   1417  *      none                                                               *
   1418  *                                                                         *
   1419  * WARNINGS:                                                               *
   1420  *      none                                                               *
   1421  *                                                                         *
   1422  * HISTORY:                                                                *
   1423  *   01/12/1995 BR : Created.                                              *
   1424  *=========================================================================*/
   1425 void * Get_VTable(void *ptr, int base_size)
   1426 {
   1427 	return(((void **)(((char *)ptr) + base_size - 4))[0]);
   1428 }
   1429 
   1430 
   1431 /***************************************************************************
   1432  * Set_VTable -- sets the VTable pointer for the given object              *
   1433  *                                                                         *
   1434  * INPUT:                                                                  *
   1435  *      ptr         pointer to check                                       *
   1436  *      base_size   size of base class                                     *
   1437  *      vtable      value of VTable to plug in                             *
   1438  *                                                                         *
   1439  * OUTPUT:                                                                 *
   1440  *      none                                                               *
   1441  *                                                                         *
   1442  * WARNINGS:                                                               *
   1443  *      none                                                               *
   1444  *                                                                         *
   1445  * HISTORY:                                                                *
   1446  *   01/12/1995 BR : Created.                                              *
   1447  *=========================================================================*/
   1448 void Set_VTable(void *ptr, int base_size, void *vtable)
   1449 {
   1450 	((void **)(((char *)ptr) + base_size - 4))[0] = vtable;
   1451 }
   1452 
   1453 
   1454 #if 0
   1455 /****************************************************************************
   1456 Dump routine: prints everything about everything related to the Save/Load
   1457 process (OK, not exactly everything, but lots of stuff)
   1458 ****************************************************************************/
   1459 void Dump(void)
   1460 {
   1461 	int i,j;
   1462 	FILE *fp;
   1463 	char *layername[] = {
   1464 		"Ground",
   1465 		"Air",
   1466 		"Top"
   1467 	};
   1468 
   1469 	/*
   1470 	------------------------------- Open file --------------------------------
   1471 	*/
   1472 	fp = fopen("dump.txt","wt");
   1473 
   1474 	/*
   1475 	------------------------------ Logic Layer -------------------------------
   1476 	*/
   1477 	fprintf(fp,"--------------------- Logic Layer ---------------------\n");
   1478 	fprintf(fp,"Count: %d\n",Logic.Count());
   1479 	for (j = 0; j < Logic.Count(); j++) {
   1480 		fprintf(fp, "Entry %d: %x \n",j,Logic[j]);
   1481 	}
   1482 	fprintf(fp,"\n");
   1483 
   1484 	/*
   1485 	------------------------------- Map Layers -------------------------------
   1486 	*/
   1487 	for (i = 0; i < LAYER_COUNT; i++) {
   1488 		fprintf(fp,"----------------- Map Layer %s ---------------------\n",
   1489 			layername[i]);
   1490 		fprintf(fp,"Count: %d\n",Map.Layer[i].Count());
   1491 		for (j = 0; j < Map.Layer[i].Count(); j++) {
   1492 			fprintf(fp, "Entry %d: %x \n",j,Map.Layer[i][j]);
   1493 		}
   1494 	}
   1495 	fprintf(fp,"\n");
   1496 
   1497 	fprintf(fp,"------------------ TeamTypes --------------------------\n");
   1498 	fprintf(fp,"ActiveCount: %d\n",TeamTypes.ActiveCount);
   1499 	for (i = 0; i < TEAMTYPE_MAX; i++) {
   1500 		fprintf(fp,"Entry %d: Active:%d Name:%s\n",i,TeamTypes[i].IsActive,
   1501 			TeamTypes[i].Get_Name());
   1502 	}
   1503 	fprintf(fp,"\n");
   1504 
   1505 	fprintf(fp,"------------------ Teams --------------------------\n");
   1506 	fprintf(fp,"ActiveCount: %d\n",Teams.ActiveCount);
   1507 	for (i = 0; i < TEAM_MAX; i++) {
   1508 		fprintf(fp,"Entry %d: Active:%d Name:%s\n",i,Teams[i].IsActive,
   1509 			Teams[i].Class->Get_Name());
   1510 	}
   1511 	fprintf(fp,"\n");
   1512 
   1513 	fprintf(fp,"------------------ Triggers --------------------------\n");
   1514 	fprintf(fp,"ActiveCount: %d\n",Triggers.ActiveCount);
   1515 	for (i = 0; i < TRIGGER_MAX; i++) {
   1516 		fprintf(fp,"Entry %d: Active:%d Name:%s\n",i,Triggers[i].IsActive,
   1517 			Triggers[i].Get_Name());
   1518 	}
   1519 	fprintf(fp,"\n");
   1520 
   1521 	fprintf(fp,"------------------ Aircraft --------------------------\n");
   1522 	fprintf(fp,"ActiveCount: %d\n",Aircraft.ActiveCount);
   1523 	for (i = 0; i < AIRCRAFT_MAX; i++) {
   1524 		fprintf(fp,"Entry %d: Active:%d \n",i,Aircraft[i].IsActive);
   1525 	}
   1526 	fprintf(fp,"\n");
   1527 
   1528 	fprintf(fp,"------------------ Anims --------------------------\n");
   1529 	fprintf(fp,"ActiveCount: %d\n",Anims.ActiveCount);
   1530 	for (i = 0; i < ANIM_MAX; i++) {
   1531 		fprintf(fp,"Entry %d: Active:%d \n",i,Anims[i].IsActive);
   1532 	}
   1533 	fprintf(fp,"\n");
   1534 
   1535 	fprintf(fp,"------------------ Buildings --------------------------\n");
   1536 	fprintf(fp,"ActiveCount: %d\n",Buildings.ActiveCount);
   1537 	for (i = 0; i < BUILDING_MAX; i++) {
   1538 		fprintf(fp,"Entry %d: Active:%d \n",i,Buildings[i].IsActive);
   1539 	}
   1540 	fprintf(fp,"\n");
   1541 
   1542 	fprintf(fp,"------------------ Bullets --------------------------\n");
   1543 	fprintf(fp,"ActiveCount: %d\n",Bullets.ActiveCount);
   1544 	for (i = 0; i < BULLET_MAX; i++) {
   1545 		fprintf(fp,"Entry %d: Active:%d \n",i,Bullets[i].IsActive);
   1546 	}
   1547 	fprintf(fp,"\n");
   1548 
   1549 	fprintf(fp,"------------------ Infantry --------------------------\n");
   1550 	fprintf(fp,"ActiveCount: %d\n",Infantry.ActiveCount);
   1551 	for (i = 0; i < INFANTRY_MAX; i++) {
   1552 		fprintf(fp,"Entry %d: Active:%d \n",i,Infantry[i].IsActive);
   1553 	}
   1554 	fprintf(fp,"\n");
   1555 
   1556 	fprintf(fp,"------------------ Overlays --------------------------\n");
   1557 	fprintf(fp,"ActiveCount: %d\n",Overlays.ActiveCount);
   1558 	for (i = 0; i < OVERLAY_MAX; i++) {
   1559 		fprintf(fp,"Entry %d: Active:%d \n",i,Overlays[i].IsActive);
   1560 	}
   1561 	fprintf(fp,"\n");
   1562 
   1563 	fprintf(fp,"------------------ Reinforcements --------------------------\n");
   1564 	fprintf(fp,"ActiveCount: %d\n",Reinforcements.ActiveCount);
   1565 	for (i = 0; i < REINFORCEMENT_MAX; i++) {
   1566 		fprintf(fp,"Entry %d: Active:%d \n",i,Reinforcements[i].IsActive);
   1567 	}
   1568 	fprintf(fp,"\n");
   1569 
   1570 	fprintf(fp,"------------------ Smudges --------------------------\n");
   1571 	fprintf(fp,"ActiveCount: %d\n",Smudges.ActiveCount);
   1572 	for (i = 0; i < SMUDGE_MAX; i++) {
   1573 		fprintf(fp,"Entry %d: Active:%d \n",i,Smudges[i].IsActive);
   1574 	}
   1575 	fprintf(fp,"\n");
   1576 
   1577 	fprintf(fp,"------------------ Templates --------------------------\n");
   1578 	fprintf(fp,"ActiveCount: %d\n",Templates.ActiveCount);
   1579 	for (i = 0; i < TEMPLATE_MAX; i++) {
   1580 		fprintf(fp,"Entry %d: Active:%d \n",i,Templates[i].IsActive);
   1581 	}
   1582 	fprintf(fp,"\n");
   1583 
   1584 	fprintf(fp,"------------------ Terrains --------------------------\n");
   1585 	fprintf(fp,"ActiveCount: %d\n",Terrains.ActiveCount);
   1586 	for (i = 0; i < TERRAIN_MAX; i++) {
   1587 		fprintf(fp,"Entry %d: Active:%d \n",i,Terrains[i].IsActive);
   1588 	}
   1589 	fprintf(fp,"\n");
   1590 
   1591 	fprintf(fp,"------------------ Units --------------------------\n");
   1592 	fprintf(fp,"ActiveCount: %d\n",Units.ActiveCount);
   1593 	for (i = 0; i < UNIT_MAX; i++) {
   1594 		fprintf(fp,"Entry %d: Active:%d \n",i,Units[i].IsActive);
   1595 	}
   1596 	fprintf(fp,"\n");
   1597 
   1598 	fprintf(fp,"------------------ Factories --------------------------\n");
   1599 	fprintf(fp,"ActiveCount: %d\n",Factories.ActiveCount);
   1600 	for (i = 0; i < FACTORY_MAX; i++) {
   1601 		fprintf(fp,"Entry %d: Active:%d \n",i,Factories[i].IsActive);
   1602 	}
   1603 	fprintf(fp,"\n");
   1604 
   1605 	fclose(fp);
   1606 
   1607 	/*
   1608 	---------------------------- Flush the cache -----------------------------
   1609 	*/
   1610 	fp = fopen("dummy.bin","wt");
   1611 	for (i = 0; i < 100; i++) {
   1612 		fprintf(fp,"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
   1613 	}
   1614 	fclose(fp);
   1615 }
   1616 #endif