Make save_p / savebuffers not global

This caused some scary issues with P_SaveNetGame the other day, and it's making ACS net sync harder. Let's just cut this off right now.

Also fixed some scary mix-ups in some of the Lua archiving code.
This commit is contained in:
Sally Coolatta 2022-12-23 08:32:01 -05:00
parent 3101cf25cd
commit 8bdb5bdb77
11 changed files with 1976 additions and 1964 deletions

View file

@ -1143,28 +1143,28 @@ static boolean SV_ResendingSavegameToAnyone(void)
static void SV_SendSaveGame(INT32 node, boolean resending) static void SV_SendSaveGame(INT32 node, boolean resending)
{ {
size_t length, compressedlen; size_t length, compressedlen;
UINT8 *savebuffer; savebuffer_t save;
UINT8 *compressedsave; UINT8 *compressedsave;
UINT8 *buffertosend; UINT8 *buffertosend;
// first save it in a malloced buffer // first save it in a malloced buffer
savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); save.buffer = (UINT8 *)malloc(SAVEGAMESIZE);
if (!savebuffer) if (!save.buffer)
{ {
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
return; return;
} }
// Leave room for the uncompressed length. // Leave room for the uncompressed length.
save_p = savebuffer + sizeof(UINT32); save.p = save.buffer + sizeof(UINT32);
P_SaveNetGame(resending); P_SaveNetGame(&save, resending);
length = save_p - savebuffer; length = save.p - save.buffer;
if (length > SAVEGAMESIZE) if (length > SAVEGAMESIZE)
{ {
free(savebuffer); free(save.buffer);
save_p = NULL; save.p = NULL;
I_Error("Savegame buffer overrun"); I_Error("Savegame buffer overrun");
} }
@ -1178,11 +1178,11 @@ static void SV_SendSaveGame(INT32 node, boolean resending)
} }
// Attempt to compress it. // Attempt to compress it.
if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) if((compressedlen = lzf_compress(save.buffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1)))
{ {
// Compressing succeeded; send compressed data // Compressing succeeded; send compressed data
free(savebuffer); free(save.buffer);
// State that we're compressed. // State that we're compressed.
buffertosend = compressedsave; buffertosend = compressedsave;
@ -1196,12 +1196,12 @@ static void SV_SendSaveGame(INT32 node, boolean resending)
free(compressedsave); free(compressedsave);
// State that we're not compressed // State that we're not compressed
buffertosend = savebuffer; buffertosend = save.buffer;
WRITEUINT32(savebuffer, 0); WRITEUINT32(save.buffer, 0);
} }
AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0); AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0);
save_p = NULL; save.p = NULL;
// Remember when we started sending the savegame so we can handle timeouts // Remember when we started sending the savegame so we can handle timeouts
sendingsavegame[node] = true; sendingsavegame[node] = true;
@ -1215,7 +1215,7 @@ static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SA
static void SV_SavedGame(void) static void SV_SavedGame(void)
{ {
size_t length; size_t length;
UINT8 *savebuffer; savebuffer_t save;
char tmpsave[256]; char tmpsave[256];
if (!cv_dumpconsistency.value) if (!cv_dumpconsistency.value)
@ -1224,29 +1224,29 @@ static void SV_SavedGame(void)
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
// first save it in a malloced buffer // first save it in a malloced buffer
save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); save.p = save.buffer = (UINT8 *)malloc(SAVEGAMESIZE);
if (!save_p) if (!save.p)
{ {
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
return; return;
} }
P_SaveNetGame(false); P_SaveNetGame(&save, false);
length = save_p - savebuffer; length = save.p - save.buffer;
if (length > SAVEGAMESIZE) if (length > SAVEGAMESIZE)
{ {
free(savebuffer); free(save.buffer);
save_p = NULL; save.p = NULL;
I_Error("Savegame buffer overrun"); I_Error("Savegame buffer overrun");
} }
// then save it! // then save it!
if (!FIL_WriteFile(tmpsave, savebuffer, length)) if (!FIL_WriteFile(tmpsave, save.buffer, length))
CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave);
free(savebuffer); free(save.buffer);
save_p = NULL; save.p = NULL;
} }
#undef TMPSAVENAME #undef TMPSAVENAME
@ -1256,13 +1256,13 @@ static void SV_SavedGame(void)
static void CL_LoadReceivedSavegame(boolean reloading) static void CL_LoadReceivedSavegame(boolean reloading)
{ {
UINT8 *savebuffer = NULL; savebuffer_t save;
size_t length, decompressedlen; size_t length, decompressedlen;
char tmpsave[256]; char tmpsave[256];
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
length = FIL_ReadFile(tmpsave, &savebuffer); length = FIL_ReadFile(tmpsave, &save.buffer);
CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length));
if (!length) if (!length)
@ -1271,16 +1271,16 @@ static void CL_LoadReceivedSavegame(boolean reloading)
return; return;
} }
save_p = savebuffer; save.p = save.buffer;
// Decompress saved game if necessary. // Decompress saved game if necessary.
decompressedlen = READUINT32(save_p); decompressedlen = READUINT32(save.p);
if(decompressedlen > 0) if(decompressedlen > 0)
{ {
UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL);
lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); lzf_decompress(save.p, length - sizeof(UINT32), decompressedbuffer, decompressedlen);
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = savebuffer = decompressedbuffer; save.p = save.buffer = decompressedbuffer;
} }
paused = false; paused = false;
@ -1290,7 +1290,7 @@ static void CL_LoadReceivedSavegame(boolean reloading)
automapactive = false; automapactive = false;
// load a base level // load a base level
if (P_LoadNetGame(reloading)) if (P_LoadNetGame(&save, reloading))
{ {
if (!reloading) if (!reloading)
{ {
@ -1312,8 +1312,8 @@ static void CL_LoadReceivedSavegame(boolean reloading)
} }
// done // done
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = NULL; save.p = NULL;
if (unlink(tmpsave) == -1) if (unlink(tmpsave) == -1)
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
consistancy[gametic%BACKUPTICS] = Consistancy(); consistancy[gametic%BACKUPTICS] = Consistancy();
@ -6064,6 +6064,7 @@ void CL_ClearRewinds(void)
rewind_t *CL_SaveRewindPoint(size_t demopos) rewind_t *CL_SaveRewindPoint(size_t demopos)
{ {
savebuffer_t save;
rewind_t *rewind; rewind_t *rewind;
if (rewindhead && rewindhead->leveltime + REWIND_POINT_INTERVAL > leveltime) if (rewindhead && rewindhead->leveltime + REWIND_POINT_INTERVAL > leveltime)
@ -6073,8 +6074,10 @@ rewind_t *CL_SaveRewindPoint(size_t demopos)
if (!rewind) if (!rewind)
return NULL; return NULL;
save_p = rewind->savebuffer; save.buffer = save.p = rewind->savebuffer;
P_SaveNetGame(false);
P_SaveNetGame(&save, false);
rewind->leveltime = leveltime; rewind->leveltime = leveltime;
rewind->next = rewindhead; rewind->next = rewindhead;
rewind->demopos = demopos; rewind->demopos = demopos;
@ -6085,6 +6088,7 @@ rewind_t *CL_SaveRewindPoint(size_t demopos)
rewind_t *CL_RewindToTime(tic_t time) rewind_t *CL_RewindToTime(tic_t time)
{ {
savebuffer_t save;
rewind_t *rewind; rewind_t *rewind;
while (rewindhead && rewindhead->leveltime > time) while (rewindhead && rewindhead->leveltime > time)
@ -6097,8 +6101,10 @@ rewind_t *CL_RewindToTime(tic_t time)
if (!rewindhead) if (!rewindhead)
return NULL; return NULL;
save_p = rewindhead->savebuffer; save.buffer = save.p = rewindhead->savebuffer;
P_LoadNetGame(false);
P_LoadNetGame(&save, false);
wipegamestate = gamestate; // No fading back in! wipegamestate = gamestate; // No fading back in!
timeinmap = leveltime; timeinmap = leveltime;

View file

@ -5776,10 +5776,9 @@ static void Command_Togglemodified_f(void)
modifiedgame = !modifiedgame; modifiedgame = !modifiedgame;
} }
extern UINT8 *save_p;
static void Command_Archivetest_f(void) static void Command_Archivetest_f(void)
{ {
UINT8 *buf; savebuffer_t save;
UINT32 i, wrote; UINT32 i, wrote;
thinker_t *th; thinker_t *th;
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)
@ -5795,28 +5794,28 @@ static void Command_Archivetest_f(void)
((mobj_t *)th)->mobjnum = i++; ((mobj_t *)th)->mobjnum = i++;
// allocate buffer // allocate buffer
buf = save_p = ZZ_Alloc(1024); save.buffer = save.p = ZZ_Alloc(1024);
// test archive // test archive
CONS_Printf("LUA_Archive...\n"); CONS_Printf("LUA_Archive...\n");
LUA_Archive(&save_p); LUA_Archive(&save.p, true);
WRITEUINT8(save_p, 0x7F); WRITEUINT8(save.p, 0x7F);
wrote = (UINT32)(save_p-buf); wrote = (UINT32)(save.p - save.buffer);
// clear Lua state, so we can really see what happens! // clear Lua state, so we can really see what happens!
CONS_Printf("Clearing state!\n"); CONS_Printf("Clearing state!\n");
LUA_ClearExtVars(); LUA_ClearExtVars();
// test unarchive // test unarchive
save_p = buf; save.p = save.buffer;
CONS_Printf("LUA_UnArchive...\n"); CONS_Printf("LUA_UnArchive...\n");
LUA_UnArchive(&save_p); LUA_UnArchive(&save.p, true);
i = READUINT8(save_p); i = READUINT8(save.p);
if (i != 0x7F || wrote != (UINT32)(save_p-buf)) if (i != 0x7F || wrote != (UINT32)(save.p - save.buffer))
CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save_p-buf)); CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save.p - save.buffer));
// free buffer // free buffer
Z_Free(buf); Z_Free(save.buffer);
CONS_Printf("Done. No crash.\n"); CONS_Printf("Done. No crash.\n");
} }
#endif #endif

