SAVELOAD.CPP 53 KB

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