CnC_Remastered_Collection

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

IOMAP.CPP (28358B)


      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/IOMAP.CPP 1     3/03/97 10:24a 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 : IOMAP.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Bill Randolph                                                *
     26  *                                                                                             *
     27  *                   Start Date : January 16, 1995                                             *
     28  *                                                                                             *
     29  *                  Last Update : March 12, 1996 [JLB]                                         *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * All map-related loading/saving routines should go in this module, so it can be overlayed.   *
     33  *---------------------------------------------------------------------------------------------*
     34  * Functions:                                                                                  *
     35  *   CellClass::Code_Pointers -- codes class's pointers for load/save                          *
     36  *   CellClass::Decode_Pointers -- decodes pointers for load/save                              *
     37  *   CellClass::Load -- Reads from a save game file.                                           *
     38  *   CellClass::Save -- Write to a save game file.                                             *
     39  *   CellClass::Should_Save -- Should the cell be written to disk?                             *
     40  *   DisplayClass::Code_Pointers -- codes class's pointers for load/save                       *
     41  *   DisplayClass::Decode_Pointers -- decodes pointers for load/save                           *
     42  *   MapClass::Code_Pointers -- codes class's pointers for load/save                           *
     43  *   MapClass::Decode_Pointers -- decodes pointers for load/save                               *
     44  *   MouseClass::Load -- Loads from a save game file.                                          *
     45  *   MouseClass::Save -- Saves to a save game file.                                            *
     46  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     47 
     48 #include "function.h"
     49 
     50 
     51 /***********************************************************************************************
     52  * CellClass::Should_Save -- Should the cell be written to disk?                               *
     53  *                                                                                             *
     54  *    This function will determine if the cell needs to be written to disk. Any cell that      *
     55  *    contains special data should be written to disk.                                         *
     56  *                                                                                             *
     57  * INPUT:   none                                                                               *
     58  *                                                                                             *
     59  * OUTPUT:  bool; Should this cell's data be written to disk?                                  *
     60  *                                                                                             *
     61  * WARNINGS:   none                                                                            *
     62  *                                                                                             *
     63  * HISTORY:                                                                                    *
     64  *   09/19/1994 JLB : Created.                                                                 *
     65  *=============================================================================================*/
     66 bool CellClass::Should_Save(void) const
     67 {
     68 	static CellClass const _identity_cell;
     69 
     70 	return(memcmp(&_identity_cell, this, sizeof(*this)) != 0);
     71 }
     72 
     73 
     74 /***********************************************************************************************
     75  * CellClass::Load -- Loads from a save game file.                                             *
     76  *                                                                                             *
     77  * INPUT:   file  -- The file to read the cell's data from.                                    *
     78  *                                                                                             *
     79  * OUTPUT:  true = success, false = failure                                                    *
     80  *                                                                                             *
     81  * WARNINGS:   none                                                                            *
     82  *                                                                                             *
     83  * HISTORY:                                                                                    *
     84  *   09/19/1994 JLB : Created.                                                                 *
     85  *=============================================================================================*/
     86 bool CellClass::Load(Straw & file)
     87 {
     88 	file.Get(this, sizeof(*this));
     89 	return(true);
     90 }
     91 
     92 
     93 /***********************************************************************************************
     94  * CellClass::Save -- Write to a save game file.                                               *
     95  *                                                                                             *
     96  * INPUT:   file  -- The file to write the cell's data to.                                     *
     97  *                                                                                             *
     98  * OUTPUT:  true = success, false = failure                                                    *
     99  *                                                                                             *
    100  * WARNINGS:   none                                                                            *
    101  *                                                                                             *
    102  * HISTORY:                                                                                    *
    103  *   09/19/1994 JLB : Created.                                                                 *
    104  *=============================================================================================*/
    105 bool CellClass::Save(Pipe & file) const
    106 {
    107 	file.Put(this, sizeof(*this));
    108 	return(true);
    109 }
    110 
    111 
    112 /***********************************************************************************************
    113  * CellClass::Code_Pointers -- codes class's pointers for load/save                            *
    114  *                                                                                             *
    115  * This routine "codes" the pointers in the class by converting them to a number               *
    116  * that still represents the object pointed to, but isn't actually a pointer.  This            *
    117  * allows a saved game to properly load without relying on the games data still                *
    118  * being in the exact same location.                                                           *
    119  *                                                                                             *
    120  * INPUT:                                                                                      *
    121  *      none.                                                                                  *
    122  *                                                                                             *
    123  * OUTPUT:                                                                                     *
    124  *      none.                                                                                  *
    125  *                                                                                             *
    126  * WARNINGS:                                                                                   *
    127  *      none.                                                                                  *
    128  *                                                                                             *
    129  * HISTORY:                                                                                    *
    130  *   01/02/1995 BR : Created.                                                                  *
    131  *=============================================================================================*/
    132 void CellClass::Code_Pointers(void)
    133 {
    134 	if (Cell_Occupier() != NULL) {
    135 		OccupierPtr = (ObjectClass *)OccupierPtr->As_Target();
    136 	}
    137 
    138 	for (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {
    139 		if (Overlapper[index] != NULL && Overlapper[index]->IsActive) {
    140 			Overlapper[index] = (ObjectClass *)Overlapper[index]->As_Target();
    141 		} else {
    142 			Overlapper[index] = NULL;
    143 		}
    144 	}
    145 
    146 	assert(CTFFlag == NULL);
    147 }
    148 
    149 
    150 /***********************************************************************************************
    151  * CellClass::Decode_Pointers -- decodes pointers for load/save                                *
    152  *                                                                                             *
    153  * This routine "decodes" the pointers coded in Code_Pointers by converting the                *
    154  * code values back into object pointers.                                                      *
    155  *                                                                                             *
    156  * INPUT:                                                                                      *
    157  *      none.                                                                                  *
    158  *                                                                                             *
    159  * OUTPUT:                                                                                     *
    160  *      none.                                                                                  *
    161  *                                                                                             *
    162  * WARNINGS:                                                                                   *
    163  *      none.                                                                                  *
    164  *                                                                                             *
    165  * HISTORY:                                                                                    *
    166  *   01/02/1995 BR : Created.                                                                  *
    167  *   03/12/1996 JLB : Simplified.                                                              *
    168  *=============================================================================================*/
    169 void CellClass::Decode_Pointers(void)
    170 {
    171 	if (OccupierPtr != NULL) {
    172 		OccupierPtr = As_Object((TARGET)OccupierPtr, false);
    173 		assert(OccupierPtr != NULL);
    174 	}
    175 
    176 	for (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {
    177 		if (Overlapper[index] != NULL) {
    178 			Overlapper[index] = As_Object((TARGET)Overlapper[index], false);
    179 			assert(Overlapper[index] != NULL);
    180 		}
    181 	}
    182 
    183 	CTFFlag = NULL;
    184 }
    185 
    186 
    187 /***********************************************************************************************
    188  * MouseClass::Load -- Loads from a save game file.                                            *
    189  *                                                                                             *
    190  * Loading the map is very complicated.  Here are the steps:                                   *
    191  * - Read the Theater for this save-game                                                       *
    192  * - call Init_Theater to perform theater-specific inits                                       *
    193  * - call Free_Cells to free the cell array, because loading the map object will overwrite     *
    194  *   the pointer to the cell array                                                             *
    195  * - read the map object from disk                                                             *
    196  * - call Alloc_Cells to re-allocate the cell array                                            *
    197  * - call Init_Cells to set the cells to a known state, because not every cell will be loaded  *
    198  * - read the cell objects into the cell array                                                 *
    199  * - After the map & all objects have been loaded & the pointers decoded, Init_IO() >MUST< be  *
    200  *   called to restore the map's button list to the proper state.                              *
    201  *                                                                                             *
    202  * INPUT:   file  -- The file to read the cell's data from.                                    *
    203  *                                                                                             *
    204  * OUTPUT:  true = success, false = failure                                                    *
    205  *                                                                                             *
    206  * WARNINGS:   none                                                                            *
    207  *                                                                                             *
    208  * HISTORY:                                                                                    *
    209  *   09/19/1994 JLB : Created.                                                                 *
    210  *   03/12/1996 JLB : Simplified.                                                              *
    211  *=============================================================================================*/
    212 bool MouseClass::Load(Straw & file)
    213 {
    214 	/*
    215 	**	Load Theater:  Even though this value is located in the DisplayClass,
    216 	**	it must be loaded first so initialization can be done before any other
    217 	**	map data is loaded.  If initialization isn't done first, data read from
    218 	**	disk will be over-written when initialization occurs.  This code must
    219 	**	go in the most-derived Map class.
    220 	*/
    221 	TheaterType theater;
    222 	if (file.Get(&theater, sizeof(theater)) != sizeof(theater)) {
    223 		return(false);
    224 	}
    225 
    226 #ifdef WIN32
    227 LastTheater = THEATER_NONE;
    228 #endif
    229 
    230 	/*
    231 	** Remove any old theater specific uncompressed shapes
    232 	*/
    233 #ifdef WIN32
    234 //	if (theater != LastTheater) {
    235 		Reset_Theater_Shapes();
    236 //	}
    237 #endif	//WIN32
    238 
    239 	/*
    240 	**	Init display mixfiles
    241 	*/
    242 	Init_Theater(theater);
    243 	TerrainTypeClass::Init(Scen.Theater);
    244 	TemplateTypeClass::Init(Scen.Theater);
    245 	OverlayTypeClass::Init(Scen.Theater);
    246 	UnitTypeClass::Init(Scen.Theater);
    247 	InfantryTypeClass::Init(Scen.Theater);
    248 	BuildingTypeClass::Init(Scen.Theater);
    249 	BulletTypeClass::Init(Scen.Theater);
    250 	AnimTypeClass::Init(Scen.Theater);
    251 	AircraftTypeClass::Init(Scen.Theater);
    252 	VesselTypeClass::Init(Scen.Theater);
    253 	SmudgeTypeClass::Init(Scen.Theater);
    254 
    255 	//LastTheater = Scen.Theater;
    256 
    257 	/*
    258 	** Free the cell array, because we're about to overwrite its pointers
    259 	*/
    260 	Free_Cells();
    261 
    262 	/*
    263 	** Read the entire map object in.  Only read in sizeof(MouseClass), so if we're
    264 	** in editor mode, none of the map editor object is read in.
    265 	*/
    266 	file.Get(this, sizeof(*this));
    267 #ifdef SCENARIO_EDITOR
    268 	new(this) MapEditClass(NoInitClass());
    269 #else
    270 	new(this) MouseClass(NoInitClass());
    271 #endif
    272 
    273 	/*
    274 	** Reallocate the cell array
    275 	*/
    276 	Alloc_Cells();
    277 
    278 	/*
    279 	** Init all cells to empty
    280 	*/
    281 	Init_Cells();
    282 
    283 	/*
    284 	**	Read # cells saved
    285 	*/
    286 	int count;
    287 	if (file.Get(&count, sizeof(count)) != sizeof(count)) {
    288 		return(false);
    289 	}
    290 
    291 	/*
    292 	**	Read cells
    293 	*/
    294 	for (int index = 0; index < count; index++) {
    295 		CELL cell = 0;
    296 		if (file.Get(&cell, sizeof(cell)) != sizeof(cell)) {
    297 			return(false);
    298 		}
    299 
    300 		if (!(*this)[cell].Load(file)) {
    301 			return(false);
    302 		}
    303 	}
    304 
    305 	LastTheater = Scen.Theater;
    306 	return(true);
    307 }
    308 
    309 
    310 /***********************************************************************************************
    311  * MouseClass::Save -- Save to a save game file.                                               *
    312  *                                                                                             *
    313  * INPUT:   file  -- The file to write the cell's data to.                                     *
    314  *                                                                                             *
    315  * OUTPUT:  true = success, false = failure                                                    *
    316  *                                                                                             *
    317  * WARNINGS:   none                                                                            *
    318  *                                                                                             *
    319  * HISTORY:                                                                                    *
    320  *   09/19/1994 JLB : Created.                                                                 *
    321  *   02/26/1996 JLB : Cleaned up.                                                              *
    322  *=============================================================================================*/
    323 bool MouseClass::Save(Pipe & file) const
    324 {
    325 	/*
    326 	**	Save Theater >first<
    327 	*/
    328 	TheaterType theater = Scen.Theater;
    329 	file.Put(&theater, sizeof(theater));
    330 
    331 	file.Put(this, sizeof(*this));
    332 
    333 	/*
    334 	**	Count how many cells will be saved.
    335 	*/
    336 	int count = 0;
    337 	CellClass const * cellptr = &(*this)[(CELL)0];
    338 	for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    339 		if (cellptr->Should_Save()) {
    340 			count++;
    341 		}
    342 		cellptr++;
    343 	}
    344 
    345 	/*
    346 	**	write out count of the cells.
    347 	*/
    348 	file.Put(&count, sizeof(count));
    349 
    350 	/*
    351 	**	Save cells that need it
    352 	*/
    353 	cellptr = &(*this)[(CELL)0];
    354 	for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    355 		if (cellptr->Should_Save()) {
    356 			file.Put(&cell, sizeof(cell));
    357 			cellptr->Save(file);
    358 			count--;
    359 		}
    360 		cellptr++;
    361 	}
    362 
    363 	if (count != 0) return(false);
    364 
    365 	return(true);
    366 }
    367 
    368 
    369 /***********************************************************************************************
    370  * DisplayClass::Code_Pointers -- codes class's pointers for load/save                         *
    371  *                                                                                             *
    372  * This routine "codes" the pointers in the class by converting them to a number               *
    373  * that still represents the object pointed to, but isn't actually a pointer.  This            *
    374  * allows a saved game to properly load without relying on the games data still                *
    375  * being in the exact same location.                                                           *
    376  *                                                                                             *
    377  * INPUT:                                                                                      *
    378  *      none.                                                                                  *
    379  *                                                                                             *
    380  * OUTPUT:                                                                                     *
    381  *      none.                                                                                  *
    382  *                                                                                             *
    383  * WARNINGS:                                                                                   *
    384  *      none.                                                                                  *
    385  *                                                                                             *
    386  * HISTORY:                                                                                    *
    387  *   01/02/1995 BR : Created.                                                                  *
    388  *=============================================================================================*/
    389 void DisplayClass::Code_Pointers(void)
    390 {
    391 	/*
    392 	**	Code PendingObjectPtr.
    393 	*/
    394 	if (PendingObjectPtr) {
    395 		PendingObjectPtr = (ObjectClass *)PendingObjectPtr->As_Target();
    396 	}
    397 
    398 	/*
    399 	** Fix for saving game while in structure placement mode. ST - 4/15/2020 2:41PM
    400 	*/
    401 	memset(CursorShapeSave, 0, sizeof(CursorShapeSave));
    402 	if (CursorSize && CursorSize != CursorShapeSave) {
    403 
    404 		int save_buffer_element_size = sizeof(CursorShapeSave) / sizeof(CursorShapeSave[0]);
    405 		
    406 		int index = 0;
    407 
    408 		while (index < save_buffer_element_size - 2 && CursorSize[index] != REFRESH_EOL) {
    409 			CursorShapeSave[index] = CursorSize[index];
    410 			index++;
    411 		}
    412 		CursorShapeSave[index] = REFRESH_EOL;
    413 	}
    414 
    415 	/*
    416 	**	Chain to parent.
    417 	*/
    418 	MapClass::Code_Pointers();
    419 }
    420 
    421 
    422 /***********************************************************************************************
    423  * DisplayClass::Decode_Pointers -- decodes pointers for load/save                             *
    424  *                                                                                             *
    425  * This routine "decodes" the pointers coded in Code_Pointers by converting the                *
    426  * code values back into object pointers.                                                      *
    427  *                                                                                             *
    428  * INPUT:                                                                                      *
    429  *      none.                                                                                  *
    430  *                                                                                             *
    431  * OUTPUT:                                                                                     *
    432  *      none.                                                                                  *
    433  *                                                                                             *
    434  * WARNINGS:                                                                                   *
    435  *      none.                                                                                  *
    436  *                                                                                             *
    437  * HISTORY:                                                                                    *
    438  *   01/02/1995 BR : Created.                                                                  *
    439  *=============================================================================================*/
    440 void DisplayClass::Decode_Pointers(void)
    441 {
    442 	/*
    443 	**	Decode PendingObjectPtr.  We can't decode PendingObject here, because we'd
    444 	**	have to reference PendingObjectPtr->Class_Of(), and the object that
    445 	**	PendingObjectPtr is pointing to hasn't been decoded yet.  Since we can't
    446 	**	decode PendingObjectPtr, we can't set the placement cursor shape here
    447 	**	either.  These have to be done as last-minute fixups.
    448 	*/
    449 	if (PendingObjectPtr) {
    450 		PendingObjectPtr = As_Object((TARGET)PendingObjectPtr, false);
    451 		assert(PendingObjectPtr != NULL);
    452 	}
    453 
    454 	if (CursorSize) {
    455 		CursorSize = CursorShapeSave;
    456 	}
    457 
    458 	/*
    459 	**	Chain to parent.
    460 	*/
    461 	MapClass::Decode_Pointers();
    462 }
    463 
    464 
    465 /***********************************************************************************************
    466  * MapClass::Code_Pointers -- codes class's pointers for load/save                             *
    467  *                                                                                             *
    468  * This routine "codes" the pointers in the class by converting them to a number               *
    469  * that still represents the object pointed to, but isn't actually a pointer.  This            *
    470  * allows a saved game to properly load without relying on the games data still                *
    471  * being in the exact same location.                                                           *
    472  *                                                                                             *
    473  * INPUT:                                                                                      *
    474  *      none.                                                                                  *
    475  *                                                                                             *
    476  * OUTPUT:                                                                                     *
    477  *      none.                                                                                  *
    478  *                                                                                             *
    479  * WARNINGS:                                                                                   *
    480  *      none.                                                                                  *
    481  *                                                                                             *
    482  * HISTORY:                                                                                    *
    483  *   01/02/1995 BR : Created.                                                                  *
    484  *=============================================================================================*/
    485 void MapClass::Code_Pointers(void)
    486 {
    487 	CELL cell;
    488 
    489 	for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    490 		(*this)[cell].Flag_Destroy();
    491 	}
    492 
    493 	CellClass * cellptr = &(*this)[(CELL)0];
    494 	for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    495 		cellptr->Code_Pointers();
    496 		cellptr++;
    497 	}
    498 }
    499 
    500 
    501 /***********************************************************************************************
    502  * MapClass::Decode_Pointers -- decodes pointers for load/save                                 *
    503  *                                                                                             *
    504  * This routine "decodes" the pointers coded in Code_Pointers by converting the                *
    505  * code values back into object pointers.                                                      *
    506  *                                                                                             *
    507  * INPUT:                                                                                      *
    508  *      none.                                                                                  *
    509  *                                                                                             *
    510  * OUTPUT:                                                                                     *
    511  *      none.                                                                                  *
    512  *                                                                                             *
    513  * WARNINGS:                                                                                   *
    514  *      none.                                                                                  *
    515  *                                                                                             *
    516  * HISTORY:                                                                                    *
    517  *   01/02/1995 BR : Created.                                                                  *
    518  *=============================================================================================*/
    519 void MapClass::Decode_Pointers(void)
    520 {
    521 	CellClass * cellptr = &(*this)[(CELL)0];
    522 	for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
    523 		cellptr->Decode_Pointers();
    524 		cellptr++;
    525 	}
    526 }
    527