View file

@ -2502,7 +2502,7 @@ void G_BeginRecording(void)
// player lua vars, always saved even if empty // player lua vars, always saved even if empty
if (demoflags & DF_LUAVARS) if (demoflags & DF_LUAVARS)
LUA_Archive(&demo_p); LUA_Archive(&demo_p, false);
memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldcmd,0,sizeof(oldcmd));
memset(&oldghost,0,sizeof(oldghost)); memset(&oldghost,0,sizeof(oldghost));
@ -3366,7 +3366,7 @@ void G_DoPlayDemo(char *defdemoname)
LUA_ClearState(); LUA_ClearState();
// No modeattacking check, DF_LUAVARS won't be present here. // No modeattacking check, DF_LUAVARS won't be present here.
LUA_UnArchive(&demo_p); LUA_UnArchive(&demo_p, false);
} }
splitscreen = 0; splitscreen = 0;

View file

@ -343,8 +343,6 @@ boolean precache = true; // if true, load all graphics at start
INT16 prevmap, nextmap; INT16 prevmap, nextmap;
static UINT8 *savebuffer;
static void weaponPrefChange(void); static void weaponPrefChange(void);
static void weaponPrefChange2(void); static void weaponPrefChange2(void);
static void weaponPrefChange3(void); static void weaponPrefChange3(void);
@ -4311,6 +4309,7 @@ void G_LoadGameData(void)
UINT32 versionID; UINT32 versionID;
UINT8 versionMinor; UINT8 versionMinor;
UINT8 rtemp; UINT8 rtemp;
savebuffer_t save;
//For records //For records
UINT32 numgamedatamapheaders; UINT32 numgamedatamapheaders;
@ -4339,7 +4338,7 @@ void G_LoadGameData(void)
return; return;
} }
length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer); length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &save.buffer);
if (!length) if (!length)
{ {
// No gamedata. We can save a new one. // No gamedata. We can save a new one.
@ -4347,35 +4346,35 @@ void G_LoadGameData(void)
return; return;
} }
save_p = savebuffer; save.p = save.buffer;
// Version check // Version check
versionID = READUINT32(save_p); versionID = READUINT32(save.p);
if (versionID != GD_VERSIONCHECK) if (versionID != GD_VERSIONCHECK)
{ {
const char *gdfolder = "the Ring Racers folder"; const char *gdfolder = "the Ring Racers folder";
if (strcmp(srb2home,".")) if (strcmp(srb2home,"."))
gdfolder = srb2home; gdfolder = srb2home;
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = NULL; save.p = NULL;
I_Error("Game data is not for Ring Racers v2.0.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); I_Error("Game data is not for Ring Racers v2.0.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
} }
versionMinor = READUINT8(save_p); versionMinor = READUINT8(save.p);
if (versionMinor > GD_VERSIONMINOR) if (versionMinor > GD_VERSIONMINOR)
{ {
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = NULL; save.p = NULL;
I_Error("Game data is from the future! (expected %d, got %d)", GD_VERSIONMINOR, versionMinor); I_Error("Game data is from the future! (expected %d, got %d)", GD_VERSIONMINOR, versionMinor);
} }
gamedata->totalplaytime = READUINT32(save_p); gamedata->totalplaytime = READUINT32(save.p);
gamedata->matchesplayed = READUINT32(save_p); gamedata->matchesplayed = READUINT32(save.p);
{ {
// Quick & dirty hash for what mod this save file is for. // Quick & dirty hash for what mod this save file is for.
UINT32 modID = READUINT32(save_p); UINT32 modID = READUINT32(save.p);
UINT32 expectedID = quickncasehash(timeattackfolder, 64); UINT32 expectedID = quickncasehash(timeattackfolder, 64);
if (modID != expectedID) if (modID != expectedID)
@ -4388,34 +4387,34 @@ void G_LoadGameData(void)
// To save space, use one bit per collected/achieved/unlocked flag // To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < MAXEMBLEMS;) for (i = 0; i < MAXEMBLEMS;)
{ {
rtemp = READUINT8(save_p); rtemp = READUINT8(save.p);
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
gamedata->collected[j+i] = ((rtemp >> j) & 1); gamedata->collected[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
for (i = 0; i < MAXUNLOCKABLES;) for (i = 0; i < MAXUNLOCKABLES;)
{ {
rtemp = READUINT8(save_p); rtemp = READUINT8(save.p);
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
gamedata->unlocked[j+i] = ((rtemp >> j) & 1); gamedata->unlocked[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
for (i = 0; i < MAXUNLOCKABLES;) for (i = 0; i < MAXUNLOCKABLES;)
{ {
rtemp = READUINT8(save_p); rtemp = READUINT8(save.p);
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
gamedata->unlockpending[j+i] = ((rtemp >> j) & 1); gamedata->unlockpending[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
for (i = 0; i < MAXCONDITIONSETS;) for (i = 0; i < MAXCONDITIONSETS;)
{ {
rtemp = READUINT8(save_p); rtemp = READUINT8(save.p);
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
gamedata->achieved[j+i] = ((rtemp >> j) & 1); gamedata->achieved[j+i] = ((rtemp >> j) & 1);
i += j; i += j;
} }
gamedata->challengegridwidth = READUINT16(save_p); gamedata->challengegridwidth = READUINT16(save.p);
Z_Free(gamedata->challengegrid); Z_Free(gamedata->challengegrid);
if (gamedata->challengegridwidth) if (gamedata->challengegridwidth)
{ {
@ -4424,7 +4423,7 @@ void G_LoadGameData(void)
PU_STATIC, NULL); PU_STATIC, NULL);
for (i = 0; i < (gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT); i++) for (i = 0; i < (gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT); i++)
{ {
gamedata->challengegrid[i] = READUINT8(save_p); gamedata->challengegrid[i] = READUINT8(save.p);
} }
} }
else else
@ -4432,10 +4431,10 @@ void G_LoadGameData(void)
gamedata->challengegrid = NULL; gamedata->challengegrid = NULL;
} }
gamedata->timesBeaten = READUINT32(save_p); gamedata->timesBeaten = READUINT32(save.p);
// Main records // Main records
numgamedatamapheaders = READUINT32(save_p); numgamedatamapheaders = READUINT32(save.p);
if (numgamedatamapheaders >= NEXTMAP_SPECIAL) if (numgamedatamapheaders >= NEXTMAP_SPECIAL)
goto datacorrupt; goto datacorrupt;
@ -4446,12 +4445,12 @@ void G_LoadGameData(void)
tic_t rectime; tic_t rectime;
tic_t reclap; tic_t reclap;
READSTRINGN(save_p, mapname, sizeof(mapname)); READSTRINGN(save.p, mapname, sizeof(mapname));
mapnum = G_MapNumber(mapname); mapnum = G_MapNumber(mapname);
rtemp = READUINT8(save_p); rtemp = READUINT8(save.p);
rectime = (tic_t)READUINT32(save_p); rectime = (tic_t)READUINT32(save.p);
reclap = (tic_t)READUINT32(save_p); reclap = (tic_t)READUINT32(save.p);
if (mapnum < nummapheaders && mapheaderinfo[mapnum]) if (mapnum < nummapheaders && mapheaderinfo[mapnum])
{ {
@ -4477,8 +4476,8 @@ void G_LoadGameData(void)
} }
// done // done
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = NULL; save.p = NULL;
// Don't consider loaded until it's a success! // Don't consider loaded until it's a success!
// It used to do this much earlier, but this would cause the gamedata to // It used to do this much earlier, but this would cause the gamedata to
@ -4498,8 +4497,8 @@ void G_LoadGameData(void)
if (strcmp(srb2home,".")) if (strcmp(srb2home,"."))
gdfolder = srb2home; gdfolder = srb2home;
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = NULL; save.p = NULL;
I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
} }
@ -4512,6 +4511,7 @@ void G_SaveGameData(void)
size_t length; size_t length;
INT32 i, j; INT32 i, j;
UINT8 btemp; UINT8 btemp;
savebuffer_t save;
if (!gamedata->loaded) if (!gamedata->loaded)
return; // If never loaded (-nodata), don't save return; // If never loaded (-nodata), don't save
@ -4531,8 +4531,8 @@ void G_SaveGameData(void)
} }
length += nummapheaders * (MAXMAPLUMPNAME+1+4+4); length += nummapheaders * (MAXMAPLUMPNAME+1+4+4);
save_p = savebuffer = (UINT8 *)malloc(length); save.p = save.buffer = (UINT8 *)malloc(length);
if (!save_p) if (!save.p)
{ {
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
return; return;
@ -4540,11 +4540,11 @@ void G_SaveGameData(void)
// Version test // Version test
WRITEUINT32(save_p, GD_VERSIONCHECK); // 4 WRITEUINT32(save.p, GD_VERSIONCHECK); // 4
WRITEUINT8(save_p, GD_VERSIONMINOR); // 1 WRITEUINT8(save.p, GD_VERSIONMINOR); // 1
WRITEUINT32(save_p, gamedata->totalplaytime); // 4 WRITEUINT32(save.p, gamedata->totalplaytime); // 4
WRITEUINT32(save_p, gamedata->matchesplayed); // 4 WRITEUINT32(save.p, gamedata->matchesplayed); // 4
WRITEUINT32(save_p, quickncasehash(timeattackfolder, 64)); WRITEUINT32(save.p, quickncasehash(timeattackfolder, 64));
// To save space, use one bit per collected/achieved/unlocked flag // To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < MAXEMBLEMS;) // MAXEMBLEMS * 1; for (i = 0; i < MAXEMBLEMS;) // MAXEMBLEMS * 1;
@ -4552,7 +4552,7 @@ void G_SaveGameData(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
btemp |= (gamedata->collected[j+i] << j); btemp |= (gamedata->collected[j+i] << j);
WRITEUINT8(save_p, btemp); WRITEUINT8(save.p, btemp);
i += j; i += j;
} }
@ -4562,7 +4562,7 @@ void G_SaveGameData(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
btemp |= (gamedata->unlocked[j+i] << j); btemp |= (gamedata->unlocked[j+i] << j);
WRITEUINT8(save_p, btemp); WRITEUINT8(save.p, btemp);
i += j; i += j;
} }
for (i = 0; i < MAXUNLOCKABLES;) for (i = 0; i < MAXUNLOCKABLES;)
@ -4570,7 +4570,7 @@ void G_SaveGameData(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
btemp |= (gamedata->unlockpending[j+i] << j); btemp |= (gamedata->unlockpending[j+i] << j);
WRITEUINT8(save_p, btemp); WRITEUINT8(save.p, btemp);
i += j; i += j;
} }
@ -4579,52 +4579,52 @@ void G_SaveGameData(void)
btemp = 0; btemp = 0;
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
btemp |= (gamedata->achieved[j+i] << j); btemp |= (gamedata->achieved[j+i] << j);
WRITEUINT8(save_p, btemp); WRITEUINT8(save.p, btemp);
i += j; i += j;
} }
if (gamedata->challengegrid) // 2 + gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT if (gamedata->challengegrid) // 2 + gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT
{ {
WRITEUINT16(save_p, gamedata->challengegridwidth); WRITEUINT16(save.p, gamedata->challengegridwidth);
for (i = 0; i < (gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT); i++) for (i = 0; i < (gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT); i++)
{ {
WRITEUINT8(save_p, gamedata->challengegrid[i]); WRITEUINT8(save.p, gamedata->challengegrid[i]);
} }
} }
else // 2 else // 2
{ {
WRITEUINT16(save_p, 0); WRITEUINT16(save.p, 0);
} }
WRITEUINT32(save_p, gamedata->timesBeaten); // 4 WRITEUINT32(save.p, gamedata->timesBeaten); // 4
// Main records // Main records
WRITEUINT32(save_p, nummapheaders); // 4 WRITEUINT32(save.p, nummapheaders); // 4
for (i = 0; i < nummapheaders; i++) // nummapheaders * (255+1+4+4) for (i = 0; i < nummapheaders; i++) // nummapheaders * (255+1+4+4)
{ {
// For figuring out which header to assing it to on load // For figuring out which header to assing it to on load
WRITESTRINGN(save_p, mapheaderinfo[i]->lumpname, MAXMAPLUMPNAME); WRITESTRINGN(save.p, mapheaderinfo[i]->lumpname, MAXMAPLUMPNAME);
WRITEUINT8(save_p, (mapheaderinfo[i]->mapvisited & MV_MAX)); WRITEUINT8(save.p, (mapheaderinfo[i]->mapvisited & MV_MAX));
if (mapheaderinfo[i]->mainrecord) if (mapheaderinfo[i]->mainrecord)
{ {
WRITEUINT32(save_p, mapheaderinfo[i]->mainrecord->time); WRITEUINT32(save.p, mapheaderinfo[i]->mainrecord->time);
WRITEUINT32(save_p, mapheaderinfo[i]->mainrecord->lap); WRITEUINT32(save.p, mapheaderinfo[i]->mainrecord->lap);
} }
else else
{ {
WRITEUINT32(save_p, 0); WRITEUINT32(save.p, 0);
WRITEUINT32(save_p, 0); WRITEUINT32(save.p, 0);
} }
} }
length = save_p - savebuffer; length = save.p - save.buffer;
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length); FIL_WriteFile(va(pandf, srb2home, gamedatafilename), save.buffer, length);
free(savebuffer); free(save.buffer);
save_p = savebuffer = NULL; save.p = save.buffer = NULL;
// Also save profiles here. // Also save profiles here.
PR_SaveProfiles(); PR_SaveProfiles();
@ -4641,6 +4641,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
size_t length; size_t length;
char vcheck[VERSIONSIZE]; char vcheck[VERSIONSIZE];
char savename[255]; char savename[255];
savebuffer_t save;
// memset savedata to all 0, fixes calling perfectly valid saves corrupt because of bots // memset savedata to all 0, fixes calling perfectly valid saves corrupt because of bots
memset(&savedata, 0, sizeof(savedata)); memset(&savedata, 0, sizeof(savedata));
@ -4655,18 +4656,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
else else
sprintf(savename, savegamename, slot); sprintf(savename, savegamename, slot);
length = FIL_ReadFile(savename, &savebuffer); length = FIL_ReadFile(savename, &save.buffer);
if (!length) if (!length)
{ {
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
return; return;
} }
save_p = savebuffer; save.p = save.buffer;
memset(vcheck, 0, sizeof (vcheck)); memset(vcheck, 0, sizeof (vcheck));
sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
if (strcmp((const char *)save_p, (const char *)vcheck)) if (strcmp((const char *)save.p, (const char *)vcheck))
{ {
#ifdef SAVEGAME_OTHERVERSIONS #ifdef SAVEGAME_OTHERVERSIONS
M_StartMessage(M_GetText("Save game from different version.\nYou can load this savegame, but\nsaving afterwards will be disabled.\n\nDo you want to continue anyway?\n\n(Press 'Y' to confirm)\n"), M_StartMessage(M_GetText("Save game from different version.\nYou can load this savegame, but\nsaving afterwards will be disabled.\n\nDo you want to continue anyway?\n\n(Press 'Y' to confirm)\n"),
@ -4676,15 +4677,15 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
M_ClearMenus(true); // so ESC backs out to title M_ClearMenus(true); // so ESC backs out to title
M_StartMessage(M_GetText("Save game from different version\n\nPress ESC\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("Save game from different version\n\nPress ESC\n"), NULL, MM_NOTHING);
Command_ExitGame_f(); Command_ExitGame_f();
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = savebuffer = NULL; save.p = save.buffer = NULL;
// no cheating! // no cheating!
memset(&savedata, 0, sizeof(savedata)); memset(&savedata, 0, sizeof(savedata));
#endif #endif
return; // bad version return; // bad version
} }
save_p += VERSIONSIZE; save.p += VERSIONSIZE;
if (demo.playback) // reset game engine if (demo.playback) // reset game engine
G_StopDemo(); G_StopDemo();
@ -4693,13 +4694,13 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
// automapactive = false; // automapactive = false;
// dearchive all the modifications // dearchive all the modifications
if (!P_LoadGame(mapoverride)) if (!P_LoadGame(&save, mapoverride))
{ {
M_ClearMenus(true); // so ESC backs out to title M_ClearMenus(true); // so ESC backs out to title
M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING);
Command_ExitGame_f(); Command_ExitGame_f();
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = savebuffer = NULL; save.p = save.buffer = NULL;
// no cheating! // no cheating!
memset(&savedata, 0, sizeof(savedata)); memset(&savedata, 0, sizeof(savedata));
@ -4707,13 +4708,13 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
} }
if (marathonmode) if (marathonmode)
{ {
marathontime = READUINT32(save_p); marathontime = READUINT32(save.p);
marathonmode |= READUINT8(save_p); marathonmode |= READUINT8(save.p);
} }
// done // done
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = savebuffer = NULL; save.p = save.buffer = NULL;
// gameaction = ga_nothing; // gameaction = ga_nothing;
// G_SetGamestate(GS_LEVEL); // G_SetGamestate(GS_LEVEL);
@ -4739,6 +4740,7 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
boolean saved; boolean saved;
char savename[256] = ""; char savename[256] = "";
const char *backup; const char *backup;
savebuffer_t save;
if (marathonmode) if (marathonmode)
strcpy(savename, liveeventbackup); strcpy(savename, liveeventbackup);
@ -4751,8 +4753,8 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
char name[VERSIONSIZE]; char name[VERSIONSIZE];
size_t length; size_t length;
save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); save.p = save.buffer = (UINT8 *)malloc(SAVEGAMESIZE);
if (!save_p) if (!save.p)
{ {
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
return; return;
@ -4760,22 +4762,22 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
memset(name, 0, sizeof (name)); memset(name, 0, sizeof (name));
sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION); sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION);
WRITEMEM(save_p, name, VERSIONSIZE); WRITEMEM(save.p, name, VERSIONSIZE);
P_SaveGame(mapnum); P_SaveGame(&save, mapnum);
if (marathonmode) if (marathonmode)
{ {
UINT32 writetime = marathontime; UINT32 writetime = marathontime;
if (!(marathonmode & MA_INGAME)) if (!(marathonmode & MA_INGAME))
writetime += TICRATE*5; // live event backup penalty because we don't know how long it takes to get to the next map writetime += TICRATE*5; // live event backup penalty because we don't know how long it takes to get to the next map
WRITEUINT32(save_p, writetime); WRITEUINT32(save.p, writetime);
WRITEUINT8(save_p, (marathonmode & ~MA_INIT)); WRITEUINT8(save.p, (marathonmode & ~MA_INIT));
} }
length = save_p - savebuffer; length = save.p - save.buffer;
saved = FIL_WriteFile(backup, savebuffer, length); saved = FIL_WriteFile(backup, save.buffer, length);
free(savebuffer); free(save.buffer);
save_p = savebuffer = NULL; save.p = save.buffer = NULL;
} }
gameaction = ga_nothing; gameaction = ga_nothing;
@ -4787,7 +4789,7 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
} }
#define BADSAVE goto cleanup; #define BADSAVE goto cleanup;
#define CHECKPOS if (save_p >= end_p) BADSAVE #define CHECKPOS if (save.p >= end_p) BADSAVE
void G_SaveGameOver(UINT32 slot, boolean modifylives) void G_SaveGameOver(UINT32 slot, boolean modifylives)
{ {
boolean saved = false; boolean saved = false;
@ -4795,6 +4797,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
char vcheck[VERSIONSIZE]; char vcheck[VERSIONSIZE];
char savename[255]; char savename[255];
const char *backup; const char *backup;
savebuffer_t save;
if (marathonmode) if (marathonmode)
strcpy(savename, liveeventbackup); strcpy(savename, liveeventbackup);
@ -4802,7 +4805,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
sprintf(savename, savegamename, slot); sprintf(savename, savegamename, slot);
backup = va("%s",savename); backup = va("%s",savename);
length = FIL_ReadFile(savename, &savebuffer); length = FIL_ReadFile(savename, &save.buffer);
if (!length) if (!length)
{ {
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
@ -4811,35 +4814,35 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
{ {
char temp[sizeof(timeattackfolder)]; char temp[sizeof(timeattackfolder)];
UINT8 *end_p = savebuffer + length; UINT8 *end_p = save.buffer + length;
UINT8 *lives_p; UINT8 *lives_p;
SINT8 pllives; SINT8 pllives;
save_p = savebuffer; save.p = save.buffer;
// Version check // Version check
memset(vcheck, 0, sizeof (vcheck)); memset(vcheck, 0, sizeof (vcheck));
sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE if (strcmp((const char *)save.p, (const char *)vcheck)) BADSAVE
save_p += VERSIONSIZE; save.p += VERSIONSIZE;
// P_UnArchiveMisc() // P_UnArchiveMisc()
(void)READINT16(save_p); (void)READINT16(save.p);
CHECKPOS CHECKPOS
(void)READUINT16(save_p); // emeralds (void)READUINT16(save.p); // emeralds
CHECKPOS CHECKPOS
READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to READSTRINGN(save.p, temp, sizeof(temp)); // mod it belongs to
if (strcmp(temp, timeattackfolder)) BADSAVE if (strcmp(temp, timeattackfolder)) BADSAVE
// P_UnArchivePlayer() // P_UnArchivePlayer()
CHECKPOS CHECKPOS
(void)READUINT16(save_p); (void)READUINT16(save.p);
CHECKPOS CHECKPOS
WRITEUINT8(save_p, numgameovers); WRITEUINT8(save.p, numgameovers);
CHECKPOS CHECKPOS
lives_p = save_p; lives_p = save.p;
pllives = READSINT8(save_p); // lives pllives = READSINT8(save.p); // lives
CHECKPOS CHECKPOS
if (modifylives && pllives < startinglivesbalance[numgameovers]) if (modifylives && pllives < startinglivesbalance[numgameovers])
{ {
@ -4847,28 +4850,28 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
WRITESINT8(lives_p, pllives); WRITESINT8(lives_p, pllives);
} }
(void)READINT32(save_p); // Score (void)READINT32(save.p); // Score
CHECKPOS CHECKPOS
(void)READINT32(save_p); // continues (void)READINT32(save.p); // continues
// File end marker check // File end marker check
CHECKPOS CHECKPOS
switch (READUINT8(save_p)) switch (READUINT8(save.p))
{ {
case 0xb7: case 0xb7:
{ {
UINT8 i, banksinuse; UINT8 i, banksinuse;
CHECKPOS CHECKPOS
banksinuse = READUINT8(save_p); banksinuse = READUINT8(save.p);
CHECKPOS CHECKPOS
if (banksinuse > NUM_LUABANKS) if (banksinuse > NUM_LUABANKS)
BADSAVE BADSAVE
for (i = 0; i < banksinuse; i++) for (i = 0; i < banksinuse; i++)
{ {
(void)READINT32(save_p); (void)READINT32(save.p);
CHECKPOS CHECKPOS
} }
if (READUINT8(save_p) != 0x1d) if (READUINT8(save.p) != 0x1d)
BADSAVE BADSAVE
} }
case 0x1d: case 0x1d:
@ -4878,7 +4881,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
} }
// done // done
saved = FIL_WriteFile(backup, savebuffer, length); saved = FIL_WriteFile(backup, save.buffer, length);
} }
cleanup: cleanup:
@ -4886,8 +4889,8 @@ cleanup:
CONS_Printf(M_GetText("Game saved.\n")); CONS_Printf(M_GetText("Game saved.\n"));
else if (!saved) else if (!saved)
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename));
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = savebuffer = NULL; save.p = save.buffer = NULL;
} }
#undef CHECKPOS #undef CHECKPOS

