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:
parent
8637dc3ce3
commit
07cdd2f461
11 changed files with 2461 additions and 1900 deletions
|
|
@ -1150,28 +1150,28 @@ static boolean SV_ResendingSavegameToAnyone(void)
|
|||
static void SV_SendSaveGame(INT32 node, boolean resending)
|
||||
{
|
||||
size_t length, compressedlen;
|
||||
UINT8 *savebuffer;
|
||||
savebuffer_t save;
|
||||
UINT8 *compressedsave;
|
||||
UINT8 *buffertosend;
|
||||
|
||||
// first save it in a malloced buffer
|
||||
savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!savebuffer)
|
||||
save.buffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!save.buffer)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
free(save.buffer);
|
||||
save.p = NULL;
|
||||
I_Error("Savegame buffer overrun");
|
||||
}
|
||||
|
||||
|
|
@ -1185,11 +1185,11 @@ static void SV_SendSaveGame(INT32 node, boolean resending)
|
|||
}
|
||||
|
||||
// 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
|
||||
|
||||
free(savebuffer);
|
||||
free(save.buffer);
|
||||
|
||||
// State that we're compressed.
|
||||
buffertosend = compressedsave;
|
||||
|
|
@ -1203,12 +1203,12 @@ static void SV_SendSaveGame(INT32 node, boolean resending)
|
|||
free(compressedsave);
|
||||
|
||||
// State that we're not compressed
|
||||
buffertosend = savebuffer;
|
||||
WRITEUINT32(savebuffer, 0);
|
||||
buffertosend = save.buffer;
|
||||
WRITEUINT32(save.buffer, 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
|
||||
sendingsavegame[node] = true;
|
||||
|
|
@ -1222,7 +1222,7 @@ static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SA
|
|||
static void SV_SavedGame(void)
|
||||
{
|
||||
size_t length;
|
||||
UINT8 *savebuffer;
|
||||
savebuffer_t save;
|
||||
char tmpsave[256];
|
||||
|
||||
if (!cv_dumpconsistency.value)
|
||||
|
|
@ -1231,29 +1231,29 @@ static void SV_SavedGame(void)
|
|||
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
|
||||
|
||||
// first save it in a malloced buffer
|
||||
save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!save_p)
|
||||
save.p = save.buffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!save.p)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
P_SaveNetGame(false);
|
||||
P_SaveNetGame(&save, false);
|
||||
|
||||
length = save_p - savebuffer;
|
||||
length = save.p - save.buffer;
|
||||
if (length > SAVEGAMESIZE)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
free(save.buffer);
|
||||
save.p = NULL;
|
||||
I_Error("Savegame buffer overrun");
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
free(save.buffer);
|
||||
save.p = NULL;
|
||||
}
|
||||
|
||||
#undef TMPSAVENAME
|
||||
|
|
@ -1263,13 +1263,13 @@ static void SV_SavedGame(void)
|
|||
|
||||
static void CL_LoadReceivedSavegame(boolean reloading)
|
||||
{
|
||||
UINT8 *savebuffer = NULL;
|
||||
savebuffer_t save;
|
||||
size_t length, decompressedlen;
|
||||
char tmpsave[256];
|
||||
|
||||
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));
|
||||
if (!length)
|
||||
|
|
@ -1278,16 +1278,16 @@ static void CL_LoadReceivedSavegame(boolean reloading)
|
|||
return;
|
||||
}
|
||||
|
||||
save_p = savebuffer;
|
||||
save.p = save.buffer;
|
||||
|
||||
// Decompress saved game if necessary.
|
||||
decompressedlen = READUINT32(save_p);
|
||||
decompressedlen = READUINT32(save.p);
|
||||
if(decompressedlen > 0)
|
||||
{
|
||||
UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL);
|
||||
lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen);
|
||||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = decompressedbuffer;
|
||||
lzf_decompress(save.p, length - sizeof(UINT32), decompressedbuffer, decompressedlen);
|
||||
Z_Free(save.buffer);
|
||||
save.p = save.buffer = decompressedbuffer;
|
||||
}
|
||||
|
||||
paused = false;
|
||||
|
|
@ -1297,7 +1297,7 @@ static void CL_LoadReceivedSavegame(boolean reloading)
|
|||
automapactive = false;
|
||||
|
||||
// load a base level
|
||||
if (P_LoadNetGame(reloading))
|
||||
if (P_LoadNetGame(&save, reloading))
|
||||
{
|
||||
if (!reloading)
|
||||
{
|
||||
|
|
@ -1319,8 +1319,8 @@ static void CL_LoadReceivedSavegame(boolean reloading)
|
|||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = NULL;
|
||||
if (unlink(tmpsave) == -1)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
|
||||
consistancy[gametic%BACKUPTICS] = Consistancy();
|
||||
|
|
@ -5998,6 +5998,7 @@ void CL_ClearRewinds(void)
|
|||
|
||||
rewind_t *CL_SaveRewindPoint(size_t demopos)
|
||||
{
|
||||
savebuffer_t save;
|
||||
rewind_t *rewind;
|
||||
|
||||
if (rewindhead && rewindhead->leveltime + REWIND_POINT_INTERVAL > leveltime)
|
||||
|
|
@ -6007,8 +6008,10 @@ rewind_t *CL_SaveRewindPoint(size_t demopos)
|
|||
if (!rewind)
|
||||
return NULL;
|
||||
|
||||
save_p = rewind->savebuffer;
|
||||
P_SaveNetGame(false);
|
||||
save.buffer = save.p = rewind->savebuffer;
|
||||
|
||||
P_SaveNetGame(&save, false);
|
||||
|
||||
rewind->leveltime = leveltime;
|
||||
rewind->next = rewindhead;
|
||||
rewind->demopos = demopos;
|
||||
|
|
@ -6019,6 +6022,7 @@ rewind_t *CL_SaveRewindPoint(size_t demopos)
|
|||
|
||||
rewind_t *CL_RewindToTime(tic_t time)
|
||||
{
|
||||
savebuffer_t save;
|
||||
rewind_t *rewind;
|
||||
|
||||
while (rewindhead && rewindhead->leveltime > time)
|
||||
|
|
@ -6031,8 +6035,10 @@ rewind_t *CL_RewindToTime(tic_t time)
|
|||
if (!rewindhead)
|
||||
return NULL;
|
||||
|
||||
save_p = rewindhead->savebuffer;
|
||||
P_LoadNetGame(false);
|
||||
save.buffer = save.p = rewindhead->savebuffer;
|
||||
|
||||
P_LoadNetGame(&save, false);
|
||||
|
||||
wipegamestate = gamestate; // No fading back in!
|
||||
timeinmap = leveltime;
|
||||
|
||||
|
|
|
|||
|
|
@ -5600,10 +5600,9 @@ static void Command_Togglemodified_f(void)
|
|||
modifiedgame = !modifiedgame;
|
||||
}
|
||||
|
||||
extern UINT8 *save_p;
|
||||
static void Command_Archivetest_f(void)
|
||||
{
|
||||
UINT8 *buf;
|
||||
savebuffer_t save;
|
||||
UINT32 i, wrote;
|
||||
thinker_t *th;
|
||||
if (gamestate != GS_LEVEL)
|
||||
|
|
@ -5619,28 +5618,28 @@ static void Command_Archivetest_f(void)
|
|||
((mobj_t *)th)->mobjnum = i++;
|
||||
|
||||
// allocate buffer
|
||||
buf = save_p = ZZ_Alloc(1024);
|
||||
save.buffer = save.p = ZZ_Alloc(1024);
|
||||
|
||||
// test archive
|
||||
CONS_Printf("LUA_Archive...\n");
|
||||
LUA_Archive(&save_p);
|
||||
WRITEUINT8(save_p, 0x7F);
|
||||
wrote = (UINT32)(save_p-buf);
|
||||
LUA_Archive(&save.p, true);
|
||||
WRITEUINT8(save.p, 0x7F);
|
||||
wrote = (UINT32)(save.p - save.buffer);
|
||||
|
||||
// clear Lua state, so we can really see what happens!
|
||||
CONS_Printf("Clearing state!\n");
|
||||
LUA_ClearExtVars();
|
||||
|
||||
// test unarchive
|
||||
save_p = buf;
|
||||
save.p = save.buffer;
|
||||
CONS_Printf("LUA_UnArchive...\n");
|
||||
LUA_UnArchive(&save_p);
|
||||
i = READUINT8(save_p);
|
||||
if (i != 0x7F || wrote != (UINT32)(save_p-buf))
|
||||
CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save_p-buf));
|
||||
LUA_UnArchive(&save.p, true);
|
||||
i = READUINT8(save.p);
|
||||
if (i != 0x7F || wrote != (UINT32)(save.p - save.buffer))
|
||||
CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save.p - save.buffer));
|
||||
|
||||
// free buffer
|
||||
Z_Free(buf);
|
||||
Z_Free(save.buffer);
|
||||
CONS_Printf("Done. No crash.\n");
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2127,7 +2127,7 @@ void G_BeginRecording(void)
|
|||
|
||||
// player lua vars, always saved even if empty
|
||||
if (demoflags & DF_LUAVARS)
|
||||
LUA_Archive(&demo_p);
|
||||
LUA_Archive(&demo_p, false);
|
||||
|
||||
memset(&oldcmd,0,sizeof(oldcmd));
|
||||
memset(&oldghost,0,sizeof(oldghost));
|
||||
|
|
@ -3108,7 +3108,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
LUA_ClearState();
|
||||
|
||||
// No modeattacking check, DF_LUAVARS won't be present here.
|
||||
LUA_UnArchive(&demo_p);
|
||||
LUA_UnArchive(&demo_p, false);
|
||||
}
|
||||
|
||||
splitscreen = 0;
|
||||
|
|
|
|||
188
src/g_game.c
188
src/g_game.c
|
|
@ -345,8 +345,6 @@ boolean precache = true; // if true, load all graphics at start
|
|||
|
||||
INT16 prevmap, nextmap;
|
||||
|
||||
static UINT8 *savebuffer;
|
||||
|
||||
static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
|
||||
{1, "Left X"}, {2, "Left Y"}, {-1, "Left X-"}, {-2, "Left Y-"},
|
||||
#if JOYAXISSET > 1
|
||||
|
|
@ -4088,6 +4086,7 @@ void G_LoadGameData(void)
|
|||
INT32 i, j;
|
||||
UINT8 modded = false;
|
||||
UINT8 rtemp;
|
||||
savebuffer_t save;
|
||||
|
||||
//For records
|
||||
tic_t rectime;
|
||||
|
|
@ -4117,37 +4116,32 @@ void G_LoadGameData(void)
|
|||
|
||||
if (M_CheckParm("-resetdata"))
|
||||
return; // Don't load (essentially, reset).
|
||||
|
||||
length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer);
|
||||
|
||||
length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &save.buffer);
|
||||
if (!length) // Aw, no game data. Their loss!
|
||||
return;
|
||||
|
||||
save_p = savebuffer;
|
||||
save.p = save.buffer;
|
||||
|
||||
// Version check
|
||||
if (READUINT32(save_p) != 0xFCAFE211)
|
||||
if (READUINT32(save.p) != 0xFCAFE211)
|
||||
{
|
||||
const char *gdfolder = "the SRB2Kart folder";
|
||||
if (strcmp(srb2home,"."))
|
||||
gdfolder = srb2home;
|
||||
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = NULL;
|
||||
I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
|
||||
}
|
||||
|
||||
totalplaytime = READUINT32(save_p);
|
||||
matchesplayed = READUINT32(save_p);
|
||||
|
||||
for (i = 0; i < PWRLV_NUMTYPES; i++)
|
||||
{
|
||||
vspowerlevel[i] = READUINT16(save_p);
|
||||
vspowerlevel[i] = READUINT16(save.p);
|
||||
if (vspowerlevel[i] < PWRLVRECORD_MIN || vspowerlevel[i] > PWRLVRECORD_MAX)
|
||||
goto datacorrupt;
|
||||
}
|
||||
|
||||
modded = READUINT8(save_p);
|
||||
|
||||
// Aha! Someone's been screwing with the save file!
|
||||
if ((modded && !savemoddata))
|
||||
goto datacorrupt;
|
||||
|
|
@ -4156,46 +4150,46 @@ void G_LoadGameData(void)
|
|||
|
||||
// TODO put another cipher on these things? meh, I don't care...
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
if ((mapvisited[i] = READUINT8(save_p)) > MV_MAX)
|
||||
if ((mapvisited[i] = READUINT8(save.p)) > MV_MAX)
|
||||
goto datacorrupt;
|
||||
|
||||
// To save space, use one bit per collected/achieved/unlocked flag
|
||||
for (i = 0; i < MAXEMBLEMS;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = READUINT8(save.p);
|
||||
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
||||
emblemlocations[j+i].collected = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = READUINT8(save.p);
|
||||
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
||||
extraemblems[j+i].collected = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXUNLOCKABLES;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = READUINT8(save.p);
|
||||
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
||||
unlockables[j+i].unlocked = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXCONDITIONSETS;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = READUINT8(save.p);
|
||||
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
||||
conditionSets[j+i].achieved = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
|
||||
timesBeaten = READUINT32(save_p);
|
||||
timesBeaten = READUINT32(save.p);
|
||||
|
||||
// Main records
|
||||
for (i = 0; i < NUMMAPS; ++i)
|
||||
{
|
||||
rectime = (tic_t)READUINT32(save_p);
|
||||
reclap = (tic_t)READUINT32(save_p);
|
||||
rectime = (tic_t)READUINT32(save.p);
|
||||
reclap = (tic_t)READUINT32(save.p);
|
||||
|
||||
if (rectime || reclap)
|
||||
{
|
||||
|
|
@ -4206,8 +4200,8 @@ void G_LoadGameData(void)
|
|||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = NULL;
|
||||
|
||||
// Silent update unlockables in case they're out of sync with conditions
|
||||
M_SilentUpdateUnlockablesAndEmblems();
|
||||
|
|
@ -4221,8 +4215,8 @@ void G_LoadGameData(void)
|
|||
if (strcmp(srb2home,"."))
|
||||
gdfolder = srb2home;
|
||||
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = NULL;
|
||||
|
||||
I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
|
||||
}
|
||||
|
|
@ -4235,12 +4229,13 @@ void G_SaveGameData(void)
|
|||
size_t length;
|
||||
INT32 i, j;
|
||||
UINT8 btemp;
|
||||
savebuffer_t save;
|
||||
|
||||
if (!gamedataloaded)
|
||||
return; // If never loaded (-nodata), don't save
|
||||
|
||||
save_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE);
|
||||
if (!save_p)
|
||||
save.p = save.buffer = (UINT8 *)malloc(GAMEDATASIZE);
|
||||
if (!save.p)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
|
||||
return;
|
||||
|
|
@ -4250,26 +4245,26 @@ void G_SaveGameData(void)
|
|||
// SRB2Kart: Let players unlock stuff with addons.
|
||||
if (modifiedgame && !savemoddata)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Version test
|
||||
WRITEUINT32(save_p, 0xFCAFE211);
|
||||
WRITEUINT32(save.p, 0xFCAFE211);
|
||||
|
||||
WRITEUINT32(save_p, totalplaytime);
|
||||
WRITEUINT32(save_p, matchesplayed);
|
||||
WRITEUINT32(save.p, totalplaytime);
|
||||
WRITEUINT32(save.p, matchesplayed);
|
||||
|
||||
for (i = 0; i < PWRLV_NUMTYPES; i++)
|
||||
WRITEUINT16(save_p, vspowerlevel[i]);
|
||||
WRITEUINT16(save.p, vspowerlevel[i]);
|
||||
|
||||
WRITEUINT8(save_p, (UINT8)savemoddata);
|
||||
WRITEUINT8(save.p, (UINT8)savemoddata);
|
||||
|
||||
// TODO put another cipher on these things? meh, I don't care...
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
WRITEUINT8(save_p, (mapvisited[i] & MV_MAX));
|
||||
WRITEUINT8(save.p, (mapvisited[i] & MV_MAX));
|
||||
|
||||
// To save space, use one bit per collected/achieved/unlocked flag
|
||||
for (i = 0; i < MAXEMBLEMS;)
|
||||
|
|
@ -4277,7 +4272,7 @@ void G_SaveGameData(void)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
||||
btemp |= (emblemlocations[j+i].collected << j);
|
||||
WRITEUINT8(save_p, btemp);
|
||||
WRITEUINT8(save.p, btemp);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
||||
|
|
@ -4285,7 +4280,7 @@ void G_SaveGameData(void)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
||||
btemp |= (extraemblems[j+i].collected << j);
|
||||
WRITEUINT8(save_p, btemp);
|
||||
WRITEUINT8(save.p, btemp);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXUNLOCKABLES;)
|
||||
|
|
@ -4293,7 +4288,7 @@ void G_SaveGameData(void)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
||||
btemp |= (unlockables[j+i].unlocked << j);
|
||||
WRITEUINT8(save_p, btemp);
|
||||
WRITEUINT8(save.p, btemp);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXCONDITIONSETS;)
|
||||
|
|
@ -4301,33 +4296,33 @@ void G_SaveGameData(void)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
||||
btemp |= (conditionSets[j+i].achieved << j);
|
||||
WRITEUINT8(save_p, btemp);
|
||||
WRITEUINT8(save.p, btemp);
|
||||
i += j;
|
||||
}
|
||||
|
||||
WRITEUINT32(save_p, timesBeaten);
|
||||
WRITEUINT32(save.p, timesBeaten);
|
||||
|
||||
// Main records
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
{
|
||||
if (mainrecords[i])
|
||||
{
|
||||
WRITEUINT32(save_p, mainrecords[i]->time);
|
||||
WRITEUINT32(save_p, mainrecords[i]->lap);
|
||||
WRITEUINT32(save.p, mainrecords[i]->time);
|
||||
WRITEUINT32(save.p, mainrecords[i]->lap);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITEUINT32(save_p, 0);
|
||||
WRITEUINT32(save_p, 0);
|
||||
WRITEUINT32(save.p, 0);
|
||||
WRITEUINT32(save.p, 0);
|
||||
}
|
||||
WRITEUINT8(save_p, 0); // compat
|
||||
WRITEUINT8(save.p, 0); // compat
|
||||
}
|
||||
|
||||
length = save_p - savebuffer;
|
||||
length = save.p - save.buffer;
|
||||
|
||||
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length);
|
||||
free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), save.buffer, length);
|
||||
free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
}
|
||||
|
||||
#define VERSIONSIZE 16
|
||||
|
|
@ -4341,6 +4336,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
size_t length;
|
||||
char vcheck[VERSIONSIZE];
|
||||
char savename[255];
|
||||
savebuffer_t save;
|
||||
|
||||
// memset savedata to all 0, fixes calling perfectly valid saves corrupt because of bots
|
||||
memset(&savedata, 0, sizeof(savedata));
|
||||
|
|
@ -4355,18 +4351,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
else
|
||||
sprintf(savename, savegamename, slot);
|
||||
|
||||
length = FIL_ReadFile(savename, &savebuffer);
|
||||
length = FIL_ReadFile(savename, &save.buffer);
|
||||
if (!length)
|
||||
{
|
||||
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
|
||||
return;
|
||||
}
|
||||
|
||||
save_p = savebuffer;
|
||||
save.p = save.buffer;
|
||||
|
||||
memset(vcheck, 0, sizeof (vcheck));
|
||||
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
|
||||
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"),
|
||||
|
|
@ -4376,15 +4372,15 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
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);
|
||||
Command_ExitGame_f();
|
||||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
|
||||
// no cheating!
|
||||
memset(&savedata, 0, sizeof(savedata));
|
||||
#endif
|
||||
return; // bad version
|
||||
}
|
||||
save_p += VERSIONSIZE;
|
||||
save.p += VERSIONSIZE;
|
||||
|
||||
if (demo.playback) // reset game engine
|
||||
G_StopDemo();
|
||||
|
|
@ -4393,13 +4389,13 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
// automapactive = false;
|
||||
|
||||
// dearchive all the modifications
|
||||
if (!P_LoadGame(mapoverride))
|
||||
if (!P_LoadGame(&save, mapoverride))
|
||||
{
|
||||
M_ClearMenus(true); // so ESC backs out to title
|
||||
M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
Command_ExitGame_f();
|
||||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
|
||||
// no cheating!
|
||||
memset(&savedata, 0, sizeof(savedata));
|
||||
|
|
@ -4407,13 +4403,13 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
}
|
||||
if (marathonmode)
|
||||
{
|
||||
marathontime = READUINT32(save_p);
|
||||
marathonmode |= READUINT8(save_p);
|
||||
marathontime = READUINT32(save.p);
|
||||
marathonmode |= READUINT8(save.p);
|
||||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
|
||||
// gameaction = ga_nothing;
|
||||
// G_SetGamestate(GS_LEVEL);
|
||||
|
|
@ -4439,6 +4435,7 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
|
|||
boolean saved;
|
||||
char savename[256] = "";
|
||||
const char *backup;
|
||||
savebuffer_t save;
|
||||
|
||||
if (marathonmode)
|
||||
strcpy(savename, liveeventbackup);
|
||||
|
|
@ -4451,8 +4448,8 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
|
|||
char name[VERSIONSIZE];
|
||||
size_t length;
|
||||
|
||||
save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!save_p)
|
||||
save.p = save.buffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!save.p)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
|
||||
return;
|
||||
|
|
@ -4460,22 +4457,22 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
|
|||
|
||||
memset(name, 0, sizeof (name));
|
||||
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)
|
||||
{
|
||||
UINT32 writetime = marathontime;
|
||||
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
|
||||
WRITEUINT32(save_p, writetime);
|
||||
WRITEUINT8(save_p, (marathonmode & ~MA_INIT));
|
||||
WRITEUINT32(save.p, writetime);
|
||||
WRITEUINT8(save.p, (marathonmode & ~MA_INIT));
|
||||
}
|
||||
|
||||
length = save_p - savebuffer;
|
||||
saved = FIL_WriteFile(backup, savebuffer, length);
|
||||
free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
length = save.p - save.buffer;
|
||||
saved = FIL_WriteFile(backup, save.buffer, length);
|
||||
free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
}
|
||||
|
||||
gameaction = ga_nothing;
|
||||
|
|
@ -4487,7 +4484,7 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
|
|||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
boolean saved = false;
|
||||
|
|
@ -4495,6 +4492,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
char vcheck[VERSIONSIZE];
|
||||
char savename[255];
|
||||
const char *backup;
|
||||
savebuffer_t save;
|
||||
|
||||
if (marathonmode)
|
||||
strcpy(savename, liveeventbackup);
|
||||
|
|
@ -4502,7 +4500,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
sprintf(savename, savegamename, slot);
|
||||
backup = va("%s",savename);
|
||||
|
||||
length = FIL_ReadFile(savename, &savebuffer);
|
||||
length = FIL_ReadFile(savename, &save.buffer);
|
||||
if (!length)
|
||||
{
|
||||
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
|
||||
|
|
@ -4511,35 +4509,35 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
|
||||
{
|
||||
char temp[sizeof(timeattackfolder)];
|
||||
UINT8 *end_p = savebuffer + length;
|
||||
UINT8 *end_p = save.buffer + length;
|
||||
UINT8 *lives_p;
|
||||
SINT8 pllives;
|
||||
|
||||
save_p = savebuffer;
|
||||
save.p = save.buffer;
|
||||
// Version check
|
||||
memset(vcheck, 0, sizeof (vcheck));
|
||||
sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
|
||||
if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE
|
||||
save_p += VERSIONSIZE;
|
||||
if (strcmp((const char *)save.p, (const char *)vcheck)) BADSAVE
|
||||
save.p += VERSIONSIZE;
|
||||
|
||||
// P_UnArchiveMisc()
|
||||
(void)READINT16(save_p);
|
||||
(void)READINT16(save.p);
|
||||
CHECKPOS
|
||||
(void)READUINT16(save_p); // emeralds
|
||||
(void)READUINT16(save.p); // emeralds
|
||||
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
|
||||
|
||||
// P_UnArchivePlayer()
|
||||
CHECKPOS
|
||||
(void)READUINT16(save_p);
|
||||
(void)READUINT16(save.p);
|
||||
CHECKPOS
|
||||
|
||||
WRITEUINT8(save_p, numgameovers);
|
||||
WRITEUINT8(save.p, numgameovers);
|
||||
CHECKPOS
|
||||
|
||||
lives_p = save_p;
|
||||
pllives = READSINT8(save_p); // lives
|
||||
lives_p = save.p;
|
||||
pllives = READSINT8(save.p); // lives
|
||||
CHECKPOS
|
||||
if (modifylives && pllives < startinglivesbalance[numgameovers])
|
||||
{
|
||||
|
|
@ -4547,28 +4545,28 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
WRITESINT8(lives_p, pllives);
|
||||
}
|
||||
|
||||
(void)READINT32(save_p); // Score
|
||||
(void)READINT32(save.p); // Score
|
||||
CHECKPOS
|
||||
(void)READINT32(save_p); // continues
|
||||
(void)READINT32(save.p); // continues
|
||||
|
||||
// File end marker check
|
||||
CHECKPOS
|
||||
switch (READUINT8(save_p))
|
||||
switch (READUINT8(save.p))
|
||||
{
|
||||
case 0xb7:
|
||||
{
|
||||
UINT8 i, banksinuse;
|
||||
CHECKPOS
|
||||
banksinuse = READUINT8(save_p);
|
||||
banksinuse = READUINT8(save.p);
|
||||
CHECKPOS
|
||||
if (banksinuse > NUM_LUABANKS)
|
||||
BADSAVE
|
||||
for (i = 0; i < banksinuse; i++)
|
||||
{
|
||||
(void)READINT32(save_p);
|
||||
(void)READINT32(save.p);
|
||||
CHECKPOS
|
||||
}
|
||||
if (READUINT8(save_p) != 0x1d)
|
||||
if (READUINT8(save.p) != 0x1d)
|
||||
BADSAVE
|
||||
}
|
||||
case 0x1d:
|
||||
|
|
@ -4578,7 +4576,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
}
|
||||
|
||||
// done
|
||||
saved = FIL_WriteFile(backup, savebuffer, length);
|
||||
saved = FIL_WriteFile(backup, save.buffer, length);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
|
@ -4586,8 +4584,8 @@ cleanup:
|
|||
CONS_Printf(M_GetText("Game saved.\n"));
|
||||
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));
|
||||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
Z_Free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
|
||||
}
|
||||
#undef CHECKPOS
|
||||
|
|
|
|||
554
src/k_profiles.c
Normal file
554
src/k_profiles.c
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_profiles.c
|
||||
/// \brief implements methods for profiles etc.
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_main.h" // pandf
|
||||
#include "byteptr.h" // READ/WRITE macros
|
||||
#include "p_saveg.h" // savebuffer_t
|
||||
#include "m_misc.h" //FIL_WriteFile()
|
||||
#include "k_profiles.h"
|
||||
#include "z_zone.h"
|
||||
#include "r_skins.h"
|
||||
|
||||
// List of all the profiles.
|
||||
static profile_t *profilesList[MAXPROFILES+1]; // +1 because we're gonna add a default "GUEST' profile.
|
||||
static UINT8 numprofiles = 0; // # of loaded profiles
|
||||
|
||||
INT32 PR_GetNumProfiles(void)
|
||||
{
|
||||
return numprofiles;
|
||||
}
|
||||
|
||||
profile_t* PR_MakeProfile(
|
||||
const char *prname,
|
||||
const char *pname,
|
||||
const char *sname, const UINT16 col,
|
||||
const char *fname, const UINT16 fcol,
|
||||
INT32 controlarray[num_gamecontrols][MAXINPUTMAPPING],
|
||||
boolean guest)
|
||||
{
|
||||
profile_t *new = Z_Malloc(sizeof(profile_t), PU_STATIC, NULL);
|
||||
UINT8 i;
|
||||
|
||||
new->version = PROFILEVER;
|
||||
|
||||
strcpy(new->profilename, prname);
|
||||
new->profilename[sizeof new->profilename - 1] = '\0';
|
||||
|
||||
strcpy(new->skinname, sname);
|
||||
strcpy(new->playername, pname);
|
||||
new->color = col;
|
||||
|
||||
strcpy(new->follower, fname);
|
||||
new->followercolor = fcol;
|
||||
new->kickstartaccel = false;
|
||||
|
||||
// Copy from gamecontrol directly as we'll be setting controls up directly in the profile.
|
||||
memcpy(new->controls, controlarray, sizeof(new->controls));
|
||||
|
||||
// Init both power levels
|
||||
for (i = 0; i < PWRLV_NUMTYPES; i++)
|
||||
{
|
||||
new->powerlevels[i] = (guest ? 0 : PWRLVRECORD_START);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const char *sname, const UINT16 col, const char *fname, UINT16 fcol, UINT8 pnum)
|
||||
{
|
||||
// Generate profile using the player's gamecontrol, as we set them directly when making profiles from menus.
|
||||
profile_t *new = PR_MakeProfile(prname, pname, sname, col, fname, fcol, gamecontrol[pnum], false);
|
||||
|
||||
// Player bound cvars:
|
||||
new->kickstartaccel = cv_kickstartaccel[pnum].value;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
boolean PR_AddProfile(profile_t *p)
|
||||
{
|
||||
if (numprofiles < MAXPROFILES+1)
|
||||
{
|
||||
profilesList[numprofiles] = p;
|
||||
numprofiles++;
|
||||
|
||||
CONS_Printf("Profile '%s' added\n", p->profilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
profile_t* PR_GetProfile(INT32 num)
|
||||
{
|
||||
if (num < numprofiles)
|
||||
return profilesList[num];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
boolean PR_DeleteProfile(INT32 num)
|
||||
{
|
||||
UINT8 i;
|
||||
profile_t* sacrifice;
|
||||
|
||||
if (num <= 0 || num > numprofiles)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sacrifice = profilesList[num];
|
||||
|
||||
// If we're deleting inbetween profiles, move everything.
|
||||
if (num < numprofiles)
|
||||
{
|
||||
for (i = num; i < numprofiles-1; i++)
|
||||
{
|
||||
profilesList[i] = profilesList[i+1];
|
||||
}
|
||||
|
||||
// Make sure to move cv_lastprofile (and title/current profile) values as well!
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS+2; i++)
|
||||
{
|
||||
consvar_t *cv;
|
||||
|
||||
if (i < MAXSPLITSCREENPLAYERS)
|
||||
cv = &cv_lastprofile[i];
|
||||
else if (i == MAXSPLITSCREENPLAYERS)
|
||||
cv = &cv_ttlprofilen;
|
||||
else
|
||||
cv = &cv_currprofile;
|
||||
|
||||
if (cv->value < num)
|
||||
{
|
||||
// Not affected.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cv->value > num)
|
||||
{
|
||||
// Shift our lastprofile number down to match the new order.
|
||||
CV_StealthSetValue(cv, cv->value-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cv != &cv_currprofile)
|
||||
{
|
||||
// There's no hope for it. If we were on the deleted profile, default back to guest.
|
||||
CV_StealthSetValue(cv, PROFILE_GUEST);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Oh boy, now we're really in for it.
|
||||
CV_StealthSetValue(cv, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// In any case, delete the last profile as well.
|
||||
profilesList[numprofiles] = NULL;
|
||||
numprofiles--;
|
||||
|
||||
PR_SaveProfiles();
|
||||
|
||||
// Finally, clear up our memory!
|
||||
Z_Free(sacrifice);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PR_InitNewProfile(void)
|
||||
{
|
||||
char pname[PROFILENAMELEN+1] = "PRF";
|
||||
profile_t *dprofile;
|
||||
UINT8 usenum = numprofiles-1;
|
||||
UINT8 i;
|
||||
boolean nameok = false;
|
||||
|
||||
pname[4] = '\0';
|
||||
|
||||
// When deleting profile, it's possible to do some pretty wacko stuff that would lead a new fresh profile to share the same name as another profile we have never changed the name of.
|
||||
// This could become an infinite loop if MAXPROFILES >= 26.
|
||||
while (!nameok)
|
||||
{
|
||||
pname[3] = 'A'+usenum;
|
||||
|
||||
for (i = 0; i < numprofiles; i++)
|
||||
{
|
||||
profile_t *pr = PR_GetProfile(i);
|
||||
if (!strcmp(pr->profilename, pname))
|
||||
{
|
||||
usenum++;
|
||||
if (pname[3] == 'Z')
|
||||
usenum = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// if we got here, then it means the name is okay!
|
||||
if (i == numprofiles-1)
|
||||
nameok = true;
|
||||
}
|
||||
}
|
||||
|
||||
dprofile = PR_MakeProfile(
|
||||
pname,
|
||||
PROFILEDEFAULTPNAME,
|
||||
PROFILEDEFAULTSKIN, PROFILEDEFAULTCOLOR,
|
||||
PROFILEDEFAULTFOLLOWER, PROFILEDEFAULTFOLLOWERCOLOR,
|
||||
gamecontroldefault,
|
||||
false
|
||||
);
|
||||
PR_AddProfile(dprofile);
|
||||
}
|
||||
|
||||
void PR_SaveProfiles(void)
|
||||
{
|
||||
size_t length = 0;
|
||||
const size_t headerlen = strlen(PROFILEHEADER);
|
||||
UINT8 i, j, k;
|
||||
savebuffer_t save;
|
||||
|
||||
save.p = save.buffer = (UINT8 *)malloc(sizeof(UINT32) + (numprofiles * sizeof(profile_t)));
|
||||
if (!save.p)
|
||||
{
|
||||
I_Error("No more free memory for saving profiles\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add header.
|
||||
WRITESTRINGN(save.p, PROFILEHEADER, headerlen);
|
||||
WRITEUINT8(save.p, PROFILEVER);
|
||||
WRITEUINT8(save.p, numprofiles);
|
||||
|
||||
for (i = 1; i < numprofiles; i++)
|
||||
{
|
||||
// Names.
|
||||
WRITESTRINGN(save.p, profilesList[i]->profilename, PROFILENAMELEN);
|
||||
WRITESTRINGN(save.p, profilesList[i]->playername, MAXPLAYERNAME);
|
||||
|
||||
// Character and colour.
|
||||
WRITESTRINGN(save.p, profilesList[i]->skinname, SKINNAMESIZE);
|
||||
WRITEUINT16(save.p, profilesList[i]->color);
|
||||
|
||||
// Follower and colour.
|
||||
WRITESTRINGN(save.p, profilesList[i]->follower, SKINNAMESIZE);
|
||||
WRITEUINT16(save.p, profilesList[i]->followercolor);
|
||||
|
||||
// PWR.
|
||||
for (j = 0; j < PWRLV_NUMTYPES; j++)
|
||||
{
|
||||
WRITEUINT16(save.p, profilesList[i]->powerlevels[j]);
|
||||
}
|
||||
|
||||
// Consvars.
|
||||
WRITEUINT8(save.p, profilesList[i]->kickstartaccel);
|
||||
|
||||
// Controls.
|
||||
for (j = 0; j < num_gamecontrols; j++)
|
||||
{
|
||||
for (k = 0; k < MAXINPUTMAPPING; k++)
|
||||
{
|
||||
WRITEINT32(save.p, profilesList[i]->controls[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
length = save.p - save.buffer;
|
||||
|
||||
if (!FIL_WriteFile(va(pandf, srb2home, PROFILESFILE), save.buffer, length))
|
||||
{
|
||||
free(save.buffer);
|
||||
I_Error("Couldn't save profiles. Are you out of Disk space / playing in a protected folder?");
|
||||
}
|
||||
free(save.buffer);
|
||||
save.p = save.buffer = NULL;
|
||||
}
|
||||
|
||||
void PR_LoadProfiles(void)
|
||||
{
|
||||
size_t length = 0;
|
||||
const size_t headerlen = strlen(PROFILEHEADER);
|
||||
UINT8 i, j, k, version;
|
||||
profile_t *dprofile = PR_MakeProfile(
|
||||
PROFILEDEFAULTNAME,
|
||||
PROFILEDEFAULTPNAME,
|
||||
PROFILEDEFAULTSKIN, PROFILEDEFAULTCOLOR,
|
||||
PROFILEDEFAULTFOLLOWER, PROFILEDEFAULTFOLLOWERCOLOR,
|
||||
gamecontroldefault,
|
||||
true
|
||||
);
|
||||
savebuffer_t save;
|
||||
|
||||
length = FIL_ReadFile(va(pandf, srb2home, PROFILESFILE), &save.buffer);
|
||||
if (!length)
|
||||
{
|
||||
// No profiles. Add the default one.
|
||||
PR_AddProfile(dprofile);
|
||||
return;
|
||||
}
|
||||
|
||||
save.p = save.buffer;
|
||||
|
||||
if (strncmp(PROFILEHEADER, (const char *)save.buffer, headerlen))
|
||||
{
|
||||
const char *gdfolder = "the Ring Racers folder";
|
||||
if (strcmp(srb2home,"."))
|
||||
gdfolder = srb2home;
|
||||
|
||||
Z_Free(save.buffer);
|
||||
save.p = NULL;
|
||||
I_Error("Not a valid Profile file.\nDelete %s (maybe in %s) and try again.", PROFILESFILE, gdfolder);
|
||||
}
|
||||
save.p += headerlen;
|
||||
|
||||
version = READUINT8(save.p);
|
||||
if (version > PROFILEVER)
|
||||
{
|
||||
Z_Free(save.buffer);
|
||||
save.p = NULL;
|
||||
I_Error("Existing %s is from the future! (expected %d, got %d)", PROFILESFILE, PROFILEVER, version);
|
||||
}
|
||||
|
||||
numprofiles = READUINT8(save.p);
|
||||
if (numprofiles > MAXPROFILES)
|
||||
numprofiles = MAXPROFILES;
|
||||
|
||||
for (i = 1; i < numprofiles; i++)
|
||||
{
|
||||
profilesList[i] = Z_Malloc(sizeof(profile_t), PU_STATIC, NULL);
|
||||
|
||||
// Version. (We always update this on successful forward step)
|
||||
profilesList[i]->version = PROFILEVER;
|
||||
|
||||
// Names.
|
||||
READSTRINGN(save.p, profilesList[i]->profilename, PROFILENAMELEN);
|
||||
READSTRINGN(save.p, profilesList[i]->playername, MAXPLAYERNAME);
|
||||
|
||||
// Character and colour.
|
||||
READSTRINGN(save.p, profilesList[i]->skinname, SKINNAMESIZE);
|
||||
profilesList[i]->color = READUINT16(save.p);
|
||||
|
||||
if (profilesList[i]->color == SKINCOLOR_NONE)
|
||||
{
|
||||
; // Valid, even outside the bounds
|
||||
}
|
||||
else if (profilesList[i]->color >= numskincolors
|
||||
|| skincolors[profilesList[i]->color].accessible == false)
|
||||
{
|
||||
profilesList[i]->color = PROFILEDEFAULTCOLOR;
|
||||
}
|
||||
|
||||
// Follower and colour.
|
||||
READSTRINGN(save.p, profilesList[i]->follower, SKINNAMESIZE);
|
||||
profilesList[i]->followercolor = READUINT16(save.p);
|
||||
|
||||
if (profilesList[i]->followercolor == FOLLOWERCOLOR_MATCH
|
||||
|| profilesList[i]->followercolor == FOLLOWERCOLOR_OPPOSITE)
|
||||
{
|
||||
; // Valid, even outside the bounds
|
||||
}
|
||||
else if (profilesList[i]->followercolor >= numskincolors
|
||||
|| profilesList[i]->followercolor == SKINCOLOR_NONE
|
||||
|| skincolors[profilesList[i]->followercolor].accessible == false)
|
||||
{
|
||||
profilesList[i]->followercolor = PROFILEDEFAULTFOLLOWERCOLOR;
|
||||
}
|
||||
|
||||
// PWR.
|
||||
for (j = 0; j < PWRLV_NUMTYPES; j++)
|
||||
{
|
||||
profilesList[i]->powerlevels[j] = READUINT16(save.p);
|
||||
if (profilesList[i]->powerlevels[j] < PWRLVRECORD_MIN
|
||||
|| profilesList[i]->powerlevels[j] > PWRLVRECORD_MAX)
|
||||
{
|
||||
// invalid, reset
|
||||
profilesList[i]->powerlevels[j] = PWRLVRECORD_START;
|
||||
}
|
||||
}
|
||||
|
||||
// Consvars.
|
||||
profilesList[i]->kickstartaccel = (boolean)READUINT8(save.p);
|
||||
|
||||
// Controls.
|
||||
for (j = 0; j < num_gamecontrols; j++)
|
||||
{
|
||||
#ifdef DEVELOP
|
||||
// Profile update 1-->2: Add gc_rankings.
|
||||
if (j == gc_rankings && version < 2)
|
||||
{
|
||||
for (k = 0; k < MAXINPUTMAPPING; k++)
|
||||
{
|
||||
profilesList[i]->controls[j][k] = gamecontroldefault[j][k];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (k = 0; k < MAXINPUTMAPPING; k++)
|
||||
{
|
||||
profilesList[i]->controls[j][k] = READINT32(save.p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the the default profile directly to avoid letting anyone tamper with it.
|
||||
profilesList[PROFILE_GUEST] = dprofile;
|
||||
}
|
||||
|
||||
skincolornum_t PR_GetProfileColor(profile_t *p)
|
||||
{
|
||||
if (p->color == SKINCOLOR_NONE)
|
||||
{
|
||||
// Get skin's prefcolor.
|
||||
INT32 foundskin = R_SkinAvailable(p->skinname);
|
||||
if (foundskin == -1)
|
||||
{
|
||||
// Return random default value
|
||||
return SKINCOLOR_RED;
|
||||
}
|
||||
|
||||
return skins[foundskin].prefcolor;
|
||||
}
|
||||
|
||||
// Get exact color.
|
||||
return p->color;
|
||||
}
|
||||
|
||||
static void PR_ApplyProfile_Appearance(profile_t *p, UINT8 playernum)
|
||||
{
|
||||
CV_StealthSet(&cv_skin[playernum], p->skinname);
|
||||
CV_StealthSetValue(&cv_playercolor[playernum], PR_GetProfileColor(p));
|
||||
CV_StealthSet(&cv_playername[playernum], p->playername);
|
||||
|
||||
// Followers
|
||||
CV_StealthSet(&cv_follower[playernum], p->follower);
|
||||
CV_StealthSetValue(&cv_followercolor[playernum], p->followercolor);
|
||||
}
|
||||
|
||||
static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum)
|
||||
{
|
||||
// toggles
|
||||
CV_StealthSetValue(&cv_kickstartaccel[playernum], p->kickstartaccel);
|
||||
|
||||
// set controls...
|
||||
memcpy(&gamecontrol[playernum], p->controls, sizeof(gamecontroldefault));
|
||||
}
|
||||
|
||||
static void PR_ApplyProfile_Memory(UINT8 profilenum, UINT8 playernum)
|
||||
{
|
||||
// set memory cvar
|
||||
CV_StealthSetValue(&cv_lastprofile[playernum], profilenum);
|
||||
|
||||
// If we're doing this on P1, also change current profile.
|
||||
if (playernum == 0)
|
||||
{
|
||||
CV_StealthSetValue(&cv_currprofile, profilenum);
|
||||
}
|
||||
}
|
||||
|
||||
void PR_ApplyProfile(UINT8 profilenum, UINT8 playernum)
|
||||
{
|
||||
profile_t *p = PR_GetProfile(profilenum);
|
||||
|
||||
// this CAN happen!!
|
||||
if (dedicated || p == NULL)
|
||||
{
|
||||
if (!dedicated)
|
||||
CONS_Printf("Profile '%d' could not be loaded as it does not exist. Guest Profile will be loaded instead.\n", profilenum);
|
||||
profilenum = 0; // make sure to set this so that the cvar is set properly.
|
||||
p = PR_GetProfile(profilenum);
|
||||
}
|
||||
|
||||
PR_ApplyProfile_Appearance(p, playernum);
|
||||
PR_ApplyProfile_Settings(p, playernum);
|
||||
PR_ApplyProfile_Memory(profilenum, playernum);
|
||||
}
|
||||
|
||||
void PR_ApplyProfileLight(UINT8 profilenum, UINT8 playernum)
|
||||
{
|
||||
profile_t *p = PR_GetProfile(profilenum);
|
||||
|
||||
// this CAN happen!!
|
||||
if (p == NULL)
|
||||
{
|
||||
// no need to be as loud...
|
||||
profilenum = 0; // make sure to set this so that the cvar is set properly.
|
||||
p = PR_GetProfile(profilenum);
|
||||
}
|
||||
|
||||
PR_ApplyProfile_Appearance(p, playernum);
|
||||
}
|
||||
|
||||
void PR_ApplyProfilePretend(UINT8 profilenum, UINT8 playernum)
|
||||
{
|
||||
profile_t *p = PR_GetProfile(profilenum);
|
||||
|
||||
// this CAN happen!!
|
||||
if (dedicated || p == NULL)
|
||||
{
|
||||
if (!dedicated)
|
||||
CONS_Printf("Profile '%d' could not be loaded as it does not exist. Guest Profile will be loaded instead.\n", profilenum);
|
||||
profilenum = 0; // make sure to set this so that the cvar is set properly.
|
||||
p = PR_GetProfile(profilenum);
|
||||
}
|
||||
|
||||
PR_ApplyProfile_Memory(profilenum, playernum);
|
||||
}
|
||||
|
||||
UINT8 PR_GetProfileNum(profile_t *p)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXPROFILES+1; i++)
|
||||
{
|
||||
profile_t *comp = PR_GetProfile(i);
|
||||
if (comp == p)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SINT8 PR_ProfileUsedBy(profile_t *p)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT8 prn = PR_GetProfileNum(p);
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (prn == cv_lastprofile[i].value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
profile_t *PR_GetPlayerProfile(player_t *player)
|
||||
{
|
||||
const UINT8 playerNum = (player - players);
|
||||
UINT8 i;
|
||||
|
||||
if (demo.playback)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (playerNum == g_localplayers[i])
|
||||
{
|
||||
return PR_GetProfile(cv_lastprofile[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -42,6 +42,8 @@ lua_State *gL = NULL;
|
|||
|
||||
int hook_defrosting;
|
||||
|
||||
static UINT8 **lua_save_p = NULL; // FIXME: Remove this horrible hack
|
||||
|
||||
// List of internal libraries to load from SRB2
|
||||
static lua_CFunction liblist[] = {
|
||||
LUA_EnumLib, // global metatable for enums
|
||||
|
|
@ -1290,10 +1292,10 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
|
|||
{
|
||||
polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex));
|
||||
if (!polyobj)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
WRITEUINT8(*p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_POLYOBJ);
|
||||
WRITEUINT16(save_p, polyobj-PolyObjects);
|
||||
WRITEUINT8(*p, ARCH_POLYOBJ);
|
||||
WRITEUINT16(*p, polyobj-PolyObjects);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1397,7 +1399,7 @@ static int NetArchive(lua_State *L)
|
|||
int TABLESINDEX = lua_upvalueindex(1);
|
||||
int i, n = lua_gettop(L);
|
||||
for (i = 1; i <= n; i++)
|
||||
ArchiveValue(&save_p, TABLESINDEX, i);
|
||||
ArchiveValue(lua_save_p, TABLESINDEX, i);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
@ -1562,7 +1564,7 @@ static UINT8 UnArchiveValue(UINT8 **p, int TABLESINDEX)
|
|||
break;
|
||||
}
|
||||
case ARCH_POLYOBJ:
|
||||
LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ);
|
||||
LUA_PushUserdata(gL, &PolyObjects[READUINT16(*p)], META_POLYOBJ);
|
||||
break;
|
||||
case ARCH_SLOPE:
|
||||
LUA_PushUserdata(gL, P_SlopeById(READUINT16(*p)), META_SLOPE);
|
||||
|
|
@ -1613,7 +1615,7 @@ static int NetUnArchive(lua_State *L)
|
|||
int TABLESINDEX = lua_upvalueindex(1);
|
||||
int i, n = lua_gettop(L);
|
||||
for (i = 1; i <= n; i++)
|
||||
UnArchiveValue(&save_p, TABLESINDEX);
|
||||
UnArchiveValue(lua_save_p, TABLESINDEX);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
@ -1652,7 +1654,7 @@ static void UnArchiveTables(UINT8 **p)
|
|||
lua_rawset(gL, -3);
|
||||
}
|
||||
|
||||
metatableid = READUINT16(save_p);
|
||||
metatableid = READUINT16(*p);
|
||||
if (metatableid)
|
||||
{
|
||||
// setmetatable(table, registry.metatables[metatableid])
|
||||
|
|
@ -1676,7 +1678,7 @@ void LUA_Step(void)
|
|||
lua_gc(gL, LUA_GCSTEP, 1);
|
||||
}
|
||||
|
||||
void LUA_Archive(UINT8 **p)
|
||||
void LUA_Archive(UINT8 **p, boolean network)
|
||||
{
|
||||
INT32 i;
|
||||
thinker_t *th;
|
||||
|
|
@ -1692,7 +1694,7 @@ void LUA_Archive(UINT8 **p)
|
|||
ArchiveExtVars(p, &players[i], "player");
|
||||
}
|
||||
|
||||
if (p == &save_p)
|
||||
if (network == true)
|
||||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
|
|
@ -1709,6 +1711,7 @@ void LUA_Archive(UINT8 **p)
|
|||
|
||||
WRITEUINT32(*p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
|
||||
|
||||
lua_save_p = p;
|
||||
LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode
|
||||
}
|
||||
|
||||
|
|
@ -1718,7 +1721,7 @@ void LUA_Archive(UINT8 **p)
|
|||
lua_pop(gL, 1); // pop tables
|
||||
}
|
||||
|
||||
void LUA_UnArchive(UINT8 **p)
|
||||
void LUA_UnArchive(UINT8 **p, boolean network)
|
||||
{
|
||||
UINT32 mobjnum;
|
||||
INT32 i;
|
||||
|
|
@ -1734,7 +1737,7 @@ void LUA_UnArchive(UINT8 **p)
|
|||
UnArchiveExtVars(p, &players[i]);
|
||||
}
|
||||
|
||||
if (p == &save_p)
|
||||
if (network == true)
|
||||
{
|
||||
do {
|
||||
mobjnum = READUINT32(*p); // read a mobjnum
|
||||
|
|
@ -1748,6 +1751,7 @@ void LUA_UnArchive(UINT8 **p)
|
|||
}
|
||||
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
|
||||
|
||||
lua_save_p = p;
|
||||
LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ void LUA_DumpFile(const char *filename);
|
|||
#endif
|
||||
fixed_t LUA_EvalMath(const char *word);
|
||||
void LUA_Step(void);
|
||||
void LUA_Archive(UINT8 **p);
|
||||
void LUA_UnArchive(UINT8 **p);
|
||||
void LUA_Archive(UINT8 **p, boolean network);
|
||||
void LUA_UnArchive(UINT8 **p, boolean network);
|
||||
|
||||
int LUA_PushGlobals(lua_State *L, const char *word);
|
||||
int LUA_WriteGlobals(lua_State *L, const char *word);
|
||||
|
|
|
|||
3444
src/p_saveg.c
3444
src/p_saveg.c
File diff suppressed because it is too large
Load diff
|
|
@ -21,10 +21,10 @@
|
|||
// Persistent storage/archiving.
|
||||
// These are the load / save game routines.
|
||||
|
||||
void P_SaveGame(INT16 mapnum);
|
||||
void P_SaveNetGame(boolean resending);
|
||||
boolean P_LoadGame(INT16 mapoverride);
|
||||
boolean P_LoadNetGame(boolean reloading);
|
||||
void P_SaveGame(savebuffer_t *save, INT16 mapnum);
|
||||
void P_SaveNetGame(savebuffer_t *save, boolean resending);
|
||||
boolean P_LoadGame(savebuffer_t *save, INT16 mapoverride);
|
||||
boolean P_LoadNetGame(savebuffer_t *save, boolean reloading);
|
||||
|
||||
mobj_t *P_FindNewPosition(UINT32 oldposition);
|
||||
|
||||
|
|
@ -38,6 +38,11 @@ struct savedata_t
|
|||
};
|
||||
|
||||
extern savedata_t savedata;
|
||||
extern UINT8 *save_p;
|
||||
|
||||
struct savebuffer_t
|
||||
{
|
||||
UINT8 *buffer;
|
||||
UINT8 *p;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -965,12 +965,12 @@ void P_WriteThings(void)
|
|||
{
|
||||
size_t i, length;
|
||||
mapthing_t *mt;
|
||||
UINT8 *savebuffer, *savebuf_p;
|
||||
savebuffer_t save;
|
||||
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"));
|
||||
return;
|
||||
|
|
@ -979,20 +979,20 @@ void P_WriteThings(void)
|
|||
mt = mapthings;
|
||||
for (i = 0; i < nummapthings; i++, mt++)
|
||||
{
|
||||
WRITEINT16(savebuf_p, mt->x);
|
||||
WRITEINT16(savebuf_p, mt->y);
|
||||
WRITEINT16(save.p, mt->x);
|
||||
WRITEINT16(save.p, mt->y);
|
||||
|
||||
WRITEINT16(savebuf_p, mt->angle);
|
||||
WRITEINT16(save.p, mt->angle);
|
||||
|
||||
temp = (INT16)(mt->type + ((INT16)mt->extrainfo << 12));
|
||||
WRITEINT16(savebuf_p, temp);
|
||||
WRITEUINT16(savebuf_p, mt->options);
|
||||
WRITEINT16(save.p, temp);
|
||||
WRITEUINT16(save.p, mt->options);
|
||||
}
|
||||
|
||||
length = savebuf_p - savebuffer;
|
||||
length = save.p - save.buffer;
|
||||
|
||||
FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length);
|
||||
free(savebuffer);
|
||||
FIL_WriteFile(va("newthings%d.lmp", gamemap), save.buffer, length);
|
||||
free(save.buffer);
|
||||
savebuf_p = NULL;
|
||||
|
||||
CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap);
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ TYPEDEF (polyfadedata_t);
|
|||
|
||||
// p_saveg.h
|
||||
TYPEDEF (savedata_t);
|
||||
TYPEDEF (savebuffer_t);
|
||||
|
||||
// p_setup.h
|
||||
TYPEDEF (levelflat_t);
|
||||
|
|
|
|||
Loading…
Reference in a new issue