| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392 |
- /*
- ** Command & Conquer(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: F:\projects\c&c\vcs\code\saveload.cpv 2.18 16 Oct 1995 16:48:44 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 : SAVELOAD.CPP *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : August 23, 1994 *
- * *
- * Last Update : June 24, 1995 [JLB] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * Code_All_Pointers -- Code all pointers. *
- * Decode_All_Pointers -- Decodes all pointers. *
- * Get_Savefile_Info -- gets description, scenario #, house *
- * Load_Game -- loads a saved game *
- * Load_Misc_Values -- Loads miscellaneous variables. *
- * Load_Misc_Values -- loads miscellaneous variables *
- * Read_Object -- reads an object from disk, in a safe way *
- * Save_Game -- saves a game to disk *
- * Save_Misc_Values -- saves miscellaneous variables *
- * Target_To_TechnoType -- converts TARGET to TechnoTypeClass *
- * TechnoType_To_Target -- converts TechnoTypeClass to TARGET *
- * Write_Object -- reads an object from disk, in a safe way *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- /*
- ********************************** Defines **********************************
- */
- #define SAVEGAME_VERSION (DESCRIP_MAX + \
- 0x01000003 + ( \
- sizeof(AircraftClass) + \
- sizeof(AircraftTypeClass) + \
- sizeof(AnimClass) + \
- sizeof(AnimTypeClass) + \
- sizeof(BuildingClass) + \
- sizeof(BuildingTypeClass) + \
- sizeof(BulletClass) + \
- sizeof(BulletTypeClass) + \
- sizeof(HouseClass) + \
- sizeof(HouseTypeClass) + \
- sizeof(InfantryClass) + \
- sizeof(InfantryTypeClass) + \
- sizeof(OverlayClass) + \
- sizeof(OverlayTypeClass) + \
- sizeof(SmudgeClass) + \
- sizeof(SmudgeTypeClass) + \
- sizeof(TeamClass) + \
- sizeof(TeamTypeClass) + \
- sizeof(TemplateClass) + \
- sizeof(TemplateTypeClass) + \
- sizeof(TerrainClass) + \
- sizeof(TerrainTypeClass) + \
- sizeof(UnitClass) + \
- sizeof(UnitTypeClass) + \
- sizeof(MouseClass) + \
- sizeof(CellClass) + \
- sizeof(FactoryClass) + \
- sizeof(BaseClass) + \
- sizeof(LayerClass) + \
- sizeof(BriefingText) + \
- sizeof(Waypoint)))
- /***************************************************************************
- * Save_Game -- saves a game to disk *
- * *
- * Saving the Map: *
- * DisplayClass::Save() invokes CellClass's Write() for every cell *
- * that needs to be saved. A cell needs to be saved if it contains *
- * any special data at all, such as a TIcon, or an Occupier. *
- * The cell saves its own CellTrigger pointer, converted to a TARGET. *
- * *
- * Saving game objects: *
- * - Any object stored in an ArrayOf class needs to be saved. The ArrayOf*
- * Save() routine invokes each object's Write() routine, if that *
- * object's IsActive is set. *
- * *
- * Saving the layers: *
- * The Map's Layers (Ground, Air, etc) of things that are on the map, *
- * and the Logic's Layer of things to process both need to be saved. *
- * LayerClass::Save() writes the entire layer array to disk *
- * *
- * Saving the houses: *
- * Each house needs to be saved, to record its Credits, Power, etc. *
- * *
- * Saving miscellaneous data: *
- * There are a lot of miscellaneous variables to save, such as the *
- * map's dimensions, the player's house, etc. *
- * *
- * INPUT: *
- * id numerical ID, for the file extension *
- * *
- * OUTPUT: *
- * true = OK, false = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/28/1994 BR : Created. *
- *=========================================================================*/
- bool Save_Game(int id,char *descr)
- {
- RawFileClass file;
- char name[_MAX_FNAME+_MAX_EXT];
- int i;
- unsigned long version;
- unsigned scenario;
- HousesType house;
- char descr_buf[DESCRIP_MAX];
- scenario = Scenario; // get current scenario #
- house = PlayerPtr->Class->House; // get current house
- /*
- ** Generate the filename to save
- */
- sprintf(name, "SAVEGAME.%03d", id);
- /*
- ** Code everybody's pointers
- */
- Code_All_Pointers();
- /*
- ** Open the file
- */
- if (!file.Open(name, WRITE)) {
- Decode_All_Pointers();
- return(false);
- }
- /*
- ** Save the description, scenario #, and house
- ** (scenario # & house are saved separately from the actual Scenario &
- ** PlayerPtr globals for convenience; we can quickly find out which
- ** house & scenario this save-game file is for by reading these values.
- ** Also, PlayerPtr is stored in a coded form in Save_Misc_Values(),
- ** which may or may not be a HousesType number; so, saving 'house'
- ** here ensures we can always pull out the house for this file.)
- */
- sprintf(descr_buf, "%s\r\n",descr); // put CR-LF after text
- descr_buf[strlen(descr_buf) + 1] = 26; // put CTRL-Z after NULL
- if (file.Write(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
- file.Close();
- return(false);
- }
- if (file.Write(&scenario, sizeof(scenario)) != sizeof(scenario)) {
- file.Close();
- return(false);
- }
- if (file.Write(&house, sizeof(house)) != sizeof(house)) {
- file.Close();
- return(false);
- }
- /*
- ** Save the save-game version, for loading verification
- */
- version = SAVEGAME_VERSION;
- if (file.Write(&version, sizeof(version)) != sizeof(version)) {
- file.Close();
- return(false);
- }
- Call_Back();
- /*
- ** Save the map. The map must be saved first, since it saves the Theater.
- */
- Map.Save(file);
- Call_Back();
- /*
- ** Save all game objects. This code saves every object that's stored in a
- ** TFixedIHeap class.
- */
- if (!Houses.Save(file) ||
- !TeamTypes.Save(file) ||
- !Teams.Save(file) ||
- !Triggers.Save(file) ||
- !Aircraft.Save(file) ||
- !Anims.Save(file) ||
- !Buildings.Save(file) ||
- !Bullets.Save(file) ||
- !Infantry.Save(file) ||
- !Overlays.Save(file) ||
- !Smudges.Save(file) ||
- !Templates.Save(file) ||
- !Terrains.Save(file) ||
- !Units.Save(file) ||
- !Factories.Save(file)) {
- file.Close();
- Decode_All_Pointers();
- return(false);
- }
- Call_Back();
- /*
- ** Save the Logic & Map layers
- */
- if (!Logic.Save(file)) {
- file.Close();
- Decode_All_Pointers();
- return(false);
- }
- for (i = 0; i < LAYER_COUNT; i++) {
- if (!Map.Layer[i].Save(file)) {
- file.Close();
- Decode_All_Pointers();
- return(false);
- }
- }
- /*
- ** Save the Score
- */
- if (!Score.Save(file)) {
- file.Close();
- Decode_All_Pointers();
- return(false);
- }
- /*
- ** Save the AI Base
- */
- if (!Base.Save(file)) {
- file.Close();
- Decode_All_Pointers();
- return(false);
- }
- /*
- ** Save miscellaneous variables.
- */
- if (!Save_Misc_Values(file)) {
- file.Close();
- Decode_All_Pointers();
- return(false);
- }
- Call_Back();
- /*
- ** Close the file; we're done
- */
- file.Close();
- Decode_All_Pointers();
- return(true);
- }
- /***************************************************************************
- * Load_Game -- loads a saved game *
- * *
- * This routine loads the data in the same way it was saved out. *
- * *
- * Loading the Map: *
- * - DisplayClass::Load() invokes CellClass's Load() for every cell *
- * that was saved. *
- * - The cell loads its own CellTrigger pointer. *
- * *
- * Loading game objects: *
- * - IHeap's Load() routine loads the # of objects stored, and loads *
- * each object. *
- * - Triggers: Add themselves to the HouseTriggers if they're associated *
- * with a house *
- * *
- * Loading the layers: *
- * LayerClass::Load() reads the entire layer array to disk *
- * *
- * Loading the houses: *
- * Each house is loaded in its entirety. *
- * *
- * Loading miscellaneous data: *
- * There are a lot of miscellaneous variables to load, such as the *
- * map's dimensions, the player's house, etc. *
- * *
- * INPUT: *
- * id numerical ID, for the file extension *
- * *
- * OUTPUT: *
- * true = OK, false = error *
- * *
- * WARNINGS: *
- * If this routine returns false, the entire game will be in an *
- * unknown state, so the scenario will have to be re-initialized. *
- * *
- * HISTORY: *
- * 12/28/1994 BR : Created. *
- *=========================================================================*/
- bool Load_Game(int id)
- {
- RawFileClass file;
- char name[_MAX_FNAME+_MAX_EXT];
- int i;
- unsigned long version;
- unsigned scenario;
- HousesType house;
- char descr_buf[DESCRIP_MAX];
- /*
- ** Generate the filename to load
- */
- sprintf(name, "SAVEGAME.%03d", id);
- /*
- ** Open the file
- */
- if (!file.Open(name, READ)) {
- return(false);
- }
- /*
- ** Read & discard the save-game's header info
- */
- if (file.Read(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
- file.Close();
- return(false);
- }
- if (file.Read(&scenario, sizeof(scenario)) != sizeof(scenario)) {
- file.Close();
- return(false);
- }
- if (file.Read(&house, sizeof(house)) != sizeof(house)) {
- file.Close();
- return(false);
- }
- Call_Back();
- /*
- ** Clear the scenario so we start fresh; this calls the Init_Clear() routine
- ** for the Map, and all object arrays. It has the following important
- ** effects:
- ** - Every cell is cleared to 0's, via MapClass::Init_Clear()
- ** - All heap elements' are cleared
- ** - The Houses are Initialized, which also clears their HouseTriggers
- ** array
- ** - The map's Layers & Logic Layer are cleared to empty
- ** - The list of currently-selected objects is cleared
- */
- Clear_Scenario();
- /*
- ** Read in & verify the save-game ID code
- */
- if (file.Read(&version,sizeof(version)) != sizeof(version)) {
- file.Close();
- return(false);
- }
- if (version != SAVEGAME_VERSION) {
- file.Close();
- return(false);
- }
- Call_Back();
- /*
- ** Set the required CD to be in the drive according to the scenario
- ** loaded.
- */
- if (RequiredCD != -2) {
- if (scenario >= 20 && scenario <60 && GameToPlay == GAME_NORMAL) {
- RequiredCD = 2;
- } else {
- if (scenario >= 60){
- /*
- ** This is a gateway bonus scenario
- */
- RequiredCD = -1;
- }else{
- if (house == HOUSE_GOOD) {
- RequiredCD = 0;
- } else {
- RequiredCD = 1;
- }
- }
- }
- }
- if(!Force_CD_Available(RequiredCD)) {
- Prog_End();
- exit(EXIT_FAILURE);
- }
- Call_Back();
- /*
- ** Load the map. The map comes first, since it loads the Theater & init's
- ** mixfiles. The map calls all the type-class's Init routines, telling them
- ** what the Theater is; this must be done before any objects are created, so
- ** they'll be properly created.
- */
- Map.Load(file);
- Call_Back();
- /*
- ** Load the object data.
- */
- if (!Houses.Load(file) ||
- !TeamTypes.Load(file) ||
- !Teams.Load(file) ||
- !Triggers.Load(file) ||
- !Aircraft.Load(file) ||
- !Anims.Load(file) ||
- !Buildings.Load(file) ||
- !Bullets.Load(file) ||
- !Infantry.Load(file) ||
- !Overlays.Load(file) ||
- !Smudges.Load(file) ||
- !Templates.Load(file) ||
- !Terrains.Load(file) ||
- !Units.Load(file) ||
- !Factories.Load(file)) {
- file.Close();
- return(false);
- }
- Call_Back();
- /*
- ** Load the Logic & Map Layers
- */
- if (!Logic.Load(file)) {
- file.Close();
- return(false);
- }
- for (i = 0; i < LAYER_COUNT; i++) {
- if (!Map.Layer[i].Load(file)) {
- file.Close();
- return(false);
- }
- }
- Call_Back();
- /*
- ** Load the Score
- */
- if (!Score.Load(file)) {
- file.Close();
- return(false);
- }
- /*
- ** Load the AI Base
- */
- if (!Base.Load(file)) {
- file.Close();
- return(false);
- }
- /*
- ** Load miscellaneous variables, including the map size & the Theater
- */
- if (!Load_Misc_Values(file)) {
- file.Close();
- return(false);
- }
- file.Close();
- Decode_All_Pointers();
- Map.Init_IO();
- Map.Flag_To_Redraw(true);
- ScenarioInit = 0;
- #ifdef DEMO
- if (Scenario != 10 && Scenario != 1 && Scenario != 6) {
- Clear_Scenario();
- return(false);
- }
- #endif
- Call_Back();
- return(true);
- }
- /***************************************************************************
- * Save_Misc_Values -- saves miscellaneous variables *
- * *
- * INPUT: *
- * file file to use for writing *
- * *
- * OUTPUT: *
- * true = success, false = failure *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/29/1994 BR : Created. *
- *=========================================================================*/
- bool Save_Misc_Values(FileClass &file)
- {
- int i;
- int count; // # ptrs in 'CurrentObject'
- ObjectClass * ptr; // for saving 'CurrentObject' ptrs
- /*
- ** Player's House.
- */
- if (file.Write(&PlayerPtr, sizeof(PlayerPtr)) != sizeof(PlayerPtr)) {
- return(false);
- }
- /*
- ** Save this scenario number.
- */
- if (file.Write(&Scenario, sizeof(Scenario)) != sizeof(Scenario)) {
- return(false);
- }
- /*
- ** Save frame #.
- */
- if (file.Write(&Frame, sizeof(Frame)) != sizeof(Frame)) {
- return(false);
- }
- /*
- ** Save VQ Movie names.
- */
- if (file.Write(WinMovie, sizeof(WinMovie)) != sizeof(WinMovie)) {
- return(false);
- }
- if (file.Write(LoseMovie, sizeof(LoseMovie)) != sizeof(LoseMovie)) {
- return(false);
- }
- /*
- ** Save currently-selected objects list.
- ** Save the # of ptrs in the list.
- */
- count = CurrentObject.Count();
- if (file.Write(&count, sizeof(count)) != sizeof(count)) {
- return(false);
- }
- /*
- ** Save the pointers.
- */
- for (i = 0; i < count; i++) {
- ptr = CurrentObject[i];
- if (file.Write(&ptr, sizeof(ptr)) != sizeof(ptr)) {
- return(false);
- }
- }
- /*
- ** Save the list of waypoints.
- */
- if (file.Write(Waypoint, sizeof(Waypoint)) != sizeof(Waypoint)) {
- return(false);
- }
- file.Write(&ScenDir, sizeof(ScenDir));
- file.Write(&ScenVar, sizeof(ScenVar));
- file.Write(&CarryOverMoney, sizeof(CarryOverMoney));
- file.Write(&CarryOverPercent, sizeof(CarryOverPercent));
- file.Write(&BuildLevel, sizeof(BuildLevel));
- file.Write(BriefMovie, sizeof(BriefMovie));
- file.Write(Views, sizeof(Views));
- file.Write(&EndCountDown, sizeof(EndCountDown));
- file.Write(BriefingText, sizeof(BriefingText));
- // This is new...
- file.Write(ActionMovie, sizeof(ActionMovie));
- return(true);
- }
- /***********************************************************************************************
- * Load_Misc_Values -- Loads miscellaneous variables. *
- * *
- * INPUT: file -- The file to load the misc values from. *
- * *
- * OUTPUT: Was the misc load process successful? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/24/1995 BRR : Created. *
- *=============================================================================================*/
- bool Load_Misc_Values(FileClass &file)
- {
- int i;
- int count; // # ptrs in 'CurrentObject'
- ObjectClass * ptr; // for loading 'CurrentObject' ptrs
- /*
- ** Player's House.
- */
- if (file.Read(&PlayerPtr, sizeof(PlayerPtr)) != sizeof(PlayerPtr)) {
- return(false);
- }
- /*
- ** Read this scenario number.
- */
- if (file.Read(&Scenario,sizeof(Scenario)) != sizeof(Scenario)) {
- return(false);
- }
- /*
- ** Load frame #.
- */
- if (file.Read(&Frame, sizeof(Frame)) != sizeof(Frame)) {
- return(false);
- }
- /*
- ** Load VQ Movie names.
- */
- if (file.Read(WinMovie, sizeof(WinMovie)) != sizeof(WinMovie)) {
- return(false);
- }
- if (file.Read(LoseMovie, sizeof(LoseMovie)) != sizeof(LoseMovie)) {
- return(false);
- }
- /*
- ** Load currently-selected objects list.
- ** Load the # of ptrs in the list.
- */
- if (file.Read(&count, sizeof(count)) != sizeof(count)) {
- return(false);
- }
- /*
- ** Load the pointers.
- */
- for (i = 0; i < count; i++) {
- if (file.Read(&ptr, sizeof(ptr)) != sizeof(ptr)) {
- return(false);
- }
- CurrentObject.Add(ptr); // add to the list
- }
- /*
- ** Save the list of waypoints.
- */
- if (file.Read(Waypoint, sizeof(Waypoint)) != sizeof(Waypoint)) {
- return(false);
- }
- file.Read(&ScenDir, sizeof(ScenDir));
- file.Read(&ScenVar, sizeof(ScenVar));
- file.Read(&CarryOverMoney, sizeof(CarryOverMoney));
- file.Read(&CarryOverPercent, sizeof(CarryOverPercent));
- file.Read(&BuildLevel, sizeof(BuildLevel));
- file.Read(BriefMovie, sizeof(BriefMovie));
- file.Read(Views, sizeof(Views));
- file.Read(&EndCountDown, sizeof(EndCountDown));
- file.Read(BriefingText, sizeof(BriefingText));
- if (file.Seek(0, SEEK_CUR) < file.Size()) {
- file.Read(ActionMovie, sizeof(ActionMovie));
- }
- return(true);
- }
- /***********************************************************************************************
- * Code_All_Pointers -- Code all pointers. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/24/1995 BRR : Created. *
- *=============================================================================================*/
- void Code_All_Pointers(void)
- {
- int i;
- /*
- ** The Map.
- */
- Map.Code_Pointers();
- /*
- ** The ArrayOf's.
- */
- TeamTypes.Code_Pointers();
- Teams.Code_Pointers();
- Triggers.Code_Pointers();
- Aircraft.Code_Pointers();
- Anims.Code_Pointers();
- Buildings.Code_Pointers();
- Bullets.Code_Pointers();
- Infantry.Code_Pointers();
- Overlays.Code_Pointers();
- Smudges.Code_Pointers();
- Templates.Code_Pointers();
- Terrains.Code_Pointers();
- Units.Code_Pointers();
- Factories.Code_Pointers();
- /*
- ** The Layers.
- */
- Logic.Code_Pointers();
- for (i = 0; i < LAYER_COUNT; i++) {
- Map.Layer[i].Code_Pointers();
- }
- /*
- ** The Score.
- */
- Score.Code_Pointers();
- /*
- ** The Base.
- */
- Base.Code_Pointers();
- /*
- ** PlayerPtr.
- */
- PlayerPtr = (HouseClass *)(PlayerPtr->Class->House);
- /*
- ** Currently-selected objects.
- */
- for (i = 0; i < CurrentObject.Count(); i++) {
- CurrentObject[i] = (ObjectClass *)CurrentObject[i]->As_Target();
- }
- /*
- ** Houses must be coded last, because the Class->House member of the HouseClass
- ** is used to code HouseClass pointers for all other objects, and if Class is
- ** coded, it will point to a meaningless value.
- */
- Houses.Code_Pointers();
- }
- /***********************************************************************************************
- * Decode_All_Pointers -- Decodes all pointers. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/24/1995 BRR : Created. *
- *=============================================================================================*/
- void Decode_All_Pointers(void)
- {
- int i;
- /*
- ** The Map.
- */
- Map.Decode_Pointers();
- /*
- ** Decode houses first, so we can properly decode all other objects'
- ** House pointers
- */
- Houses.Decode_Pointers();
- /*
- ** The ArrayOf's.
- */
- TeamTypes.Decode_Pointers();
- Teams.Decode_Pointers();
- Triggers.Decode_Pointers();
- Aircraft.Decode_Pointers();
- Anims.Decode_Pointers();
- Buildings.Decode_Pointers();
- Bullets.Decode_Pointers();
- Infantry.Decode_Pointers();
- Overlays.Decode_Pointers();
- Smudges.Decode_Pointers();
- Templates.Decode_Pointers();
- Terrains.Decode_Pointers();
- Units.Decode_Pointers();
- Factories.Decode_Pointers();
- /*
- ** The Layers.
- */
- Logic.Decode_Pointers();
- for (i = 0; i < LAYER_COUNT; i++) {
- Map.Layer[i].Decode_Pointers();
- }
- /*
- ** The Score.
- */
- Score.Decode_Pointers();
- /*
- ** The Base.
- */
- Base.Decode_Pointers();
- /*
- ** PlayerPtr.
- */
- PlayerPtr = HouseClass::As_Pointer((HousesType)PlayerPtr);
- Whom = PlayerPtr->Class->House;
- switch (PlayerPtr->Class->House) {
- case HOUSE_GOOD:
- ScenPlayer = SCEN_PLAYER_GDI;
- break;
- case HOUSE_BAD:
- ScenPlayer = SCEN_PLAYER_NOD;
- break;
- case HOUSE_JP:
- ScenPlayer = SCEN_PLAYER_JP;
- break;
- }
- Check_Ptr(PlayerPtr,__FILE__,__LINE__);
- Set_Scenario_Name(ScenarioName, Scenario, ScenPlayer, ScenDir, ScenVar);
- /*
- ** Currently-selected objects.
- */
- for (i = 0; i < CurrentObject.Count(); i++) {
- CurrentObject[i] = As_Object((TARGET)CurrentObject[i]);
- Check_Ptr(CurrentObject[i],__FILE__,__LINE__);
- }
- /*
- ** Last-Minute Fixups; to resolve these pointers properly requires all other
- ** pointers to be loaded & decoded.
- */
- if (Map.PendingObjectPtr) {
- Map.PendingObject = &Map.PendingObjectPtr->Class_Of();
- Check_Ptr((void *)Map.PendingObject, __FILE__, __LINE__);
- Map.Set_Cursor_Shape(Map.PendingObject->Occupy_List(true));
- } else {
- Map.PendingObject = 0;
- Map.Set_Cursor_Shape(0);
- }
- }
- /***********************************************************************************************
- * Read_Object -- reads an object from disk *
- * *
- * This routine reads in an object and fills in the virtual function table pointer. *
- * *
- * INPUT: *
- * ptr pointer to object to read *
- * base_size size of object's absolute base class *
- * class_size size of the class itself *
- * file file to use for I/O *
- * vtable virtual function table pointer value, NULL if none *
- * *
- * OUTPUT: *
- * true = OK, false = error *
- * *
- * WARNINGS: *
- * This routine ASSUMES the program modules are compiled with: *
- * -Vb- Always make the virtual function table ptr 2 bytes long *
- * -Vt Put the virtual function table after the 1st class's data *
- * *
- * ALSO, the class used to compute 'base_size' must come first in a multiple-inheritence *
- * hierarchy. AND, if your class multiply-inherits from other classes, only ONE of those *
- * classes can contain virtual functions! If you include virtual functions in the other *
- * classes, the compiler will generate multiple virtual function tables, and this load/save *
- * technique will fail. *
- * *
- * Each class hierarchy is stored in memory as a chain: first the data for the base-est *
- * class, then the virtual function table pointer for this hierarchy, then the data for *
- * all derived classes. If any of these derived classes multiply-inherit, the base class *
- * for the multiple inheritance is stored as a separate chain following this chain. The *
- * new chain will contain its own virtual function table pointer, if the multiply- *
- * inherited hierarchy contains any virtual functions. Thus, the declaration *
- * class A *
- * class B: public A *
- * class C: public B, X *
- * is stored as: *
- * A data *
- * A's Virtual Table Pointer *
- * B data *
- * X data *
- * [X's Virtual Table Pointer] *
- * C data *
- * *
- * and *
- * class A *
- * class B: public A *
- * class C: public X, B *
- * is stored in memory as: *
- * X data *
- * [X's Virtual Table Pointer] *
- * A data *
- * A's Virtual Table Pointer *
- * B data *
- * C data *
- * *
- * *
- * HISTORY: *
- * 01/10/1995 BR : Created. *
- *=============================================================================================*/
- bool Read_Object(void *ptr, int base_size, int class_size, FileClass & file, void * vtable)
- {
- int size; // object size in bytes
- /*
- ** Read size of this chunk.
- */
- if (file.Read(&size,sizeof(size)) != sizeof(size)) {
- return(false);
- }
- /*
- ** Error if incorrect size.
- */
- if (size != class_size) {
- return(false);
- }
- /*
- ** Read object data.
- */
- if (file.Read(ptr, class_size) != (class_size)) {
- return(false);
- }
- /*
- ** Fill in VTable.
- */
- if (vtable) {
- ((void **)(((char *)ptr) + base_size - 4))[0] = vtable;
- }
- return(true);
- }
- /***********************************************************************************************
- * Write_Object -- reads an object from disk, in a safe way *
- * *
- * This routine writes an object in 2 pieces, skipping the embedded *
- * virtual function table pointer. *
- * *
- * INPUT: *
- * ptr pointer to object to write *
- * class_size size of the class itself *
- * file file to use for I/O *
- * *
- * OUTPUT: *
- * true = OK, false = error *
- * *
- * WARNINGS: *
- * This routine ASSUMES the program modules are compiled with: *
- * -Vb- Always make the virtual function table ptr 2 bytes long *
- * -Vt Put the virtual function table after the 1st class's data *
- * *
- * Also see warnings for Read_Object(). *
- * *
- * HISTORY: *
- * 01/10/1995 BR : Created. *
- *=============================================================================================*/
- bool Write_Object(void *ptr, int class_size, FileClass & file)
- {
- /*
- ** Save size of this chunk.
- */
- if (file.Write(&class_size,sizeof(class_size)) != sizeof(class_size)) {
- return(false);
- }
- /*
- ** Save object data.
- */
- if (file.Write(ptr, class_size) != (class_size)) {
- return(false);
- }
- return(true);
- }
- /***************************************************************************
- * Get_Savefile_Info -- gets description, scenario #, house *
- * *
- * INPUT: *
- * id numerical ID, for the file extension *
- * buf buffer to store description in *
- * scenp ptr to variable to hold scenario *
- * housep ptr to variable to hold house *
- * *
- * OUTPUT: *
- * true = OK, false = error (save-game file invalid) *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 01/12/1995 BR : Created. *
- *=========================================================================*/
- bool Get_Savefile_Info(int id, char *buf, unsigned *scenp, HousesType *housep)
- {
- RawFileClass file;
- char name[_MAX_FNAME+_MAX_EXT];
- unsigned long version;
- char descr_buf[DESCRIP_MAX];
- /*
- ** Generate the filename to load
- */
- sprintf(name, "SAVEGAME.%03d", id);
- /*
- ** If the file opens OK, read the file
- */
- if (file.Open(name, READ)) {
- /*
- ** Read in the description, scenario #, and the house
- */
- if (file.Read(descr_buf, DESCRIP_MAX) != DESCRIP_MAX) {
- file.Close();
- return(false);
- }
- descr_buf[strlen(descr_buf) - 2] = '\0'; // trim off CR/LF
- strcpy(buf, descr_buf);
- if (file.Read(scenp, sizeof(unsigned)) != sizeof(unsigned)) {
- file.Close();
- return(false);
- }
- if (file.Read(housep, sizeof(HousesType)) != sizeof(HousesType)) {
- file.Close();
- return(false);
- }
- /*
- ** Read & verify the save-game version #
- */
- if (file.Read(&version,sizeof(version)) != sizeof(version)) {
- file.Close();
- return(false);
- }
- if (version!=SAVEGAME_VERSION) {
- file.Close();
- return(false);
- }
- file.Close();
- return(true);
- }
- return(false);
- }
- /***************************************************************************
- * TechnoType_To_Target -- converts TechnoTypeClass to TARGET *
- * *
- * INPUT: *
- * ptr pointer to convert *
- * *
- * OUTPUT: *
- * target value *
- * *
- * WARNINGS: *
- * Be certain that you only use the returned target value by passing *
- * it to Target_To_TechnoType; do NOT call As_Techno, or you'll get *
- * a totally invalid pointer. *
- * *
- * HISTORY: *
- * 01/12/1995 BR : Created. *
- *=========================================================================*/
- TARGET TechnoType_To_Target(TechnoTypeClass const * ptr)
- {
- TARGET target;
- switch (ptr->What_Am_I()) {
- case RTTI_INFANTRYTYPE:
- target = Build_Target(KIND_INFANTRY, ((InfantryTypeClass const *)ptr)->Type);
- break;
- case RTTI_UNITTYPE:
- target = Build_Target(KIND_UNIT, ((UnitTypeClass const *)ptr)->Type);
- break;
- case RTTI_AIRCRAFTTYPE:
- target = Build_Target(KIND_AIRCRAFT, ((AircraftTypeClass const *)ptr)->Type);
- break;
- case RTTI_BUILDINGTYPE:
- target = Build_Target(KIND_BUILDING, ((BuildingTypeClass const *)ptr)->Type);
- break;
- default:
- target = 0;
- break;
- }
- return(target);
- }
- /***************************************************************************
- * Target_To_TechnoType -- converts TARGET to TechnoTypeClass *
- * *
- * INPUT: *
- * target TARGET value to convert *
- * *
- * OUTPUT: *
- * pointer to the TechnoTypeClass for this target value *
- * *
- * WARNINGS: *
- * The TARGET value MUST have been generated with TechnoType_To_Target;*
- * If you give this routine a target generated by an As_Target() *
- * routine, it will return a bogus pointer. *
- * *
- * HISTORY: *
- * 01/12/1995 BR : Created. *
- *=========================================================================*/
- TechnoTypeClass const * Target_To_TechnoType(TARGET target)
- {
- switch (Target_Kind(target)) {
- case KIND_INFANTRY:
- return(&InfantryTypeClass::As_Reference((InfantryType)Target_Value(target)));
- case KIND_UNIT:
- return(&UnitTypeClass::As_Reference((UnitType)Target_Value(target)));
- case KIND_AIRCRAFT:
- return(&AircraftTypeClass::As_Reference((AircraftType)Target_Value(target)));
- case KIND_BUILDING:
- return(&BuildingTypeClass::As_Reference((StructType)Target_Value(target)));
- }
- return(NULL);
- }
- /***************************************************************************
- * Get_VTable -- gets the VTable pointer for the given object *
- * *
- * INPUT: *
- * ptr pointer to check *
- * *
- * OUTPUT: *
- * none *
- * *
- * WARNINGS: *
- * none *
- * *
- * HISTORY: *
- * 01/12/1995 BR : Created. *
- *=========================================================================*/
- void * Get_VTable(void *ptr, int base_size)
- {
- return(((void **)(((char *)ptr) + base_size - 4))[0]);
- }
- /***************************************************************************
- * Set_VTable -- sets the VTable pointer for the given object *
- * *
- * INPUT: *
- * ptr pointer to check *
- * base_size size of base class *
- * vtable value of VTable to plug in *
- * *
- * OUTPUT: *
- * none *
- * *
- * WARNINGS: *
- * none *
- * *
- * HISTORY: *
- * 01/12/1995 BR : Created. *
- *=========================================================================*/
- void Set_VTable(void *ptr, int base_size, void *vtable)
- {
- ((void **)(((char *)ptr) + base_size - 4))[0] = vtable;
- }
- #if 0
- /****************************************************************************
- Dump routine: prints everything about everything related to the Save/Load
- process (OK, not exactly everything, but lots of stuff)
- ****************************************************************************/
- void Dump(void)
- {
- int i,j;
- FILE *fp;
- char *layername[] = {
- "Ground",
- "Air",
- "Top"
- };
- /*
- ------------------------------- Open file --------------------------------
- */
- fp = fopen("dump.txt","wt");
- /*
- ------------------------------ Logic Layer -------------------------------
- */
- fprintf(fp,"--------------------- Logic Layer ---------------------\n");
- fprintf(fp,"Count: %d\n",Logic.Count());
- for (j = 0; j < Logic.Count(); j++) {
- fprintf(fp, "Entry %d: %x \n",j,Logic[j]);
- }
- fprintf(fp,"\n");
- /*
- ------------------------------- Map Layers -------------------------------
- */
- for (i = 0; i < LAYER_COUNT; i++) {
- fprintf(fp,"----------------- Map Layer %s ---------------------\n",
- layername[i]);
- fprintf(fp,"Count: %d\n",Map.Layer[i].Count());
- for (j = 0; j < Map.Layer[i].Count(); j++) {
- fprintf(fp, "Entry %d: %x \n",j,Map.Layer[i][j]);
- }
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ TeamTypes --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",TeamTypes.ActiveCount);
- for (i = 0; i < TEAMTYPE_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d Name:%s\n",i,TeamTypes[i].IsActive,
- TeamTypes[i].Get_Name());
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Teams --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Teams.ActiveCount);
- for (i = 0; i < TEAM_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d Name:%s\n",i,Teams[i].IsActive,
- Teams[i].Class->Get_Name());
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Triggers --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Triggers.ActiveCount);
- for (i = 0; i < TRIGGER_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d Name:%s\n",i,Triggers[i].IsActive,
- Triggers[i].Get_Name());
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Aircraft --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Aircraft.ActiveCount);
- for (i = 0; i < AIRCRAFT_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Aircraft[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Anims --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Anims.ActiveCount);
- for (i = 0; i < ANIM_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Anims[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Buildings --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Buildings.ActiveCount);
- for (i = 0; i < BUILDING_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Buildings[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Bullets --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Bullets.ActiveCount);
- for (i = 0; i < BULLET_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Bullets[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Infantry --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Infantry.ActiveCount);
- for (i = 0; i < INFANTRY_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Infantry[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Overlays --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Overlays.ActiveCount);
- for (i = 0; i < OVERLAY_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Overlays[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Reinforcements --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Reinforcements.ActiveCount);
- for (i = 0; i < REINFORCEMENT_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Reinforcements[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Smudges --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Smudges.ActiveCount);
- for (i = 0; i < SMUDGE_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Smudges[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Templates --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Templates.ActiveCount);
- for (i = 0; i < TEMPLATE_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Templates[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Terrains --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Terrains.ActiveCount);
- for (i = 0; i < TERRAIN_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Terrains[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Units --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Units.ActiveCount);
- for (i = 0; i < UNIT_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Units[i].IsActive);
- }
- fprintf(fp,"\n");
- fprintf(fp,"------------------ Factories --------------------------\n");
- fprintf(fp,"ActiveCount: %d\n",Factories.ActiveCount);
- for (i = 0; i < FACTORY_MAX; i++) {
- fprintf(fp,"Entry %d: Active:%d \n",i,Factories[i].IsActive);
- }
- fprintf(fp,"\n");
- fclose(fp);
- /*
- ---------------------------- Flush the cache -----------------------------
- */
- fp = fopen("dummy.bin","wt");
- for (i = 0; i < 100; i++) {
- fprintf(fp,"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
- }
- fclose(fp);
- }
- #endif
|