IOMAP.CPP 27 KB

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