CnC_Remastered_Collection

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

SAVELOAD.CPP (53991B)


      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: /counterstrike/SAVELOAD.CPP 9     3/17/97 1:04a Steve_tall $ */
     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 : July 8, 1996 [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_MPlayer_Values -- Loads multiplayer-specific values                                  *
     38  *   Load_Misc_Values -- loads miscellaneous variables                                         *
     39  *   MPlayer_Save_Message -- pops up a "saving..." message                                     *
     40  *   Put_All -- Store all save game data to the pipe.                                          *
     41  *   Reconcile_Players -- Reconciles loaded data with the 'Players' vector							  *
     42  *   Save_Game -- saves a game to disk                                                         *
     43  *   Save_MPlayer_Values -- Saves multiplayer-specific values                                  *
     44  *   Save_Misc_Values -- saves miscellaneous variables                                         *
     45  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     46 
     47 #include	"function.h"
     48 #include	"vortex.h"
     49 #ifdef WIN32
     50 #include "tcpip.h"
     51 #include "ccdde.h"
     52 
     53 //#include "WolDebug.h"
     54 
     55 extern bool DLLSave(Pipe &file);
     56 extern bool DLLLoad(Straw &file);
     57 
     58 extern bool SpawnedFromWChat;
     59 #endif
     60 
     61 //#define	SAVE_BLOCK_SIZE	512
     62 #define	SAVE_BLOCK_SIZE	4096
     63 //#define	SAVE_BLOCK_SIZE	1024
     64 
     65 /*
     66 ********************************** Defines **********************************
     67 */
     68 #define	SAVEGAME_VERSION		(DESCRIP_MAX + \
     69 										0x01000006 + ( \
     70 										sizeof(AircraftClass) + \
     71 										sizeof(AircraftTypeClass) + \
     72 										sizeof(AnimClass) + \
     73 										sizeof(AnimTypeClass) + \
     74 										sizeof(BaseClass) + \
     75 										sizeof(BuildingClass) + \
     76 										sizeof(BuildingTypeClass) + \
     77 										sizeof(BulletClass) + \
     78 										sizeof(BulletTypeClass) + \
     79 										sizeof(CellClass) + \
     80 										sizeof(FactoryClass) + \
     81 										sizeof(HouseClass) + \
     82 										sizeof(HouseTypeClass) + \
     83 										sizeof(InfantryClass) + \
     84 										sizeof(InfantryTypeClass) + \
     85 										sizeof(LayerClass) + \
     86 										sizeof(MouseClass) + \
     87 										sizeof(OverlayClass) + \
     88 										sizeof(OverlayTypeClass) + \
     89 										sizeof(SmudgeClass) + \
     90 										sizeof(SmudgeTypeClass) + \
     91 										sizeof(TeamClass) + \
     92 										sizeof(TeamTypeClass) + \
     93 										sizeof(TemplateClass) + \
     94 										sizeof(TemplateTypeClass) + \
     95 										sizeof(TerrainClass) + \
     96 										sizeof(TerrainTypeClass) + \
     97 										sizeof(TriggerClass) + \
     98 										sizeof(TriggerTypeClass) + \
     99 										sizeof(UnitClass) + \
    100 										sizeof(UnitTypeClass) + \
    101 										sizeof(VesselClass) + \
    102 										sizeof(ScenarioClass) + \
    103 										sizeof(ChronalVortexClass)))
    104 //										sizeof(Waypoint)))
    105 
    106 
    107 static int Reconcile_Players(void);
    108 extern bool Is_Mission_Counterstrike (char *file_name);
    109 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    110 extern bool Is_Mission_Aftermath (char *file_name);
    111 #endif
    112 
    113 /***********************************************************************************************
    114  * Put_All -- Store all save game data to the pipe.                                            *
    115  *                                                                                             *
    116  *    This is the bulk processor of the game related save game data. All the game object       *
    117  *    and state data is stored to the pipe specified.                                          *
    118  *                                                                                             *
    119  * INPUT:   pipe  -- Reference to the pipe that will receive the save game data.               *
    120  *                                                                                             *
    121  * OUTPUT:  none                                                                               *
    122  *                                                                                             *
    123  * WARNINGS:   none                                                                            *
    124  *                                                                                             *
    125  * HISTORY:                                                                                    *
    126  *   07/08/1996 JLB : Created.                                                                 *
    127  *=============================================================================================*/
    128 static void Put_All(Pipe & pipe, int save_net)
    129 {
    130 	/*
    131 	**	Save the scenario global information.
    132 	*/
    133 	pipe.Put(&Scen, sizeof(Scen));
    134 
    135 	/*
    136 	**	Save the map.  The map must be saved first, since it saves the Theater.
    137 	*/
    138 	if (!save_net) Call_Back();
    139 	Map.Save(pipe);
    140 
    141 	if (!save_net) Call_Back();
    142 
    143 	/*
    144 	**	Save all game objects.  This code saves every object that's stored in a
    145 	**	TFixedIHeap class.
    146 	*/
    147 	Houses.Save(pipe);
    148 	if (!save_net) Call_Back();
    149 	TeamTypes.Save(pipe);
    150 	if (!save_net) Call_Back();
    151 	Teams.Save(pipe);
    152 	if (!save_net) Call_Back();
    153 	TriggerTypes.Save(pipe);
    154 	if (!save_net) Call_Back();
    155 	Triggers.Save(pipe);
    156 	if (!save_net) Call_Back();
    157 	Aircraft.Save(pipe);
    158 	if (!save_net) Call_Back();
    159 	Anims.Save(pipe);
    160 
    161 	if (!save_net) Call_Back();
    162 
    163 	Buildings.Save(pipe);
    164 	if (!save_net) Call_Back();
    165 	Bullets.Save(pipe);
    166 	if (!save_net) Call_Back();
    167 	Infantry.Save(pipe);
    168 	if (!save_net) Call_Back();
    169 	Overlays.Save(pipe);
    170 	if (!save_net) Call_Back();
    171 	Smudges.Save(pipe);
    172 	if (!save_net) Call_Back();
    173 	Templates.Save(pipe);
    174 	if (!save_net) Call_Back();
    175 	Terrains.Save(pipe);
    176 	if (!save_net) Call_Back();
    177 	Units.Save(pipe);
    178 	if (!save_net) Call_Back();
    179 	Factories.Save(pipe);
    180 	if (!save_net) Call_Back();
    181 	Vessels.Save(pipe);
    182 
    183 	if (!save_net) Call_Back();
    184 
    185 	/*
    186 	**	Save the Logic & Map layers
    187 	*/
    188 	Logic.Save(pipe);
    189 
    190 	int count = MapTriggers.Count();
    191 	pipe.Put(&count, sizeof(count));
    192 	int index;
    193 	for (int index = 0; index < MapTriggers.Count(); index++) {
    194 		TARGET target = MapTriggers[index]->As_Target();
    195 		pipe.Put(&target, sizeof(target));
    196 	}
    197 	if (!save_net) Call_Back();
    198 	count = LogicTriggers.Count();
    199 	pipe.Put(&count, sizeof(count));
    200 	for (index = 0; index < LogicTriggers.Count(); index++) {
    201 		TARGET target = LogicTriggers[index]->As_Target();
    202 		pipe.Put(&target, sizeof(target));
    203 	}
    204 	if (!save_net) Call_Back();
    205 	for (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
    206 		count = HouseTriggers[h].Count();
    207 		pipe.Put(&count, sizeof(count));
    208 		for (index = 0; index < HouseTriggers[h].Count(); index++) {
    209 			TARGET target = HouseTriggers[h][index]->As_Target();
    210 			pipe.Put(&target, sizeof(target));
    211 		}
    212 	}
    213 	if (!save_net) Call_Back();
    214 
    215 	for (int i = 0; i < LAYER_COUNT; i++) {
    216 		Map.Layer[i].Save(pipe);
    217 	}
    218 
    219 	if (!save_net) Call_Back();
    220 
    221 	/*
    222 	**	Save the Score
    223 	*/
    224 	pipe.Put(&Score, sizeof(Score));
    225 	if (!save_net) Call_Back();
    226 
    227 	/*
    228 	**	Save the AI Base
    229 	*/
    230 	Base.Save(pipe);
    231 	if (!save_net) Call_Back();
    232 
    233 	/*
    234 	**	Save out the carry over list (if present). First see how
    235 	**	many carry over objects are in the list.
    236 	*/
    237 	int carry_count = 0;
    238 	CarryoverClass const * cptr = Carryover;
    239 	while (cptr != NULL) {
    240 		carry_count++;
    241 		cptr = (CarryoverClass const *)cptr->Get_Next();
    242 	}
    243 
    244 	if (!save_net) Call_Back();
    245 
    246 	/*
    247 	**	Save out the number of objects in the list.
    248 	*/
    249 	pipe.Put(&carry_count, sizeof(carry_count));
    250 	if (!save_net) Call_Back();
    251 
    252 	/*
    253 	**	Now write out the objects themselves.
    254 	*/
    255 	CarryoverClass const * object_to_write = Carryover;
    256 	while (object_to_write != NULL) {
    257 		pipe.Put(object_to_write, sizeof(*object_to_write));
    258 		object_to_write = (CarryoverClass const *)object_to_write->Get_Next();
    259 	}
    260 	if (!save_net) Call_Back();
    261 
    262 	/*
    263 	**	Save miscellaneous variables.
    264 	*/
    265 	Save_Misc_Values(pipe);
    266 
    267 	if (!save_net) Call_Back();
    268 
    269 	/*
    270 	**	Save multiplayer values
    271 	*/
    272 	pipe.Put(&save_net, sizeof(save_net));		// Write out whether we saved the net values so we know if we have to load them again. ST - 10/22/2019 2:10PM
    273 	if (save_net) {
    274 		Save_MPlayer_Values(pipe);
    275 	}
    276 
    277 	pipe.Flush();
    278 }
    279 
    280 
    281 /***************************************************************************
    282  * Save_Game -- saves a game to disk                                       *
    283  *                                                                         *
    284  * Saving the Map:                                                         *
    285  *     DisplayClass::Save() invokes CellClass's Write() for every cell     *
    286  *     that needs to be saved.  A cell needs to be saved if it contains    *
    287  *     any special data at all, such as a TIcon, or an Occupier.           *
    288  *   The cell saves its own CellTrigger pointer, converted to a TARGET.    *
    289  *                                                                         *
    290  * Saving game objects:                                                    *
    291  *   - Any object stored in an ArrayOf class needs to be saved.  The ArrayOf*
    292  *     Save() routine invokes each object's Write() routine, if that       *
    293  *     object's IsActive is set.                                           *
    294  *                                                                         *
    295  * Saving the layers:                                                      *
    296  *   The Map's Layers (Ground, Air, etc) of things that are on the map,    *
    297  *     and the Logic's Layer of things to process both need to be saved.   *
    298  *     LayerClass::Save() writes the entire layer array to disk            *
    299  *                                                                         *
    300  * Saving the houses:                                                      *
    301  *   Each house needs to be saved, to record its Credits, Power, etc.      *
    302  *                                                                         *
    303  * Saving miscellaneous data:                                              *
    304  *   There are a lot of miscellaneous variables to save, such as the       *
    305  *     map's dimensions, the player's house, etc.                          *
    306  *                                                                         *
    307  * INPUT:                                                                  *
    308  *      id      numerical ID, for the file extension                       *
    309  *                                                                         *
    310  * OUTPUT:                                                                 *
    311  *      true = OK, false = error                                           *
    312  *                                                                         *
    313  * WARNINGS:                                                               *
    314  *      none.                                                              *
    315  *                                                                         *
    316  * HISTORY:                                                                *
    317  *   12/28/1994 BR : Created.                                              *
    318  *   02/27/1996 JLB : Uses simpler game control value save operation.      *
    319  *=========================================================================*/
    320 bool Save_Game(int id, char const * descr, bool )
    321 {
    322 	char name[_MAX_FNAME+_MAX_EXT];
    323 
    324 	/*
    325 	**	Generate the filename to save.  If 'id' is -1, it means save a
    326 	** network/modem game; otherwise, use 'id' as the file extension.
    327 	*/
    328 	if (id==-1) {
    329 		strcpy(name, NET_SAVE_FILE_NAME);
    330 		//save_net = 1;
    331 	} else {
    332 		sprintf(name, "SAVEGAME.%03d", id);
    333 	}
    334 
    335 	return Save_Game(name, descr);
    336 }
    337 
    338 
    339 
    340 /*
    341 ** Version that takes file name. ST - 9/9/2019 11:10AM
    342 */
    343 bool NowSavingGame = false; // TEMP MBL: Need to discuss better solution with Steve
    344 bool Save_Game(const char *file_name, const char *descr)
    345 {
    346 	NowSavingGame = true; // TEMP MBL: Need to discuss better solution with Steve
    347 
    348 	int save_net = 0;									// 1 = save network/modem game
    349 	
    350 	if (Session.Type  == GAME_GLYPHX_MULTIPLAYER) {
    351 		save_net = 1;
    352 	}
    353 	
    354 	unsigned scenario;
    355 	HousesType house;
    356 
    357 	scenario = Scen.Scenario;						// get current scenario #
    358 	house = PlayerPtr->Class->House;				// get current house
    359 
    360 	/*
    361 	**	Code everybody's pointers
    362 	*/
    363 	Code_All_Pointers();
    364 
    365 	/*
    366 	**	Open the file
    367 	*/
    368 	BufferIOFileClass file(file_name);
    369 
    370 	FilePipe fpipe(&file);
    371 
    372 	/*
    373 	** Save the DLLs variables first, so we can do a version check in the DLL when we begin the load
    374 	*/
    375 	if (RunningAsDLL) {
    376 		DLLSave(fpipe);
    377 	}
    378 
    379 	/*
    380 	**	Save the description, scenario #, and house
    381 	**	(scenario # & house are saved separately from the actual Scenario &
    382 	**	PlayerPtr globals for convenience; we can quickly find out which
    383 	**	house & scenario this save-game file is for by reading these values.
    384 	**	Also, PlayerPtr is stored in a coded form in Save_Misc_Values(),
    385 	**	which may or may not be a HousesType number; so, saving 'house'
    386 	**	here ensures we can always pull out the house for this file.)
    387 	*/
    388 	char descr_buf[DESCRIP_MAX];
    389 	memset(descr_buf, '\0', sizeof(descr_buf));
    390 	sprintf(descr_buf, "%s\r\n", descr);			// put CR-LF after text
    391 	//descr_buf[strlen(descr_buf) + 1] = 26;		// put CTRL-Z after NULL
    392 	fpipe.Put(descr_buf, DESCRIP_MAX);
    393 
    394 	fpipe.Put(&scenario, sizeof(scenario));
    395 
    396 	fpipe.Put(&house, sizeof(house));
    397 
    398 	/*
    399 	**	Save the save-game version, for loading verification
    400 	*/
    401 	unsigned long version = SAVEGAME_VERSION;
    402 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    403 	version++;
    404 #endif
    405 	fpipe.Put(&version, sizeof(version));
    406 
    407 	int pos = file.Seek(0, SEEK_CUR);
    408 
    409 	/*
    410 	**	Store a dummy message digest.
    411 	*/
    412 	char digest[20];
    413 	fpipe.Put(digest, sizeof(digest));
    414 
    415 
    416 	/*
    417 	**	Dump the save game data to the file. The data is compressed
    418 	**	and then encrypted. The message digest is calculated in the
    419 	**	process by using the data just as it is written to disk.
    420 	*/
    421 	SHAPipe sha;
    422 	BlowPipe bpipe(BlowPipe::ENCRYPT);
    423 	LZOPipe pipe(LZOPipe::COMPRESS, SAVE_BLOCK_SIZE);
    424 //	LZWPipe pipe(LZWPipe::COMPRESS, SAVE_BLOCK_SIZE);
    425 //	LCWPipe pipe(LCWPipe::COMPRESS, SAVE_BLOCK_SIZE);
    426 	bpipe.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);
    427 
    428 	sha.Put_To(fpipe);
    429 	bpipe.Put_To(sha);
    430 	pipe.Put_To(bpipe);
    431 	Put_All(pipe, save_net);
    432 
    433 	/*
    434 	**	Output the real final message digest. This is the one that is of
    435 	**	the data image as it exists on the disk.
    436 	*/
    437 	pipe.Flush();
    438 	file.Seek(pos, SEEK_SET);
    439 	sha.Result(digest);
    440 	fpipe.Put(digest, sizeof(digest));
    441 
    442 	pipe.End();
    443 
    444 	Decode_All_Pointers();
    445 
    446 	NowSavingGame = false; // TEMP MBL: Need to discuss better solution with Steve
    447 
    448 	return(true);
    449 }
    450 
    451 
    452 /***************************************************************************
    453  * Load_Game -- loads a saved game                                         *
    454  *                                                                         *
    455  * This routine loads the data in the same way it was saved out.           *
    456  *                                                                         *
    457  * Loading the Map:                                                        *
    458  *   - DisplayClass::Load() invokes CellClass's Load() for every cell      *
    459  *     that was saved.                                                     *
    460  * - The cell loads its own CellTrigger pointer.                           *
    461  *                                                                         *
    462  * Loading game objects:                                                   *
    463  * - IHeap's Load() routine loads the # of objects stored, and loads       *
    464  *   each object.                                                          *
    465  * - Triggers: Add themselves to the HouseTriggers if they're associated   *
    466  *   with a house                                                          *
    467  *                                                                         *
    468  * Loading the layers:                                                     *
    469  *     LayerClass::Load() reads the entire layer array to disk             *
    470  *                                                                         *
    471  * Loading the houses:                                                     *
    472  *   Each house is loaded in its entirety.                                 *
    473  *                                                                         *
    474  * Loading miscellaneous data:                                             *
    475  *   There are a lot of miscellaneous variables to load, such as the       *
    476  *     map's dimensions, the player's house, etc.                          *
    477  *                                                                         *
    478  * INPUT:                                                                  *
    479  *      id         numerical ID, for the file extension                    *
    480  *                                                                         *
    481  * OUTPUT:                                                                 *
    482  *      true = OK, false = error                                           *
    483  *                                                                         *
    484  * WARNINGS:                                                               *
    485  *      If this routine returns false, the entire game will be in an       *
    486  *      unknown state, so the scenario will have to be re-initialized.     *
    487  *                                                                         *
    488  * HISTORY:                                                                *
    489  *   12/28/1994 BR : Created. 						   								*
    490  *   1/20/97  V.Grippi Added expansion CD check                            *
    491  *=========================================================================*/
    492 bool Load_Game(int id)
    493 {
    494 	char name[_MAX_FNAME+_MAX_EXT];
    495 
    496 	/*
    497 	**	Generate the filename to load.  If 'id' is -1, it means save a
    498 	** network/modem game; otherwise, use 'id' as the file extension.
    499 	*/
    500 	if (id == -1) {
    501 		strcpy(name, NET_SAVE_FILE_NAME);
    502 		//load_net = 1;
    503 	} else {
    504 		sprintf(name, "SAVEGAME.%03d", id);
    505 	}
    506 	return Load_Game(name);
    507 }
    508 
    509 
    510 /*
    511 ** Version that takes a file name instead. ST - 9/9/2019 11:13AM
    512 */
    513 bool Load_Game(const char *file_name)
    514 {		
    515 	int i;
    516 	unsigned scenario;
    517 	HousesType house;
    518 	char descr_buf[DESCRIP_MAX];
    519 	int load_net = 0;									// 1 = save network/modem game
    520 	
    521 	/*
    522 	**	Open the file
    523 	*/
    524 	RawFileClass file(file_name);
    525 	if (!file.Is_Available()) {
    526 		return(false);
    527 	}
    528 
    529 	FileStraw fstraw(file);
    530 
    531 	Call_Back();
    532 
    533 	/*
    534 	** Load the DLLs variables first, in case we need to do something different based on version
    535 	*/
    536 	if (RunningAsDLL) {
    537 		DLLLoad(fstraw);
    538 	}
    539 
    540 	/*
    541 	**	Read & discard the save-game's header info
    542 	*/
    543 	if (fstraw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
    544 		return(false);
    545 	}
    546 
    547 	if (fstraw.Get(&scenario, sizeof(scenario)) != sizeof(scenario)) {
    548 		return(false);
    549 	}
    550 
    551 	if (fstraw.Get(&house, sizeof(house)) != sizeof(house)) {
    552 		return(false);
    553 	}
    554 
    555 	/*
    556 	**	Read in & verify the save-game ID code
    557 	*/
    558 	unsigned long version;
    559 	if (fstraw.Get(&version, sizeof(version)) != sizeof(version)) {
    560 		return(false);
    561 	}
    562 	GameVersion = version;
    563 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    564 	if (version != SAVEGAME_VERSION && ((version-1) != SAVEGAME_VERSION) ) {
    565 	      	return(false);
    566 	}
    567 #else
    568 	if (version != SAVEGAME_VERSION /*&& version != 0x0100616D*/){
    569 	      	return(false);
    570 	}
    571 #endif
    572 	/*
    573 	**	Get the message digest that is embedded in the file.
    574 	*/
    575 	char digest[20];
    576 	fstraw.Get(digest, sizeof(digest));
    577 
    578 	/*
    579 	**	Remember the file position since we must seek back here to
    580 	**	perform the real saved game read.
    581 	*/
    582 	long pos = file.Seek(0, SEEK_CUR);
    583 
    584 	/*
    585 	**	Pass the rest of the file through the hash straw so that
    586 	**	the digest can be compaired to the one in the file.
    587 	*/
    588 	SHAStraw sha;
    589 	sha.Get_From(fstraw);
    590 	for (;;) {
    591 		if (sha.Get(_staging_buffer, sizeof(_staging_buffer)) != sizeof(_staging_buffer)) break;
    592 	}
    593 	char actual[20];
    594 	sha.Result(actual);
    595 	sha.Get_From(NULL);
    596 
    597 	Call_Back();
    598 
    599 	/*
    600 	**	Compare the two digests. If they differ then return a failure condition
    601 	**	before any damage could be done.
    602 	*/
    603 	if (memcmp(actual, digest, sizeof(digest)) != 0) {
    604 		return(false);
    605 	}
    606 
    607 	/*
    608 	**	Set up the pipe so that the scenario data can be read.
    609 	*/
    610 	file.Seek(pos, SEEK_SET);
    611 	BlowStraw bstraw(BlowStraw::DECRYPT);
    612 	LZOStraw straw(LZOStraw::DECOMPRESS, SAVE_BLOCK_SIZE);
    613 //	LZWStraw straw(LZWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);
    614 //	LCWStraw straw(LCWStraw::DECOMPRESS, SAVE_BLOCK_SIZE);
    615 
    616 	bstraw.Key(&FastKey, BlowfishEngine::MAX_KEY_LENGTH);
    617 	bstraw.Get_From(fstraw);
    618 	straw.Get_From(bstraw);
    619 
    620 	/*
    621 	**	Clear the scenario so we start fresh; this calls the Init_Clear() routine
    622 	**	for the Map, and all object arrays.  It has the following important
    623 	**	effects:
    624 	**	- Every cell is cleared to 0's, via MapClass::Init_Clear()
    625 	**	- All heap elements' are cleared
    626 	**	- The Houses are Initialized, which also clears their HouseTriggers
    627 	**	  array
    628 	**	- The map's Layers & Logic Layer are cleared to empty
    629 	**	- The list of currently-selected objects is cleared
    630 	*/
    631 	Clear_Scenario();
    632 
    633 	/*
    634 	**	Load the scenario global information.
    635 	*/
    636 	straw.Get(&Scen, sizeof(Scen));
    637 
    638 	/*
    639 	**	Fixup the Sessionclass scenario info so we can work out which
    640 	** CD to request later
    641 	*/
    642 	if ( load_net ){
    643 
    644 		CCFileClass scenario_file (Scen.ScenarioName);
    645 		if ( !scenario_file.Is_Available() ){
    646 
    647 			int cd = -1;
    648 			if (Is_Mission_Counterstrike (Scen.ScenarioName)) {
    649 				cd = 2;
    650 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    651 				if (Expansion_AM_Present()) {
    652 					int current_drive = CCFileClass::Get_CD_Drive();
    653 					int index = Get_CD_Index(current_drive, 1*60);
    654 					if (index == 3) cd = 3;
    655 				}
    656 #endif
    657 			}
    658 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    659 			if (Is_Mission_Aftermath (Scen.ScenarioName)) {
    660 				cd = 3;
    661 #ifdef BOGUSCD
    662 	cd = -1;
    663 #endif
    664 			}
    665 #endif
    666 			RequiredCD = cd;
    667 			if (!Force_CD_Available (RequiredCD)) {
    668 				Emergency_Exit(EXIT_FAILURE);
    669 			}
    670 
    671 			/*
    672 			** Update the internal list of scenarios to include the counterstrike
    673 			** list.
    674 			*/
    675 			Session.Read_Scenario_Descriptions();
    676 		} else {
    677 			/*
    678 			** The scenario is available so set RequiredCD to whatever is currently
    679 			** in the drive.
    680 			*/
    681 			int current_drive = CCFileClass::Get_CD_Drive();
    682 			RequiredCD = Get_CD_Index(current_drive, 1*60);
    683 		}
    684 	}
    685 
    686 	/*
    687 	**	Load the map.  The map comes first, since it loads the Theater & init's
    688 	**	mixfiles.  The map calls all the type-class's Init routines, telling them
    689 	**	what the Theater is; this must be done before any objects are created, so
    690 	**	they'll be properly created.
    691 	*/
    692 	Map.Load(straw);
    693 
    694 	Call_Back();
    695 
    696 	/*
    697 	**	Load the object data.
    698 	*/
    699 	Houses.Load(straw);
    700 	TeamTypes.Load(straw);
    701 	Teams.Load(straw);
    702 	TriggerTypes.Load(straw);
    703 	Triggers.Load(straw);
    704 	Aircraft.Load(straw);
    705 	Anims.Load(straw);
    706 	Buildings.Load(straw);
    707 	Bullets.Load(straw);
    708 
    709 	Call_Back();
    710 
    711 	Infantry.Load(straw);
    712 	Overlays.Load(straw);
    713 	Smudges.Load(straw);
    714 	Templates.Load(straw);
    715 	Terrains.Load(straw);
    716 	Units.Load(straw);
    717 	Factories.Load(straw);
    718 	Vessels.Load(straw);
    719 
    720 	/*
    721 	**	Load the Logic & Map Layers
    722 	*/
    723 	Logic.Load(straw);
    724 
    725 	int count;
    726 	straw.Get(&count, sizeof(count));
    727 	MapTriggers.Clear();
    728 	int index;
    729 	for (index = 0; index < count; index++) {
    730 		TARGET target;
    731 		straw.Get(&target, sizeof(target));
    732 		MapTriggers.Add(As_Trigger(target));
    733 	}
    734 
    735 	straw.Get(&count, sizeof(count));
    736 	LogicTriggers.Clear();
    737 	for (index = 0; index < count; index++) {
    738 		TARGET target;
    739 		straw.Get(&target, sizeof(target));
    740 		LogicTriggers.Add(As_Trigger(target));
    741 	}
    742 
    743 	for (HousesType h = HOUSE_FIRST; h < HOUSE_COUNT; h++) {
    744 		straw.Get(&count, sizeof(count));
    745 		HouseTriggers[h].Clear();
    746 		for (index = 0; index < count; index++) {
    747 			TARGET target;
    748 			straw.Get(&target, sizeof(target));
    749 			HouseTriggers[h].Add(As_Trigger(target));
    750 		}
    751 	}
    752 
    753 	for (i = 0; i < LAYER_COUNT; i++) {
    754 		Map.Layer[i].Load(straw);
    755 	}
    756 
    757 	Call_Back();
    758 
    759 	/*
    760 	**	Load the Score
    761 	*/
    762 	straw.Get(&Score, sizeof(Score));
    763 	new(&Score) ScoreClass(NoInitClass());
    764 
    765 	/*
    766 	**	Load the AI Base
    767 	*/
    768 	Base.Load(straw);
    769 
    770 	/*
    771 	**	Delete any carryover pseudo-saved game list.
    772 	*/
    773 	while (Carryover != NULL) {
    774 		CarryoverClass * cptr = (CarryoverClass *)Carryover->Get_Next();
    775 		Carryover->Remove();
    776 		delete Carryover;
    777 		Carryover = cptr;
    778 	}
    779 
    780 	/*
    781 	**	Load any carryover pseudo-saved game list.
    782 	*/
    783 	int carry_count = 0;
    784 	straw.Get(&carry_count, sizeof(carry_count));
    785 	while (carry_count) {
    786 		CarryoverClass * cptr = new CarryoverClass;
    787 		assert(cptr != NULL);
    788 
    789 		straw.Get(cptr, sizeof(CarryoverClass));
    790 		new (cptr) CarryoverClass(NoInitClass());
    791 		cptr->Zap();
    792 
    793 		if (!Carryover) {
    794 			Carryover = cptr;
    795 		} else {
    796 			cptr->Add_Tail(*Carryover);
    797 		}
    798 		carry_count--;
    799 	}
    800 
    801 	Call_Back();
    802 
    803 	/*
    804 	**	Load miscellaneous variables, including the map size & the Theater
    805 	*/
    806 	Load_Misc_Values(straw);
    807 
    808 	/*
    809 	**	Load multiplayer values
    810 	*/
    811 	straw.Get(&load_net, sizeof(load_net));
    812 	if (load_net) {
    813 		Load_MPlayer_Values(straw);
    814 	}
    815 
    816 	file.Close();
    817 	Decode_All_Pointers();
    818 	Map.Init_IO();
    819 	Map.Flag_To_Redraw(true);
    820 
    821 	/*
    822 	**	Fixup any expediency data that can be inferred from the physical
    823 	**	data loaded.
    824 	*/
    825 	Post_Load_Game(load_net);
    826 
    827 	/*
    828 	** Re-init unit trackers. They will be garbage pointers after the load
    829 	*/
    830 	for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
    831 		HouseClass * hptr = HouseClass::As_Pointer(house);
    832 		if (hptr && hptr->IsActive) {
    833 			hptr->Init_Unit_Trackers();
    834 		}
    835 	}
    836 
    837 	Call_Back();
    838 
    839 	/*
    840 	**	Set the required CD to be in the drive according to the scenario
    841 	**	loaded.
    842 	*/
    843 	if (RequiredCD != -2 && !load_net) {
    844 
    845 #ifdef FIXIT_ANTS
    846 		/*
    847 		**	Determines if this an ant mission. Since the ant mission looks no different from
    848 		**	a regular mission, examining of the scenario name is the only way to tell.
    849 		*/
    850 		if (toupper(Scen.ScenarioName[0]) == 'S' &&
    851 			toupper(Scen.ScenarioName[1]) == 'C' &&
    852 			toupper(Scen.ScenarioName[2]) == 'A' &&
    853 			toupper(Scen.ScenarioName[3]) == '0' &&
    854 			toupper(Scen.ScenarioName[5]) == 'E' &&
    855 			toupper(Scen.ScenarioName[6]) == 'A') {
    856 
    857 			AntsEnabled = true;
    858 		} else{
    859 			AntsEnabled = false;
    860 		}
    861 #endif
    862 
    863 		if (Scen.Scenario == 1) {
    864 			RequiredCD = -1;
    865 		} else {
    866 #ifdef FIXIT_ANTS
    867 			if (Scen.Scenario > 19 || AntsEnabled) {
    868 			   RequiredCD = 2;
    869 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    870 				if(Scen.Scenario >= 36) {
    871 					RequiredCD = 3;
    872 #ifdef BOGUSCD
    873 	RequiredCD = -1;
    874 #endif
    875 				}
    876 #endif
    877 			} else {
    878 #endif	//FIXIT_ANTS
    879 				if (PlayerPtr->Class->House != HOUSE_USSR  && PlayerPtr->Class->House != HOUSE_UKRAINE) {
    880 					RequiredCD = 0;
    881 				} else {
    882 					RequiredCD = 1;
    883 				}
    884 #ifdef FIXIT_ANTS
    885 			}
    886 #endif	//FIXIT_ANTS
    887 		}
    888 
    889 	}else{
    890 
    891 		if ( load_net ){
    892 
    893 			CCFileClass scenario_file (Scen.ScenarioName);
    894 
    895 			/*
    896 			** Fix up the session class variables
    897 			*/
    898 			for ( int s=0 ; s<Session.Scenarios.Count() ; s++ ) {
    899 				if (Session.Scenarios[s]->Description() == Scen.Description){
    900 
    901 					memcpy (Session.Options.ScenarioDescription, Scen.Description,
    902 								sizeof (Session.Options.ScenarioDescription));
    903 					memcpy (Session.ScenarioFileName, Scen.ScenarioName,
    904 								sizeof (Session.ScenarioFileName));
    905 					Session.ScenarioFileLength = scenario_file.Size();
    906 					memcpy (Session.ScenarioDigest, Session.Scenarios[s]->Get_Digest(),
    907 								sizeof (Session.ScenarioDigest));
    908 					Session.ScenarioIsOfficial = Session.Scenarios[s]->Get_Official();
    909 					Scen.Scenario = s;
    910 					Session.Options.ScenarioIndex = s;
    911 					break;
    912 				}
    913 			}
    914 		}
    915 	}
    916 
    917 	if (!Force_CD_Available(RequiredCD)) {
    918 		Prog_End("Load_Game Force_CD_Available failed", true);
    919 		Emergency_Exit(EXIT_FAILURE);
    920 	}
    921 
    922 	ScenarioInit = 0;
    923 
    924 	if (load_net) {
    925 
    926 		// Removed as this is ensured by the GlyphX & DLL save/load code. ST - 10/22/2019 5:20PM
    927 		//if (!Reconcile_Players()) {	// (must do after Decode pointers)
    928 		//	return(false);
    929 		//}
    930 		
    931 		//!!!!!!!!!! put Fixup_Player_Units() here
    932 		Session.LoadGame = true;
    933 	}
    934 
    935 	Map.Reload_Sidebar();	// re-load sidebar art.
    936 
    937 	/*
    938 	**	Rescan the scenario file for any rules updates.
    939 	*/
    940 	CCINIClass ini;
    941 	int result = ini.Load(CCFileClass(Scen.ScenarioName), true);
    942 
    943 	/*
    944 	**	Reset the rules values to their initial settings.
    945 	*/
    946 	Rule.General(RuleINI);
    947 	Rule.Recharge(RuleINI);
    948 	Rule.AI(RuleINI);
    949 	Rule.Powerups(RuleINI);
    950 	Rule.Land_Types(RuleINI);
    951 	Rule.Themes(RuleINI);
    952 	Rule.IQ(RuleINI);
    953 	Rule.Objects(RuleINI);
    954 	Rule.Difficulty(RuleINI);
    955 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98 - But does this incorporate *changes*? - NO.
    956 	Rule.General(AftermathINI);
    957 	Rule.Recharge(AftermathINI);
    958 	Rule.AI(AftermathINI);
    959 	Rule.Powerups(AftermathINI);
    960 	Rule.Land_Types(AftermathINI);
    961 	Rule.Themes(AftermathINI);
    962 	Rule.IQ(AftermathINI);
    963 	Rule.Objects(AftermathINI);
    964 	Rule.Difficulty(AftermathINI);
    965 #endif
    966 
    967 	/*
    968 	**	Override any rules values specified in this
    969 	**	particular scenario file.
    970 	*/
    971 	Rule.General(ini);
    972 	Rule.Recharge(ini);
    973 	Rule.AI(ini);
    974 	Rule.Powerups(ini);
    975 	Rule.Land_Types(ini);                               \
    976 	Rule.Themes(ini);
    977 	Rule.IQ(ini);
    978 	Rule.Objects(ini);
    979 	Rule.Difficulty(ini);
    980 #ifdef FIXIT_CSII	//	ajw - Added runtime check for Aftermath to skirmish mode.
    981 	if (load_net) {
    982 		bool readini = false;
    983 		switch(Session.Type) {
    984 			case GAME_NORMAL:
    985 				readini = false;
    986 				break;
    987 			case GAME_SKIRMISH:
    988 				readini = Is_Aftermath_Installed();
    989 				break;
    990 			default:
    991 #ifdef FIXIT_VERSION_3
    992 				readini = bAftermathMultiplayer;
    993 #else
    994 				if (PlayingAgainstVersion >= VERSION_AFTERMATH_CS) {
    995 					readini = true;
    996 				}
    997 #endif
    998 				break;
    999 		}
   1000 		if(readini) {
   1001 			/*
   1002 			** Find out if the CD in the current drive is the Aftermath disc.
   1003 		  	*/
   1004 			if(Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60) != 3) {
   1005 				GamePalette.Set(FADE_PALETTE_FAST, Call_Back);
   1006 				if (!Force_CD_Available(3)) {	// force Aftermath CD in drive.
   1007 					Prog_End("Load_Game Force_CD_Available(3) failed", true);
   1008 #ifndef FIXIT_VERSION_3			//	WChat eliminated.
   1009 #ifdef WIN32
   1010 if(Special.IsFromWChat || SpawnedFromWChat) {
   1011 	char packet[10] = {"Hello"};
   1012 	Send_Data_To_DDE_Server (packet, strlen(packet), DDEServerClass::DDE_CONNECTION_FAILED);
   1013 }
   1014 #endif
   1015 #endif
   1016 					Emergency_Exit(EXIT_FAILURE);
   1017 		     	}
   1018 			}
   1019 			CCINIClass mpini;
   1020 			if (mpini.Load(CCFileClass("MPLAYER.INI"), false)) {
   1021 				Rule.General(mpini);
   1022 				Rule.Recharge(mpini);
   1023 				Rule.AI(mpini);
   1024 				Rule.Powerups(mpini);
   1025 				Rule.Land_Types(mpini);
   1026 				Rule.Themes(mpini);
   1027 				Rule.IQ(mpini);
   1028 				Rule.Objects(mpini);
   1029 				Rule.Difficulty(mpini);
   1030 			}
   1031 		}
   1032 
   1033 	}
   1034 #endif
   1035 
   1036 	if (Scen.TransitTheme == THEME_NONE) {
   1037 		Theme.Queue_Song(THEME_FIRST);
   1038 	} else {
   1039 		Theme.Queue_Song(Scen.TransitTheme);
   1040 	}
   1041 	
   1042 	if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
   1043 		Rule.IsSmartDefense = true;
   1044 	}
   1045 	
   1046 	return(true);
   1047 }
   1048 
   1049 
   1050 /***************************************************************************
   1051  * Save_Misc_Values -- saves miscellaneous variables                       *
   1052  *                                                                         *
   1053  * INPUT:                                                                  *
   1054  *      file      file to use for writing                                  *
   1055  *                                                                         *
   1056  * OUTPUT:                                                                 *
   1057  *      true = success, false = failure                                    *
   1058  *                                                                         *
   1059  * WARNINGS:                                                               *
   1060  *      none.                                                              *
   1061  *                                                                         *
   1062  * HISTORY:                                                                *
   1063  *   12/29/1994 BR : Created.                                              *
   1064  *   03/12/1996 JLB : Simplified.                                          *
   1065  *=========================================================================*/
   1066 bool Save_Misc_Values(Pipe & file)
   1067 {
   1068 	int i, j;
   1069 	int count;								// # ptrs in 'CurrentObject'
   1070 	ObjectClass * ptr;					// for saving 'CurrentObject' ptrs
   1071 
   1072 	/*
   1073 	**	Player's House.
   1074 	*/
   1075 	int x = PlayerPtr->Class->House;
   1076 	file.Put(&x, sizeof(x));
   1077 
   1078 	/*
   1079 	**	Save frame #.
   1080 	*/
   1081 	file.Put(&Frame, sizeof(Frame));
   1082 
   1083 	/*
   1084 	**	Save currently-selected objects list.
   1085 	**	Save the # of ptrs in the list.
   1086 	*/
   1087 	for (i = 0; i < SelectedObjectsType::COUNT; i++) {
   1088 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
   1089 		count = selection.Count();
   1090 		file.Put(&count, sizeof(count));
   1091 
   1092 		/*
   1093 		**	Save the pointers.
   1094 		*/
   1095 		for (j = 0; j < count; j++) {
   1096 			ptr = selection[j];
   1097 			file.Put(&ptr, sizeof(ptr));
   1098 		}
   1099 	}
   1100 
   1101 	/*
   1102 	** Save the chronal vortex
   1103 	*/
   1104 	ChronalVortex.Save(file);
   1105 
   1106 	/*
   1107 	**	Save Tanya flags.
   1108 	*/
   1109 	file.Put(&IsTanyaDead, sizeof(IsTanyaDead));
   1110 	file.Put(&SaveTanya, sizeof(SaveTanya));
   1111 
   1112 	return(true);
   1113 }
   1114 
   1115 
   1116 /***********************************************************************************************
   1117  * Load_Misc_Values -- Loads miscellaneous variables.                                          *
   1118  *                                                                                             *
   1119  * INPUT:   file  -- The file to load the misc values from.                                    *
   1120  *                                                                                             *
   1121  * OUTPUT:  Was the misc load process successful?                                              *
   1122  *                                                                                             *
   1123  * WARNINGS:   none                                                                            *
   1124  *                                                                                             *
   1125  * HISTORY:                                                                                    *
   1126  *   06/24/1995 BRR : Created.                                                                 *
   1127  *   03/12/1996 JLB : Simplified.                                                              *
   1128  *=============================================================================================*/
   1129 bool Load_Misc_Values(Straw & file)
   1130 {
   1131 	ObjectClass * ptr;					// for loading 'CurrentObject' ptrs
   1132 
   1133 	/*
   1134 	**	Player's House.
   1135 	*/
   1136 	int x;
   1137 	file.Get(&x, sizeof(x));
   1138 //	file.Get(&PlayerPtr, sizeof(PlayerPtr));
   1139 	PlayerPtr = HouseClass::As_Pointer((HousesType)x);
   1140 
   1141 	/*
   1142 	**	Load frame #.
   1143 	*/
   1144 	file.Get(&Frame, sizeof(Frame));
   1145 
   1146 	for (int i = 0; i < SelectedObjectsType::COUNT; i++) {
   1147 		/*
   1148 		**	Load currently-selected objects list.
   1149 		**	Load the # of ptrs in the list.
   1150 		*/
   1151 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
   1152 		int count;								// # ptrs in 'CurrentObject'
   1153 		file.Get(&count, sizeof(count));
   1154 
   1155 		/*
   1156 		**	Load the pointers.
   1157 		*/
   1158 		for (int j = 0; j < count; j++) {
   1159 			file.Get(&ptr, sizeof(ptr));
   1160 			selection.Add(ptr);	// add to the list
   1161 		}
   1162 	}
   1163 
   1164 	/*
   1165 	** Load the chronal vortex
   1166 	*/
   1167 	ChronalVortex.Load(file);
   1168 
   1169 	/*
   1170 	**	Save Tanya flags.
   1171 	*/
   1172 	file.Get(&IsTanyaDead, sizeof(IsTanyaDead));
   1173 	file.Get(&SaveTanya, sizeof(SaveTanya));
   1174 
   1175 	return(true);
   1176 }
   1177 
   1178 
   1179 /***************************************************************************
   1180  * Save_MPlayer_Values -- Saves multiplayer-specific values                *
   1181  *                                                                         *
   1182  * This routine saves multiplayer values that need to be restored for a		*
   1183  * save game.  In addition to saving the random # seed for this scenario, 	*
   1184  * it saves the contents of the actual random number generator; this 		*
   1185  * ensures that the random # sequencer will pick up where it left off when	*
   1186  * the game was saved.																		*
   1187  * This routine also saves the header for a Recording file, so it must 		*
   1188  * save some data not needed specifically by a save-game file (ie Seed).	*
   1189  *                                                                         *
   1190  * INPUT:                                                                  *
   1191  *		file		file to save to															*
   1192  *                                                                         *
   1193  * OUTPUT:                                                                 *
   1194  *		true = success, false = failure													*
   1195  *                                                                         *
   1196  * WARNINGS:                                                               *
   1197  *		none.																						*
   1198  *                                                                         *
   1199  * HISTORY:                                                                *
   1200  *   09/28/1995 BRR : Created.                                             *
   1201  *=========================================================================*/
   1202 bool Save_MPlayer_Values(Pipe & file)
   1203 {
   1204 	Session.Save(file);
   1205 	file.Put(&BuildLevel, sizeof(BuildLevel));
   1206 	file.Put(&Debug_Unshroud, sizeof(Debug_Unshroud));
   1207 	file.Put(&Seed, sizeof(Seed));
   1208 	file.Put(&Whom, sizeof(Whom));
   1209 	file.Put(&Special, sizeof(SpecialClass));
   1210 	file.Put(&Options, sizeof(GameOptionsClass));
   1211 
   1212 	return (true);
   1213 }
   1214 
   1215 
   1216 /***************************************************************************
   1217  * Load_MPlayer_Values -- Loads multiplayer-specific values                *
   1218  *                                                                         *
   1219  * INPUT:                                                                  *
   1220  *		file			file to load from														*
   1221  *                                                                         *
   1222  * OUTPUT:                                                                 *
   1223  *		true = success, false = failure													*
   1224  *                                                                         *
   1225  * WARNINGS:                                                               *
   1226  *		none.																						*
   1227  *                                                                         *
   1228  * HISTORY:                                                                *
   1229  *   09/28/1995 BRR : Created.                                             *
   1230  *=========================================================================*/
   1231 bool Load_MPlayer_Values(Straw & file)
   1232 {
   1233 	Session.Load(file);
   1234 	file.Get(&BuildLevel, sizeof(BuildLevel));
   1235 	file.Get(&Debug_Unshroud, sizeof(Debug_Unshroud));
   1236 	file.Get(&Seed, sizeof(Seed));
   1237 	file.Get(&Whom, sizeof(Whom));
   1238 	file.Get(&Special, sizeof(SpecialClass));
   1239 	file.Get(&Options, sizeof(GameOptionsClass));
   1240 
   1241 	return (true);
   1242 }
   1243 
   1244 /*
   1245 ** ST - 9/26/2019 11:43AM
   1246 */
   1247 extern void DLL_Code_Pointers(void);
   1248 extern void DLL_Decode_Pointers(void);
   1249 
   1250 /***********************************************************************************************
   1251  * Code_All_Pointers -- Code all pointers.                                                     *
   1252  *                                                                                             *
   1253  * INPUT:   none                                                                               *
   1254  *                                                                                             *
   1255  * OUTPUT:  none                                                                               *
   1256  *                                                                                             *
   1257  * WARNINGS:   none                                                                            *
   1258  *                                                                                             *
   1259  * HISTORY:                                                                                    *
   1260  *   06/24/1995 BRR : Created.                                                                 *
   1261  *=============================================================================================*/
   1262 void Code_All_Pointers(void)
   1263 {
   1264 	int i, j;
   1265 
   1266 	/*
   1267 	**	The Map.
   1268 	*/
   1269 	Map.Code_Pointers();
   1270 
   1271 	/*
   1272 	**	The ArrayOf's.
   1273 	*/
   1274 	TeamTypes.Code_Pointers();
   1275 	Teams.Code_Pointers();
   1276 	Triggers.Code_Pointers();
   1277 	Aircraft.Code_Pointers();
   1278 	Anims.Code_Pointers();
   1279 	Buildings.Code_Pointers();
   1280 	Bullets.Code_Pointers();
   1281 	Infantry.Code_Pointers();
   1282 	Overlays.Code_Pointers();
   1283 	Smudges.Code_Pointers();
   1284 	Templates.Code_Pointers();
   1285 	Terrains.Code_Pointers();
   1286 	Units.Code_Pointers();
   1287 	Factories.Code_Pointers();
   1288 	Vessels.Code_Pointers();
   1289 
   1290 	/*
   1291 	**	The Layers.
   1292 	*/
   1293 	Logic.Code_Pointers();
   1294 	for (i = 0; i < LAYER_COUNT; i++) {
   1295 		Map.Layer[i].Code_Pointers();
   1296 	}
   1297 
   1298 	/*
   1299 	**	The Score.
   1300 	*/
   1301 	Score.Code_Pointers();
   1302 
   1303 	/*
   1304 	**	The Base.
   1305 	*/
   1306 	Base.Code_Pointers();
   1307 
   1308 	/*
   1309 	**	PlayerPtr.
   1310 	*/
   1311 //	PlayerPtr = (HouseClass *)(PlayerPtr->Class->House);
   1312 
   1313 	/*
   1314 	**	Currently-selected objects.
   1315 	*/
   1316 	for (i = 0; i < SelectedObjectsType::COUNT; i++) {
   1317 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(i);
   1318 		for (j = 0; j < selection.Count(); j++) {
   1319 			selection[j] = (ObjectClass *)selection[j]->As_Target();
   1320 		}
   1321 	}
   1322 
   1323 	/*
   1324 	** DLL data
   1325 	*/
   1326 	DLL_Code_Pointers();
   1327 
   1328 	/*
   1329 	** Houses must be coded last, because the Class->House member of the HouseClass
   1330 	** is used to code HouseClass pointers for all other objects, and if Class is
   1331 	** coded, it will point to a meaningless value.
   1332 	*/
   1333 	Houses.Code_Pointers();
   1334 }
   1335 
   1336 
   1337 /***********************************************************************************************
   1338  * Decode_All_Pointers -- Decodes all pointers.                                                *
   1339  *                                                                                             *
   1340  * INPUT:   none                                                                               *
   1341  *                                                                                             *
   1342  * OUTPUT:  none                                                                               *
   1343  *                                                                                             *
   1344  * WARNINGS:   none                                                                            *
   1345  *                                                                                             *
   1346  * HISTORY:                                                                                    *
   1347  *   06/24/1995 BRR : Created.                                                                 *
   1348  *=============================================================================================*/
   1349 void Decode_All_Pointers(void)
   1350 {
   1351 	/*
   1352 	**	The Map.
   1353 	*/
   1354 	Map.Decode_Pointers();
   1355 
   1356 	/*
   1357 	** Decode houses first, so we can properly decode all other objects'
   1358 	** House pointers
   1359 	*/
   1360 	Houses.Decode_Pointers();
   1361 
   1362 	/*
   1363 	** DLL data
   1364 	*/
   1365 	DLL_Decode_Pointers();
   1366 
   1367 	/*
   1368 	**	The ArrayOf's.
   1369 	*/
   1370 	TeamTypes.Decode_Pointers();
   1371 	Teams.Decode_Pointers();
   1372 	Triggers.Decode_Pointers();
   1373 	Aircraft.Decode_Pointers();
   1374 	Anims.Decode_Pointers();
   1375 	Buildings.Decode_Pointers();
   1376 	Bullets.Decode_Pointers();
   1377 	Infantry.Decode_Pointers();
   1378 	Overlays.Decode_Pointers();
   1379 	Smudges.Decode_Pointers();
   1380 	Templates.Decode_Pointers();
   1381 	Terrains.Decode_Pointers();
   1382 	Units.Decode_Pointers();
   1383 	Factories.Decode_Pointers();
   1384 	Vessels.Decode_Pointers();
   1385 
   1386 	/*
   1387 	**	The Layers.
   1388 	*/
   1389 	Logic.Decode_Pointers();
   1390 	for (int i = 0; i < LAYER_COUNT; i++) {
   1391 		Map.Layer[i].Decode_Pointers();
   1392 	}
   1393 
   1394 	/*
   1395 	**	The Score.
   1396 	*/
   1397 	Score.Decode_Pointers();
   1398 
   1399 	/*
   1400 	**	The Base.
   1401 	*/
   1402 	Base.Decode_Pointers();
   1403 
   1404 	/*
   1405 	**	PlayerPtr.
   1406 	*/
   1407 //	PlayerPtr = HouseClass::As_Pointer((HousesType)PlayerPtr);
   1408 	Whom = PlayerPtr->Class->House;
   1409 	assert(PlayerPtr != NULL);
   1410 
   1411 	/*
   1412 	**	Currently-selected objects.
   1413 	*/
   1414 	for (int index = 0; index < SelectedObjectsType::COUNT; index++) {
   1415 		DynamicVectorClass<ObjectClass *>& selection = CurrentObject.Raw(index);
   1416 		for (int j = 0; j < selection.Count(); j++) {
   1417 			selection[j] = As_Object((TARGET)selection[j]);
   1418 			assert(selection[j] != NULL);
   1419 		}
   1420 	}
   1421 
   1422 	/*
   1423 	**	Last-Minute Fixups; to resolve these pointers properly requires all other
   1424 	**	pointers to be loaded & decoded.
   1425 	*/
   1426 	if (Map.PendingObjectPtr) {
   1427 		Map.PendingObject = &Map.PendingObjectPtr->Class_Of();
   1428 		assert(Map.PendingObject != NULL);
   1429 		Map.Set_Cursor_Shape(Map.PendingObject->Occupy_List(true));
   1430 #ifdef BG
   1431 		Map.Set_Placement_List(Map.PendingObject->Placement_List(true));
   1432 #endif
   1433 	} else {
   1434 		Map.PendingObject = 0;
   1435 		Map.Set_Cursor_Shape(0);
   1436 	}
   1437 }
   1438 
   1439 
   1440 /***************************************************************************
   1441  * Get_Savefile_Info -- gets description, scenario #, house                *
   1442  *                                                                         *
   1443  * INPUT:                                                                  *
   1444  *      id         numerical ID, for the file extension                    *
   1445  *      buf      buffer to store description in                            *
   1446  *      scenp      ptr to variable to hold scenario                        *
   1447  *      housep   ptr to variable to hold house                             *
   1448  *                                                                         *
   1449  * OUTPUT:                                                                 *
   1450  *      true = OK, false = error (save-game file invalid)                  *
   1451  *                                                                         *
   1452  * WARNINGS:                                                               *
   1453  *      none.                                                              *
   1454  *                                                                         *
   1455  * HISTORY:                                                                *
   1456  *   01/12/1995 BR : Created.                                              *
   1457  *=========================================================================*/
   1458 bool Get_Savefile_Info(int id, char * buf, unsigned * scenp, HousesType * housep)
   1459 {
   1460 	char name[_MAX_FNAME+_MAX_EXT];
   1461 	unsigned long version;
   1462 	char descr_buf[DESCRIP_MAX];
   1463 
   1464 	/*
   1465 	**	Generate the filename to load
   1466 	*/
   1467 	sprintf(name, "SAVEGAME.%03d", id);
   1468 	BufferIOFileClass file(name);
   1469 
   1470 	FileStraw straw(file);
   1471 
   1472 	/*
   1473 	**	Read in the description, scenario #, and the house
   1474 	*/
   1475 	if (straw.Get(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
   1476 		return(false);
   1477 	}
   1478 
   1479 	descr_buf[strlen(descr_buf) - 2] = '\0';	// trim off CR/LF
   1480 	strcpy(buf, descr_buf);
   1481 
   1482 	if (straw.Get(scenp, sizeof(unsigned)) != sizeof(unsigned)) {
   1483 		return(false);
   1484 	}
   1485 
   1486 	if (straw.Get(housep, sizeof(HousesType)) != sizeof(HousesType)) {
   1487 		return(false);
   1488 	}
   1489 
   1490 	/*
   1491 	**	Read & verify the save-game version #
   1492 	*/
   1493 	if (straw.Get(&version, sizeof(version)) != sizeof(version)) {
   1494 		return(false);
   1495 	}
   1496 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   1497 	if (version != SAVEGAME_VERSION && ((version-1 != SAVEGAME_VERSION)) ) {
   1498 #else
   1499 	if (version != SAVEGAME_VERSION) {
   1500 #endif
   1501 		return(false);
   1502 	}
   1503 	return(true);
   1504 }
   1505 
   1506 
   1507 /***************************************************************************
   1508  * Reconcile_Players -- Reconciles loaded data with the 'Players' vector	*
   1509  *                                                                         *
   1510  * This function is for supporting loading a saved multiplayer game.  		*
   1511  * When the game is loaded, we have to figure out which house goes with		*
   1512  * which entry in the Players vector.  We also have to figure out if 		*
   1513  * everyone who was originally in the game is still with us, and if not, 	*
   1514  * turn their stuff over to the computer.												*
   1515  *                                                                         *
   1516  * So, this function does the following:												*
   1517  * - For every name in 'Players', makes sure that name is in the House		*
   1518  *   array; if not, it's a fatal error.												*
   1519  * - For every human-controlled house, makes sure there's a player	 		*
   1520  *   with that name; if not, it turns that house over to the computer.		*
   1521  * - Fills in the Player's house ID														*
   1522  *                                                                         *
   1523  * This assumes that each player MUST keep their name the same as it was	*
   1524  * when the game was saved!  It's also assumed that the network 				*
   1525  * connections have not been formed yet, since Player[i]->Player.ID will	*
   1526  * be invalid until this routine has been called.									*
   1527  *                                                                         *
   1528  * INPUT:                                                                  *
   1529  *		none.																						*
   1530  *                                                                         *
   1531  * OUTPUT:                                                                 *
   1532  *		true = OK, false = error															*
   1533  *                                                                         *
   1534  * WARNINGS:                                                               *
   1535  *		none.																						*
   1536  *                                                                         *
   1537  * HISTORY:                                                                *
   1538  *   09/29/1995 BRR : Created.                                             *
   1539  *=========================================================================*/
   1540 static int Reconcile_Players(void)
   1541 {
   1542 	int i;
   1543 	int found;
   1544 	HousesType house;
   1545 	HouseClass * housep;
   1546 
   1547 	/*
   1548 	**	If there are no players, there's nothing to do.
   1549 	*/
   1550 	if (Session.Players.Count()==0)
   1551 		return (true);
   1552 
   1553 	/*
   1554 	**	Make sure every name we're connected to can be found in a House
   1555 	*/
   1556 	for (i = 0; i < Session.Players.Count(); i++) {
   1557 		found = 0;
   1558 		for (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +
   1559 			Session.MaxPlayers; house++) {
   1560 
   1561 			housep = HouseClass::As_Pointer(house);
   1562 			if (!housep) {
   1563 				continue;
   1564 			}
   1565 
   1566 			if (!stricmp(Session.Players[i]->Name, housep->IniName)) {
   1567 				found = 1;
   1568 				break;
   1569 			}
   1570 		}
   1571 		if (!found)
   1572 			return (false);
   1573 	}
   1574 
   1575 	//
   1576 	// Loop through all Houses; if we find a human-owned house that we're
   1577 	// not connected to, turn it over to the computer.
   1578 	//
   1579 	for (house = HOUSE_MULTI1; house < HOUSE_MULTI1 +
   1580 		Session.MaxPlayers; house++) {
   1581 		housep = HouseClass::As_Pointer(house);
   1582 		if (!housep) {
   1583 			continue;
   1584 		}
   1585 
   1586 		//
   1587 		// Skip this house if it wasn't human to start with.
   1588 		//
   1589 		if (!housep->IsHuman) {
   1590 			continue;
   1591 		}
   1592 
   1593 		//
   1594 		// Try to find this name in the Players vector; if it's found, set
   1595 		// its ID to this house.
   1596 		//
   1597 		found = 0;
   1598 		for (i = 0; i < Session.Players.Count(); i++) {
   1599 			if (!stricmp(Session.Players[i]->Name, housep->IniName)) {
   1600 				found = 1;
   1601 				Session.Players[i]->Player.ID = house;
   1602 				break;
   1603 			}
   1604 		}
   1605 
   1606 		/*
   1607 		**	If this name wasn't found, remove it
   1608 		*/
   1609 		if (!found) {
   1610 
   1611 			/*
   1612 			**	Turn the player's house over to the computer's AI
   1613 			*/
   1614 			housep->IsHuman = false;
   1615 			housep->IsStarted = true;
   1616 //			housep->Smartness = IQ_MENSA;
   1617 			housep->IQ = Rule.MaxIQ;
   1618 			strcpy (housep->IniName, Text_String(TXT_COMPUTER));
   1619 
   1620 			Session.NumPlayers--;
   1621 		}
   1622 	}
   1623 
   1624 	//
   1625 	// If all went well, our Session.NumPlayers value should now equal the value
   1626 	// from the saved game, minus any players we removed.
   1627 	//
   1628 	if (Session.NumPlayers == Session.Players.Count()) {
   1629 		return (true);
   1630 	} else {
   1631 		return (false);
   1632 	}
   1633 }
   1634 
   1635 
   1636 /***************************************************************************
   1637  * MPlayer_Save_Message -- pops up a "saving..." message                   *
   1638  *                                                                         *
   1639  * INPUT:                                                                  *
   1640  *		none.																						*
   1641  *                                                                         *
   1642  * OUTPUT:                                                                 *
   1643  *		none.																						*
   1644  *                                                                         *
   1645  * WARNINGS:                                                               *
   1646  *		none.																						*
   1647  *                                                                         *
   1648  * HISTORY:                                                                *
   1649  *   10/30/1995 BRR : Created.                                             *
   1650  *=========================================================================*/
   1651 void MPlayer_Save_Message(void)
   1652 {
   1653 	//char *txt = Text_String(
   1654 }