1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2019 EDuke32 developers and contributors
4 Copyright (C) 2019 Nuke.YKT
5
6 This file is part of NBlood.
7
8 NBlood is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License version 2
10 as published by the Free Software Foundation.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22 //-------------------------------------------------------------------------
23 #include <stdio.h>
24 #include "build.h"
25 #include "compat.h"
26 #include "mmulti.h"
27 #include "common_game.h"
28 #include "config.h"
29 #include "ai.h"
30 #include "asound.h"
31 #include "blood.h"
32 #include "demo.h"
33 #include "globals.h"
34 #include "db.h"
35 #include "messages.h"
36 #include "menu.h"
37 #include "network.h"
38 #include "loadsave.h"
39 #include "resource.h"
40 #include "screen.h"
41 #include "sectorfx.h"
42 #include "seq.h"
43 #include "sfx.h"
44 #include "sound.h"
45 #include "view.h"
46 #ifdef NOONE_EXTENSIONS
47 #include "nnexts.h"
48 #endif
49
50 GAMEOPTIONS gSaveGameOptions[10];
51 char *gSaveGamePic[10];
52 unsigned int gSavedOffset = 0;
53
54 unsigned int dword_27AA38 = 0;
55 unsigned int dword_27AA3C = 0;
56 unsigned int dword_27AA40 = 0;
57 void *dword_27AA44 = NULL;
58
59 LoadSave LoadSave::head(123);
60 FILE *LoadSave::hSFile = NULL;
61 int LoadSave::hLFile = -1;
62
63 short word_27AA54 = 0;
64
sub_76FD4(void)65 void sub_76FD4(void)
66 {
67 if (!dword_27AA44)
68 dword_27AA44 = Resource::Alloc(0x186a0);
69 }
70
Save(void)71 void LoadSave::Save(void)
72 {
73 ThrowError("Pure virtual function called");
74 }
75
Load(void)76 void LoadSave::Load(void)
77 {
78 ThrowError("Pure virtual function called");
79 }
80
Read(void * pData,int nSize)81 void LoadSave::Read(void *pData, int nSize)
82 {
83 dword_27AA38 += nSize;
84 dassert(hLFile != -1);
85 if (kread(hLFile, pData, nSize) != nSize)
86 ThrowError("Error reading save file.");
87 }
88
Write(void * pData,int nSize)89 void LoadSave::Write(void *pData, int nSize)
90 {
91 dword_27AA38 += nSize;
92 dword_27AA3C += nSize;
93 dassert(hSFile != NULL);
94 if (fwrite(pData, 1, nSize, hSFile) != (size_t)nSize)
95 ThrowError("File error #%d writing save file.", errno);
96 }
97
LoadGame(char * pzFile)98 void LoadSave::LoadGame(char *pzFile)
99 {
100 bool demoWasPlayed = gDemo.at1;
101 if (gDemo.at1)
102 gDemo.Close();
103
104 sndKillAllSounds();
105 sfxKillAllSounds();
106 ambKillAll();
107 seqKillAll();
108 if (!gGameStarted)
109 {
110 memset(xsprite, 0, sizeof(xsprite));
111 memset(sprite, 0, sizeof(spritetype)*kMaxSprites);
112 automapping = 1;
113 }
114 hLFile = kopen4load(pzFile, 0);
115 if (hLFile == -1)
116 ThrowError("Error loading save file.");
117 LoadSave *rover = head.next;
118 while (rover != &head)
119 {
120 rover->Load();
121 rover = rover->next;
122 }
123 kclose(hLFile);
124 hLFile = -1;
125 if (!gGameStarted)
126 scrLoadPLUs();
127 InitSectorFX();
128 viewInitializePrediction();
129 PreloadCache();
130 if (!bVanilla && !gMe->packSlots[1].isActive) // if diving suit is not active, turn off reverb sound effect
131 sfxSetReverb(0);
132 ambInit();
133 #ifdef YAX_ENABLE
134 yax_update(numyaxbunches > 0 ? 2 : 1);
135 #endif
136 memset(myMinLag, 0, sizeof(myMinLag));
137 otherMinLag = 0;
138 myMaxLag = 0;
139 gNetFifoClock = 0;
140 gNetFifoTail = 0;
141 memset(gNetFifoHead, 0, sizeof(gNetFifoHead));
142 gPredictTail = 0;
143 gNetFifoMasterTail = 0;
144 memset(gFifoInput, 0, sizeof(gFifoInput));
145 memset(gChecksum, 0, sizeof(gChecksum));
146 memset(gCheckFifo, 0, sizeof(gCheckFifo));
147 memset(gCheckHead, 0, sizeof(gCheckHead));
148 gSendCheckTail = 0;
149 gCheckTail = 0;
150 gBufferJitter = 0;
151 bOutOfSync = 0;
152 for (int i = 0; i < gNetPlayers; i++)
153 playerSetRace(&gPlayer[i], gPlayer[i].lifeMode);
154 if (VanillaMode())
155 viewSetMessage("");
156 else
157 gGameMessageMgr.Clear();
158 viewSetErrorMessage("");
159 if (!gGameStarted)
160 {
161 netWaitForEveryone(0);
162 memset(gPlayerReady, 0, sizeof(gPlayerReady));
163 }
164 gFrameTicks = 0;
165 gFrame = 0;
166 gCacheMiss = 0;
167 gFrameRate = 0;
168 totalclock = 0;
169 gPaused = 0;
170 gGameStarted = 1;
171 bVanilla = false;
172
173
174 #ifdef USE_STRUCT_TRACKERS
175 Bmemset(sectorchanged, 0, sizeof(sectorchanged));
176 Bmemset(spritechanged, 0, sizeof(spritechanged));
177 Bmemset(wallchanged, 0, sizeof(wallchanged));
178 #endif
179
180 #ifdef USE_OPENGL
181 Polymost_prepare_loadboard();
182 #endif
183
184 #ifdef POLYMER
185 if (videoGetRenderMode() == REND_POLYMER)
186 polymer_loadboard();
187
188 // this light pointer nulling needs to be outside the videoGetRenderMode check
189 // because we might be loading the savegame using another renderer but
190 // change to Polymer later
191 for (int i=0; i<kMaxSprites; i++)
192 {
193 gPolymerLight[i].lightptr = NULL;
194 gPolymerLight[i].lightId = -1;
195 }
196 #endif
197
198 if ((unsigned)gGameOptions.nEpisode >= gEpisodeCount || (unsigned)gGameOptions.nLevel >= gEpisodeInfo[gGameOptions.nEpisode].nLevels
199 || Bstrcasecmp(gEpisodeInfo[gGameOptions.nEpisode].levelsInfo[gGameOptions.nLevel].Filename, gGameOptions.zLevelName) != 0)
200 {
201 if (!gSysRes.Lookup(gGameOptions.zLevelName, "MAP"))
202 {
203 gGameOptions.nEpisode = 0;
204 gGameOptions.nLevel = 0;
205 }
206 else
207 {
208 levelAddUserMap(gGameOptions.zLevelName);
209 }
210 }
211
212 if (MusicRestartsOnLoadToggle
213 || demoWasPlayed
214 || (gMusicPrevLoadedEpisode != gGameOptions.nEpisode || gMusicPrevLoadedLevel != gGameOptions.nLevel))
215 {
216 levelTryPlayMusicOrNothing(gGameOptions.nEpisode, gGameOptions.nLevel);
217 }
218 gMusicPrevLoadedEpisode = gGameOptions.nEpisode;
219 gMusicPrevLoadedLevel = gGameOptions.nLevel;
220
221 netBroadcastPlayerInfo(myconnectindex);
222 //sndPlaySong(gGameOptions.zLevelSong, 1);
223 }
224
SaveGame(char * pzFile)225 void LoadSave::SaveGame(char *pzFile)
226 {
227 hSFile = fopen(pzFile, "wb");
228 if (hSFile == NULL)
229 ThrowError("File error #%d creating save file.", errno);
230 dword_27AA38 = 0;
231 dword_27AA40 = 0;
232 LoadSave *rover = head.next;
233 while (rover != &head)
234 {
235 rover->Save();
236 if (dword_27AA38 > dword_27AA40)
237 dword_27AA40 = dword_27AA38;
238 dword_27AA38 = 0;
239 rover = rover->next;
240 }
241 fclose(hSFile);
242 hSFile = NULL;
243 }
244
245 class MyLoadSave : public LoadSave
246 {
247 public:
248 virtual void Load(void);
249 virtual void Save(void);
250 };
251
Load(void)252 void MyLoadSave::Load(void)
253 {
254 psky_t *pSky = tileSetupSky(0);
255 int id;
256 Read(&id, sizeof(id));
257 if (id != 0x5653424e/*'VSBN'*/)
258 ThrowError("Old saved game found");
259 short version;
260 Read(&version, sizeof(version));
261 if (version != BYTEVERSION)
262 ThrowError("Incompatible version of saved game found!");
263 Read(&gGameOptions, sizeof(gGameOptions));
264 Read(&numsectors, sizeof(numsectors));
265 Read(&numwalls, sizeof(numwalls));
266 Read(&numsectors, sizeof(numsectors));
267 int nNumSprites;
268 Read(&nNumSprites, sizeof(nNumSprites));
269 memset(sector, 0, sizeof(sector[0])*kMaxSectors);
270 memset(wall, 0, sizeof(wall[0])*kMaxWalls);
271 memset(sprite, 0, sizeof(sprite[0])*kMaxSprites);
272 Read(sector, sizeof(sector[0])*numsectors);
273 Read(wall, sizeof(wall[0])*numwalls);
274 Read(sprite, sizeof(sprite[0])*kMaxSprites);
275 Read(qsector_filler, sizeof(qsector_filler[0])*numsectors);
276 Read(qsprite_filler, sizeof(qsprite_filler[0])*kMaxSprites);
277 Read(&randomseed, sizeof(randomseed));
278 Read(¶llaxtype, sizeof(parallaxtype));
279 Read(&showinvisibility, sizeof(showinvisibility));
280 Read(&pSky->horizfrac, sizeof(pSky->horizfrac));
281 Read(&pSky->yoffs, sizeof(pSky->yoffs));
282 Read(&pSky->yscale, sizeof(pSky->yscale));
283 Read(&gVisibility, sizeof(gVisibility));
284 Read(&g_visibility, sizeof(g_visibility));
285 Read(¶llaxvisibility, sizeof(parallaxvisibility));
286 Read(pSky->tileofs, sizeof(pSky->tileofs));
287 Read(&pSky->lognumtiles, sizeof(pSky->lognumtiles));
288 Read(headspritesect, sizeof(headspritesect));
289 Read(headspritestat, sizeof(headspritestat));
290 Read(prevspritesect, sizeof(prevspritesect));
291 Read(prevspritestat, sizeof(prevspritestat));
292 Read(nextspritesect, sizeof(nextspritesect));
293 Read(nextspritestat, sizeof(nextspritestat));
294 Read(show2dsector, sizeof(show2dsector));
295 Read(show2dwall, sizeof(show2dwall));
296 Read(show2dsprite, sizeof(show2dsprite));
297 Read(&automapping, sizeof(automapping));
298 Read(gotpic, sizeof(gotpic));
299 Read(gotsector, sizeof(gotsector));
300 Read(&gFrameClock, sizeof(gFrameClock));
301 Read(&gFrameTicks, sizeof(gFrameTicks));
302 Read(&gFrame, sizeof(gFrame));
303 ClockTicks nGameClock;
304 Read(&totalclock, sizeof(totalclock));
305 totalclock = nGameClock;
306 Read(&gLevelTime, sizeof(gLevelTime));
307 Read(&gPaused, sizeof(gPaused));
308 Read(&gbAdultContent, sizeof(gbAdultContent));
309 Read(baseWall, sizeof(baseWall[0])*numwalls);
310 Read(baseSprite, sizeof(baseSprite[0])*nNumSprites);
311 Read(baseFloor, sizeof(baseFloor[0])*numsectors);
312 Read(baseCeil, sizeof(baseCeil[0])*numsectors);
313 Read(velFloor, sizeof(velFloor[0])*numsectors);
314 Read(velCeil, sizeof(velCeil[0])*numsectors);
315 Read(&gHitInfo, sizeof(gHitInfo));
316 Read(&byte_1A76C6, sizeof(byte_1A76C6));
317 Read(&byte_1A76C8, sizeof(byte_1A76C8));
318 Read(&byte_1A76C7, sizeof(byte_1A76C7));
319 Read(&byte_19AE44, sizeof(byte_19AE44));
320 Read(gStatCount, sizeof(gStatCount));
321 Read(nextXSprite, sizeof(nextXSprite));
322 Read(nextXWall, sizeof(nextXWall));
323 Read(nextXSector, sizeof(nextXSector));
324 memset(xsprite, 0, sizeof(xsprite));
325 for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
326 {
327 if (sprite[nSprite].statnum < kMaxStatus)
328 {
329 int nXSprite = sprite[nSprite].extra;
330 if (nXSprite > 0)
331 Read(&xsprite[nXSprite], sizeof(XSPRITE));
332 }
333 }
334 memset(xwall, 0, sizeof(xwall));
335 for (int nWall = 0; nWall < numwalls; nWall++)
336 {
337 int nXWall = wall[nWall].extra;
338 if (nXWall > 0)
339 Read(&xwall[nXWall], sizeof(XWALL));
340 }
341 memset(xsector, 0, sizeof(xsector));
342 for (int nSector = 0; nSector < numsectors; nSector++)
343 {
344 int nXSector = sector[nSector].extra;
345 if (nXSector > 0)
346 Read(&xsector[nXSector], sizeof(XSECTOR));
347 }
348 Read(xvel, nNumSprites*sizeof(xvel[0]));
349 Read(yvel, nNumSprites*sizeof(yvel[0]));
350 Read(zvel, nNumSprites*sizeof(zvel[0]));
351 Read(&gMapRev, sizeof(gMapRev));
352 Read(&gSongId, sizeof(gSkyCount));
353 Read(&gFogMode, sizeof(gFogMode));
354 #ifdef NOONE_EXTENSIONS
355 Read(&gModernMap, sizeof(gModernMap));
356 #endif
357 #ifdef YAX_ENABLE
358 Read(&numyaxbunches, sizeof(numyaxbunches));
359 #endif
360 psky_t skyInfo;
361 Read(&skyInfo, sizeof(skyInfo));
362
363 *tileSetupSky(0) = skyInfo;
364 gCheatMgr.sub_5BCF4();
365
366 }
367
Save(void)368 void MyLoadSave::Save(void)
369 {
370 psky_t *pSky = tileSetupSky(0);
371 int nNumSprites = 0;
372 int id = 0x5653424e/*'VSBN'*/;
373 Write(&id, sizeof(id));
374 short version = BYTEVERSION;
375 Write(&version, sizeof(version));
376 for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
377 {
378 if (sprite[nSprite].statnum < kMaxStatus && nSprite > nNumSprites)
379 nNumSprites = nSprite;
380 }
381 //nNumSprites += 2;
382 nNumSprites++;
383 Write(&gGameOptions, sizeof(gGameOptions));
384 Write(&numsectors, sizeof(numsectors));
385 Write(&numwalls, sizeof(numwalls));
386 Write(&numsectors, sizeof(numsectors));
387 Write(&nNumSprites, sizeof(nNumSprites));
388 Write(sector, sizeof(sector[0])*numsectors);
389 Write(wall, sizeof(wall[0])*numwalls);
390 Write(sprite, sizeof(sprite[0])*kMaxSprites);
391 Write(qsector_filler, sizeof(qsector_filler[0])*numsectors);
392 Write(qsprite_filler, sizeof(qsprite_filler[0])*kMaxSprites);
393 Write(&randomseed, sizeof(randomseed));
394 Write(¶llaxtype, sizeof(parallaxtype));
395 Write(&showinvisibility, sizeof(showinvisibility));
396 Write(&pSky->horizfrac, sizeof(pSky->horizfrac));
397 Write(&pSky->yoffs, sizeof(pSky->yoffs));
398 Write(&pSky->yscale, sizeof(pSky->yscale));
399 Write(&gVisibility, sizeof(gVisibility));
400 Write(&g_visibility, sizeof(g_visibility));
401 Write(¶llaxvisibility, sizeof(parallaxvisibility));
402 Write(pSky->tileofs, sizeof(pSky->tileofs));
403 Write(&pSky->lognumtiles, sizeof(pSky->lognumtiles));
404 Write(headspritesect, sizeof(headspritesect));
405 Write(headspritestat, sizeof(headspritestat));
406 Write(prevspritesect, sizeof(prevspritesect));
407 Write(prevspritestat, sizeof(prevspritestat));
408 Write(nextspritesect, sizeof(nextspritesect));
409 Write(nextspritestat, sizeof(nextspritestat));
410 Write(show2dsector, sizeof(show2dsector));
411 Write(show2dwall, sizeof(show2dwall));
412 Write(show2dsprite, sizeof(show2dsprite));
413 Write(&automapping, sizeof(automapping));
414 Write(gotpic, sizeof(gotpic));
415 Write(gotsector, sizeof(gotsector));
416 Write(&gFrameClock, sizeof(gFrameClock));
417 Write(&gFrameTicks, sizeof(gFrameTicks));
418 Write(&gFrame, sizeof(gFrame));
419 ClockTicks nGameClock = totalclock;
420 Write(&nGameClock, sizeof(nGameClock));
421 Write(&gLevelTime, sizeof(gLevelTime));
422 Write(&gPaused, sizeof(gPaused));
423 Write(&gbAdultContent, sizeof(gbAdultContent));
424 Write(baseWall, sizeof(baseWall[0])*numwalls);
425 Write(baseSprite, sizeof(baseSprite[0])*nNumSprites);
426 Write(baseFloor, sizeof(baseFloor[0])*numsectors);
427 Write(baseCeil, sizeof(baseCeil[0])*numsectors);
428 Write(velFloor, sizeof(velFloor[0])*numsectors);
429 Write(velCeil, sizeof(velCeil[0])*numsectors);
430 Write(&gHitInfo, sizeof(gHitInfo));
431 Write(&byte_1A76C6, sizeof(byte_1A76C6));
432 Write(&byte_1A76C8, sizeof(byte_1A76C8));
433 Write(&byte_1A76C7, sizeof(byte_1A76C7));
434 Write(&byte_19AE44, sizeof(byte_19AE44));
435 Write(gStatCount, sizeof(gStatCount));
436 Write(nextXSprite, sizeof(nextXSprite));
437 Write(nextXWall, sizeof(nextXWall));
438 Write(nextXSector, sizeof(nextXSector));
439 for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
440 {
441 if (sprite[nSprite].statnum < kMaxStatus)
442 {
443 int nXSprite = sprite[nSprite].extra;
444 if (nXSprite > 0)
445 Write(&xsprite[nXSprite], sizeof(XSPRITE));
446 }
447 }
448 for (int nWall = 0; nWall < numwalls; nWall++)
449 {
450 int nXWall = wall[nWall].extra;
451 if (nXWall > 0)
452 Write(&xwall[nXWall], sizeof(XWALL));
453 }
454 for (int nSector = 0; nSector < numsectors; nSector++)
455 {
456 int nXSector = sector[nSector].extra;
457 if (nXSector > 0)
458 Write(&xsector[nXSector], sizeof(XSECTOR));
459 }
460 Write(xvel, nNumSprites*sizeof(xvel[0]));
461 Write(yvel, nNumSprites*sizeof(yvel[0]));
462 Write(zvel, nNumSprites*sizeof(zvel[0]));
463 Write(&gMapRev, sizeof(gMapRev));
464 Write(&gSongId, sizeof(gSkyCount));
465 Write(&gFogMode, sizeof(gFogMode));
466 #ifdef NOONE_EXTENSIONS
467 Write(&gModernMap, sizeof(gModernMap));
468 #endif
469 #ifdef YAX_ENABLE
470 Write(&numyaxbunches, sizeof(numyaxbunches));
471 #endif
472 psky_t skyInfo = *tileSetupSky(0);
473 Write(&skyInfo, sizeof(skyInfo));
474 }
475
LoadSavedInfo(void)476 void LoadSavedInfo(void)
477 {
478 auto pList = klistpath("./", "game*.sav", BUILDVFS_FIND_FILE);
479 int nCount = 0;
480 for (auto pIterator = pList; pIterator != NULL && nCount < 10; pIterator = pIterator->next, nCount++)
481 {
482 int hFile = kopen4loadfrommod(pIterator->name, 0);
483 if (hFile == -1)
484 ThrowError("Error loading save file header.");
485 int vc;
486 short v4;
487 vc = 0;
488 v4 = word_27AA54;
489 if ((uint32_t)kread(hFile, &vc, sizeof(vc)) != sizeof(vc))
490 {
491 kclose(hFile);
492 continue;
493 }
494 if (vc != 0x5653424e/*'VSBN'*/)
495 {
496 kclose(hFile);
497 continue;
498 }
499 kread(hFile, &v4, sizeof(v4));
500 if (v4 != BYTEVERSION)
501 {
502 kclose(hFile);
503 continue;
504 }
505 if ((uint32_t)kread(hFile, &gSaveGameOptions[nCount], sizeof(gSaveGameOptions[0])) != sizeof(gSaveGameOptions[0]))
506 ThrowError("Error reading save file.");
507 UpdateSavedInfo(nCount);
508 kclose(hFile);
509 }
510 klistfree(pList);
511 }
512
UpdateSavedInfo(int nSlot)513 void UpdateSavedInfo(int nSlot)
514 {
515 strcpy(strRestoreGameStrings[gSaveGameOptions[nSlot].nSaveGameSlot], gSaveGameOptions[nSlot].szUserGameName);
516 restoreGameDifficulty[gSaveGameOptions[nSlot].nSaveGameSlot] = gSaveGameOptions[nSlot].nDifficulty;
517 }
518
519 static MyLoadSave *myLoadSave;
520
521
LoadSaveSetup(void)522 void LoadSaveSetup(void)
523 {
524 void ActorLoadSaveConstruct(void);
525 void AILoadSaveConstruct(void);
526 void EndGameLoadSaveConstruct(void);
527 void EventQLoadSaveConstruct(void);
528 void LevelsLoadSaveConstruct(void);
529 void MessagesLoadSaveConstruct(void);
530 void MirrorLoadSaveConstruct(void);
531 void PlayerLoadSaveConstruct(void);
532 void SeqLoadSaveConstruct(void);
533 void TriggersLoadSaveConstruct(void);
534 void ViewLoadSaveConstruct(void);
535 void WarpLoadSaveConstruct(void);
536 void WeaponLoadSaveConstruct(void);
537
538 myLoadSave = new MyLoadSave();
539
540 ActorLoadSaveConstruct();
541 AILoadSaveConstruct();
542 EndGameLoadSaveConstruct();
543 EventQLoadSaveConstruct();
544 LevelsLoadSaveConstruct();
545 MessagesLoadSaveConstruct();
546 MirrorLoadSaveConstruct();
547 PlayerLoadSaveConstruct();
548 SeqLoadSaveConstruct();
549 TriggersLoadSaveConstruct();
550 ViewLoadSaveConstruct();
551 WarpLoadSaveConstruct();
552 WeaponLoadSaveConstruct();
553 }