SV_SAVE.C 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757
  1. //**************************************************************************
  2. //**
  3. //** sv_save.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: sv_save.c,v $
  6. //** $Revision: 1.36 $
  7. //** $Date: 95/10/17 00:10:02 $
  8. //** $Author: bgokey $
  9. //**
  10. //**************************************************************************
  11. // HEADER FILES ------------------------------------------------------------
  12. #include "h2def.h"
  13. #include "p_local.h"
  14. // MACROS ------------------------------------------------------------------
  15. #define MAX_TARGET_PLAYERS 512
  16. #define MOBJ_NULL -1
  17. #define MOBJ_XX_PLAYER -2
  18. #define GET_BYTE (*SavePtr.b++)
  19. #define GET_WORD (*SavePtr.w++)
  20. #define GET_LONG (*SavePtr.l++)
  21. #define MAX_MAPS 99
  22. #define BASE_SLOT 6
  23. #define REBORN_SLOT 7
  24. #define REBORN_DESCRIPTION "TEMP GAME"
  25. #define MAX_THINKER_SIZE 256
  26. // TYPES -------------------------------------------------------------------
  27. typedef enum
  28. {
  29. ASEG_GAME_HEADER = 101,
  30. ASEG_MAP_HEADER,
  31. ASEG_WORLD,
  32. ASEG_POLYOBJS,
  33. ASEG_MOBJS,
  34. ASEG_THINKERS,
  35. ASEG_SCRIPTS,
  36. ASEG_PLAYERS,
  37. ASEG_SOUNDS,
  38. ASEG_MISC,
  39. ASEG_END
  40. } gameArchiveSegment_t;
  41. typedef enum
  42. {
  43. TC_NULL,
  44. TC_MOVE_CEILING,
  45. TC_VERTICAL_DOOR,
  46. TC_MOVE_FLOOR,
  47. TC_PLAT_RAISE,
  48. TC_INTERPRET_ACS,
  49. TC_FLOOR_WAGGLE,
  50. TC_LIGHT,
  51. TC_PHASE,
  52. TC_BUILD_PILLAR,
  53. TC_ROTATE_POLY,
  54. TC_MOVE_POLY,
  55. TC_POLY_DOOR
  56. } thinkClass_t;
  57. typedef struct
  58. {
  59. thinkClass_t tClass;
  60. think_t thinkerFunc;
  61. void (*mangleFunc)();
  62. void (*restoreFunc)();
  63. size_t size;
  64. } thinkInfo_t;
  65. typedef struct
  66. {
  67. thinker_t thinker;
  68. sector_t *sector;
  69. } ssthinker_t;
  70. // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
  71. void P_SpawnPlayer(mapthing_t *mthing);
  72. // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
  73. // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
  74. static void ArchiveWorld(void);
  75. static void UnarchiveWorld(void);
  76. static void ArchivePolyobjs(void);
  77. static void UnarchivePolyobjs(void);
  78. static void ArchiveMobjs(void);
  79. static void UnarchiveMobjs(void);
  80. static void ArchiveThinkers(void);
  81. static void UnarchiveThinkers(void);
  82. static void ArchiveScripts(void);
  83. static void UnarchiveScripts(void);
  84. static void ArchivePlayers(void);
  85. static void UnarchivePlayers(void);
  86. static void ArchiveSounds(void);
  87. static void UnarchiveSounds(void);
  88. static void ArchiveMisc(void);
  89. static void UnarchiveMisc(void);
  90. static void SetMobjArchiveNums(void);
  91. static void RemoveAllThinkers(void);
  92. static void MangleMobj(mobj_t *mobj);
  93. static void RestoreMobj(mobj_t *mobj);
  94. static int GetMobjNum(mobj_t *mobj);
  95. static void SetMobjPtr(int *archiveNum);
  96. static void MangleSSThinker(ssthinker_t *sst);
  97. static void RestoreSSThinker(ssthinker_t *sst);
  98. static void RestoreSSThinkerNoSD(ssthinker_t *sst);
  99. static void MangleScript(acs_t *script);
  100. static void RestoreScript(acs_t *script);
  101. static void RestorePlatRaise(plat_t *plat);
  102. static void RestoreMoveCeiling(ceiling_t *ceiling);
  103. static void AssertSegment(gameArchiveSegment_t segType);
  104. static void ClearSaveSlot(int slot);
  105. static void CopySaveSlot(int sourceSlot, int destSlot);
  106. static void CopyFile(char *sourceName, char *destName);
  107. static boolean ExistingFile(char *name);
  108. static void OpenStreamOut(char *fileName);
  109. static void CloseStreamOut(void);
  110. static void StreamOutBuffer(void *buffer, int size);
  111. static void StreamOutByte(byte val);
  112. static void StreamOutWord(unsigned short val);
  113. static void StreamOutLong(unsigned int val);
  114. // EXTERNAL DATA DECLARATIONS ----------------------------------------------
  115. extern int ACScriptCount;
  116. extern byte *ActionCodeBase;
  117. extern acsInfo_t *ACSInfo;
  118. // PUBLIC DATA DEFINITIONS -------------------------------------------------
  119. char *SavePath;
  120. // PRIVATE DATA DEFINITIONS ------------------------------------------------
  121. static int MobjCount;
  122. static mobj_t **MobjList;
  123. static int **TargetPlayerAddrs;
  124. static int TargetPlayerCount;
  125. static byte *SaveBuffer;
  126. static boolean SavingPlayers;
  127. static union
  128. {
  129. byte *b;
  130. short *w;
  131. int *l;
  132. } SavePtr;
  133. static FILE *SavingFP;
  134. // This list has been prioritized using frequency estimates
  135. static thinkInfo_t ThinkerInfo[] =
  136. {
  137. {
  138. TC_MOVE_FLOOR,
  139. T_MoveFloor,
  140. MangleSSThinker,
  141. RestoreSSThinker,
  142. sizeof(floormove_t)
  143. },
  144. {
  145. TC_PLAT_RAISE,
  146. T_PlatRaise,
  147. MangleSSThinker,
  148. RestorePlatRaise,
  149. sizeof(plat_t)
  150. },
  151. {
  152. TC_MOVE_CEILING,
  153. T_MoveCeiling,
  154. MangleSSThinker,
  155. RestoreMoveCeiling,
  156. sizeof(ceiling_t)
  157. },
  158. {
  159. TC_LIGHT,
  160. T_Light,
  161. MangleSSThinker,
  162. RestoreSSThinkerNoSD,
  163. sizeof(light_t)
  164. },
  165. {
  166. TC_VERTICAL_DOOR,
  167. T_VerticalDoor,
  168. MangleSSThinker,
  169. RestoreSSThinker,
  170. sizeof(vldoor_t)
  171. },
  172. {
  173. TC_PHASE,
  174. T_Phase,
  175. MangleSSThinker,
  176. RestoreSSThinkerNoSD,
  177. sizeof(phase_t)
  178. },
  179. {
  180. TC_INTERPRET_ACS,
  181. T_InterpretACS,
  182. MangleScript,
  183. RestoreScript,
  184. sizeof(acs_t)
  185. },
  186. {
  187. TC_ROTATE_POLY,
  188. T_RotatePoly,
  189. NULL,
  190. NULL,
  191. sizeof(polyevent_t)
  192. },
  193. {
  194. TC_BUILD_PILLAR,
  195. T_BuildPillar,
  196. MangleSSThinker,
  197. RestoreSSThinker,
  198. sizeof(pillar_t)
  199. },
  200. {
  201. TC_MOVE_POLY,
  202. T_MovePoly,
  203. NULL,
  204. NULL,
  205. sizeof(polyevent_t)
  206. },
  207. {
  208. TC_POLY_DOOR,
  209. T_PolyDoor,
  210. NULL,
  211. NULL,
  212. sizeof(polydoor_t)
  213. },
  214. {
  215. TC_FLOOR_WAGGLE,
  216. T_FloorWaggle,
  217. MangleSSThinker,
  218. RestoreSSThinker,
  219. sizeof(floorWaggle_t)
  220. },
  221. { // Terminator
  222. TC_NULL, NULL, NULL, NULL, 0
  223. }
  224. };
  225. // CODE --------------------------------------------------------------------
  226. //==========================================================================
  227. //
  228. // SV_SaveGame
  229. //
  230. //==========================================================================
  231. void SV_SaveGame(int slot, char *description)
  232. {
  233. char fileName[100];
  234. char versionText[HXS_VERSION_TEXT_LENGTH];
  235. // Open the output file
  236. sprintf(fileName, "%shex6.hxs", SavePath);
  237. OpenStreamOut(fileName);
  238. // Write game save description
  239. StreamOutBuffer(description, HXS_DESCRIPTION_LENGTH);
  240. // Write version info
  241. memset(versionText, 0, HXS_VERSION_TEXT_LENGTH);
  242. strcpy(versionText, HXS_VERSION_TEXT);
  243. StreamOutBuffer(versionText, HXS_VERSION_TEXT_LENGTH);
  244. // Place a header marker
  245. StreamOutLong(ASEG_GAME_HEADER);
  246. // Write current map and difficulty
  247. StreamOutByte(gamemap);
  248. StreamOutByte(gameskill);
  249. // Write global script info
  250. StreamOutBuffer(WorldVars, sizeof(WorldVars));
  251. StreamOutBuffer(ACSStore, sizeof(ACSStore));
  252. ArchivePlayers();
  253. // Place a termination marker
  254. StreamOutLong(ASEG_END);
  255. // Close the output file
  256. CloseStreamOut();
  257. // Save out the current map
  258. SV_SaveMap(true); // true = save player info
  259. // Clear all save files at destination slot
  260. ClearSaveSlot(slot);
  261. // Copy base slot to destination slot
  262. CopySaveSlot(BASE_SLOT, slot);
  263. }
  264. //==========================================================================
  265. //
  266. // SV_SaveMap
  267. //
  268. //==========================================================================
  269. void SV_SaveMap(boolean savePlayers)
  270. {
  271. char fileName[100];
  272. SavingPlayers = savePlayers;
  273. // Open the output file
  274. sprintf(fileName, "%shex6%02d.hxs", SavePath, gamemap);
  275. OpenStreamOut(fileName);
  276. // Place a header marker
  277. StreamOutLong(ASEG_MAP_HEADER);
  278. // Write the level timer
  279. StreamOutLong(leveltime);
  280. // Set the mobj archive numbers
  281. SetMobjArchiveNums();
  282. ArchiveWorld();
  283. ArchivePolyobjs();
  284. ArchiveMobjs();
  285. ArchiveThinkers();
  286. ArchiveScripts();
  287. ArchiveSounds();
  288. ArchiveMisc();
  289. // Place a termination marker
  290. StreamOutLong(ASEG_END);
  291. // Close the output file
  292. CloseStreamOut();
  293. }
  294. //==========================================================================
  295. //
  296. // SV_LoadGame
  297. //
  298. //==========================================================================
  299. void SV_LoadGame(int slot)
  300. {
  301. int i;
  302. char fileName[100];
  303. player_t playerBackup[MAXPLAYERS];
  304. mobj_t *mobj;
  305. // Copy all needed save files to the base slot
  306. if(slot != BASE_SLOT)
  307. {
  308. ClearSaveSlot(BASE_SLOT);
  309. CopySaveSlot(slot, BASE_SLOT);
  310. }
  311. // Create the name
  312. sprintf(fileName, "%shex6.hxs", SavePath);
  313. // Load the file
  314. M_ReadFile(fileName, &SaveBuffer);
  315. // Set the save pointer and skip the description field
  316. SavePtr.b = SaveBuffer+HXS_DESCRIPTION_LENGTH;
  317. // Check the version text
  318. if(strcmp(SavePtr.b, HXS_VERSION_TEXT))
  319. { // Bad version
  320. return;
  321. }
  322. SavePtr.b += HXS_VERSION_TEXT_LENGTH;
  323. AssertSegment(ASEG_GAME_HEADER);
  324. gameepisode = 1;
  325. gamemap = GET_BYTE;
  326. gameskill = GET_BYTE;
  327. // Read global script info
  328. memcpy(WorldVars, SavePtr.b, sizeof(WorldVars));
  329. SavePtr.b += sizeof(WorldVars);
  330. memcpy(ACSStore, SavePtr.b, sizeof(ACSStore));
  331. SavePtr.b += sizeof(ACSStore);
  332. // Read the player structures
  333. UnarchivePlayers();
  334. AssertSegment(ASEG_END);
  335. Z_Free(SaveBuffer);
  336. // Save player structs
  337. for(i = 0; i < MAXPLAYERS; i++)
  338. {
  339. playerBackup[i] = players[i];
  340. }
  341. // Load the current map
  342. SV_LoadMap();
  343. // Don't need the player mobj relocation info for load game
  344. Z_Free(TargetPlayerAddrs);
  345. // Restore player structs
  346. inv_ptr = 0;
  347. curpos = 0;
  348. for(i = 0; i < MAXPLAYERS; i++)
  349. {
  350. mobj = players[i].mo;
  351. players[i] = playerBackup[i];
  352. players[i].mo = mobj;
  353. if(i == consoleplayer)
  354. {
  355. players[i].readyArtifact = players[i].inventory[inv_ptr].type;
  356. }
  357. }
  358. }
  359. //==========================================================================
  360. //
  361. // SV_UpdateRebornSlot
  362. //
  363. // Copies the base slot to the reborn slot.
  364. //
  365. //==========================================================================
  366. void SV_UpdateRebornSlot(void)
  367. {
  368. ClearSaveSlot(REBORN_SLOT);
  369. CopySaveSlot(BASE_SLOT, REBORN_SLOT);
  370. }
  371. //==========================================================================
  372. //
  373. // SV_ClearRebornSlot
  374. //
  375. //==========================================================================
  376. void SV_ClearRebornSlot(void)
  377. {
  378. ClearSaveSlot(REBORN_SLOT);
  379. }
  380. //==========================================================================
  381. //
  382. // SV_MapTeleport
  383. //
  384. //==========================================================================
  385. void SV_MapTeleport(int map, int position)
  386. {
  387. int i;
  388. int j;
  389. char fileName[100];
  390. player_t playerBackup[MAXPLAYERS];
  391. mobj_t *targetPlayerMobj;
  392. mobj_t *mobj;
  393. int inventoryPtr;
  394. int currentInvPos;
  395. boolean rClass;
  396. boolean playerWasReborn;
  397. boolean oldWeaponowned[NUMWEAPONS];
  398. int oldKeys;
  399. int oldPieces;
  400. int bestWeapon;
  401. if(!deathmatch)
  402. {
  403. if(P_GetMapCluster(gamemap) == P_GetMapCluster(map))
  404. { // Same cluster - save map without saving player mobjs
  405. SV_SaveMap(false);
  406. }
  407. else
  408. { // Entering new cluster - clear base slot
  409. ClearSaveSlot(BASE_SLOT);
  410. }
  411. }
  412. // Store player structs for later
  413. rClass = randomclass;
  414. randomclass = false;
  415. for(i = 0; i < MAXPLAYERS; i++)
  416. {
  417. playerBackup[i] = players[i];
  418. }
  419. // Save some globals that get trashed during the load
  420. inventoryPtr = inv_ptr;
  421. currentInvPos = curpos;
  422. // Only SV_LoadMap() uses TargetPlayerAddrs, so it's NULLed here
  423. // for the following check (player mobj redirection)
  424. TargetPlayerAddrs = NULL;
  425. gamemap = map;
  426. sprintf(fileName, "%shex6%02d.hxs", SavePath, gamemap);
  427. if(!deathmatch && ExistingFile(fileName))
  428. { // Unarchive map
  429. SV_LoadMap();
  430. }
  431. else
  432. { // New map
  433. G_InitNew(gameskill, gameepisode, gamemap);
  434. // Destroy all freshly spawned players
  435. for(i = 0; i < MAXPLAYERS; i++)
  436. {
  437. if(playeringame[i])
  438. {
  439. P_RemoveMobj(players[i].mo);
  440. }
  441. }
  442. }
  443. // Restore player structs
  444. targetPlayerMobj = NULL;
  445. for(i = 0; i < MAXPLAYERS; i++)
  446. {
  447. if(!playeringame[i])
  448. {
  449. continue;
  450. }
  451. players[i] = playerBackup[i];
  452. P_ClearMessage(&players[i]);
  453. players[i].attacker = NULL;
  454. players[i].poisoner = NULL;
  455. if(netgame)
  456. {
  457. if(players[i].playerstate == PST_DEAD)
  458. { // In a network game, force all players to be alive
  459. players[i].playerstate = PST_REBORN;
  460. }
  461. if(!deathmatch)
  462. { // Cooperative net-play, retain keys and weapons
  463. oldKeys = players[i].keys;
  464. oldPieces = players[i].pieces;
  465. for(j = 0; j < NUMWEAPONS; j++)
  466. {
  467. oldWeaponowned[j] = players[i].weaponowned[j];
  468. }
  469. }
  470. }
  471. playerWasReborn = (players[i].playerstate == PST_REBORN);
  472. if(deathmatch)
  473. {
  474. memset(players[i].frags, 0, sizeof(players[i].frags));
  475. mobj = P_SpawnMobj(playerstarts[0][i].x<<16,
  476. playerstarts[0][i].y<<16, 0, MT_PLAYER_FIGHTER);
  477. players[i].mo = mobj;
  478. G_DeathMatchSpawnPlayer(i);
  479. P_RemoveMobj(mobj);
  480. }
  481. else
  482. {
  483. P_SpawnPlayer(&playerstarts[position][i]);
  484. }
  485. if(playerWasReborn && netgame && !deathmatch)
  486. { // Restore keys and weapons when reborn in co-op
  487. players[i].keys = oldKeys;
  488. players[i].pieces = oldPieces;
  489. for(bestWeapon = 0, j = 0; j < NUMWEAPONS; j++)
  490. {
  491. if(oldWeaponowned[j])
  492. {
  493. bestWeapon = j;
  494. players[i].weaponowned[j] = true;
  495. }
  496. }
  497. players[i].mana[MANA_1] = 25;
  498. players[i].mana[MANA_2] = 25;
  499. if(bestWeapon)
  500. { // Bring up the best weapon
  501. players[i].pendingweapon = bestWeapon;
  502. }
  503. }
  504. if(targetPlayerMobj == NULL)
  505. { // The poor sap
  506. targetPlayerMobj = players[i].mo;
  507. }
  508. }
  509. randomclass = rClass;
  510. // Redirect anything targeting a player mobj
  511. if(TargetPlayerAddrs)
  512. {
  513. for(i = 0; i < TargetPlayerCount; i++)
  514. {
  515. *TargetPlayerAddrs[i] = (int)targetPlayerMobj;
  516. }
  517. Z_Free(TargetPlayerAddrs);
  518. }
  519. // Destroy all things touching players
  520. for(i = 0; i < MAXPLAYERS; i++)
  521. {
  522. if(playeringame[i])
  523. {
  524. P_TeleportMove(players[i].mo, players[i].mo->x,
  525. players[i].mo->y);
  526. }
  527. }
  528. // Restore trashed globals
  529. inv_ptr = inventoryPtr;
  530. curpos = currentInvPos;
  531. // Launch waiting scripts
  532. if(!deathmatch)
  533. {
  534. P_CheckACSStore();
  535. }
  536. // For single play, save immediately into the reborn slot
  537. if(!netgame)
  538. {
  539. SV_SaveGame(REBORN_SLOT, REBORN_DESCRIPTION);
  540. }
  541. }
  542. //==========================================================================
  543. //
  544. // SV_GetRebornSlot
  545. //
  546. //==========================================================================
  547. int SV_GetRebornSlot(void)
  548. {
  549. return(REBORN_SLOT);
  550. }
  551. //==========================================================================
  552. //
  553. // SV_RebornSlotAvailable
  554. //
  555. // Returns true if the reborn slot is available.
  556. //
  557. //==========================================================================
  558. boolean SV_RebornSlotAvailable(void)
  559. {
  560. char fileName[100];
  561. sprintf(fileName, "%shex%d.hxs", SavePath, REBORN_SLOT);
  562. return ExistingFile(fileName);
  563. }
  564. //==========================================================================
  565. //
  566. // SV_LoadMap
  567. //
  568. //==========================================================================
  569. void SV_LoadMap(void)
  570. {
  571. char fileName[100];
  572. // Load a base level
  573. G_InitNew(gameskill, gameepisode, gamemap);
  574. // Remove all thinkers
  575. RemoveAllThinkers();
  576. // Create the name
  577. sprintf(fileName, "%shex6%02d.hxs", SavePath, gamemap);
  578. // Load the file
  579. M_ReadFile(fileName, &SaveBuffer);
  580. SavePtr.b = SaveBuffer;
  581. AssertSegment(ASEG_MAP_HEADER);
  582. // Read the level timer
  583. leveltime = GET_LONG;
  584. UnarchiveWorld();
  585. UnarchivePolyobjs();
  586. UnarchiveMobjs();
  587. UnarchiveThinkers();
  588. UnarchiveScripts();
  589. UnarchiveSounds();
  590. UnarchiveMisc();
  591. AssertSegment(ASEG_END);
  592. // Free mobj list and save buffer
  593. Z_Free(MobjList);
  594. Z_Free(SaveBuffer);
  595. }
  596. //==========================================================================
  597. //
  598. // SV_InitBaseSlot
  599. //
  600. //==========================================================================
  601. void SV_InitBaseSlot(void)
  602. {
  603. ClearSaveSlot(BASE_SLOT);
  604. }
  605. //==========================================================================
  606. //
  607. // ArchivePlayers
  608. //
  609. //==========================================================================
  610. static void ArchivePlayers(void)
  611. {
  612. int i;
  613. int j;
  614. player_t tempPlayer;
  615. StreamOutLong(ASEG_PLAYERS);
  616. for(i = 0; i < MAXPLAYERS; i++)
  617. {
  618. StreamOutByte(playeringame[i]);
  619. }
  620. for(i = 0; i < MAXPLAYERS; i++)
  621. {
  622. if(!playeringame[i])
  623. {
  624. continue;
  625. }
  626. StreamOutByte(PlayerClass[i]);
  627. tempPlayer = players[i];
  628. for(j = 0; j < NUMPSPRITES; j++)
  629. {
  630. if(tempPlayer.psprites[j].state)
  631. {
  632. tempPlayer.psprites[j].state =
  633. (state_t *)(tempPlayer.psprites[j].state-states);
  634. }
  635. }
  636. StreamOutBuffer(&tempPlayer, sizeof(player_t));
  637. }
  638. }
  639. //==========================================================================
  640. //
  641. // UnarchivePlayers
  642. //
  643. //==========================================================================
  644. static void UnarchivePlayers(void)
  645. {
  646. int i, j;
  647. AssertSegment(ASEG_PLAYERS);
  648. for(i = 0; i < MAXPLAYERS; i++)
  649. {
  650. playeringame[i] = GET_BYTE;
  651. }
  652. for(i = 0; i < MAXPLAYERS; i++)
  653. {
  654. if(!playeringame[i])
  655. {
  656. continue;
  657. }
  658. PlayerClass[i] = GET_BYTE;
  659. memcpy(&players[i], SavePtr.b, sizeof(player_t));
  660. SavePtr.b += sizeof(player_t);
  661. players[i].mo = NULL; // Will be set when unarc thinker
  662. P_ClearMessage(&players[i]);
  663. players[i].attacker = NULL;
  664. players[i].poisoner = NULL;
  665. for(j = 0; j < NUMPSPRITES; j++)
  666. {
  667. if(players[i].psprites[j].state)
  668. {
  669. players[i].psprites[j].state =
  670. &states[(int)players[i].psprites[j].state];
  671. }
  672. }
  673. }
  674. }
  675. //==========================================================================
  676. //
  677. // ArchiveWorld
  678. //
  679. //==========================================================================
  680. static void ArchiveWorld(void)
  681. {
  682. int i;
  683. int j;
  684. sector_t *sec;
  685. line_t *li;
  686. side_t *si;
  687. StreamOutLong(ASEG_WORLD);
  688. for(i = 0, sec = sectors; i < numsectors; i++, sec++)
  689. {
  690. StreamOutWord(sec->floorheight>>FRACBITS);
  691. StreamOutWord(sec->ceilingheight>>FRACBITS);
  692. StreamOutWord(sec->floorpic);
  693. StreamOutWord(sec->ceilingpic);
  694. StreamOutWord(sec->lightlevel);
  695. StreamOutWord(sec->special);
  696. StreamOutWord(sec->tag);
  697. StreamOutWord(sec->seqType);
  698. }
  699. for(i = 0, li = lines; i < numlines; i++, li++)
  700. {
  701. StreamOutWord(li->flags);
  702. StreamOutByte(li->special);
  703. StreamOutByte(li->arg1);
  704. StreamOutByte(li->arg2);
  705. StreamOutByte(li->arg3);
  706. StreamOutByte(li->arg4);
  707. StreamOutByte(li->arg5);
  708. for(j = 0; j < 2; j++)
  709. {
  710. if(li->sidenum[j] == -1)
  711. {
  712. continue;
  713. }
  714. si = &sides[li->sidenum[j]];
  715. StreamOutWord(si->textureoffset>>FRACBITS);
  716. StreamOutWord(si->rowoffset>>FRACBITS);
  717. StreamOutWord(si->toptexture);
  718. StreamOutWord(si->bottomtexture);
  719. StreamOutWord(si->midtexture);
  720. }
  721. }
  722. }
  723. //==========================================================================
  724. //
  725. // UnarchiveWorld
  726. //
  727. //==========================================================================
  728. static void UnarchiveWorld(void)
  729. {
  730. int i;
  731. int j;
  732. sector_t *sec;
  733. line_t *li;
  734. side_t *si;
  735. AssertSegment(ASEG_WORLD);
  736. for(i = 0, sec = sectors; i < numsectors; i++, sec++)
  737. {
  738. sec->floorheight = GET_WORD<<FRACBITS;
  739. sec->ceilingheight = GET_WORD<<FRACBITS;
  740. sec->floorpic = GET_WORD;
  741. sec->ceilingpic = GET_WORD;
  742. sec->lightlevel = GET_WORD;
  743. sec->special = GET_WORD;
  744. sec->tag = GET_WORD;
  745. sec->seqType = GET_WORD;
  746. sec->specialdata = 0;
  747. sec->soundtarget = 0;
  748. }
  749. for(i = 0, li = lines; i < numlines; i++, li++)
  750. {
  751. li->flags = GET_WORD;
  752. li->special = GET_BYTE;
  753. li->arg1 = GET_BYTE;
  754. li->arg2 = GET_BYTE;
  755. li->arg3 = GET_BYTE;
  756. li->arg4 = GET_BYTE;
  757. li->arg5 = GET_BYTE;
  758. for(j = 0; j < 2; j++)
  759. {
  760. if(li->sidenum[j] == -1)
  761. {
  762. continue;
  763. }
  764. si = &sides[li->sidenum[j]];
  765. si->textureoffset = GET_WORD<<FRACBITS;
  766. si->rowoffset = GET_WORD<<FRACBITS;
  767. si->toptexture = GET_WORD;
  768. si->bottomtexture = GET_WORD;
  769. si->midtexture = GET_WORD;
  770. }
  771. }
  772. }
  773. //==========================================================================
  774. //
  775. // SetMobjArchiveNums
  776. //
  777. // Sets the archive numbers in all mobj structs. Also sets the MobjCount
  778. // global. Ignores player mobjs if SavingPlayers is false.
  779. //
  780. //==========================================================================
  781. static void SetMobjArchiveNums(void)
  782. {
  783. mobj_t *mobj;
  784. thinker_t *thinker;
  785. MobjCount = 0;
  786. for(thinker = thinkercap.next; thinker != &thinkercap;
  787. thinker = thinker->next)
  788. {
  789. if(thinker->function == P_MobjThinker)
  790. {
  791. mobj = (mobj_t *)thinker;
  792. if(mobj->player && !SavingPlayers)
  793. { // Skipping player mobjs
  794. continue;
  795. }
  796. mobj->archiveNum = MobjCount++;
  797. }
  798. }
  799. }
  800. //==========================================================================
  801. //
  802. // ArchiveMobjs
  803. //
  804. //==========================================================================
  805. static void ArchiveMobjs(void)
  806. {
  807. int count;
  808. thinker_t *thinker;
  809. mobj_t tempMobj;
  810. StreamOutLong(ASEG_MOBJS);
  811. StreamOutLong(MobjCount);
  812. count = 0;
  813. for(thinker = thinkercap.next; thinker != &thinkercap;
  814. thinker = thinker->next)
  815. {
  816. if(thinker->function != P_MobjThinker)
  817. { // Not a mobj thinker
  818. continue;
  819. }
  820. if(((mobj_t *)thinker)->player && !SavingPlayers)
  821. { // Skipping player mobjs
  822. continue;
  823. }
  824. count++;
  825. memcpy(&tempMobj, thinker, sizeof(mobj_t));
  826. MangleMobj(&tempMobj);
  827. StreamOutBuffer(&tempMobj, sizeof(mobj_t));
  828. }
  829. if(count != MobjCount)
  830. {
  831. I_Error("ArchiveMobjs: bad mobj count");
  832. }
  833. }
  834. //==========================================================================
  835. //
  836. // UnarchiveMobjs
  837. //
  838. //==========================================================================
  839. static void UnarchiveMobjs(void)
  840. {
  841. int i;
  842. mobj_t *mobj;
  843. AssertSegment(ASEG_MOBJS);
  844. TargetPlayerAddrs = Z_Malloc(MAX_TARGET_PLAYERS*sizeof(int *),
  845. PU_STATIC, NULL);
  846. TargetPlayerCount = 0;
  847. MobjCount = GET_LONG;
  848. MobjList = Z_Malloc(MobjCount*sizeof(mobj_t *), PU_STATIC, NULL);
  849. for(i = 0; i < MobjCount; i++)
  850. {
  851. MobjList[i] = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);
  852. }
  853. for(i = 0; i < MobjCount; i++)
  854. {
  855. mobj = MobjList[i];
  856. memcpy(mobj, SavePtr.b, sizeof(mobj_t));
  857. SavePtr.b += sizeof(mobj_t);
  858. mobj->thinker.function = P_MobjThinker;
  859. RestoreMobj(mobj);
  860. P_AddThinker(&mobj->thinker);
  861. }
  862. P_CreateTIDList();
  863. P_InitCreatureCorpseQueue(true); // true = scan for corpses
  864. }
  865. //==========================================================================
  866. //
  867. // MangleMobj
  868. //
  869. //==========================================================================
  870. static void MangleMobj(mobj_t *mobj)
  871. {
  872. boolean corpse;
  873. corpse = mobj->flags&MF_CORPSE;
  874. mobj->state = (state_t *)(mobj->state-states);
  875. if(mobj->player)
  876. {
  877. mobj->player = (player_t *)((mobj->player-players)+1);
  878. }
  879. if(corpse)
  880. {
  881. mobj->target = (mobj_t *)MOBJ_NULL;
  882. }
  883. else
  884. {
  885. mobj->target = (mobj_t *)GetMobjNum(mobj->target);
  886. }
  887. switch(mobj->type)
  888. {
  889. // Just special1
  890. case MT_BISH_FX:
  891. case MT_HOLY_FX:
  892. case MT_DRAGON:
  893. case MT_THRUSTFLOOR_UP:
  894. case MT_THRUSTFLOOR_DOWN:
  895. case MT_MINOTAUR:
  896. case MT_SORCFX1:
  897. case MT_MSTAFF_FX2:
  898. if(corpse)
  899. {
  900. mobj->special1 = MOBJ_NULL;
  901. }
  902. else
  903. {
  904. mobj->special1 = GetMobjNum((mobj_t *)mobj->special1);
  905. }
  906. break;
  907. // Just special2
  908. case MT_LIGHTNING_FLOOR:
  909. case MT_LIGHTNING_ZAP:
  910. if(corpse)
  911. {
  912. mobj->special2 = MOBJ_NULL;
  913. }
  914. else
  915. {
  916. mobj->special2 = GetMobjNum((mobj_t *)mobj->special2);
  917. }
  918. break;
  919. // Both special1 and special2
  920. case MT_HOLY_TAIL:
  921. case MT_LIGHTNING_CEILING:
  922. if(corpse)
  923. {
  924. mobj->special1 = MOBJ_NULL;
  925. mobj->special2 = MOBJ_NULL;
  926. }
  927. else
  928. {
  929. mobj->special1 = GetMobjNum((mobj_t *)mobj->special1);
  930. mobj->special2 = GetMobjNum((mobj_t *)mobj->special2);
  931. }
  932. break;
  933. // Miscellaneous
  934. case MT_KORAX:
  935. mobj->special1 = 0; // Searching index
  936. break;
  937. default:
  938. break;
  939. }
  940. }
  941. //==========================================================================
  942. //
  943. // GetMobjNum
  944. //
  945. //==========================================================================
  946. static int GetMobjNum(mobj_t *mobj)
  947. {
  948. if(mobj == NULL)
  949. {
  950. return MOBJ_NULL;
  951. }
  952. if(mobj->player && !SavingPlayers)
  953. {
  954. return MOBJ_XX_PLAYER;
  955. }
  956. return mobj->archiveNum;
  957. }
  958. //==========================================================================
  959. //
  960. // RestoreMobj
  961. //
  962. //==========================================================================
  963. static void RestoreMobj(mobj_t *mobj)
  964. {
  965. mobj->state = &states[(int)mobj->state];
  966. if(mobj->player)
  967. {
  968. mobj->player = &players[(int)mobj->player-1];
  969. mobj->player->mo = mobj;
  970. }
  971. P_SetThingPosition(mobj);
  972. mobj->info = &mobjinfo[mobj->type];
  973. mobj->floorz = mobj->subsector->sector->floorheight;
  974. mobj->ceilingz = mobj->subsector->sector->ceilingheight;
  975. SetMobjPtr((int *)&mobj->target);
  976. switch(mobj->type)
  977. {
  978. // Just special1
  979. case MT_BISH_FX:
  980. case MT_HOLY_FX:
  981. case MT_DRAGON:
  982. case MT_THRUSTFLOOR_UP:
  983. case MT_THRUSTFLOOR_DOWN:
  984. case MT_MINOTAUR:
  985. case MT_SORCFX1:
  986. SetMobjPtr(&mobj->special1);
  987. break;
  988. // Just special2
  989. case MT_LIGHTNING_FLOOR:
  990. case MT_LIGHTNING_ZAP:
  991. SetMobjPtr(&mobj->special2);
  992. break;
  993. // Both special1 and special2
  994. case MT_HOLY_TAIL:
  995. case MT_LIGHTNING_CEILING:
  996. SetMobjPtr(&mobj->special1);
  997. SetMobjPtr(&mobj->special2);
  998. break;
  999. default:
  1000. break;
  1001. }
  1002. }
  1003. //==========================================================================
  1004. //
  1005. // SetMobjPtr
  1006. //
  1007. //==========================================================================
  1008. static void SetMobjPtr(int *archiveNum)
  1009. {
  1010. if(*archiveNum == MOBJ_NULL)
  1011. {
  1012. *archiveNum = 0;
  1013. return;
  1014. }
  1015. if(*archiveNum == MOBJ_XX_PLAYER)
  1016. {
  1017. if(TargetPlayerCount == MAX_TARGET_PLAYERS)
  1018. {
  1019. I_Error("RestoreMobj: exceeded MAX_TARGET_PLAYERS");
  1020. }
  1021. TargetPlayerAddrs[TargetPlayerCount++] = archiveNum;
  1022. *archiveNum = 0;
  1023. return;
  1024. }
  1025. *archiveNum = (int)MobjList[*archiveNum];
  1026. }
  1027. //==========================================================================
  1028. //
  1029. // ArchiveThinkers
  1030. //
  1031. //==========================================================================
  1032. static void ArchiveThinkers(void)
  1033. {
  1034. thinker_t *thinker;
  1035. thinkInfo_t *info;
  1036. byte buffer[MAX_THINKER_SIZE];
  1037. StreamOutLong(ASEG_THINKERS);
  1038. for(thinker = thinkercap.next; thinker != &thinkercap;
  1039. thinker = thinker->next)
  1040. {
  1041. for(info = ThinkerInfo; info->tClass != TC_NULL; info++)
  1042. {
  1043. if(thinker->function == info->thinkerFunc)
  1044. {
  1045. StreamOutByte(info->tClass);
  1046. memcpy(buffer, thinker, info->size);
  1047. if(info->mangleFunc)
  1048. {
  1049. info->mangleFunc(buffer);
  1050. }
  1051. StreamOutBuffer(buffer, info->size);
  1052. break;
  1053. }
  1054. }
  1055. }
  1056. // Add a termination marker
  1057. StreamOutByte(TC_NULL);
  1058. }
  1059. //==========================================================================
  1060. //
  1061. // UnarchiveThinkers
  1062. //
  1063. //==========================================================================
  1064. static void UnarchiveThinkers(void)
  1065. {
  1066. int tClass;
  1067. thinker_t *thinker;
  1068. thinkInfo_t *info;
  1069. AssertSegment(ASEG_THINKERS);
  1070. while((tClass = GET_BYTE) != TC_NULL)
  1071. {
  1072. for(info = ThinkerInfo; info->tClass != TC_NULL; info++)
  1073. {
  1074. if(tClass == info->tClass)
  1075. {
  1076. thinker = Z_Malloc(info->size, PU_LEVEL, NULL);
  1077. memcpy(thinker, SavePtr.b, info->size);
  1078. SavePtr.b += info->size;
  1079. thinker->function = info->thinkerFunc;
  1080. if(info->restoreFunc)
  1081. {
  1082. info->restoreFunc(thinker);
  1083. }
  1084. P_AddThinker(thinker);
  1085. break;
  1086. }
  1087. }
  1088. if(info->tClass == TC_NULL)
  1089. {
  1090. I_Error("UnarchiveThinkers: Unknown tClass %d in "
  1091. "savegame", tClass);
  1092. }
  1093. }
  1094. }
  1095. //==========================================================================
  1096. //
  1097. // MangleSSThinker
  1098. //
  1099. //==========================================================================
  1100. static void MangleSSThinker(ssthinker_t *sst)
  1101. {
  1102. sst->sector = (sector_t *)(sst->sector-sectors);
  1103. }
  1104. //==========================================================================
  1105. //
  1106. // RestoreSSThinker
  1107. //
  1108. //==========================================================================
  1109. static void RestoreSSThinker(ssthinker_t *sst)
  1110. {
  1111. sst->sector = &sectors[(int)sst->sector];
  1112. sst->sector->specialdata = sst->thinker.function;
  1113. }
  1114. //==========================================================================
  1115. //
  1116. // RestoreSSThinkerNoSD
  1117. //
  1118. //==========================================================================
  1119. static void RestoreSSThinkerNoSD(ssthinker_t *sst)
  1120. {
  1121. sst->sector = &sectors[(int)sst->sector];
  1122. }
  1123. //==========================================================================
  1124. //
  1125. // MangleScript
  1126. //
  1127. //==========================================================================
  1128. static void MangleScript(acs_t *script)
  1129. {
  1130. script->ip = (int *)((int)(script->ip)-(int)ActionCodeBase);
  1131. script->line = script->line ?
  1132. (line_t *)(script->line-lines) : (line_t *)-1;
  1133. script->activator = (mobj_t *)GetMobjNum(script->activator);
  1134. }
  1135. //==========================================================================
  1136. //
  1137. // RestoreScript
  1138. //
  1139. //==========================================================================
  1140. static void RestoreScript(acs_t *script)
  1141. {
  1142. script->ip = (int *)(ActionCodeBase+(int)script->ip);
  1143. if((int)script->line == -1)
  1144. {
  1145. script->line = NULL;
  1146. }
  1147. else
  1148. {
  1149. script->line = &lines[(int)script->line];
  1150. }
  1151. SetMobjPtr((int *)&script->activator);
  1152. }
  1153. //==========================================================================
  1154. //
  1155. // RestorePlatRaise
  1156. //
  1157. //==========================================================================
  1158. static void RestorePlatRaise(plat_t *plat)
  1159. {
  1160. plat->sector = &sectors[(int)plat->sector];
  1161. plat->sector->specialdata = T_PlatRaise;
  1162. P_AddActivePlat(plat);
  1163. }
  1164. //==========================================================================
  1165. //
  1166. // RestoreMoveCeiling
  1167. //
  1168. //==========================================================================
  1169. static void RestoreMoveCeiling(ceiling_t *ceiling)
  1170. {
  1171. ceiling->sector = &sectors[(int)ceiling->sector];
  1172. ceiling->sector->specialdata = T_MoveCeiling;
  1173. P_AddActiveCeiling(ceiling);
  1174. }
  1175. //==========================================================================
  1176. //
  1177. // ArchiveScripts
  1178. //
  1179. //==========================================================================
  1180. static void ArchiveScripts(void)
  1181. {
  1182. int i;
  1183. StreamOutLong(ASEG_SCRIPTS);
  1184. for(i = 0; i < ACScriptCount; i++)
  1185. {
  1186. StreamOutWord(ACSInfo[i].state);
  1187. StreamOutWord(ACSInfo[i].waitValue);
  1188. }
  1189. StreamOutBuffer(MapVars, sizeof(MapVars));
  1190. }
  1191. //==========================================================================
  1192. //
  1193. // UnarchiveScripts
  1194. //
  1195. //==========================================================================
  1196. static void UnarchiveScripts(void)
  1197. {
  1198. int i;
  1199. AssertSegment(ASEG_SCRIPTS);
  1200. for(i = 0; i < ACScriptCount; i++)
  1201. {
  1202. ACSInfo[i].state = GET_WORD;
  1203. ACSInfo[i].waitValue = GET_WORD;
  1204. }
  1205. memcpy(MapVars, SavePtr.b, sizeof(MapVars));
  1206. SavePtr.b += sizeof(MapVars);
  1207. }
  1208. //==========================================================================
  1209. //
  1210. // ArchiveMisc
  1211. //
  1212. //==========================================================================
  1213. static void ArchiveMisc(void)
  1214. {
  1215. int ix;
  1216. StreamOutLong(ASEG_MISC);
  1217. for (ix=0; ix<MAXPLAYERS; ix++)
  1218. {
  1219. StreamOutLong(localQuakeHappening[ix]);
  1220. }
  1221. }
  1222. //==========================================================================
  1223. //
  1224. // UnarchiveMisc
  1225. //
  1226. //==========================================================================
  1227. static void UnarchiveMisc(void)
  1228. {
  1229. int ix;
  1230. AssertSegment(ASEG_MISC);
  1231. for (ix=0; ix<MAXPLAYERS; ix++)
  1232. {
  1233. localQuakeHappening[ix] = GET_LONG;
  1234. }
  1235. }
  1236. //==========================================================================
  1237. //
  1238. // RemoveAllThinkers
  1239. //
  1240. //==========================================================================
  1241. static void RemoveAllThinkers(void)
  1242. {
  1243. thinker_t *thinker;
  1244. thinker_t *nextThinker;
  1245. thinker = thinkercap.next;
  1246. while(thinker != &thinkercap)
  1247. {
  1248. nextThinker = thinker->next;
  1249. if(thinker->function == P_MobjThinker)
  1250. {
  1251. P_RemoveMobj((mobj_t *)thinker);
  1252. }
  1253. else
  1254. {
  1255. Z_Free(thinker);
  1256. }
  1257. thinker = nextThinker;
  1258. }
  1259. P_InitThinkers();
  1260. }
  1261. //==========================================================================
  1262. //
  1263. // ArchiveSounds
  1264. //
  1265. //==========================================================================
  1266. static void ArchiveSounds(void)
  1267. {
  1268. seqnode_t *node;
  1269. sector_t *sec;
  1270. int difference;
  1271. int i;
  1272. StreamOutLong(ASEG_SOUNDS);
  1273. // Save the sound sequences
  1274. StreamOutLong(ActiveSequences);
  1275. for(node = SequenceListHead; node; node = node->next)
  1276. {
  1277. StreamOutLong(node->sequence);
  1278. StreamOutLong(node->delayTics);
  1279. StreamOutLong(node->volume);
  1280. StreamOutLong(SN_GetSequenceOffset(node->sequence,
  1281. node->sequencePtr));
  1282. StreamOutLong(node->currentSoundID);
  1283. for(i = 0; i < po_NumPolyobjs; i++)
  1284. {
  1285. if(node->mobj == (mobj_t *)&polyobjs[i].startSpot)
  1286. {
  1287. break;
  1288. }
  1289. }
  1290. if(i == po_NumPolyobjs)
  1291. { // Sound is attached to a sector, not a polyobj
  1292. sec = R_PointInSubsector(node->mobj->x, node->mobj->y)->sector;
  1293. difference = (int)((byte *)sec
  1294. -(byte *)&sectors[0])/sizeof(sector_t);
  1295. StreamOutLong(0); // 0 -- sector sound origin
  1296. }
  1297. else
  1298. {
  1299. StreamOutLong(1); // 1 -- polyobj sound origin
  1300. difference = i;
  1301. }
  1302. StreamOutLong(difference);
  1303. }
  1304. }
  1305. //==========================================================================
  1306. //
  1307. // UnarchiveSounds
  1308. //
  1309. //==========================================================================
  1310. static void UnarchiveSounds(void)
  1311. {
  1312. int i;
  1313. int numSequences;
  1314. int sequence;
  1315. int delayTics;
  1316. int volume;
  1317. int seqOffset;
  1318. int soundID;
  1319. int polySnd;
  1320. int secNum;
  1321. mobj_t *sndMobj;
  1322. AssertSegment(ASEG_SOUNDS);
  1323. // Reload and restart all sound sequences
  1324. numSequences = GET_LONG;
  1325. i = 0;
  1326. while(i < numSequences)
  1327. {
  1328. sequence = GET_LONG;
  1329. delayTics = GET_LONG;
  1330. volume = GET_LONG;
  1331. seqOffset = GET_LONG;
  1332. soundID = GET_LONG;
  1333. polySnd = GET_LONG;
  1334. secNum = GET_LONG;
  1335. if(!polySnd)
  1336. {
  1337. sndMobj = (mobj_t *)&sectors[secNum].soundorg;
  1338. }
  1339. else
  1340. {
  1341. sndMobj = (mobj_t *)&polyobjs[secNum].startSpot;
  1342. }
  1343. SN_StartSequence(sndMobj, sequence);
  1344. SN_ChangeNodeData(i, seqOffset, delayTics, volume, soundID);
  1345. i++;
  1346. }
  1347. }
  1348. //==========================================================================
  1349. //
  1350. // ArchivePolyobjs
  1351. //
  1352. //==========================================================================
  1353. static void ArchivePolyobjs(void)
  1354. {
  1355. int i;
  1356. StreamOutLong(ASEG_POLYOBJS);
  1357. StreamOutLong(po_NumPolyobjs);
  1358. for(i = 0; i < po_NumPolyobjs; i++)
  1359. {
  1360. StreamOutLong(polyobjs[i].tag);
  1361. StreamOutLong(polyobjs[i].angle);
  1362. StreamOutLong(polyobjs[i].startSpot.x);
  1363. StreamOutLong(polyobjs[i].startSpot.y);
  1364. }
  1365. }
  1366. //==========================================================================
  1367. //
  1368. // UnarchivePolyobjs
  1369. //
  1370. //==========================================================================
  1371. static void UnarchivePolyobjs(void)
  1372. {
  1373. int i;
  1374. fixed_t deltaX;
  1375. fixed_t deltaY;
  1376. AssertSegment(ASEG_POLYOBJS);
  1377. if(GET_LONG != po_NumPolyobjs)
  1378. {
  1379. I_Error("UnarchivePolyobjs: Bad polyobj count");
  1380. }
  1381. for(i = 0; i < po_NumPolyobjs; i++)
  1382. {
  1383. if(GET_LONG != polyobjs[i].tag)
  1384. {
  1385. I_Error("UnarchivePolyobjs: Invalid polyobj tag");
  1386. }
  1387. PO_RotatePolyobj(polyobjs[i].tag, (angle_t)GET_LONG);
  1388. deltaX = GET_LONG-polyobjs[i].startSpot.x;
  1389. deltaY = GET_LONG-polyobjs[i].startSpot.y;
  1390. PO_MovePolyobj(polyobjs[i].tag, deltaX, deltaY);
  1391. }
  1392. }
  1393. //==========================================================================
  1394. //
  1395. // AssertSegment
  1396. //
  1397. //==========================================================================
  1398. static void AssertSegment(gameArchiveSegment_t segType)
  1399. {
  1400. if(GET_LONG != segType)
  1401. {
  1402. I_Error("Corrupt save game: Segment [%d] failed alignment check",
  1403. segType);
  1404. }
  1405. }
  1406. //==========================================================================
  1407. //
  1408. // ClearSaveSlot
  1409. //
  1410. // Deletes all save game files associated with a slot number.
  1411. //
  1412. //==========================================================================
  1413. static void ClearSaveSlot(int slot)
  1414. {
  1415. int i;
  1416. char fileName[100];
  1417. for(i = 0; i < MAX_MAPS; i++)
  1418. {
  1419. sprintf(fileName, "%shex%d%02d.hxs", SavePath, slot, i);
  1420. remove(fileName);
  1421. }
  1422. sprintf(fileName, "%shex%d.hxs", SavePath, slot);
  1423. remove(fileName);
  1424. }
  1425. //==========================================================================
  1426. //
  1427. // CopySaveSlot
  1428. //
  1429. // Copies all the save game files from one slot to another.
  1430. //
  1431. //==========================================================================
  1432. static void CopySaveSlot(int sourceSlot, int destSlot)
  1433. {
  1434. int i;
  1435. char sourceName[100];
  1436. char destName[100];
  1437. for(i = 0; i < MAX_MAPS; i++)
  1438. {
  1439. sprintf(sourceName, "%shex%d%02d.hxs", SavePath, sourceSlot, i);
  1440. if(ExistingFile(sourceName))
  1441. {
  1442. sprintf(destName, "%shex%d%02d.hxs", SavePath, destSlot, i);
  1443. CopyFile(sourceName, destName);
  1444. }
  1445. }
  1446. sprintf(sourceName, "%shex%d.hxs", SavePath, sourceSlot);
  1447. if(ExistingFile(sourceName))
  1448. {
  1449. sprintf(destName, "%shex%d.hxs", SavePath, destSlot);
  1450. CopyFile(sourceName, destName);
  1451. }
  1452. }
  1453. //==========================================================================
  1454. //
  1455. // CopyFile
  1456. //
  1457. //==========================================================================
  1458. static void CopyFile(char *sourceName, char *destName)
  1459. {
  1460. int length;
  1461. byte *buffer;
  1462. length = M_ReadFile(sourceName, &buffer);
  1463. M_WriteFile(destName, buffer, length);
  1464. Z_Free(buffer);
  1465. }
  1466. //==========================================================================
  1467. //
  1468. // ExistingFile
  1469. //
  1470. //==========================================================================
  1471. static boolean ExistingFile(char *name)
  1472. {
  1473. FILE *fp;
  1474. if((fp = fopen(name, "rb")) != NULL)
  1475. {
  1476. fclose(fp);
  1477. return true;
  1478. }
  1479. else
  1480. {
  1481. return false;
  1482. }
  1483. }
  1484. //==========================================================================
  1485. //
  1486. // OpenStreamOut
  1487. //
  1488. //==========================================================================
  1489. static void OpenStreamOut(char *fileName)
  1490. {
  1491. SavingFP = fopen(fileName, "wb");
  1492. }
  1493. //==========================================================================
  1494. //
  1495. // CloseStreamOut
  1496. //
  1497. //==========================================================================
  1498. static void CloseStreamOut(void)
  1499. {
  1500. if(SavingFP)
  1501. {
  1502. fclose(SavingFP);
  1503. }
  1504. }
  1505. //==========================================================================
  1506. //
  1507. // StreamOutBuffer
  1508. //
  1509. //==========================================================================
  1510. static void StreamOutBuffer(void *buffer, int size)
  1511. {
  1512. fwrite(buffer, size, 1, SavingFP);
  1513. }
  1514. //==========================================================================
  1515. //
  1516. // StreamOutByte
  1517. //
  1518. //==========================================================================
  1519. static void StreamOutByte(byte val)
  1520. {
  1521. fwrite(&val, sizeof(byte), 1, SavingFP);
  1522. }
  1523. //==========================================================================
  1524. //
  1525. // StreamOutWord
  1526. //
  1527. //==========================================================================
  1528. static void StreamOutWord(unsigned short val)
  1529. {
  1530. fwrite(&val, sizeof(unsigned short), 1, SavingFP);
  1531. }
  1532. //==========================================================================
  1533. //
  1534. // StreamOutLong
  1535. //
  1536. //==========================================================================
  1537. static void StreamOutLong(unsigned int val)
  1538. {
  1539. fwrite(&val, sizeof(int), 1, SavingFP);
  1540. }