Rewrite the savegame format in terms of the generic saving/loading system.

This makes savegames practically the same as the initial snapshot of a demo.
Saves are now named 'dukesavX.esv' (demos: 'edemoX.edm').
Additionally, many changes that couldn't/needn't be cleanly separated are added
with this commit:
 - make spriteext_t have the same size across 32/64 bit platforms (actor_t partially)
 - prevent saving/loading in MP games (it certainly didn't work and still doesn't)
 - it's time we start using assertions! Define NDEBUG for releasse builds.
 - reset savegame major and minor versions (we have a new magic string, so no conflict)

git-svn-id: https://svn.eduke32.com/eduke32@2207 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2011-12-25 15:34:06 +00:00
parent 61257b0f6b
commit b3474c75b2
10 changed files with 768 additions and 316 deletions

View file

@ -84,6 +84,8 @@ ifneq (0,$(RELEASE))
endif
ifeq (0,$(DEBUGANYWAY))
debug+= -fomit-frame-pointer
else
debug+= -DNDEBUG
endif
ifneq (0,$(LTO))
LIBS+= -flto

View file

@ -240,10 +240,13 @@ typedef struct {
uint8_t filler;
float alpha;
spritetype *tspr;
#if defined LUNATIC_ENABLE && UINTPTR_MAX == 0xffffffff
#if !defined UINTPTR_MAX
# error Need UINTPTR_MAX define to select between 32- and 64-bit structs
#endif
#if UINTPTR_MAX == 0xffffffff
/* On a 32-bit build, pad the struct so it has the same size everywhere.
* REMINDER: Will break savegames. */
void *dummy_;
const intptr_t dummy_;
#endif
} spriteext_t;

View file