View file

@ -10,9 +10,10 @@
/// \file k_profiles.c /// \file k_profiles.c
/// \brief implements methods for profiles etc. /// \brief implements methods for profiles etc.
#include "doomtype.h"
#include "d_main.h" // pandf #include "d_main.h" // pandf
#include "byteptr.h" // READ/WRITE macros #include "byteptr.h" // READ/WRITE macros
#include "p_saveg.h" // save_p #include "p_saveg.h" // savebuffer_t
#include "m_misc.h" //FIL_WriteFile() #include "m_misc.h" //FIL_WriteFile()
#include "k_profiles.h" #include "k_profiles.h"
#include "z_zone.h" #include "z_zone.h"
@ -211,68 +212,67 @@ void PR_InitNewProfile(void)
PR_AddProfile(dprofile); PR_AddProfile(dprofile);
} }
static UINT8 *savebuffer;
void PR_SaveProfiles(void) void PR_SaveProfiles(void)
{ {
size_t length = 0; size_t length = 0;
const size_t headerlen = strlen(PROFILEHEADER); const size_t headerlen = strlen(PROFILEHEADER);
UINT8 i, j, k; UINT8 i, j, k;
savebuffer_t save;
save_p = savebuffer = (UINT8 *)malloc(sizeof(UINT32) + (numprofiles * sizeof(profile_t))); save.p = save.buffer = (UINT8 *)malloc(sizeof(UINT32) + (numprofiles * sizeof(profile_t)));
if (!save_p) if (!save.p)
{ {
I_Error("No more free memory for saving profiles\n"); I_Error("No more free memory for saving profiles\n");
return; return;
} }
// Add header. // Add header.
WRITESTRINGN(save_p, PROFILEHEADER, headerlen); WRITESTRINGN(save.p, PROFILEHEADER, headerlen);
WRITEUINT8(save_p, PROFILEVER); WRITEUINT8(save.p, PROFILEVER);
WRITEUINT8(save_p, numprofiles); WRITEUINT8(save.p, numprofiles);
for (i = 1; i < numprofiles; i++) for (i = 1; i < numprofiles; i++)
{ {
// Names. // Names.
WRITESTRINGN(save_p, profilesList[i]->profilename, PROFILENAMELEN); WRITESTRINGN(save.p, profilesList[i]->profilename, PROFILENAMELEN);
WRITESTRINGN(save_p, profilesList[i]->playername, MAXPLAYERNAME); WRITESTRINGN(save.p, profilesList[i]->playername, MAXPLAYERNAME);
// Character and colour. // Character and colour.
WRITESTRINGN(save_p, profilesList[i]->skinname, SKINNAMESIZE); WRITESTRINGN(save.p, profilesList[i]->skinname, SKINNAMESIZE);
WRITEUINT16(save_p, profilesList[i]->color); WRITEUINT16(save.p, profilesList[i]->color);
// Follower and colour. // Follower and colour.
WRITESTRINGN(save_p, profilesList[i]->follower, SKINNAMESIZE); WRITESTRINGN(save.p, profilesList[i]->follower, SKINNAMESIZE);
WRITEUINT16(save_p, profilesList[i]->followercolor); WRITEUINT16(save.p, profilesList[i]->followercolor);
// PWR. // PWR.
for (j = 0; j < PWRLV_NUMTYPES; j++) for (j = 0; j < PWRLV_NUMTYPES; j++)
{ {
WRITEUINT16(save_p, profilesList[i]->powerlevels[j]); WRITEUINT16(save.p, profilesList[i]->powerlevels[j]);
} }
// Consvars. // Consvars.
WRITEUINT8(save_p, profilesList[i]->kickstartaccel); WRITEUINT8(save.p, profilesList[i]->kickstartaccel);
// Controls. // Controls.
for (j = 0; j < num_gamecontrols; j++) for (j = 0; j < num_gamecontrols; j++)
{ {
for (k = 0; k < MAXINPUTMAPPING; k++) for (k = 0; k < MAXINPUTMAPPING; k++)
{ {
WRITEINT32(save_p, profilesList[i]->controls[j][k]); WRITEINT32(save.p, profilesList[i]->controls[j][k]);
} }
} }
} }
length = save_p - savebuffer; length = save.p - save.buffer;
if (!FIL_WriteFile(va(pandf, srb2home, PROFILESFILE), savebuffer, length)) if (!FIL_WriteFile(va(pandf, srb2home, PROFILESFILE), save.buffer, length))
{ {
free(savebuffer); free(save.buffer);
I_Error("Couldn't save profiles. Are you out of Disk space / playing in a protected folder?"); I_Error("Couldn't save profiles. Are you out of Disk space / playing in a protected folder?");
} }
free(savebuffer); free(save.buffer);
save_p = savebuffer = NULL; save.p = save.buffer = NULL;
} }
void PR_LoadProfiles(void) void PR_LoadProfiles(void)
@ -288,8 +288,9 @@ void PR_LoadProfiles(void)
gamecontroldefault, gamecontroldefault,
true true
); );
savebuffer_t save;
length = FIL_ReadFile(va(pandf, srb2home, PROFILESFILE), &savebuffer); length = FIL_ReadFile(va(pandf, srb2home, PROFILESFILE), &save.buffer);
if (!length) if (!length)
{ {
// No profiles. Add the default one. // No profiles. Add the default one.
@ -297,29 +298,29 @@ void PR_LoadProfiles(void)
return; return;
} }
save_p = savebuffer; save.p = save.buffer;
if (strncmp(PROFILEHEADER, (const char *)savebuffer, headerlen)) if (strncmp(PROFILEHEADER, (const char *)save.buffer, headerlen))
{ {
const char *gdfolder = "the Ring Racers folder"; const char *gdfolder = "the Ring Racers folder";
if (strcmp(srb2home,".")) if (strcmp(srb2home,"."))
gdfolder = srb2home; gdfolder = srb2home;
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = NULL; save.p = NULL;
I_Error("Not a valid Profile file.\nDelete %s (maybe in %s) and try again.", PROFILESFILE, gdfolder); I_Error("Not a valid Profile file.\nDelete %s (maybe in %s) and try again.", PROFILESFILE, gdfolder);
} }
save_p += headerlen; save.p += headerlen;
version = READUINT8(save_p); version = READUINT8(save.p);
if (version > PROFILEVER) if (version > PROFILEVER)
{ {
Z_Free(savebuffer); Z_Free(save.buffer);
save_p = NULL; save.p = NULL;
I_Error("Existing %s is from the future! (expected %d, got %d)", PROFILESFILE, PROFILEVER, version); I_Error("Existing %s is from the future! (expected %d, got %d)", PROFILESFILE, PROFILEVER, version);
} }
numprofiles = READUINT8(save_p); numprofiles = READUINT8(save.p);
if (numprofiles > MAXPROFILES) if (numprofiles > MAXPROFILES)
numprofiles = MAXPROFILES; numprofiles = MAXPROFILES;
@ -331,12 +332,12 @@ void PR_LoadProfiles(void)
profilesList[i]->version = PROFILEVER; profilesList[i]->version = PROFILEVER;
// Names. // Names.
READSTRINGN(save_p, profilesList[i]->profilename, PROFILENAMELEN); READSTRINGN(save.p, profilesList[i]->profilename, PROFILENAMELEN);
READSTRINGN(save_p, profilesList[i]->playername, MAXPLAYERNAME); READSTRINGN(save.p, profilesList[i]->playername, MAXPLAYERNAME);
// Character and colour. // Character and colour.
READSTRINGN(save_p, profilesList[i]->skinname, SKINNAMESIZE); READSTRINGN(save.p, profilesList[i]->skinname, SKINNAMESIZE);
profilesList[i]->color = READUINT16(save_p); profilesList[i]->color = READUINT16(save.p);
if (profilesList[i]->color == SKINCOLOR_NONE) if (profilesList[i]->color == SKINCOLOR_NONE)
{ {
@ -349,8 +350,8 @@ void PR_LoadProfiles(void)
} }
// Follower and colour. // Follower and colour.
READSTRINGN(save_p, profilesList[i]->follower, SKINNAMESIZE); READSTRINGN(save.p, profilesList[i]->follower, SKINNAMESIZE);
profilesList[i]->followercolor = READUINT16(save_p); profilesList[i]->followercolor = READUINT16(save.p);
if (profilesList[i]->followercolor == FOLLOWERCOLOR_MATCH if (profilesList[i]->followercolor == FOLLOWERCOLOR_MATCH
|| profilesList[i]->followercolor == FOLLOWERCOLOR_OPPOSITE) || profilesList[i]->followercolor == FOLLOWERCOLOR_OPPOSITE)
@ -367,7 +368,7 @@ void PR_LoadProfiles(void)
// PWR. // PWR.
for (j = 0; j < PWRLV_NUMTYPES; j++) for (j = 0; j < PWRLV_NUMTYPES; j++)
{ {
profilesList[i]->powerlevels[j] = READUINT16(save_p); profilesList[i]->powerlevels[j] = READUINT16(save.p);
if (profilesList[i]->powerlevels[j] < PWRLVRECORD_MIN if (profilesList[i]->powerlevels[j] < PWRLVRECORD_MIN
|| profilesList[i]->powerlevels[j] > PWRLVRECORD_MAX) || profilesList[i]->powerlevels[j] > PWRLVRECORD_MAX)
{ {
@ -377,7 +378,7 @@ void PR_LoadProfiles(void)
} }
// Consvars. // Consvars.
profilesList[i]->kickstartaccel = (boolean)READUINT8(save_p); profilesList[i]->kickstartaccel = (boolean)READUINT8(save.p);
// Controls. // Controls.
for (j = 0; j < num_gamecontrols; j++) for (j = 0; j < num_gamecontrols; j++)
@ -396,7 +397,7 @@ void PR_LoadProfiles(void)
for (k = 0; k < MAXINPUTMAPPING; k++) for (k = 0; k < MAXINPUTMAPPING; k++)
{ {
profilesList[i]->controls[j][k] = READINT32(save_p); profilesList[i]->controls[j][k] = READINT32(save.p);
} }
} }
} }

