| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: /CounterStrike/IOMAP.CPP 1 3/03/97 10:24a Joe_bostic $ */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : IOMAP.CPP *
- * *
- * Programmer : Bill Randolph *
- * *
- * Start Date : January 16, 1995 *
- * *
- * Last Update : March 12, 1996 [JLB] *
- * *
- *---------------------------------------------------------------------------------------------*
- * All map-related loading/saving routines should go in this module, so it can be overlayed. *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * CellClass::Code_Pointers -- codes class's pointers for load/save *
- * CellClass::Decode_Pointers -- decodes pointers for load/save *
- * CellClass::Load -- Reads from a save game file. *
- * CellClass::Save -- Write to a save game file. *
- * CellClass::Should_Save -- Should the cell be written to disk? *
- * DisplayClass::Code_Pointers -- codes class's pointers for load/save *
- * DisplayClass::Decode_Pointers -- decodes pointers for load/save *
- * MapClass::Code_Pointers -- codes class's pointers for load/save *
- * MapClass::Decode_Pointers -- decodes pointers for load/save *
- * MouseClass::Load -- Loads from a save game file. *
- * MouseClass::Save -- Saves to a save game file. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- /***********************************************************************************************
- * CellClass::Should_Save -- Should the cell be written to disk? *
- * *
- * This function will determine if the cell needs to be written to disk. Any cell that *
- * contains special data should be written to disk. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: bool; Should this cell's data be written to disk? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/19/1994 JLB : Created. *
- *=============================================================================================*/
- bool CellClass::Should_Save(void) const
- {
- static CellClass const _identity_cell;
- return(memcmp(&_identity_cell, this, sizeof(*this)) != 0);
- }
- /***********************************************************************************************
- * CellClass::Load -- Loads from a save game file. *
- * *
- * INPUT: file -- The file to read the cell's data from. *
- * *
- * OUTPUT: true = success, false = failure *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/19/1994 JLB : Created. *
- *=============================================================================================*/
- bool CellClass::Load(Straw & file)
- {
- file.Get(this, sizeof(*this));
- return(true);
- }
- /***********************************************************************************************
- * CellClass::Save -- Write to a save game file. *
- * *
- * INPUT: file -- The file to write the cell's data to. *
- * *
- * OUTPUT: true = success, false = failure *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/19/1994 JLB : Created. *
- *=============================================================================================*/
- bool CellClass::Save(Pipe & file) const
- {
- file.Put(this, sizeof(*this));
- return(true);
- }
- /***********************************************************************************************
- * CellClass::Code_Pointers -- codes class's pointers for load/save *
- * *
- * This routine "codes" the pointers in the class by converting them to a number *
- * that still represents the object pointed to, but isn't actually a pointer. This *
- * allows a saved game to properly load without relying on the games data still *
- * being in the exact same location. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/02/1995 BR : Created. *
- *=============================================================================================*/
- void CellClass::Code_Pointers(void)
- {
- if (Cell_Occupier() != NULL) {
- OccupierPtr = (ObjectClass *)OccupierPtr->As_Target();
- }
- for (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {
- if (Overlapper[index] != NULL && Overlapper[index]->IsActive) {
- Overlapper[index] = (ObjectClass *)Overlapper[index]->As_Target();
- } else {
- Overlapper[index] = NULL;
- }
- }
- }
- /***********************************************************************************************
- * CellClass::Decode_Pointers -- decodes pointers for load/save *
- * *
- * This routine "decodes" the pointers coded in Code_Pointers by converting the *
- * code values back into object pointers. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/02/1995 BR : Created. *
- * 03/12/1996 JLB : Simplified. *
- *=============================================================================================*/
- void CellClass::Decode_Pointers(void)
- {
- if (OccupierPtr != NULL) {
- OccupierPtr = As_Object((TARGET)OccupierPtr);
- assert(OccupierPtr != NULL);
- }
- for (int index = 0; index < ARRAY_SIZE(Overlapper); index++) {
- if (Overlapper[index] != NULL) {
- Overlapper[index] = As_Object((TARGET)Overlapper[index]);
- assert(Overlapper[index] != NULL);
- }
- }
- }
- /***********************************************************************************************
- * MouseClass::Load -- Loads from a save game file. *
- * *
- * Loading the map is very complicated. Here are the steps: *
- * - Read the Theater for this save-game *
- * - call Init_Theater to perform theater-specific inits *
- * - call Free_Cells to free the cell array, because loading the map object will overwrite *
- * the pointer to the cell array *
- * - read the map object from disk *
- * - call Alloc_Cells to re-allocate the cell array *
- * - call Init_Cells to set the cells to a known state, because not every cell will be loaded *
- * - read the cell objects into the cell array *
- * - After the map & all objects have been loaded & the pointers decoded, Init_IO() >MUST< be *
- * called to restore the map's button list to the proper state. *
- * *
- * INPUT: file -- The file to read the cell's data from. *
- * *
- * OUTPUT: true = success, false = failure *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/19/1994 JLB : Created. *
- * 03/12/1996 JLB : Simplified. *
- *=============================================================================================*/
- bool MouseClass::Load(Straw & file)
- {
- /*
- ** Load Theater: Even though this value is located in the DisplayClass,
- ** it must be loaded first so initialization can be done before any other
- ** map data is loaded. If initialization isn't done first, data read from
- ** disk will be over-written when initialization occurs. This code must
- ** go in the most-derived Map class.
- */
- TheaterType theater;
- if (file.Get(&theater, sizeof(theater)) != sizeof(theater)) {
- return(false);
- }
- #ifdef WIN32
- LastTheater = THEATER_NONE;
- #endif
- /*
- ** Remove any old theater specific uncompressed shapes
- */
- #ifdef WIN32
- // if (theater != LastTheater) {
- Reset_Theater_Shapes();
- // }
- #endif //WIN32
- /*
- ** Init display mixfiles
- */
- Init_Theater(theater);
- TerrainTypeClass::Init(Scen.Theater);
- TemplateTypeClass::Init(Scen.Theater);
- OverlayTypeClass::Init(Scen.Theater);
- UnitTypeClass::Init(Scen.Theater);
- InfantryTypeClass::Init(Scen.Theater);
- BuildingTypeClass::Init(Scen.Theater);
- BulletTypeClass::Init(Scen.Theater);
- AnimTypeClass::Init(Scen.Theater);
- AircraftTypeClass::Init(Scen.Theater);
- VesselTypeClass::Init(Scen.Theater);
- SmudgeTypeClass::Init(Scen.Theater);
- //LastTheater = Scen.Theater;
- /*
- ** Free the cell array, because we're about to overwrite its pointers
- */
- Free_Cells();
- /*
- ** Read the entire map object in. Only read in sizeof(MouseClass), so if we're
- ** in editor mode, none of the map editor object is read in.
- */
- file.Get(this, sizeof(*this));
- #ifdef SCENARIO_EDITOR
- new(this) MapEditClass(NoInitClass());
- #else
- new(this) MouseClass(NoInitClass());
- #endif
- /*
- ** Reallocate the cell array
- */
- Alloc_Cells();
- /*
- ** Init all cells to empty
- */
- Init_Cells();
- /*
- ** Read # cells saved
- */
- int count;
- if (file.Get(&count, sizeof(count)) != sizeof(count)) {
- return(false);
- }
- /*
- ** Read cells
- */
- for (int index = 0; index < count; index++) {
- CELL cell = 0;
- if (file.Get(&cell, sizeof(cell)) != sizeof(cell)) {
- return(false);
- }
- if (!(*this)[cell].Load(file)) {
- return(false);
- }
- }
- LastTheater = Scen.Theater;
- return(true);
- }
- /***********************************************************************************************
- * MouseClass::Save -- Save to a save game file. *
- * *
- * INPUT: file -- The file to write the cell's data to. *
- * *
- * OUTPUT: true = success, false = failure *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/19/1994 JLB : Created. *
- * 02/26/1996 JLB : Cleaned up. *
- *=============================================================================================*/
- bool MouseClass::Save(Pipe & file) const
- {
- /*
- ** Save Theater >first<
- */
- TheaterType theater = Scen.Theater;
- file.Put(&theater, sizeof(theater));
- file.Put(this, sizeof(*this));
- /*
- ** Count how many cells will be saved.
- */
- int count = 0;
- CellClass const * cellptr = &(*this)[(CELL)0];
- for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
- if (cellptr->Should_Save()) {
- count++;
- }
- cellptr++;
- }
- /*
- ** write out count of the cells.
- */
- file.Put(&count, sizeof(count));
- /*
- ** Save cells that need it
- */
- cellptr = &(*this)[(CELL)0];
- for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
- if (cellptr->Should_Save()) {
- file.Put(&cell, sizeof(cell));
- cellptr->Save(file);
- count--;
- }
- cellptr++;
- }
- if (count != 0) return(false);
- return(true);
- }
- /***********************************************************************************************
- * DisplayClass::Code_Pointers -- codes class's pointers for load/save *
- * *
- * This routine "codes" the pointers in the class by converting them to a number *
- * that still represents the object pointed to, but isn't actually a pointer. This *
- * allows a saved game to properly load without relying on the games data still *
- * being in the exact same location. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/02/1995 BR : Created. *
- *=============================================================================================*/
- void DisplayClass::Code_Pointers(void)
- {
- /*
- ** Code PendingObjectPtr.
- */
- if (PendingObjectPtr) {
- PendingObjectPtr = (ObjectClass *)PendingObjectPtr->As_Target();
- }
- /*
- ** Chain to parent.
- */
- MapClass::Code_Pointers();
- }
- /***********************************************************************************************
- * DisplayClass::Decode_Pointers -- decodes pointers for load/save *
- * *
- * This routine "decodes" the pointers coded in Code_Pointers by converting the *
- * code values back into object pointers. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/02/1995 BR : Created. *
- *=============================================================================================*/
- void DisplayClass::Decode_Pointers(void)
- {
- /*
- ** Decode PendingObjectPtr. We can't decode PendingObject here, because we'd
- ** have to reference PendingObjectPtr->Class_Of(), and the object that
- ** PendingObjectPtr is pointing to hasn't been decoded yet. Since we can't
- ** decode PendingObjectPtr, we can't set the placement cursor shape here
- ** either. These have to be done as last-minute fixups.
- */
- if (PendingObjectPtr) {
- PendingObjectPtr = As_Object((TARGET)PendingObjectPtr);
- assert(PendingObjectPtr != NULL);
- }
- /*
- ** Chain to parent.
- */
- MapClass::Decode_Pointers();
- }
- /***********************************************************************************************
- * MapClass::Code_Pointers -- codes class's pointers for load/save *
- * *
- * This routine "codes" the pointers in the class by converting them to a number *
- * that still represents the object pointed to, but isn't actually a pointer. This *
- * allows a saved game to properly load without relying on the games data still *
- * being in the exact same location. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/02/1995 BR : Created. *
- *=============================================================================================*/
- void MapClass::Code_Pointers(void)
- {
- CellClass * cellptr = &(*this)[(CELL)0];
- for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
- cellptr->Code_Pointers();
- cellptr++;
- }
- }
- /***********************************************************************************************
- * MapClass::Decode_Pointers -- decodes pointers for load/save *
- * *
- * This routine "decodes" the pointers coded in Code_Pointers by converting the *
- * code values back into object pointers. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/02/1995 BR : Created. *
- *=============================================================================================*/
- void MapClass::Decode_Pointers(void)
- {
- CellClass * cellptr = &(*this)[(CELL)0];
- for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
- cellptr->Decode_Pointers();
- cellptr++;
- }
- }
|