mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 04:00:42 +00:00
d8dfe752b5
After merging the CD enabling CVAR they had the same default (off) as Blood which is wrong. This also addresses other music related issues, like not properly cycling through the RR music.
480 lines
14 KiB
C++
480 lines
14 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
Copyright (C) 2019 Nuke.YKT
|
|
|
|
This file is part of NBlood.
|
|
|
|
NBlood is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License version 2
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
#include "ns.h" // Must come before everything else!
|
|
|
|
#include <stdio.h>
|
|
#include "build.h"
|
|
#include "compat.h"
|
|
#include "mmulti.h"
|
|
#include "common_game.h"
|
|
#include "config.h"
|
|
#include "ai.h"
|
|
#include "asound.h"
|
|
#include "blood.h"
|
|
#include "demo.h"
|
|
#include "globals.h"
|
|
#include "db.h"
|
|
#include "messages.h"
|
|
#include "gamemenu.h"
|
|
#include "network.h"
|
|
#include "loadsave.h"
|
|
#include "resource.h"
|
|
#include "screen.h"
|
|
#include "sectorfx.h"
|
|
#include "seq.h"
|
|
#include "sfx.h"
|
|
#include "sound.h"
|
|
#include "i_specialpaths.h"
|
|
#include "view.h"
|
|
#include "savegamehelp.h"
|
|
#include "z_music.h"
|
|
#include "mapinfo.h"
|
|
|
|
BEGIN_BLD_NS
|
|
|
|
char *gSaveGamePic[10];
|
|
unsigned int gSavedOffset = 0;
|
|
|
|
unsigned int dword_27AA38 = 0;
|
|
unsigned int dword_27AA3C = 0;
|
|
unsigned int dword_27AA40 = 0;
|
|
void *dword_27AA44 = NULL;
|
|
|
|
FileWriter *LoadSave::hSFile = NULL;
|
|
FileReader LoadSave::hLFile;
|
|
TDeletingArray<LoadSave*> LoadSave::loadSaves;
|
|
|
|
short word_27AA54 = 0;
|
|
|
|
void sub_76FD4(void)
|
|
{
|
|
#if 0
|
|
if (!dword_27AA44)
|
|
dword_27AA44 = Resource::Alloc(0x186a0);
|
|
#endif
|
|
}
|
|
|
|
void LoadSave::Save(void)
|
|
{
|
|
ThrowError("Pure virtual function called");
|
|
}
|
|
|
|
void LoadSave::Load(void)
|
|
{
|
|
ThrowError("Pure virtual function called");
|
|
}
|
|
|
|
void LoadSave::Read(void *pData, int nSize)
|
|
{
|
|
dword_27AA38 += nSize;
|
|
dassert(hLFile.isOpen());
|
|
if (hLFile.Read(pData, nSize) != nSize)
|
|
ThrowError("Error reading save file.");
|
|
}
|
|
|
|
void LoadSave::Write(void *pData, int nSize)
|
|
{
|
|
dword_27AA38 += nSize;
|
|
dword_27AA3C += nSize;
|
|
dassert(hSFile != NULL);
|
|
if (hSFile->Write(pData, nSize) != (size_t)nSize)
|
|
ThrowError("File error #%d writing save file.", errno);
|
|
}
|
|
|
|
bool GameInterface::LoadGame(FSaveGameNode* node)
|
|
{
|
|
bool demoWasPlayed = gDemo.at1;
|
|
if (gDemo.at1)
|
|
gDemo.Close();
|
|
|
|
sndKillAllSounds();
|
|
sfxKillAllSounds();
|
|
ambKillAll();
|
|
seqKillAll();
|
|
if (!gGameStarted)
|
|
{
|
|
memset(xsprite, 0, sizeof(xsprite));
|
|
memset(sprite, 0, sizeof(spritetype)*kMaxSprites);
|
|
automapping = 1;
|
|
}
|
|
OpenSaveGameForRead(node->Filename);
|
|
LoadSave::hLFile = ReadSavegameChunk("snapshot.bld");
|
|
if (!LoadSave::hLFile.isOpen())
|
|
return false;
|
|
|
|
for (auto rover : LoadSave::loadSaves)
|
|
{
|
|
rover->Load();
|
|
}
|
|
|
|
LoadSave::hLFile.Close();
|
|
FinishSavegameRead();
|
|
if (!gGameStarted)
|
|
scrLoadPLUs();
|
|
InitSectorFX();
|
|
viewInitializePrediction();
|
|
PreloadCache();
|
|
if (!bVanilla && !gMe->packSlots[1].isActive) // if diving suit is not active, turn off reverb sound effect
|
|
sfxSetReverb(0);
|
|
ambInit();
|
|
#ifdef YAX_ENABLE
|
|
yax_update(numyaxbunches > 0 ? 2 : 1);
|
|
#endif
|
|
memset(myMinLag, 0, sizeof(myMinLag));
|
|
otherMinLag = 0;
|
|
myMaxLag = 0;
|
|
gNetFifoClock = 0;
|
|
gNetFifoTail = 0;
|
|
memset(gNetFifoHead, 0, sizeof(gNetFifoHead));
|
|
gPredictTail = 0;
|
|
gNetFifoMasterTail = 0;
|
|
memset(gFifoInput, 0, sizeof(gFifoInput));
|
|
memset(gChecksum, 0, sizeof(gChecksum));
|
|
memset(gCheckFifo, 0, sizeof(gCheckFifo));
|
|
memset(gCheckHead, 0, sizeof(gCheckHead));
|
|
gSendCheckTail = 0;
|
|
gCheckTail = 0;
|
|
gBufferJitter = 0;
|
|
bOutOfSync = 0;
|
|
for (int i = 0; i < gNetPlayers; i++)
|
|
playerSetRace(&gPlayer[i], gPlayer[i].lifeMode);
|
|
if (VanillaMode())
|
|
viewSetMessage("");
|
|
else
|
|
gGameMessageMgr.Clear();
|
|
viewSetErrorMessage("");
|
|
if (!gGameStarted)
|
|
{
|
|
netWaitForEveryone(0);
|
|
memset(gPlayerReady, 0, sizeof(gPlayerReady));
|
|
}
|
|
gFrameTicks = 0;
|
|
gFrame = 0;
|
|
gCacheMiss = 0;
|
|
gFrameRate = 0;
|
|
totalclock = 0;
|
|
gPaused = 0;
|
|
gGameStarted = 1;
|
|
bVanilla = false;
|
|
|
|
Mus_ResumeSaved();
|
|
|
|
netBroadcastPlayerInfo(myconnectindex);
|
|
return true;
|
|
}
|
|
|
|
bool GameInterface::SaveGame(FSaveGameNode* node)
|
|
{
|
|
OpenSaveGameForWrite(node->Filename);
|
|
LoadSave::hSFile = WriteSavegameChunk("snapshot.bld");
|
|
|
|
try
|
|
{
|
|
dword_27AA38 = 0;
|
|
dword_27AA40 = 0;
|
|
for (auto rover : LoadSave::loadSaves)
|
|
{
|
|
rover->Save();
|
|
if (dword_27AA38 > dword_27AA40)
|
|
dword_27AA40 = dword_27AA38;
|
|
dword_27AA38 = 0;
|
|
}
|
|
}
|
|
catch (std::runtime_error & err)
|
|
{
|
|
// Let's not abort for write errors.
|
|
Printf(TEXTCOLOR_RED "%s\n", err.what());
|
|
return false;
|
|
}
|
|
G_WriteSaveHeader(node->SaveTitle);
|
|
LoadSave::hSFile = NULL;
|
|
|
|
return FinishSavegameWrite();
|
|
}
|
|
|
|
class MyLoadSave : public LoadSave
|
|
{
|
|
public:
|
|
virtual void Load(void);
|
|
virtual void Save(void);
|
|
};
|
|
|
|
void MyLoadSave::Load(void)
|
|
{
|
|
psky_t *pSky = tileSetupSky(0);
|
|
int id;
|
|
Read(&id, sizeof(id));
|
|
if (id != 0x5653424e/*'VSBN'*/)
|
|
ThrowError("Old saved game found");
|
|
short version;
|
|
Read(&version, sizeof(version));
|
|
if (version != BYTEVERSION)
|
|
ThrowError("Incompatible version of saved game found!");
|
|
Read(&gGameOptions, sizeof(gGameOptions));
|
|
Read(&numsectors, sizeof(numsectors));
|
|
Read(&numwalls, sizeof(numwalls));
|
|
Read(&numsectors, sizeof(numsectors));
|
|
int nNumSprites;
|
|
Read(&nNumSprites, sizeof(nNumSprites));
|
|
memset(sector, 0, sizeof(sector[0])*kMaxSectors);
|
|
memset(wall, 0, sizeof(wall[0])*kMaxWalls);
|
|
memset(sprite, 0, sizeof(sprite[0])*kMaxSprites);
|
|
Read(sector, sizeof(sector[0])*numsectors);
|
|
Read(wall, sizeof(wall[0])*numwalls);
|
|
Read(sprite, sizeof(sprite[0])*kMaxSprites);
|
|
Read(qsector_filler, sizeof(qsector_filler[0])*numsectors);
|
|
Read(qsprite_filler, sizeof(qsprite_filler[0])*kMaxSprites);
|
|
Read(&randomseed, sizeof(randomseed));
|
|
Read(¶llaxtype, sizeof(parallaxtype));
|
|
Read(&showinvisibility, sizeof(showinvisibility));
|
|
Read(&pSky->horizfrac, sizeof(pSky->horizfrac));
|
|
Read(&pSky->yoffs, sizeof(pSky->yoffs));
|
|
Read(&pSky->yscale, sizeof(pSky->yscale));
|
|
Read(&gVisibility, sizeof(gVisibility));
|
|
Read(&g_visibility, sizeof(g_visibility));
|
|
Read(¶llaxvisibility, sizeof(parallaxvisibility));
|
|
Read(pSky->tileofs, sizeof(pSky->tileofs));
|
|
Read(&pSky->lognumtiles, sizeof(pSky->lognumtiles));
|
|
Read(headspritesect, sizeof(headspritesect));
|
|
Read(headspritestat, sizeof(headspritestat));
|
|
Read(prevspritesect, sizeof(prevspritesect));
|
|
Read(prevspritestat, sizeof(prevspritestat));
|
|
Read(nextspritesect, sizeof(nextspritesect));
|
|
Read(nextspritestat, sizeof(nextspritestat));
|
|
Read(show2dsector, sizeof(show2dsector));
|
|
Read(show2dwall, sizeof(show2dwall));
|
|
Read(show2dsprite, sizeof(show2dsprite));
|
|
Read(&automapping, sizeof(automapping));
|
|
Read(gotpic, sizeof(gotpic));
|
|
Read(gotsector, sizeof(gotsector));
|
|
Read(&gFrameClock, sizeof(gFrameClock));
|
|
Read(&gFrameTicks, sizeof(gFrameTicks));
|
|
Read(&gFrame, sizeof(gFrame));
|
|
ClockTicks nGameClock;
|
|
Read(&totalclock, sizeof(totalclock));
|
|
totalclock = nGameClock;
|
|
Read(&gLevelTime, sizeof(gLevelTime));
|
|
Read(&gPaused, sizeof(gPaused));
|
|
Read(&gbAdultContent, sizeof(gbAdultContent));
|
|
Read(baseWall, sizeof(baseWall[0])*numwalls);
|
|
Read(baseSprite, sizeof(baseSprite[0])*nNumSprites);
|
|
Read(baseFloor, sizeof(baseFloor[0])*numsectors);
|
|
Read(baseCeil, sizeof(baseCeil[0])*numsectors);
|
|
Read(velFloor, sizeof(velFloor[0])*numsectors);
|
|
Read(velCeil, sizeof(velCeil[0])*numsectors);
|
|
Read(&gHitInfo, sizeof(gHitInfo));
|
|
Read(&byte_1A76C6, sizeof(byte_1A76C6));
|
|
Read(&byte_1A76C8, sizeof(byte_1A76C8));
|
|
Read(&byte_1A76C7, sizeof(byte_1A76C7));
|
|
Read(&byte_19AE44, sizeof(byte_19AE44));
|
|
Read(gStatCount, sizeof(gStatCount));
|
|
Read(nextXSprite, sizeof(nextXSprite));
|
|
Read(nextXWall, sizeof(nextXWall));
|
|
Read(nextXSector, sizeof(nextXSector));
|
|
memset(xsprite, 0, sizeof(xsprite));
|
|
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
|
{
|
|
if (sprite[nSprite].statnum < kMaxStatus)
|
|
{
|
|
int nXSprite = sprite[nSprite].extra;
|
|
if (nXSprite > 0)
|
|
Read(&xsprite[nXSprite], sizeof(XSPRITE));
|
|
}
|
|
}
|
|
memset(xwall, 0, sizeof(xwall));
|
|
for (int nWall = 0; nWall < numwalls; nWall++)
|
|
{
|
|
int nXWall = wall[nWall].extra;
|
|
if (nXWall > 0)
|
|
Read(&xwall[nXWall], sizeof(XWALL));
|
|
}
|
|
memset(xsector, 0, sizeof(xsector));
|
|
for (int nSector = 0; nSector < numsectors; nSector++)
|
|
{
|
|
int nXSector = sector[nSector].extra;
|
|
if (nXSector > 0)
|
|
Read(&xsector[nXSector], sizeof(XSECTOR));
|
|
}
|
|
Read(xvel, nNumSprites*sizeof(xvel[0]));
|
|
Read(yvel, nNumSprites*sizeof(yvel[0]));
|
|
Read(zvel, nNumSprites*sizeof(zvel[0]));
|
|
Read(&gMapRev, sizeof(gMapRev));
|
|
Read(&gSongId, sizeof(gSkyCount));
|
|
Read(&gFogMode, sizeof(gFogMode));
|
|
Read(&gModernMap, sizeof(gModernMap));
|
|
#ifdef YAX_ENABLE
|
|
Read(&numyaxbunches, sizeof(numyaxbunches));
|
|
#endif
|
|
gCheatMgr.sub_5BCF4();
|
|
|
|
}
|
|
|
|
void MyLoadSave::Save(void)
|
|
{
|
|
psky_t *pSky = tileSetupSky(0);
|
|
int nNumSprites = 0;
|
|
int id = 0x5653424e/*'VSBN'*/;
|
|
Write(&id, sizeof(id));
|
|
short version = BYTEVERSION;
|
|
Write(&version, sizeof(version));
|
|
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
|
{
|
|
if (sprite[nSprite].statnum < kMaxStatus && nSprite > nNumSprites)
|
|
nNumSprites = nSprite;
|
|
}
|
|
//nNumSprites += 2;
|
|
nNumSprites++;
|
|
Write(&gGameOptions, sizeof(gGameOptions));
|
|
Write(&numsectors, sizeof(numsectors));
|
|
Write(&numwalls, sizeof(numwalls));
|
|
Write(&numsectors, sizeof(numsectors));
|
|
Write(&nNumSprites, sizeof(nNumSprites));
|
|
Write(sector, sizeof(sector[0])*numsectors);
|
|
Write(wall, sizeof(wall[0])*numwalls);
|
|
Write(sprite, sizeof(sprite[0])*kMaxSprites);
|
|
Write(qsector_filler, sizeof(qsector_filler[0])*numsectors);
|
|
Write(qsprite_filler, sizeof(qsprite_filler[0])*kMaxSprites);
|
|
Write(&randomseed, sizeof(randomseed));
|
|
Write(¶llaxtype, sizeof(parallaxtype));
|
|
Write(&showinvisibility, sizeof(showinvisibility));
|
|
Write(&pSky->horizfrac, sizeof(pSky->horizfrac));
|
|
Write(&pSky->yoffs, sizeof(pSky->yoffs));
|
|
Write(&pSky->yscale, sizeof(pSky->yscale));
|
|
Write(&gVisibility, sizeof(gVisibility));
|
|
Write(&g_visibility, sizeof(g_visibility));
|
|
Write(¶llaxvisibility, sizeof(parallaxvisibility));
|
|
Write(pSky->tileofs, sizeof(pSky->tileofs));
|
|
Write(&pSky->lognumtiles, sizeof(pSky->lognumtiles));
|
|
Write(headspritesect, sizeof(headspritesect));
|
|
Write(headspritestat, sizeof(headspritestat));
|
|
Write(prevspritesect, sizeof(prevspritesect));
|
|
Write(prevspritestat, sizeof(prevspritestat));
|
|
Write(nextspritesect, sizeof(nextspritesect));
|
|
Write(nextspritestat, sizeof(nextspritestat));
|
|
Write(show2dsector, sizeof(show2dsector));
|
|
Write(show2dwall, sizeof(show2dwall));
|
|
Write(show2dsprite, sizeof(show2dsprite));
|
|
Write(&automapping, sizeof(automapping));
|
|
Write(gotpic, sizeof(gotpic));
|
|
Write(gotsector, sizeof(gotsector));
|
|
Write(&gFrameClock, sizeof(gFrameClock));
|
|
Write(&gFrameTicks, sizeof(gFrameTicks));
|
|
Write(&gFrame, sizeof(gFrame));
|
|
ClockTicks nGameClock = totalclock;
|
|
Write(&nGameClock, sizeof(nGameClock));
|
|
Write(&gLevelTime, sizeof(gLevelTime));
|
|
Write(&gPaused, sizeof(gPaused));
|
|
Write(&gbAdultContent, sizeof(gbAdultContent));
|
|
Write(baseWall, sizeof(baseWall[0])*numwalls);
|
|
Write(baseSprite, sizeof(baseSprite[0])*nNumSprites);
|
|
Write(baseFloor, sizeof(baseFloor[0])*numsectors);
|
|
Write(baseCeil, sizeof(baseCeil[0])*numsectors);
|
|
Write(velFloor, sizeof(velFloor[0])*numsectors);
|
|
Write(velCeil, sizeof(velCeil[0])*numsectors);
|
|
Write(&gHitInfo, sizeof(gHitInfo));
|
|
Write(&byte_1A76C6, sizeof(byte_1A76C6));
|
|
Write(&byte_1A76C8, sizeof(byte_1A76C8));
|
|
Write(&byte_1A76C7, sizeof(byte_1A76C7));
|
|
Write(&byte_19AE44, sizeof(byte_19AE44));
|
|
Write(gStatCount, sizeof(gStatCount));
|
|
Write(nextXSprite, sizeof(nextXSprite));
|
|
Write(nextXWall, sizeof(nextXWall));
|
|
Write(nextXSector, sizeof(nextXSector));
|
|
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
|
{
|
|
if (sprite[nSprite].statnum < kMaxStatus)
|
|
{
|
|
int nXSprite = sprite[nSprite].extra;
|
|
if (nXSprite > 0)
|
|
Write(&xsprite[nXSprite], sizeof(XSPRITE));
|
|
}
|
|
}
|
|
for (int nWall = 0; nWall < numwalls; nWall++)
|
|
{
|
|
int nXWall = wall[nWall].extra;
|
|
if (nXWall > 0)
|
|
Write(&xwall[nXWall], sizeof(XWALL));
|
|
}
|
|
for (int nSector = 0; nSector < numsectors; nSector++)
|
|
{
|
|
int nXSector = sector[nSector].extra;
|
|
if (nXSector > 0)
|
|
Write(&xsector[nXSector], sizeof(XSECTOR));
|
|
}
|
|
Write(xvel, nNumSprites*sizeof(xvel[0]));
|
|
Write(yvel, nNumSprites*sizeof(yvel[0]));
|
|
Write(zvel, nNumSprites*sizeof(zvel[0]));
|
|
Write(&gMapRev, sizeof(gMapRev));
|
|
Write(&gSongId, sizeof(gSkyCount));
|
|
Write(&gFogMode, sizeof(gFogMode));
|
|
Write(&gModernMap, sizeof(gModernMap));
|
|
#ifdef YAX_ENABLE
|
|
Write(&numyaxbunches, sizeof(numyaxbunches));
|
|
#endif
|
|
}
|
|
|
|
void LoadSavedInfo(void)
|
|
{
|
|
}
|
|
|
|
void UpdateSavedInfo(int nSlot)
|
|
{
|
|
}
|
|
|
|
static MyLoadSave *myLoadSave;
|
|
|
|
|
|
void ActorLoadSaveConstruct(void);
|
|
void AILoadSaveConstruct(void);
|
|
void EndGameLoadSaveConstruct(void);
|
|
void EventQLoadSaveConstruct(void);
|
|
void LevelsLoadSaveConstruct(void);
|
|
void MessagesLoadSaveConstruct(void);
|
|
void MirrorLoadSaveConstruct(void);
|
|
void PlayerLoadSaveConstruct(void);
|
|
void SeqLoadSaveConstruct(void);
|
|
void TriggersLoadSaveConstruct(void);
|
|
void ViewLoadSaveConstruct(void);
|
|
void WarpLoadSaveConstruct(void);
|
|
void WeaponLoadSaveConstruct(void);
|
|
|
|
void LoadSaveSetup(void)
|
|
{
|
|
myLoadSave = new MyLoadSave();
|
|
|
|
ActorLoadSaveConstruct();
|
|
AILoadSaveConstruct();
|
|
EndGameLoadSaveConstruct();
|
|
EventQLoadSaveConstruct();
|
|
LevelsLoadSaveConstruct();
|
|
MessagesLoadSaveConstruct();
|
|
MirrorLoadSaveConstruct();
|
|
PlayerLoadSaveConstruct();
|
|
SeqLoadSaveConstruct();
|
|
TriggersLoadSaveConstruct();
|
|
ViewLoadSaveConstruct();
|
|
WarpLoadSaveConstruct();
|
|
WeaponLoadSaveConstruct();
|
|
}
|
|
|
|
END_BLD_NS
|