View file

@ -41,6 +41,8 @@ lua_State *gL = NULL;
int hook_defrosting; int hook_defrosting;
static UINT8 **lua_save_p = NULL; // FIXME: Remove this horrible hack
// List of internal libraries to load from SRB2 // List of internal libraries to load from SRB2
static lua_CFunction liblist[] = { static lua_CFunction liblist[] = {
LUA_EnumLib, // global metatable for enums LUA_EnumLib, // global metatable for enums
@ -1248,10 +1250,10 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{ {
polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex)); polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex));
if (!polyobj) if (!polyobj)
WRITEUINT8(save_p, ARCH_NULL); WRITEUINT8(*p, ARCH_NULL);
else { else {
WRITEUINT8(save_p, ARCH_POLYOBJ); WRITEUINT8(*p, ARCH_POLYOBJ);
WRITEUINT16(save_p, polyobj-PolyObjects); WRITEUINT16(*p, polyobj-PolyObjects);
} }
break; break;
} }
@ -1355,7 +1357,7 @@ static int NetArchive(lua_State *L)
int TABLESINDEX = lua_upvalueindex(1); int TABLESINDEX = lua_upvalueindex(1);
int i, n = lua_gettop(L); int i, n = lua_gettop(L);
for (i = 1; i <= n; i++) for (i = 1; i <= n; i++)
ArchiveValue(&save_p, TABLESINDEX, i); ArchiveValue(lua_save_p, TABLESINDEX, i);
return n; return n;
} }
@ -1517,7 +1519,7 @@ static UINT8 UnArchiveValue(UINT8 **p, int TABLESINDEX)
break; break;
} }
case ARCH_POLYOBJ: case ARCH_POLYOBJ:
LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ); LUA_PushUserdata(gL, &PolyObjects[READUINT16(*p)], META_POLYOBJ);
break; break;
case ARCH_SLOPE: case ARCH_SLOPE:
LUA_PushUserdata(gL, P_SlopeById(READUINT16(*p)), META_SLOPE); LUA_PushUserdata(gL, P_SlopeById(READUINT16(*p)), META_SLOPE);
@ -1568,7 +1570,7 @@ static int NetUnArchive(lua_State *L)
int TABLESINDEX = lua_upvalueindex(1); int TABLESINDEX = lua_upvalueindex(1);
int i, n = lua_gettop(L); int i, n = lua_gettop(L);
for (i = 1; i <= n; i++) for (i = 1; i <= n; i++)
UnArchiveValue(&save_p, TABLESINDEX); UnArchiveValue(lua_save_p, TABLESINDEX);
return n; return n;
} }
@ -1602,7 +1604,7 @@ static void UnArchiveTables(UINT8 **p)
lua_rawset(gL, -3); lua_rawset(gL, -3);
} }
metatableid = READUINT16(save_p); metatableid = READUINT16(*p);
if (metatableid) if (metatableid)
{ {
// setmetatable(table, registry.metatables[metatableid]) // setmetatable(table, registry.metatables[metatableid])
@ -1626,7 +1628,7 @@ void LUA_Step(void)
lua_gc(gL, LUA_GCSTEP, 1); lua_gc(gL, LUA_GCSTEP, 1);
} }
void LUA_Archive(UINT8 **p) void LUA_Archive(UINT8 **p, boolean network)
{ {
INT32 i; INT32 i;
thinker_t *th; thinker_t *th;
@ -1642,7 +1644,7 @@ void LUA_Archive(UINT8 **p)
ArchiveExtVars(p, &players[i], "player"); ArchiveExtVars(p, &players[i], "player");
} }
if (p == &save_p) if (network == true)
{ {
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
@ -1659,6 +1661,7 @@ void LUA_Archive(UINT8 **p)
WRITEUINT32(*p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. WRITEUINT32(*p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
lua_save_p = p;
LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode
} }
@ -1668,7 +1671,7 @@ void LUA_Archive(UINT8 **p)
lua_pop(gL, 1); // pop tables lua_pop(gL, 1); // pop tables
} }
void LUA_UnArchive(UINT8 **p) void LUA_UnArchive(UINT8 **p, boolean network)
{ {
UINT32 mobjnum; UINT32 mobjnum;
INT32 i; INT32 i;
@ -1684,7 +1687,7 @@ void LUA_UnArchive(UINT8 **p)
UnArchiveExtVars(p, &players[i]); UnArchiveExtVars(p, &players[i]);
} }
if (p == &save_p) if (network == true)
{ {
do { do {
mobjnum = READUINT32(*p); // read a mobjnum mobjnum = READUINT32(*p); // read a mobjnum
@ -1698,6 +1701,7 @@ void LUA_UnArchive(UINT8 **p)
} }
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
lua_save_p = p;
LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode
} }