@ -85,7 +85,7 @@ typedef struct {
int8_t filler[6]; // 6b
} projectile_t;
// (+ 40 8 6 16 16 4 8 6 4 4 16)
// (+ 40 8 6 16 16 4 8 6 4 20)
typedef struct {
#ifdef SAMESIZE_ACTOR_T
int32_t t_data[10]; // 40b sometimes used to hold offsets to con code
@ -108,12 +108,16 @@ typedef struct {
void *lightptr;
#endif
#if !defined SAMESIZE_ACTOR_T || UINTPTR_MAX == 0xffffffff
/* 32-bit or old, same-declaration version */
int8_t filler[24]; // pad struct to 128 bytes
// pad struct to 128 bytes
#if !defined UINTPTR_MAX
# error Need UINTPTR_MAX define to select between 32- and 64-bit structs
#endif
#if UINTPTR_MAX == 0xffffffff
/* 32-bit */
const int8_t filler[20];
#else
/* 64-bit, will break older savegames */
int8_t filler[16];
/* 64-bit */
const int8_t filler[12];
#endif
} actor_t;

View file

@ -25,6 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "menus.h"
#include "savegame.h"
#include <assert.h>
char firstdemofile[BMAX_PATH];
FILE *g_demo_filePtr = (FILE *)NULL;
@ -35,7 +37,7 @@ int32_t g_demo_soundToggle;
int32_t g_demo_paused=0;
int32_t g_demo_rewind=0;
int32_t g_demo_showStats=1;
int32_t g_demo_recFilePtr;
int32_t g_demo_recFilePtr = -1;
static int32_t demo_hasdiffs, demorec_diffs=1, demorec_difftics = 2*(TICRATE/TICSPERFRAME);
int32_t demoplay_diffs=1;
@ -69,11 +71,13 @@ void demo_preparewarp(void)
}
int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
{
char d[14];
int32_t i;
savehead_t saveh;
Bstrcpy(d, "edemo_.edm");
if (g_whichDemo == 10)
@ -87,9 +91,19 @@ int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
}
else if ((g_demo_recFilePtr = kopen4loadfrommod(d,g_loadFromGroupOnly)) == -1) return(0);
i=sv_loadsnapshot(g_demo_recFilePtr, &demo_hasdiffs, &g_demo_totalCnt, &demo_synccompress);
if (i==0)
assert(g_whichDemo >= 1);
i = sv_loadsnapshot(g_demo_recFilePtr, -g_whichDemo, &saveh);
if (i)
{
OSD_Printf(OSD_ERROR "There were errors opening demo %d (code: %d).\n", g_whichDemo, i);
kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
return 0;
}
demo_hasdiffs = saveh.recdiffsp;
g_demo_totalCnt = saveh.reccnt;
demo_synccompress = saveh.synccompress;
demo_hasseeds = demo_synccompress&2;
demo_synccompress &= 1;
@ -107,20 +121,6 @@ int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
totalclock = ototalclock = lockclock = 0;
return 1;
}
else
{
OSD_Printf(OSD_ERROR "There were errors opening demo %d (code: %d).\n", g_whichDemo, i);
kclose(g_demo_recFilePtr);
return 0;
}
#if 0
corrupt:
OSD_Printf(OSD_ERROR "Demo %d header is corrupt.\n",g_whichDemo);
ud.reccnt = 0;
kclose(g_demo_recFilePtr);
return 0;
#endif
}
#if KRANDDEBUG
@ -133,7 +133,11 @@ void G_OpenDemoWrite(void)
char d[14];
int32_t i, demonum=1;
if (ud.recstat == 2) kclose(g_demo_recFilePtr);
if (ud.recstat == 2)
{
kclose(g_demo_recFilePtr);
g_demo_recFilePtr = -1;
}
if ((g_player[myconnectindex].ps->gm&MODE_GAME) && g_player[myconnectindex].ps->dead_flag)
{
@ -178,7 +182,7 @@ void G_OpenDemoWrite(void)
if ((g_demo_filePtr = Bfopen(d,"wb")) == NULL) return;
i=sv_saveandmakesnapshot(g_demo_filePtr, demorec_diffs_cvar, demorec_diffcompress_cvar,
i=sv_saveandmakesnapshot(g_demo_filePtr, -1, demorec_diffs_cvar, demorec_diffcompress_cvar,
demorec_synccompress_cvar|(demorec_seeds_cvar<<1));
if (i)
{
@ -260,8 +264,9 @@ void G_CloseDemoWrite(void)
fwrite("EnD!", 4, 1, g_demo_filePtr);
if (fseek(g_demo_filePtr, 20, SEEK_SET))
perror("G_CloseDemoWrite: fseek");
// lastly, we need to write the number of written recsyncs to the demo file
if (fseek(g_demo_filePtr, offsetof(savehead_t, reccnt), SEEK_SET))
perror("G_CloseDemoWrite: final fseek");
else
fwrite(&g_demo_cnt, sizeof(g_demo_cnt), 1, g_demo_filePtr);
@ -411,7 +416,6 @@ RECHECK:
}
else
{
// j = sv_loadsnapshot(g_demo_recFilePtr, &g_demo_totalCnt);
j = doupdatestate(1);
if (!j)
{
@ -486,7 +490,7 @@ corrupt:
nextdemo:
foundemo = 0;
ud.reccnt = 0;
kclose(g_demo_recFilePtr);
kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
g_player[myconnectindex].ps->gm |= MODE_MENU;
if (g_demo_goalCnt>0)
{
@ -502,7 +506,7 @@ nextdemo:
TRAVERSE_CONNECT(j)
{
copybufbyte(&recsync[bigi], &inputfifo[0][j], sizeof(input_t));
Bmemcpy(&inputfifo[0][j], &recsync[bigi], sizeof(input_t));
bigi++;
ud.reccnt--;
}
@ -663,13 +667,13 @@ nextdemo:
#if KRANDDEBUG
krd_print("krandplay.log");
#endif
kclose(g_demo_recFilePtr);
kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
}
return 0;
}
}
ud.multimode = numplayers; // fixes 2 infinite loops after watching demo
kclose(g_demo_recFilePtr);
kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
#if 0
{

View file

@ -43,7 +43,6 @@ extern int32_t g_demo_showStats;
extern int32_t g_demo_soundToggle;
extern int32_t g_demo_totalCnt;
int32_t G_OpenDemoRead(int32_t g_whichDemo);
int32_t G_PlaybackDemo(void);
void demo_preparewarp(void);
void G_CloseDemoWrite(void);

View file

@ -7784,9 +7784,16 @@ FAKE_F3:
/* inputloc = Bstrlen(&ud.savegame[g_lastSaveSlot][0]);
g_currentMenu = 360+g_lastSaveSlot;
probey = g_lastSaveSlot; */
if ((g_netServer || ud.multimode > 1))
G_SavePlayer(-1-(g_lastSaveSlot));
else G_SavePlayer(g_lastSaveSlot);
if (g_netServer || ud.multimode > 1)
{
Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "MULTIPLAYER SAVING NOT SUPPORTED YET");
P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
//G_SavePlayer(-1-(g_lastSaveSlot));
}
else
{
G_SavePlayer(g_lastSaveSlot);
}
}
}
@ -7844,10 +7851,13 @@ FAKE_F3:
KB_ClearKeysDown();
FX_StopAllSounds();
if ((g_netServer || ud.multimode > 1))
if (g_netServer || ud.multimode > 1)
{
G_LoadPlayer(-1-g_lastSaveSlot);
g_player[myconnectindex].ps->gm = MODE_GAME;
Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "MULTIPLAYER LOADING NOT SUPPORTED YET");
P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
// G_LoadPlayer(-1-g_lastSaveSlot);
// g_player[myconnectindex].ps->gm = MODE_GAME;
}
else
{

View file

@ -34,7 +34,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <sys/stat.h>
extern char inputloc;
extern int32_t g_demo_recFilePtr;
int16_t g_skillSoundID=-1;
int32_t probey=0;
static int32_t lastsavehead=0,last_menu_pos=0,last_menu,sh,onbar,buttonstat;
@ -472,10 +471,11 @@ static void modval(int32_t min, int32_t max,int32_t *p,int32_t dainc,int32_t dam
#define MWIN(X) rotatesprite( 320<<15,200<<15,X,0,MENUSCREEN,-16,0,10+64,0,0,xdim-1,ydim-1)
#define MWINXY(X,OX,OY) rotatesprite( ( 320+(OX) )<<15, ( 200+(OY) )<<15,X,0,MENUSCREEN,-16,0,10+64,0,0,xdim-1,ydim-1)
extern int32_t G_LoadSaveHeader(char spot,struct savehead_ *saveh);
//extern int32_t G_LoadSaveHeader(char spot,struct savehead_ *saveh);
#pragma pack(push,1)
static struct savehead_ savehead;
static savehead_t savehead;
//static struct savehead_ savehead;
#pragma pack(pop)
//static int32_t volnum,levnum,plrskl,numplr;
@ -559,7 +559,7 @@ void G_CheckPlayerColor(int32_t *color, int32_t prev_color)
static void Menus_LoadSave_DisplayCommon1(void)
{
if (lastsavehead != probey)
G_LoadSaveHeader(probey,&savehead);
G_LoadSaveHeaderNew(probey, &savehead);
lastsavehead = probey;
rotatesprite(101<<16,97<<16,65536L>>1,512,TILE_LOADSHOT,-32,0,4+10+64,0,0,xdim-1,ydim-1);
@ -567,9 +567,9 @@ static void Menus_LoadSave_DisplayCommon1(void)
if (ud.savegame[probey][20] == 32)
{
menutext(40,70,0,0,"OLD VERSION");
Bsprintf(tempbuf,"SAVED: %d", savehead.byteversion);
Bsprintf(tempbuf,"SAVED: %d.%d.%d", savehead.majorver, savehead.minorver, savehead.bytever);
mgametext(40,82,tempbuf,0,2+8+16);
Bsprintf(tempbuf,"OUR: %d", BYTEVERSION);
Bsprintf(tempbuf,"OUR: %d.%d.%d", SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION);
mgametext(40+16,92,tempbuf,0,2+8+16);
}
}
@ -1342,10 +1342,13 @@ void M_DisplayMenus(void)
KB_ClearKeysDown();
FX_StopAllSounds();
if ((g_netServer || ud.multimode > 1))
if (g_netServer || ud.multimode > 1)
{
G_LoadPlayer(-1-g_lastSaveSlot);
g_player[myconnectindex].ps->gm = MODE_GAME;
Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "MULTIPLAYER LOADING NOT SUPPORTED YET");
P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
// G_LoadPlayer(-1-g_lastSaveSlot);
// g_player[myconnectindex].ps->gm = MODE_GAME;
}
else
{
@ -1477,10 +1480,11 @@ void M_DisplayMenus(void)
M_DisplaySaveGameList();
Bsprintf(tempbuf,"PLAYERS: %-2d ",savehead.numplr);
Bsprintf(tempbuf,"PLAYERS: %-2d ",savehead.numplayers);
mgametext(160,156,tempbuf,0,2+8+16);
Bsprintf(tempbuf,"EPISODE: %-2d / LEVEL: %-2d / SKILL: %-2d",1+savehead.volnum,1+savehead.levnum,savehead.plrskl);
Bsprintf(tempbuf,"EPISODE: %-2d / LEVEL: %-2d / SKILL: %-2d",
1+savehead.volnum, 1+savehead.levnum, savehead.skill);
mgametext(160,168,tempbuf,0,2+8+16);
if (savehead.volnum == 0 && savehead.levnum == 7)
@ -4740,9 +4744,16 @@ cheat_for_port_credits:
ud.savegame[g_currentMenu-360][20] = 127;
}
if ((g_netServer || ud.multimode > 1))
G_SavePlayer(-1-(g_currentMenu-360));
else G_SavePlayer(g_currentMenu-360);
if (g_netServer || ud.multimode > 1)
{
Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "MULTIPLAYER SAVING NOT SUPPORTED YET");
P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
//G_SavePlayer(-1-(g_currentMenu-360));
}
else
{
G_SavePlayer(g_currentMenu-360);
}
g_lastSaveSlot = g_currentMenu-360;
g_player[myconnectindex].ps->gm = MODE_GAME;
@ -4773,9 +4784,10 @@ cheat_for_port_credits:
{
Menus_LoadSave_DisplayCommon1();
Bsprintf(tempbuf,"PLAYERS: %-2d ",savehead.numplr);
Bsprintf(tempbuf,"PLAYERS: %-2d ", savehead.numplayers);
mgametext(160,156,tempbuf,0,2+8+16);
Bsprintf(tempbuf,"EPISODE: %-2d / LEVEL: %-2d / SKILL: %-2d",1+savehead.volnum,1+savehead.levnum,savehead.plrskl);
Bsprintf(tempbuf,"EPISODE: %-2d / LEVEL: %-2d / SKILL: %-2d",
1+savehead.volnum, 1+savehead.levnum, savehead.skill);
mgametext(160,168,tempbuf,0,2+8+16);
if (savehead.volnum == 0 && savehead.levnum == 7)
mgametext(160,180,savehead.boardfn,0,2+8+16);

View file

@ -27,14 +27,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern char inputloc;
extern int16_t g_skillSoundID;
extern int32_t g_demo_recFilePtr;
extern int32_t g_lastSaveSlot;
extern int32_t g_quitDeadline;
extern int32_t probey;
extern int32_t voting;
int32_t G_LoadSaveHeader(char spot,struct savehead_ *saveh);
int32_t menutext_(int32_t x,int32_t y,int32_t s,int32_t p,char *t,int32_t bits);
void ChangeToMenu(int32_t cm);
void G_CheckPlayerColor(int32_t *color,int32_t prev_color);
void M_DisplayMenus(void);
#endif

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __savegame_h__
#define __savegame_h__
#define SV_MAJOR_VER 1
#define SV_MINOR_VER 1
#pragma pack(push,1)
# if 0
struct savehead_
{
char name[21];
@ -31,17 +35,41 @@ struct savehead_
int32_t numplr,volnum,levnum,plrskl;
char boardfn[BMAX_PATH];
};
# endif
typedef struct
{
char headerstr[11];
uint8_t majorver, minorver, ptrsize;
uint16_t bytever;
// 16 bytes
uint8_t comprthres;
uint8_t recdiffsp, diffcompress, synccompress;
// 4 bytes
int32_t reccnt, snapsiz;
// 8 bytes
char savename[22]; // should be of the same length as ud.savegame[i]
uint8_t numplayers, volnum, levnum, skill;
char boardfn[256]; // BMAX_PATH
// 282 bytes
} savehead_t; // 310 bytes
#pragma pack(pop)
int32_t sv_updatestate(int32_t frominit);
int32_t sv_readdiff(int32_t fil);
uint32_t sv_writediff(FILE *fil);
int32_t sv_loadsnapshot(int32_t fil,int32_t *ret_hasdiffs,int32_t *ret_demoticcnt,int32_t *ret_synccompress);
int32_t sv_saveandmakesnapshot(FILE *fil,int32_t recdiffs,int32_t diffcompress,int32_t synccompress);
int32_t sv_loadheader(int32_t fil, int32_t spot, savehead_t *h);
int32_t sv_loadsnapshot(int32_t fil, int32_t spot, savehead_t *h);
int32_t sv_saveandmakesnapshot(FILE *fil, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress);
void sv_freemem();
int32_t G_SavePlayer(int32_t spot);
int32_t G_LoadPlayer(int32_t spot);
int32_t G_LoadSaveHeader(char spot,struct savehead_ *saveh);
int32_t G_LoadSaveHeaderNew(int32_t spot, savehead_t *saveh);
//int32_t G_LoadSaveHeader(char spot,struct savehead_ *saveh);
void ReadSaveGameHeaders(void);
extern char *bitptr;