- added savegame records for all global data that looks to be game relevant.

The data organization here is a mess, no wonder that this game could only save at the beginning of a level.
Fortunately it's all static so no allocations and pointers to track.
This commit is contained in:
Christoph Oelckers 2019-12-26 22:00:04 +01:00
parent 90fecbc6c0
commit 79d0818201
37 changed files with 570 additions and 54 deletions

View file

@ -28,7 +28,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_PS_NS
#define kMaxAnims 400
short nMagicSeq = -1;
@ -41,6 +40,16 @@ short AnimsFree[kMaxAnims];
Anim AnimList[kMaxAnims];
uint8_t AnimFlags[kMaxAnims];
static SavegameHelper sgh("anims",
SV(nMagicSeq),
SV(nPreMagicSeq),
SV(nSavePointSeq),
SV(nAnimsFree),
SA(AnimRunRec),
SA(AnimsFree),
SA(AnimList),
SA(AnimFlags),
nullptr);
void InitAnims()
{

View file

@ -71,6 +71,13 @@ static actionSeq ActionSeq[] = {
short nAnubisDrum = 0;
static SavegameHelper sgh("anubis",
SA(AnubisList),
SV(AnubisSprite),
SV(AnubisCount),
SV(nAnubisDrum),
nullptr);
void InitAnubis()
{

View file

@ -59,6 +59,14 @@ uint8_t nBubblesFree[kMaxBubbles];
machine Machine[kMaxMachines];
Bubble BubbleList[kMaxBubbles];
static SavegameHelper sgh("bubbles",
SA(BubbleCount),
SA(nFreeCount),
SA(nMachineCount),
SA(nBubblesFree),
SA(Machine),
SA(BubbleList),
nullptr);
void InitBubbles()
{

View file

@ -74,6 +74,22 @@ short lasthitsect, lasthitsprite, lasthitwall;
int nBulletCount = 0;
short nRadialBullet = 0;
static SavegameHelper sgh("bullet",
SV(BulletFree),
SV(BulletList),
SV(nBulletEnemy),
SA(nBulletsFree),
SA(lasthitz),
SA(lasthitx),
SA(lasthity),
SA(lasthitsect),
SA(lasthitsprite),
SA(lasthitwall),
SV(nBulletCount),
SV(nRadialBullet),
nullptr);
bulletInfo BulletInfo[] = {
{ 25, 1, 20, -1, -1, 13, 0, 0, -1, 0 },
{ 25, -1, 65000, -1, 31, 73, 0, 0, -1, 0 },

View file

@ -3401,5 +3401,65 @@ bool GameInterface::CanSave()
return new GameInterface;
}
//short lastlevel;
//short forcelevel = -1;
//int lLocalCodes = 0;
//int flash;
//short textpages;
// This is only the static global data.
static SavegameHelper sgh("exhumed",
SA(cPupData),
SV(nPupData),
SV(nPixels),
SA(curx),
SA(cury),
SA(destvelx),
SA(destvely),
SA(pixelval),
SA(origy),
SA(origx),
SA(velx),
SA(vely),
SV(nMouthTile),
SV(nSpiritSprite),
SV(word_964E8),
SV(word_964EA),
SV(word_964EC),
SV(nSpiritRepeatX),
SV(nSpiritRepeatY),
SV(nPixelsToShow),
SV(nCreaturesLeft), // todo: also maintain a total counter.
SV(nFreeze),
SV(nSnakeCam),
SV(nLocalSpr),
SV(levelnew),
SV(nClockVal), // kTile3603
SV(nRedTicks),
SV(nAlarmTicks),
SV(nButtonColor),
SV(nEnergyChan),
SV(lCountDown),
SV(nEnergyTowers),
SV(nHeadStage),
SV(nTalkTime),
SV(levelnum),
SV(moveframes),
SV(totalmoves),
SV(nCurBodyNum),
SV(nBodyTotal),
SV(bSnakeCam),
SV(bSlipMode),
nullptr);
// These need to be saved as diffs.
//int lHeadStartClock; // Timer
//int lNextStateChange; // Timer
//int nHeadTimeStart; // Timer
//int localclock; // timer
//short* pPupData;
//uint8_t* Worktile;
END_PS_NS

View file

@ -27,6 +27,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "m_argv.h"
#include "gamecontrol.h"
#include "c_buttons.h"
#include <algorithm>
#include "tarray.h"
#include "save.h"
#include "zstring.h"
#include "filesystem/filesystem.h"
BEGIN_PS_NS

View file

@ -77,6 +77,15 @@ struct Chunk
Fish FishList[kMaxFishes];
Chunk FishChunk[kMaxChunks];
static SavegameHelper sgh("fish",
SV(FishSprite),
SV(FishCount),
SV(nChunksFree),
SA(nFreeChunk),
SA(FishList),
SA(FishChunk),
nullptr);
void InitFishes()
{

View file

@ -56,6 +56,13 @@ struct Grenade
Grenade GrenadeList[kMaxGrenades];
static SavegameHelper sgh("grenade",
SV(nGrenadeCount),
SV(nGrenadesFree),
SA(GrenadeFree),
SA(GrenadeList),
nullptr);
void InitGrenades()
{

View file

@ -74,6 +74,11 @@ short nTemperature[kMaxPlayers];
short nMinAmmo[] = { 0, 24, 51, 50, 1, 0, 0 };
short word_96E26 = 0;
static SavegameHelper sgh("gun",
SA(nTemperature),
SV(word_96E26),
nullptr);
void RestoreMinAmmo(short nPlayer)
{

View file

@ -76,58 +76,7 @@ int SectBelow[kMaxSectors] = { 0 };
uint8_t bIsVersion6 = kTrue;
#if 0
// definitions for map version 6 structures
#pragma pack(1)
// 37 bytes
struct Sector_6
{
uint16_t wallptr, wallnum;
short ceilingpicnum, floorpicnum;
short ceilingheinum, floorheinum;
int ceilingz, floorz;
int8_t ceilingshade, floorshade;
uint8_t ceilingxpanning, floorxpanning;
uint8_t ceilingypanning, floorypanning;
uint8_t ceilingstat, floorstat;
uint8_t ceilingpal, floorpal;
uint8_t visibility;
short lotag, hitag, extra;
};
struct Wall_6
{
int x, y;
short point2, nextsector, nextwall;
short picnum, overpicnum;
int8_t shade;
uint8_t pal;
short cstat;
uint8_t xrepeat, yrepeat, xpanning, ypanning;
short lotag, hitag, extra;
};
// 43 bytes
struct Sprite_6
{
int x, y, z;
short cstat;
int8_t shade;
uint8_t pal, clipdist;
uint8_t xrepeat, yrepeat;
int8_t xoffset, yoffset;
short picnum, ang, xvel, yvel, zvel, owner;
short sectnum, statnum;
short lotag, hitag, extra;
};
#pragma pack()
static Sector_6 sector_6[1024];
static Wall_6 wall_6[8192];
static Sprite_6 sprite_6[4096];
#endif
uint8_t LoadLevel(int nMap)
@ -996,4 +945,25 @@ int mysaveconfig()
{
return 1;
}
static SavegameHelper sgh("init",
SV(initx),
SV(inity),
SV(initz),
SV(inita),
SV(initsect),
SV(nCurChunkNum),
SA(nBodyGunSprite),
SV(nCurBodyGunNum),
SA(SectSoundSect),
SA(SectSound),
SA(SectFlag),
SA(SectDepth),
SA(SectAbove),
SA(SectDamage),
SA(SectSpeed),
SA(SectBelow),
nullptr);
END_PS_NS

View file

@ -113,6 +113,12 @@ short nRegenerates;
short nFirstRegenerate;
short nMagicCount;
static SavegameHelper sgh("items",
SV(nRegenerates),
SV(nFirstRegenerate),
SV(nMagicCount),
nullptr);
void BuildItemAnim(short nSprite)
{

View file

@ -61,6 +61,13 @@ static actionSeq ActionSeq[] = {
{42, 1}
};
static SavegameHelper sgh("lavadude",
SA(LavaList),
SV(LavaCount),
SV(LavaSprite),
nullptr);
// done
void InitLava()
{

View file

@ -90,6 +90,28 @@ short nGlowCount;
int bDoFlicks = 0;
int bDoGlows = 0;
static SavegameHelper sgh("lightning",
SA(sFlash),
SA(sGlow),
SA(nNextFlash),
SA(sFlicker),
SA(nFreeFlash),
SA(sFlowInfo),
SA(flickermask),
SV(bTorch),
SV(nFirstFlash),
SV(nLastFlash),
SV(nFlashDepth),
SV(nFlashes),
SV(nFlowCount),
SV(nFlickerCount),
SV(nGlowCount),
SV(bDoFlicks),
SV(bDoGlows),
nullptr);
// done
int GrabFlash()
{

View file

@ -52,6 +52,12 @@ struct Lion
Lion LionList[kMaxLions];
static SavegameHelper sgh("lion",
SV(LionCount),
SA(MoveHook),
SA(LionList),
nullptr);
void InitLion()
{

View file

@ -2036,4 +2036,9 @@ LABEL_28:
MySetView(nViewLeft, nViewTop, nViewRight, nViewBottom);
MaskStatus();
}
static SavegameHelper sgh("menu",
SA(nCinemaSeen),
nullptr);
END_PS_NS

View file

@ -65,6 +65,21 @@ BlockInfo sBlockInfo[kMaxPushBlocks];
short nChunkSprite[kMaxChunks];
static SavegameHelper sgh("move",
SV(nPushBlocks),
SV(overridesect),
SV(NearCount),
SV(hihit),
SV(sprceiling),
SV(sprfloor),
SV(lohit),
SA(nBodySprite),
SA(NearSector),
SA(sBlockInfo),
SA(nChunkSprite),
nullptr);
signed int lsqrt(int a1)
{
int v1; // edx@1

View file

@ -58,6 +58,12 @@ static actionSeq ActionSeq[] = {
{50, 0}
};
static SavegameHelper sgh("mummy",
SV(nMummies),
SA(MummyList),
nullptr);
// done
void InitMummy()
{

View file

@ -2673,4 +2673,46 @@ void PostProcess()
}
}
}
static SavegameHelper sgh("objects",
SA(sTrap),
SA(sBob),
SA(sTrail),
SA(sTrailPoint),
SA(Elevator),
SA(ObjectList),
SA(sMoveSect),
SA(SlideData),
SA(sMoveDir),
SA(WallFace),
SA(SlideData2),
SA(PointList),
SA(nTrapInterval),
SA(sBobID),
SA(PointFree),
SA(SlideFree),
SA(nTrailPointVal),
SA(nTrailPointPrev),
SA(nTrailPointNext),
SA(sDrip),
SV(PointCount),
SV(SlideCount),
SV(ElevCount),
SV(WallFaceCount),
SV(lFinaleStart),
SV(nTrailPoints),
SV(nEnergyBlocks),
SV(nMoveSects),
SV(nFinaleStage),
SV(nTrails),
SV(nTraps),
SV(nFinaleSpr),
SV(ObjectCount),
SV(nDrips),
SV(nBobs),
SV(nDronePitch),
SV(nSmokeSparks),
nullptr);
END_PS_NS

View file

@ -3112,4 +3112,56 @@ loc_1BD2E:
}
}
}
static SavegameHelper sgh("player",
SV(lPlayerXVel),
SV(lPlayerYVel),
SV(nPlayerDAng),
SV(obobangle),
SV(bobangle),
SV(bPlayerPan),
SV(bLockPan),
SV(g_MyAimMode),
SV(nStandHeight),
SV(PlayerCount),
SV(nNetStartSprites),
SV(nCurStartSprite),
SV(nLocalPlayer),
SA(nBreathTimer),
SA(nPlayerSwear),
SA(nPlayerPushSect),
SA(nDeathType),
SA(nPlayerScore),
SA(nPlayerColor),
SA(nPlayerDY),
SA(nPlayerDX),
SA(playerNames),
SA(nPistolClip),
SA(nXDamage),
SA(nYDamage),
SA(nDoppleSprite),
SA(namelen),
SA(nPlayerOldWeapon),
SA(nPlayerClip),
SA(nPlayerPushSound),
SA(nTauntTimer),
SA(nPlayerTorch),
SA(nPlayerWeapons),
SA(nPlayerLives),
SA(nPlayerItem),
SA(PlayerList),
SA(nPlayerInvisible),
SA(nPlayerDouble),
SA(nPlayerViewSect),
SA(nPlayerFloorSprite),
SA(sPlayerSave),
SA(totalvel),
SA(eyelevel),
SA(nNetStartSprite),
SA(nPlayerGrenade),
SA(nGrenadePlayer),
SA(word_D282A),
nullptr);
END_PS_NS

View file

@ -87,7 +87,6 @@ short QueenChan[kMaxQueens];
struct Queen
{
short nHealth;
@ -137,6 +136,27 @@ short MoveQS[25];
short MoveQA[25];
static SavegameHelper sgh("queen",
SV(QueenCount),
SV(nQHead),
SV(nEggsFree),
SV(nHeadVel),
SV(nVelShift),
SV(QueenHead),
SA(tailspr),
SA(nEggFree),
SA(QueenChan),
SA(QueenEgg),
SA(QueenList),
SA(MoveQX),
SA(MoveQY),
SA(MoveQZ),
SA(MoveQS),
SA(MoveQA),
nullptr);
void InitQueens()
{
QueenCount = 1;

View file

@ -41,6 +41,12 @@ static actionSeq ActionSeq[] = {
{2, 1}, {0, 0}, {1, 0}, {2, 0}
};
static SavegameHelper sgh("ra",
SA(Ra),
SV(RaCount),
nullptr);
void FreeRa(short nPlayer)
{
int nRun = Ra[nPlayer].field_4;

View file

@ -17,6 +17,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//-------------------------------------------------------------------------
#include "ns.h"
#include "random.h"
#include "exhumed.h"
BEGIN_PS_NS
@ -24,6 +25,12 @@ int randA = 0;
int randB = 0x11111111;
int randC = 0x1010101;
static SavegameHelper sgh("rand",
SV(randA),
SV(randB),
SV(randC),
nullptr);
void InitRandom()
{

View file

@ -53,6 +53,14 @@ Rat RatList[kMaxRats];
static actionSeq ActionSeq[] = {{0, 1}, {1, 0}, {1, 0}, {9, 1}, {0, 1}};
static SavegameHelper sgh("rat",
SV(nMinChunk),
SV(nPlayerPic),
SV(nRatCount),
SV(nMaxChunk),
SA(RatList),
nullptr);
void InitRats()
{
nRatCount = 0;

View file

@ -60,6 +60,13 @@ static actionSeq ActionSeq[] = {
};
static SavegameHelper sgh("rex",
SV(RexCount),
SA(RexChan),
SA(RexList),
nullptr);
void InitRexs()
{
RexCount = kMaxRex;

View file

@ -52,6 +52,12 @@ struct Roach
Roach RoachList[kMaxRoach];
static SavegameHelper sgh("roach",
SV(RoachSprite),
SV(RoachCount),
SA(RoachList),
nullptr);
/* Kilmaat Sentry */

View file

@ -1842,4 +1842,24 @@ void runlist_DamageEnemy(int nSprite, int nSprite2, short nDamage)
}
}
}
static SavegameHelper sgh("runlist",
SV(RunCount),
SV(nRadialSpr),
SV(nStackCount),
SV(word_966BE),
SV(ChannelList),
SV(ChannelLast),
SV(nRadialOwner),
SV(nDamageRadius),
SV(nRadialDamage),
SV(RunChain),
SV(NewRun),
SA(sRunStack),
SA(RunFree),
SA(sRunChannels),
SA(RunData),
SV(word_96760),
nullptr);
END_PS_NS

View file

@ -18,10 +18,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "ns.h"
#include "save.h"
#include <stdio.h>
#include <stdarg.h>
//#include <fcntl.h>
//#include <sys/stat.h>
//#include <io.h>
#include "engine.h"
#include "exhumed.h"
#include "savegamehelp.h"
BEGIN_PS_NS
@ -121,4 +124,55 @@ int loadgame(int nSlot)
return 1; // CHECKME
}
static TArray<SavegameHelper*> sghelpers(TArray<SavegameHelper*>::NoInit);
SavegameHelper::SavegameHelper(const char* name, ...)
{
Name = name;
sghelpers.Push(this);
va_list ap;
va_start(ap, name);
for(;;)
{
void* addr = va_arg(ap, void*);
if (!addr) break;
size_t size = va_arg(ap, size_t);
Elements.Push(std::make_pair(addr, size));
}
}
void SavegameHelper::Load()
{
auto fr = ReadSavegameChunk(Name);
for (auto& entry : Elements)
{
auto read = fr.Read(entry.first, entry.second);
if (read != entry.second) I_Error("Save game read error in %s", Name.GetChars());
}
// reset the sky in case it hasn't been done yet.
psky_t* pSky = tileSetupSky(0);
pSky->tileofs[0] = 0;
pSky->tileofs[1] = 0;
pSky->tileofs[2] = 0;
pSky->tileofs[3] = 0;
pSky->yoffs = 256;
pSky->lognumtiles = 2;
pSky->horizfrac = 65536;
pSky->yscale = 65536;
parallaxtype = 2;
g_visibility = 2048;
}
void SavegameHelper::Save()
{
auto fw = WriteSavegameChunk(Name);
for (auto& entry : Elements)
{
auto write = fw->Write(entry.first, entry.second);
if (write != entry.second) I_Error("Save game write error in %s", Name.GetChars());
}
}
END_PS_NS

View file

@ -18,12 +18,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef __save_h__
#define __save_h__
#include "zstring.h"
BEGIN_PS_NS
int savegame(int nSlot);
int loadgame(int nSlot);
struct SavegameHelper
{
FString Name;
TArray<std::pair<void*, size_t>> Elements;
SavegameHelper(const char* name, ...);
void Load();
void Save();
};
#define SV(v) &v, sizeof(v)
#define SA(a) a, sizeof(a)
END_PS_NS
#endif

View file

@ -53,6 +53,11 @@ static actionSeq ActionSeq[] = {
{53, 1}
};
static SavegameHelper sgh("scorp",
SV(ScorpCount),
SA(scorpion),
SA(ScorpChan),
nullptr);
void InitScorp()
{

View file

@ -661,4 +661,14 @@ int seq_PlotSequence(short nSprite, short edx, short nFrame, short ecx)
return nPict;
}
static SavegameHelper sgh("sequence",
SV(nPilotLightFrame),
SV(nPilotLightCount),
SV(nPilotLightBase),
SV(laststatustile),
SV(nShadowWidth),
SV(nFlameHeight),
nullptr);
END_PS_NS

View file

@ -64,6 +64,12 @@ struct Set
Set SetList[kMaxSets];
short SetChan[kMaxSets];
static SavegameHelper sgh("set",
SV(SetCount),
SA(SetList),
SA(SetChan),
nullptr);
void InitSets()
{

View file

@ -47,6 +47,14 @@ short nPlayerSnake[kMaxPlayers];
Snake SnakeList[kMaxSnakes];
short nSnakePlayer[kMaxSnakes];
static SavegameHelper sgh("snake",
SV(nSnakeCount),
SV(nSnakesFree),
SA(SnakeFree),
SA(nPlayerSnake),
SA(SnakeList),
SA(nSnakePlayer),
nullptr);
void InitSnakes()
{

View file

@ -50,6 +50,11 @@ Spider SpiderList[kMaxSpiders];
static actionSeq ActionSeq[] = { {16, 0}, {8, 0}, {32, 0}, {24, 0}, {0, 0}, {40, 1}, {41, 1} };
static SavegameHelper sgh("spider",
SV(SpiderSprite),
SV(SpiderCount),
SA(SpiderList),
nullptr);
void InitSpider()
{

View file

@ -850,4 +850,49 @@ void DrawStatus()
}
}
// I'm not sure this really needs to be saved.
static SavegameHelper sgh("status",
SV(nMaskY),
SV(nAnimsFree),
SV(message_timer),
SV(magicperline),
SV(airperline),
SV(healthperline),
SV(nAirFrames),
SV(nCounter),
SV(nCounterDest),
SV(nStatusSeqOffset),
SV(nItemFrames),
SV(laststatusx),
SV(laststatusy),
SV(nItemSeq),
SV(nMagicFrames),
SV(nHealthLevel),
SV(nItemFrame),
SV(nMeterRange),
SV(nMagicLevel),
SV(nHealthFrame),
SV(nMagicFrame),
SV(statusx),
SV(statusy),
SV(nHealthFrames),
SV(airframe),
SV(nFirstAnim),
SV(nLastAnim),
SV(nItemAltSeq),
SV(airpages),
SV(ammodelay),
SV(nCounterBullet),
SA(statusmask),
SA(message_text),
SA(nDigit),
SA(StatusAnim),
SA(StatusAnimsFree),
SA(StatusAnimFlags),
SA(nItemSeqOffset),
SA(word_9AD54),
SA(dword_9AD64),
nullptr);
END_PS_NS

View file

@ -50,7 +50,12 @@ struct Switch
Switch SwitchData[kMaxSwitches];
static SavegameHelper sgh("switch",
SV(LinkCount),
SV(SwitchCount),
SA(LinkMap),
SA(SwitchData),
nullptr);
void InitLink()
{

View file

@ -650,4 +650,31 @@ void Clip()
bClip = kTrue;
}
static SavegameHelper sgh("view",
SV(nCamerax),
SV(nCameray),
SV(nCameraz),
SV(bTouchFloor),
SV(nChunkTotal),
SV(nCameraa),
SV(nCamerapan),
SV(nViewTop),
SV(bClip),
SV(nViewBottom),
SV(nViewRight),
SV(besttarget),
SV(nViewLeft),
SV(bCamera),
SV(nViewy),
SV(viewz),
SV(enemy),
SV(nEnemyPal),
SA(nDestVertPan),
SA(dVertPan),
SA(nVertPan),
SA(nQuake),
nullptr);
END_PS_NS

View file

@ -55,6 +55,12 @@ Wasp WaspList[kMaxWasps];
static actionSeq ActionSeq[] = {{0,0}, {0,0}, {9,0}, {18,0}, {27,1}, {28,1}, {29,1}};
static SavegameHelper sgh("wasp",
SV(nVelShift),
SV(nWaspCount),
SA(WaspList),
nullptr);
void InitWasps()
{