View file

@ -53,8 +53,8 @@ void LUA_DumpFile(const char *filename);
#endif #endif
fixed_t LUA_EvalMath(const char *word); fixed_t LUA_EvalMath(const char *word);
void LUA_Step(void); void LUA_Step(void);
void LUA_Archive(UINT8 **p); void LUA_Archive(UINT8 **p, boolean network);
void LUA_UnArchive(UINT8 **p); void LUA_UnArchive(UINT8 **p, boolean network);
int LUA_PushGlobals(lua_State *L, const char *word); int LUA_PushGlobals(lua_State *L, const char *word);
int LUA_WriteGlobals(lua_State *L, const char *word); int LUA_WriteGlobals(lua_State *L, const char *word);

File diff suppressed because it is too large Load diff

View file

@ -21,10 +21,10 @@
// Persistent storage/archiving. // Persistent storage/archiving.
// These are the load / save game routines. // These are the load / save game routines.
void P_SaveGame(INT16 mapnum); void P_SaveGame(savebuffer_t *save, INT16 mapnum);
void P_SaveNetGame(boolean resending); void P_SaveNetGame(savebuffer_t *save, boolean resending);
boolean P_LoadGame(INT16 mapoverride); boolean P_LoadGame(savebuffer_t *save, INT16 mapoverride);
boolean P_LoadNetGame(boolean reloading); boolean P_LoadNetGame(savebuffer_t *save, boolean reloading);
mobj_t *P_FindNewPosition(UINT32 oldposition); mobj_t *P_FindNewPosition(UINT32 oldposition);
@ -38,6 +38,11 @@ struct savedata_t
}; };
extern savedata_t savedata; extern savedata_t savedata;
extern UINT8 *save_p;
struct savebuffer_t
{
UINT8 *buffer;
UINT8 *p;
};
#endif #endif

