IOMAP.CPP 28 KB

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