View file

@ -722,12 +722,12 @@ void P_WriteThings(void)
const char * filename; const char * filename;
size_t i, length; size_t i, length;
mapthing_t *mt; mapthing_t *mt;
UINT8 *savebuffer, *savebuf_p; savebuffer_t save;
INT16 temp; INT16 temp;
savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t)); save.p = save.buffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t));
if (!savebuf_p) if (!save.p)
{ {
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for thing writing!\n")); CONS_Alert(CONS_ERROR, M_GetText("No more free memory for thing writing!\n"));
return; return;
@ -736,23 +736,23 @@ void P_WriteThings(void)
mt = mapthings; mt = mapthings;
for (i = 0; i < nummapthings; i++, mt++) for (i = 0; i < nummapthings; i++, mt++)
{ {
WRITEINT16(savebuf_p, mt->x); WRITEINT16(save.p, mt->x);
WRITEINT16(savebuf_p, mt->y); WRITEINT16(save.p, mt->y);
WRITEINT16(savebuf_p, mt->angle); WRITEINT16(save.p, mt->angle);
temp = (INT16)(mt->type + ((INT16)mt->extrainfo << 12)); temp = (INT16)(mt->type + ((INT16)mt->extrainfo << 12));
WRITEINT16(savebuf_p, temp); WRITEINT16(save.p, temp);
WRITEUINT16(savebuf_p, mt->options); WRITEUINT16(save.p, mt->options);
} }
length = savebuf_p - savebuffer; length = save.p - save.buffer;
filename = va("newthings-%s.lmp", G_BuildMapName(gamemap)); filename = va("newthings-%s.lmp", G_BuildMapName(gamemap));
FIL_WriteFile(filename, savebuffer, length); FIL_WriteFile(filename, save.buffer, length);
free(savebuffer); free(save.buffer);
savebuf_p = NULL; save.p = NULL;
CONS_Printf(M_GetText("%s saved.\n"), filename); CONS_Printf(M_GetText("%s saved.\n"), filename);
} }

View file

@ -258,6 +258,7 @@ TYPEDEF (polyfadedata_t);
// p_saveg.h // p_saveg.h
TYPEDEF (savedata_t); TYPEDEF (savedata_t);
TYPEDEF (savebuffer_t);
// p_setup.h // p_setup.h
TYPEDEF (levelflat_t); TYPEDEF (levelflat_t);