mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-14 08:50:53 +00:00
Lift savebuffer limits
This commit is contained in:
parent
8824ce8787
commit
792b80cddb
8 changed files with 2240 additions and 1988 deletions
242
src/g_game.c
242
src/g_game.c
|
@ -256,8 +256,6 @@ boolean precache = true; // if true, load all graphics at start
|
|||
|
||||
INT16 prevmap, nextmap;
|
||||
|
||||
static UINT8 *savebuffer;
|
||||
|
||||
// Analog Control
|
||||
static void UserAnalog_OnChange(void);
|
||||
static void UserAnalog2_OnChange(void);
|
||||
|
@ -4396,7 +4394,7 @@ void G_LoadGameSettings(void)
|
|||
// Loads the main data file, which stores information such as emblems found, etc.
|
||||
void G_LoadGameData(gamedata_t *data)
|
||||
{
|
||||
size_t length;
|
||||
save_t savebuffer;
|
||||
INT32 i, j;
|
||||
|
||||
UINT32 versionID;
|
||||
|
@ -4438,18 +4436,18 @@ void G_LoadGameData(gamedata_t *data)
|
|||
return;
|
||||
}
|
||||
|
||||
length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer);
|
||||
if (!length)
|
||||
savebuffer.size = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer.buf);
|
||||
if (!savebuffer.size)
|
||||
{
|
||||
// No gamedata. We can save a new one.
|
||||
data->loaded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
save_p = savebuffer;
|
||||
savebuffer.pos = 0;
|
||||
|
||||
// Version check
|
||||
versionID = READUINT32(save_p);
|
||||
versionID = P_ReadUINT32(&savebuffer);
|
||||
if (versionID != GAMEDATA_ID
|
||||
#ifdef COMPAT_GAMEDATA_ID // backwards compat behavior
|
||||
&& versionID != COMPAT_GAMEDATA_ID
|
||||
|
@ -4460,8 +4458,7 @@ void G_LoadGameData(gamedata_t *data)
|
|||
if (strcmp(srb2home,"."))
|
||||
gdfolder = srb2home;
|
||||
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(savebuffer.buf);
|
||||
I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
|
||||
}
|
||||
|
||||
|
@ -4473,14 +4470,14 @@ void G_LoadGameData(gamedata_t *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
data->totalplaytime = READUINT32(save_p);
|
||||
data->totalplaytime = P_ReadUINT32(&savebuffer);
|
||||
|
||||
#ifdef COMPAT_GAMEDATA_ID
|
||||
if (versionID == COMPAT_GAMEDATA_ID)
|
||||
{
|
||||
// We'll temporarily use the old condition when loading an older file.
|
||||
// The proper mod-specific hash will get saved in afterwards.
|
||||
boolean modded = READUINT8(save_p);
|
||||
boolean modded = P_ReadUINT8(&savebuffer);
|
||||
|
||||
if (modded && !savemoddata)
|
||||
{
|
||||
|
@ -4500,13 +4497,13 @@ void G_LoadGameData(gamedata_t *data)
|
|||
strcpy(currentfilename, gamedatafilename);
|
||||
STRBUFCPY(backupfilename, strcat(currentfilename, bak));
|
||||
|
||||
FIL_WriteFile(va(pandf, srb2home, backupfilename), savebuffer, length);
|
||||
FIL_WriteFile(va(pandf, srb2home, backupfilename), &savebuffer.buf, savebuffer.size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Quick & dirty hash for what mod this save file is for.
|
||||
UINT32 modID = READUINT32(save_p);
|
||||
UINT32 modID = P_ReadUINT32(&savebuffer);
|
||||
UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder);
|
||||
|
||||
if (modID != expectedID)
|
||||
|
@ -4518,50 +4515,50 @@ void G_LoadGameData(gamedata_t *data)
|
|||
|
||||
// TODO put another cipher on these things? meh, I don't care...
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX)
|
||||
if ((data->mapvisited[i] = P_ReadUINT8(&savebuffer)) > MV_MAX)
|
||||
goto datacorrupt;
|
||||
|
||||
// To save space, use one bit per collected/achieved/unlocked flag
|
||||
for (i = 0; i < max_emblems;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = P_ReadUINT8(&savebuffer);
|
||||
for (j = 0; j < 8 && j+i < max_emblems; ++j)
|
||||
data->collected[j+i] = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < max_extraemblems;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = P_ReadUINT8(&savebuffer);
|
||||
for (j = 0; j < 8 && j+i < max_extraemblems; ++j)
|
||||
data->extraCollected[j+i] = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < max_unlockables;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = P_ReadUINT8(&savebuffer);
|
||||
for (j = 0; j < 8 && j+i < max_unlockables; ++j)
|
||||
data->unlocked[j+i] = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < max_conditionsets;)
|
||||
{
|
||||
rtemp = READUINT8(save_p);
|
||||
rtemp = P_ReadUINT8(&savebuffer);
|
||||
for (j = 0; j < 8 && j+i < max_conditionsets; ++j)
|
||||
data->achieved[j+i] = ((rtemp >> j) & 1);
|
||||
i += j;
|
||||
}
|
||||
|
||||
data->timesBeaten = READUINT32(save_p);
|
||||
data->timesBeatenWithEmeralds = READUINT32(save_p);
|
||||
data->timesBeatenUltimate = READUINT32(save_p);
|
||||
data->timesBeaten = P_ReadUINT32(&savebuffer);
|
||||
data->timesBeatenWithEmeralds = P_ReadUINT32(&savebuffer);
|
||||
data->timesBeatenUltimate = P_ReadUINT32(&savebuffer);
|
||||
|
||||
// Main records
|
||||
for (i = 0; i < NUMMAPS; ++i)
|
||||
{
|
||||
recscore = READUINT32(save_p);
|
||||
rectime = (tic_t)READUINT32(save_p);
|
||||
recrings = READUINT16(save_p);
|
||||
save_p++; // compat
|
||||
recscore = P_ReadUINT32(&savebuffer);
|
||||
rectime = (tic_t)P_ReadUINT32(&savebuffer);
|
||||
recrings = P_ReadUINT16(&savebuffer);
|
||||
P_ReadUINT8(&savebuffer); // compat
|
||||
|
||||
if (recrings > 10000 || recscore > MAXSCORE)
|
||||
goto datacorrupt;
|
||||
|
@ -4578,16 +4575,16 @@ void G_LoadGameData(gamedata_t *data)
|
|||
// Nights records
|
||||
for (i = 0; i < NUMMAPS; ++i)
|
||||
{
|
||||
if ((recmares = READUINT8(save_p)) == 0)
|
||||
if ((recmares = P_ReadUINT8(&savebuffer)) == 0)
|
||||
continue;
|
||||
|
||||
G_AllocNightsRecordData((INT16)i, data);
|
||||
|
||||
for (curmare = 0; curmare < (recmares+1); ++curmare)
|
||||
{
|
||||
data->nightsrecords[i]->score[curmare] = READUINT32(save_p);
|
||||
data->nightsrecords[i]->grade[curmare] = READUINT8(save_p);
|
||||
data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p);
|
||||
data->nightsrecords[i]->score[curmare] = P_ReadUINT32(&savebuffer);
|
||||
data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(&savebuffer);
|
||||
data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(&savebuffer);
|
||||
|
||||
if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
|
||||
{
|
||||
|
@ -4599,8 +4596,7 @@ void G_LoadGameData(gamedata_t *data)
|
|||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(savebuffer.buf);
|
||||
|
||||
// Don't consider loaded until it's a success!
|
||||
// It used to do this much earlier, but this would cause the gamedata to
|
||||
|
@ -4621,8 +4617,7 @@ void G_LoadGameData(gamedata_t *data)
|
|||
if (strcmp(srb2home,"."))
|
||||
gdfolder = srb2home;
|
||||
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(savebuffer.buf);
|
||||
|
||||
I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
|
||||
}
|
||||
|
@ -4632,9 +4627,8 @@ void G_LoadGameData(gamedata_t *data)
|
|||
// Saves the main data file, which stores information such as emblems found, etc.
|
||||
void G_SaveGameData(gamedata_t *data)
|
||||
{
|
||||
UINT8 *data_p;
|
||||
save_t savebuffer;
|
||||
|
||||
size_t length;
|
||||
INT32 i, j;
|
||||
UINT8 btemp;
|
||||
|
||||
|
@ -4646,30 +4640,31 @@ void G_SaveGameData(gamedata_t *data)
|
|||
if (!data->loaded)
|
||||
return; // If never loaded (-nodata), don't save
|
||||
|
||||
data_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE);
|
||||
if (!data_p)
|
||||
savebuffer.size = GAMEDATASIZE;
|
||||
savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
|
||||
if (!savebuffer.buf)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
|
||||
return;
|
||||
}
|
||||
savebuffer.pos = 0;
|
||||
|
||||
if (usedCheats)
|
||||
{
|
||||
free(savebuffer);
|
||||
savebuffer = NULL;
|
||||
free(savebuffer.buf);
|
||||
return;
|
||||
}
|
||||
|
||||
// Version test
|
||||
WRITEUINT32(data_p, GAMEDATA_ID);
|
||||
P_WriteUINT32(&savebuffer, GAMEDATA_ID);
|
||||
|
||||
WRITEUINT32(data_p, data->totalplaytime);
|
||||
P_WriteUINT32(&savebuffer, data->totalplaytime);
|
||||
|
||||
WRITEUINT32(data_p, quickncasehash(timeattackfolder, sizeof timeattackfolder));
|
||||
P_WriteUINT32(&savebuffer, quickncasehash(timeattackfolder, sizeof timeattackfolder));
|
||||
|
||||
// TODO put another cipher on these things? meh, I don't care...
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
WRITEUINT8(data_p, (data->mapvisited[i] & MV_MAX));
|
||||
P_WriteUINT8(&savebuffer, (data->mapvisited[i] & MV_MAX));
|
||||
|
||||
// To save space, use one bit per collected/achieved/unlocked flag
|
||||
for (i = 0; i < MAXEMBLEMS;)
|
||||
|
@ -4677,7 +4672,7 @@ void G_SaveGameData(gamedata_t *data)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
||||
btemp |= (data->collected[j+i] << j);
|
||||
WRITEUINT8(data_p, btemp);
|
||||
P_WriteUINT8(&savebuffer, btemp);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
||||
|
@ -4685,7 +4680,7 @@ void G_SaveGameData(gamedata_t *data)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
||||
btemp |= (data->extraCollected[j+i] << j);
|
||||
WRITEUINT8(data_p, btemp);
|
||||
P_WriteUINT8(&savebuffer, btemp);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXUNLOCKABLES;)
|
||||
|
@ -4693,7 +4688,7 @@ void G_SaveGameData(gamedata_t *data)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
||||
btemp |= (data->unlocked[j+i] << j);
|
||||
WRITEUINT8(data_p, btemp);
|
||||
P_WriteUINT8(&savebuffer, btemp);
|
||||
i += j;
|
||||
}
|
||||
for (i = 0; i < MAXCONDITIONSETS;)
|
||||
|
@ -4701,30 +4696,30 @@ void G_SaveGameData(gamedata_t *data)
|
|||
btemp = 0;
|
||||
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
||||
btemp |= (data->achieved[j+i] << j);
|
||||
WRITEUINT8(data_p, btemp);
|
||||
P_WriteUINT8(&savebuffer, btemp);
|
||||
i += j;
|
||||
}
|
||||
|
||||
WRITEUINT32(data_p, data->timesBeaten);
|
||||
WRITEUINT32(data_p, data->timesBeatenWithEmeralds);
|
||||
WRITEUINT32(data_p, data->timesBeatenUltimate);
|
||||
P_WriteUINT32(&savebuffer, data->timesBeaten);
|
||||
P_WriteUINT32(&savebuffer, data->timesBeatenWithEmeralds);
|
||||
P_WriteUINT32(&savebuffer, data->timesBeatenUltimate);
|
||||
|
||||
// Main records
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
{
|
||||
if (data->mainrecords[i])
|
||||
{
|
||||
WRITEUINT32(data_p, data->mainrecords[i]->score);
|
||||
WRITEUINT32(data_p, data->mainrecords[i]->time);
|
||||
WRITEUINT16(data_p, data->mainrecords[i]->rings);
|
||||
P_WriteUINT32(&savebuffer, data->mainrecords[i]->score);
|
||||
P_WriteUINT32(&savebuffer, data->mainrecords[i]->time);
|
||||
P_WriteUINT16(&savebuffer, data->mainrecords[i]->rings);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITEUINT32(data_p, 0);
|
||||
WRITEUINT32(data_p, 0);
|
||||
WRITEUINT16(data_p, 0);
|
||||
P_WriteUINT32(&savebuffer, 0);
|
||||
P_WriteUINT32(&savebuffer, 0);
|
||||
P_WriteUINT16(&savebuffer, 0);
|
||||
}
|
||||
WRITEUINT8(data_p, 0); // compat
|
||||
P_WriteUINT8(&savebuffer, 0); // compat
|
||||
}
|
||||
|
||||
// NiGHTS records
|
||||
|
@ -4732,25 +4727,22 @@ void G_SaveGameData(gamedata_t *data)
|
|||
{
|
||||
if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares)
|
||||
{
|
||||
WRITEUINT8(data_p, 0);
|
||||
P_WriteUINT8(&savebuffer, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
WRITEUINT8(data_p, data->nightsrecords[i]->nummares);
|
||||
P_WriteUINT8(&savebuffer, data->nightsrecords[i]->nummares);
|
||||
|
||||
for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare)
|
||||
{
|
||||
WRITEUINT32(data_p, data->nightsrecords[i]->score[curmare]);
|
||||
WRITEUINT8(data_p, data->nightsrecords[i]->grade[curmare]);
|
||||
WRITEUINT32(data_p, data->nightsrecords[i]->time[curmare]);
|
||||
P_WriteUINT32(&savebuffer, data->nightsrecords[i]->score[curmare]);
|
||||
P_WriteUINT8(&savebuffer, data->nightsrecords[i]->grade[curmare]);
|
||||
P_WriteUINT32(&savebuffer, data->nightsrecords[i]->time[curmare]);
|
||||
}
|
||||
}
|
||||
|
||||
length = data_p - savebuffer;
|
||||
|
||||
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length);
|
||||
free(savebuffer);
|
||||
savebuffer = NULL;
|
||||
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer.buf, savebuffer.pos);
|
||||
free(savebuffer.buf);
|
||||
}
|
||||
|
||||
#define VERSIONSIZE 16
|
||||
|
@ -4761,7 +4753,7 @@ void G_SaveGameData(gamedata_t *data)
|
|||
//
|
||||
void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
||||
{
|
||||
size_t length;
|
||||
save_t savebuffer;
|
||||
char vcheck[VERSIONSIZE];
|
||||
char savename[255];
|
||||
|
||||
|
@ -4778,18 +4770,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
else
|
||||
sprintf(savename, savegamename, slot);
|
||||
|
||||
length = FIL_ReadFile(savename, &savebuffer);
|
||||
if (!length)
|
||||
savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf);
|
||||
if (!savebuffer.size)
|
||||
{
|
||||
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
|
||||
return;
|
||||
}
|
||||
|
||||
save_p = savebuffer;
|
||||
savebuffer.pos = 0;
|
||||
|
||||
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 *)&savebuffer.buf[savebuffer.pos], (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"),
|
||||
|
@ -4799,15 +4791,14 @@ 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(savebuffer.buf);
|
||||
|
||||
// no cheating!
|
||||
memset(&savedata, 0, sizeof(savedata));
|
||||
#endif
|
||||
return; // bad version
|
||||
}
|
||||
save_p += VERSIONSIZE;
|
||||
savebuffer.pos += VERSIONSIZE;
|
||||
|
||||
// if (demoplayback) // reset game engine
|
||||
// G_StopDemo();
|
||||
|
@ -4816,13 +4807,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
// automapactive = false;
|
||||
|
||||
// dearchive all the modifications
|
||||
if (!P_LoadGame(mapoverride))
|
||||
if (!P_LoadGame(&savebuffer, 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(savebuffer.buf);
|
||||
|
||||
// no cheating!
|
||||
memset(&savedata, 0, sizeof(savedata));
|
||||
|
@ -4830,13 +4820,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
}
|
||||
if (marathonmode)
|
||||
{
|
||||
marathontime = READUINT32(save_p);
|
||||
marathonmode |= READUINT8(save_p);
|
||||
marathontime = P_ReadUINT32(&savebuffer);
|
||||
marathonmode |= P_ReadUINT8(&savebuffer);
|
||||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
Z_Free(savebuffer.buf);
|
||||
|
||||
displayplayer = consoleplayer;
|
||||
multiplayer = splitscreen = false;
|
||||
|
@ -4854,6 +4843,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
//
|
||||
void G_SaveGame(UINT32 slot, INT16 mapnum)
|
||||
{
|
||||
save_t savebuffer;
|
||||
boolean saved;
|
||||
char savename[256] = "";
|
||||
const char *backup;
|
||||
|
@ -4867,33 +4857,32 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
|
|||
gameaction = ga_nothing;
|
||||
{
|
||||
char name[VERSIONSIZE];
|
||||
size_t length;
|
||||
|
||||
save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!save_p)
|
||||
savebuffer.size = SAVEGAMESIZE;
|
||||
savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
|
||||
if (!savebuffer.buf)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
|
||||
return;
|
||||
}
|
||||
savebuffer.pos = 0;
|
||||
|
||||
memset(name, 0, sizeof (name));
|
||||
sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION);
|
||||
WRITEMEM(save_p, name, VERSIONSIZE);
|
||||
P_WriteMem(&savebuffer, name, VERSIONSIZE);
|
||||
|
||||
P_SaveGame(mapnum);
|
||||
P_SaveGame(&savebuffer, 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));
|
||||
P_WriteUINT32(&savebuffer, writetime);
|
||||
P_WriteUINT8(&savebuffer, (marathonmode & ~MA_INIT));
|
||||
}
|
||||
|
||||
length = save_p - savebuffer;
|
||||
saved = FIL_WriteFile(backup, savebuffer, length);
|
||||
free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.pos);
|
||||
free(savebuffer.buf);
|
||||
}
|
||||
|
||||
gameaction = ga_nothing;
|
||||
|
@ -4905,11 +4894,10 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
|
|||
}
|
||||
|
||||
#define BADSAVE goto cleanup;
|
||||
#define CHECKPOS if (save_p >= end_p) BADSAVE
|
||||
void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
||||
{
|
||||
save_t savebuffer;
|
||||
boolean saved = false;
|
||||
size_t length;
|
||||
char vcheck[VERSIONSIZE];
|
||||
char savename[255];
|
||||
const char *backup;
|
||||
|
@ -4920,42 +4908,38 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
sprintf(savename, savegamename, slot);
|
||||
backup = va("%s",savename);
|
||||
|
||||
length = FIL_ReadFile(savename, &savebuffer);
|
||||
if (!length)
|
||||
savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf);
|
||||
if (!savebuffer.size)
|
||||
{
|
||||
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
|
||||
return;
|
||||
}
|
||||
|
||||
savebuffer.pos = 0;
|
||||
|
||||
{
|
||||
char temp[sizeof(timeattackfolder)];
|
||||
UINT8 *end_p = savebuffer + length;
|
||||
UINT8 *lives_p;
|
||||
SINT8 pllives;
|
||||
#ifdef NEWSKINSAVES
|
||||
INT16 backwardsCompat = 0;
|
||||
#endif
|
||||
|
||||
save_p = savebuffer;
|
||||
// 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 *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck)) BADSAVE
|
||||
savebuffer.pos += VERSIONSIZE;
|
||||
|
||||
// P_UnArchiveMisc()
|
||||
(void)READINT16(save_p);
|
||||
CHECKPOS
|
||||
(void)READUINT16(save_p); // emeralds
|
||||
CHECKPOS
|
||||
READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to
|
||||
(void)P_ReadINT16(&savebuffer);
|
||||
(void)P_ReadUINT16(&savebuffer); // emeralds
|
||||
P_ReadStringN(&savebuffer, temp, sizeof(temp)); // mod it belongs to
|
||||
if (strcmp(temp, timeattackfolder)) BADSAVE
|
||||
|
||||
// P_UnArchivePlayer()
|
||||
CHECKPOS
|
||||
#ifdef NEWSKINSAVES
|
||||
backwardsCompat = READUINT16(save_p);
|
||||
CHECKPOS
|
||||
backwardsCompat = P_ReadUINT16(&savebuffer);
|
||||
|
||||
if (backwardsCompat == NEWSKINSAVES) // New save, read skin names
|
||||
#endif
|
||||
|
@ -4963,47 +4947,37 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
char ourSkinName[SKINNAMESIZE+1];
|
||||
char botSkinName[SKINNAMESIZE+1];
|
||||
|
||||
READSTRINGN(save_p, ourSkinName, SKINNAMESIZE);
|
||||
CHECKPOS
|
||||
P_ReadStringN(&savebuffer, ourSkinName, SKINNAMESIZE);
|
||||
|
||||
READSTRINGN(save_p, botSkinName, SKINNAMESIZE);
|
||||
CHECKPOS
|
||||
P_ReadStringN(&savebuffer, botSkinName, SKINNAMESIZE);
|
||||
}
|
||||
|
||||
WRITEUINT8(save_p, numgameovers);
|
||||
CHECKPOS
|
||||
P_WriteUINT8(&savebuffer, numgameovers);
|
||||
|
||||
lives_p = save_p;
|
||||
pllives = READSINT8(save_p); // lives
|
||||
CHECKPOS
|
||||
lives_p = &savebuffer.buf[savebuffer.pos];
|
||||
pllives = P_ReadSINT8(&savebuffer); // lives
|
||||
if (modifylives && pllives < startinglivesbalance[numgameovers])
|
||||
{
|
||||
pllives = startinglivesbalance[numgameovers];
|
||||
WRITESINT8(lives_p, pllives);
|
||||
*lives_p = startinglivesbalance[numgameovers];
|
||||
}
|
||||
|
||||
(void)READINT32(save_p); // Score
|
||||
CHECKPOS
|
||||
(void)READINT32(save_p); // continues
|
||||
(void)P_ReadINT32(&savebuffer); // Score
|
||||
(void)P_ReadINT32(&savebuffer); // continues
|
||||
|
||||
// File end marker check
|
||||
CHECKPOS
|
||||
switch (READUINT8(save_p))
|
||||
switch (P_ReadUINT8(&savebuffer))
|
||||
{
|
||||
case 0xb7:
|
||||
{
|
||||
UINT8 i, banksinuse;
|
||||
CHECKPOS
|
||||
banksinuse = READUINT8(save_p);
|
||||
CHECKPOS
|
||||
banksinuse = P_ReadUINT8(&savebuffer);
|
||||
if (banksinuse > NUM_LUABANKS)
|
||||
BADSAVE
|
||||
for (i = 0; i < banksinuse; i++)
|
||||
{
|
||||
(void)READINT32(save_p);
|
||||
CHECKPOS
|
||||
(void)P_ReadINT32(&savebuffer);
|
||||
}
|
||||
if (READUINT8(save_p) != 0x1d)
|
||||
if (P_ReadUINT8(&savebuffer) != 0x1d)
|
||||
BADSAVE
|
||||
}
|
||||
case 0x1d:
|
||||
|
@ -5013,7 +4987,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
}
|
||||
|
||||
// done
|
||||
saved = FIL_WriteFile(backup, savebuffer, length);
|
||||
saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.size);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
@ -5021,11 +4995,9 @@ 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(savebuffer.buf);
|
||||
|
||||
}
|
||||
#undef CHECKPOS
|
||||
#undef BADSAVE
|
||||
|
||||
//
|
||||
|
|
281
src/lua_script.c
281
src/lua_script.c
|
@ -1098,7 +1098,7 @@ static UINT8 GetUserdataArchType(int index)
|
|||
return ARCH_NULL;
|
||||
}
|
||||
|
||||
static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
||||
static UINT8 ArchiveValue(save_t *save_p, int TABLESINDEX, int myindex)
|
||||
{
|
||||
if (myindex < 0)
|
||||
myindex = lua_gettop(gL)+1+myindex;
|
||||
|
@ -1106,34 +1106,34 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
case LUA_TNONE:
|
||||
case LUA_TNIL:
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
break;
|
||||
// This might be a problem. D:
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
case LUA_TTHREAD:
|
||||
case LUA_TFUNCTION:
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
return 2;
|
||||
case LUA_TBOOLEAN:
|
||||
WRITEUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE);
|
||||
P_WriteUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE);
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
{
|
||||
lua_Integer number = lua_tointeger(gL, myindex);
|
||||
if (number >= INT8_MIN && number <= INT8_MAX)
|
||||
{
|
||||
WRITEUINT8(save_p, ARCH_INT8);
|
||||
WRITESINT8(save_p, number);
|
||||
P_WriteUINT8(save_p, ARCH_INT8);
|
||||
P_WriteSINT8(save_p, number);
|
||||
}
|
||||
else if (number >= INT16_MIN && number <= INT16_MAX)
|
||||
{
|
||||
WRITEUINT8(save_p, ARCH_INT16);
|
||||
WRITEINT16(save_p, number);
|
||||
P_WriteUINT8(save_p, ARCH_INT16);
|
||||
P_WriteINT16(save_p, number);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITEUINT8(save_p, ARCH_INT32);
|
||||
WRITEFIXED(save_p, number);
|
||||
P_WriteUINT8(save_p, ARCH_INT32);
|
||||
P_WriteFixed(save_p, number);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1144,23 +1144,23 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
UINT32 i = 0;
|
||||
// if you're wondering why we're writing a string to save_p this way,
|
||||
// it turns out that Lua can have embedded zeros ('\0') in the strings,
|
||||
// so we can't use WRITESTRING as that cuts off when it finds a '\0'.
|
||||
// so we can't use P_WriteString as that cuts off when it finds a '\0'.
|
||||
// Saving the size of the string also allows us to get the size of the string on the other end,
|
||||
// fixing the awful crashes previously encountered for reading strings longer than 1024
|
||||
// (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?)
|
||||
// -- Monster Iestyn 05/08/18
|
||||
if (len < 255)
|
||||
{
|
||||
WRITEUINT8(save_p, ARCH_SMALLSTRING);
|
||||
WRITEUINT8(save_p, len); // save size of string
|
||||
P_WriteUINT8(save_p, ARCH_SMALLSTRING);
|
||||
P_WriteUINT8(save_p, len); // save size of string
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITEUINT8(save_p, ARCH_LARGESTRING);
|
||||
WRITEUINT32(save_p, len); // save size of string
|
||||
P_WriteUINT8(save_p, ARCH_LARGESTRING);
|
||||
P_WriteUINT32(save_p, len); // save size of string
|
||||
}
|
||||
while (i < len)
|
||||
WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros
|
||||
P_WriteChar(save_p, s[i++]); // write chars individually, including the embedded zeros
|
||||
break;
|
||||
}
|
||||
case LUA_TTABLE:
|
||||
|
@ -1186,13 +1186,13 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
if (t == 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WRITEUINT8(save_p, ARCH_TABLE);
|
||||
WRITEUINT16(save_p, t);
|
||||
P_WriteUINT8(save_p, ARCH_TABLE);
|
||||
P_WriteUINT16(save_p, t);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
|
@ -1208,25 +1208,25 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
case ARCH_MOBJINFO:
|
||||
{
|
||||
mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex));
|
||||
WRITEUINT8(save_p, ARCH_MOBJINFO);
|
||||
WRITEUINT16(save_p, info - mobjinfo);
|
||||
P_WriteUINT8(save_p, ARCH_MOBJINFO);
|
||||
P_WriteUINT16(save_p, info - mobjinfo);
|
||||
break;
|
||||
}
|
||||
case ARCH_STATE:
|
||||
{
|
||||
state_t *state = *((state_t **)lua_touserdata(gL, myindex));
|
||||
WRITEUINT8(save_p, ARCH_STATE);
|
||||
WRITEUINT16(save_p, state - states);
|
||||
P_WriteUINT8(save_p, ARCH_STATE);
|
||||
P_WriteUINT16(save_p, state - states);
|
||||
break;
|
||||
}
|
||||
case ARCH_MOBJ:
|
||||
{
|
||||
mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex));
|
||||
if (!mobj)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_MOBJ);
|
||||
WRITEUINT32(save_p, mobj->mobjnum);
|
||||
P_WriteUINT8(save_p, ARCH_MOBJ);
|
||||
P_WriteUINT32(save_p, mobj->mobjnum);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1234,10 +1234,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
player_t *player = *((player_t **)lua_touserdata(gL, myindex));
|
||||
if (!player)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_PLAYER);
|
||||
WRITEUINT8(save_p, player - players);
|
||||
P_WriteUINT8(save_p, ARCH_PLAYER);
|
||||
P_WriteUINT8(save_p, player - players);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1245,10 +1245,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex));
|
||||
if (!mapthing)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_MAPTHING);
|
||||
WRITEUINT16(save_p, mapthing - mapthings);
|
||||
P_WriteUINT8(save_p, ARCH_MAPTHING);
|
||||
P_WriteUINT16(save_p, mapthing - mapthings);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1256,10 +1256,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex));
|
||||
if (!vertex)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_VERTEX);
|
||||
WRITEUINT16(save_p, vertex - vertexes);
|
||||
P_WriteUINT8(save_p, ARCH_VERTEX);
|
||||
P_WriteUINT16(save_p, vertex - vertexes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1267,10 +1267,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
line_t *line = *((line_t **)lua_touserdata(gL, myindex));
|
||||
if (!line)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_LINE);
|
||||
WRITEUINT16(save_p, line - lines);
|
||||
P_WriteUINT8(save_p, ARCH_LINE);
|
||||
P_WriteUINT16(save_p, line - lines);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1278,10 +1278,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
side_t *side = *((side_t **)lua_touserdata(gL, myindex));
|
||||
if (!side)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_SIDE);
|
||||
WRITEUINT16(save_p, side - sides);
|
||||
P_WriteUINT8(save_p, ARCH_SIDE);
|
||||
P_WriteUINT16(save_p, side - sides);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1289,10 +1289,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex));
|
||||
if (!subsector)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_SUBSECTOR);
|
||||
WRITEUINT16(save_p, subsector - subsectors);
|
||||
P_WriteUINT8(save_p, ARCH_SUBSECTOR);
|
||||
P_WriteUINT16(save_p, subsector - subsectors);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1300,10 +1300,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex));
|
||||
if (!sector)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_SECTOR);
|
||||
WRITEUINT16(save_p, sector - sectors);
|
||||
P_WriteUINT8(save_p, ARCH_SECTOR);
|
||||
P_WriteUINT16(save_p, sector - sectors);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1312,10 +1312,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex));
|
||||
if (!seg)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_SEG);
|
||||
WRITEUINT16(save_p, seg - segs);
|
||||
P_WriteUINT8(save_p, ARCH_SEG);
|
||||
P_WriteUINT16(save_p, seg - segs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1323,10 +1323,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
node_t *node = *((node_t **)lua_touserdata(gL, myindex));
|
||||
if (!node)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_NODE);
|
||||
WRITEUINT16(save_p, node - nodes);
|
||||
P_WriteUINT8(save_p, ARCH_NODE);
|
||||
P_WriteUINT16(save_p, node - nodes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1335,16 +1335,16 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex));
|
||||
if (!rover)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
UINT16 i = P_GetFFloorID(rover);
|
||||
if (i == UINT16_MAX) // invalid ID
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else
|
||||
{
|
||||
WRITEUINT8(save_p, ARCH_FFLOOR);
|
||||
WRITEUINT16(save_p, rover->target - sectors);
|
||||
WRITEUINT16(save_p, i);
|
||||
P_WriteUINT8(save_p, ARCH_FFLOOR);
|
||||
P_WriteUINT16(save_p, rover->target - sectors);
|
||||
P_WriteUINT16(save_p, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1353,10 +1353,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex));
|
||||
if (!polyobj)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_POLYOBJ);
|
||||
WRITEUINT16(save_p, polyobj-PolyObjects);
|
||||
P_WriteUINT8(save_p, ARCH_POLYOBJ);
|
||||
P_WriteUINT16(save_p, polyobj-PolyObjects);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1364,10 +1364,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex));
|
||||
if (!slope)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_SLOPE);
|
||||
WRITEUINT16(save_p, slope->id);
|
||||
P_WriteUINT8(save_p, ARCH_SLOPE);
|
||||
P_WriteUINT16(save_p, slope->id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1375,36 +1375,36 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
{
|
||||
mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
|
||||
if (!header)
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
else {
|
||||
WRITEUINT8(save_p, ARCH_MAPHEADER);
|
||||
WRITEUINT16(save_p, header - *mapheaderinfo);
|
||||
P_WriteUINT8(save_p, ARCH_MAPHEADER);
|
||||
P_WriteUINT16(save_p, header - *mapheaderinfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARCH_SKINCOLOR:
|
||||
{
|
||||
skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex));
|
||||
WRITEUINT8(save_p, ARCH_SKINCOLOR);
|
||||
WRITEUINT16(save_p, info - skincolors);
|
||||
P_WriteUINT8(save_p, ARCH_SKINCOLOR);
|
||||
P_WriteUINT16(save_p, info - skincolors);
|
||||
break;
|
||||
}
|
||||
case ARCH_MOUSE:
|
||||
{
|
||||
mouse_t *m = *((mouse_t **)lua_touserdata(gL, myindex));
|
||||
WRITEUINT8(save_p, ARCH_MOUSE);
|
||||
WRITEUINT8(save_p, m == &mouse ? 1 : 2);
|
||||
P_WriteUINT8(save_p, ARCH_MOUSE);
|
||||
P_WriteUINT8(save_p, m == &mouse ? 1 : 2);
|
||||
break;
|
||||
}
|
||||
case ARCH_SKIN:
|
||||
{
|
||||
skin_t *skin = *((skin_t **)lua_touserdata(gL, myindex));
|
||||
WRITEUINT8(save_p, ARCH_SKIN);
|
||||
WRITEUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256
|
||||
P_WriteUINT8(save_p, ARCH_SKIN);
|
||||
P_WriteUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
P_WriteUINT8(save_p, ARCH_NULL);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
|
@ -1412,14 +1412,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ArchiveExtVars(void *pointer, const char *ptype)
|
||||
static void ArchiveExtVars(save_t *save_p, void *pointer, const char *ptype)
|
||||
{
|
||||
int TABLESINDEX;
|
||||
UINT16 i;
|
||||
|
||||
if (!gL) {
|
||||
if (fastcmp(ptype,"player")) // players must always be included, even if no vars
|
||||
WRITEUINT16(save_p, 0);
|
||||
P_WriteUINT16(save_p, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1435,7 +1435,7 @@ static void ArchiveExtVars(void *pointer, const char *ptype)
|
|||
{ // no extra values table
|
||||
lua_pop(gL, 1);
|
||||
if (fastcmp(ptype,"player")) // players must always be included, even if no vars
|
||||
WRITEUINT16(save_p, 0);
|
||||
P_WriteUINT16(save_p, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1447,20 +1447,20 @@ static void ArchiveExtVars(void *pointer, const char *ptype)
|
|||
if (i == 0)
|
||||
{
|
||||
if (fastcmp(ptype,"player")) // always include players even if they have no extra variables
|
||||
WRITEUINT16(save_p, 0);
|
||||
P_WriteUINT16(save_p, 0);
|
||||
lua_pop(gL, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header
|
||||
WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum);
|
||||
WRITEUINT16(save_p, i);
|
||||
P_WriteUINT32(save_p, ((mobj_t *)pointer)->mobjnum);
|
||||
P_WriteUINT16(save_p, i);
|
||||
lua_pushnil(gL);
|
||||
while (lua_next(gL, -2))
|
||||
{
|
||||
I_Assert(lua_type(gL, -2) == LUA_TSTRING);
|
||||
WRITESTRING(save_p, lua_tostring(gL, -2));
|
||||
if (ArchiveValue(TABLESINDEX, -1) == 2)
|
||||
P_WriteString(save_p, lua_tostring(gL, -2));
|
||||
if (ArchiveValue(save_p, TABLESINDEX, -1) == 2)
|
||||
CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1));
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
|
@ -1468,16 +1468,19 @@ static void ArchiveExtVars(void *pointer, const char *ptype)
|
|||
lua_pop(gL, 1);
|
||||
}
|
||||
|
||||
// FIXME: remove and pass as local variable
|
||||
static save_t *lua_save_p;
|
||||
|
||||
static int NetArchive(lua_State *L)
|
||||
{
|
||||
int TABLESINDEX = lua_upvalueindex(1);
|
||||
int i, n = lua_gettop(L);
|
||||
for (i = 1; i <= n; i++)
|
||||
ArchiveValue(TABLESINDEX, i);
|
||||
ArchiveValue(lua_save_p, TABLESINDEX, i);
|
||||
return n;
|
||||
}
|
||||
|
||||
static void ArchiveTables(void)
|
||||
static void ArchiveTables(save_t *save_p)
|
||||
{
|
||||
int TABLESINDEX;
|
||||
UINT16 i, n;
|
||||
|
@ -1496,14 +1499,14 @@ static void ArchiveTables(void)
|
|||
while (lua_next(gL, -2))
|
||||
{
|
||||
// Write key
|
||||
e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
|
||||
e = ArchiveValue(save_p, TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
|
||||
if (e == 1)
|
||||
n++; // the table contained a new table we'll have to archive. :(
|
||||
else if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise)
|
||||
CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i);
|
||||
|
||||
// Write value
|
||||
e = ArchiveValue(TABLESINDEX, -1);
|
||||
e = ArchiveValue(save_p, TABLESINDEX, -1);
|
||||
if (e == 1)
|
||||
n++; // the table contained a new table we'll have to archive. :(
|
||||
else if (e == 2) // invalid value type
|
||||
|
@ -1511,7 +1514,7 @@ static void ArchiveTables(void)
|
|||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
WRITEUINT8(save_p, ARCH_TEND);
|
||||
P_WriteUINT8(save_p, ARCH_TEND);
|
||||
|
||||
// Write metatable ID
|
||||
if (lua_getmetatable(gL, -1))
|
||||
|
@ -1520,19 +1523,19 @@ static void ArchiveTables(void)
|
|||
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
|
||||
lua_pushvalue(gL, -2);
|
||||
lua_gettable(gL, -2);
|
||||
WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
|
||||
P_WriteUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
|
||||
lua_pop(gL, 3);
|
||||
}
|
||||
else
|
||||
WRITEUINT16(save_p, 0);
|
||||
P_WriteUINT16(save_p, 0);
|
||||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 UnArchiveValue(int TABLESINDEX)
|
||||
static UINT8 UnArchiveValue(save_t *save_p, int TABLESINDEX)
|
||||
{
|
||||
UINT8 type = READUINT8(save_p);
|
||||
UINT8 type = P_ReadUINT8(save_p);
|
||||
switch (type)
|
||||
{
|
||||
case ARCH_NULL:
|
||||
|
@ -1545,13 +1548,13 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
|
|||
lua_pushboolean(gL, false);
|
||||
break;
|
||||
case ARCH_INT8:
|
||||
lua_pushinteger(gL, READSINT8(save_p));
|
||||
lua_pushinteger(gL, P_ReadSINT8(save_p));
|
||||
break;
|
||||
case ARCH_INT16:
|
||||
lua_pushinteger(gL, READINT16(save_p));
|
||||
lua_pushinteger(gL, P_ReadINT16(save_p));
|
||||
break;
|
||||
case ARCH_INT32:
|
||||
lua_pushinteger(gL, READFIXED(save_p));
|
||||
lua_pushinteger(gL, P_ReadFixed(save_p));
|
||||
break;
|
||||
case ARCH_SMALLSTRING:
|
||||
case ARCH_LARGESTRING:
|
||||
|
@ -1562,23 +1565,23 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
|
|||
|
||||
// See my comments in the ArchiveValue function;
|
||||
// it's much the same for reading strings as writing them!
|
||||
// (i.e. we can't use READSTRING either)
|
||||
// (i.e. we can't use P_ReadString either)
|
||||
// -- Monster Iestyn 05/08/18
|
||||
if (type == ARCH_SMALLSTRING)
|
||||
len = READUINT8(save_p); // length of string, including embedded zeros
|
||||
len = P_ReadUINT8(save_p); // length of string, including embedded zeros
|
||||
else
|
||||
len = READUINT32(save_p); // length of string, including embedded zeros
|
||||
len = P_ReadUINT32(save_p); // length of string, including embedded zeros
|
||||
value = malloc(len); // make temp buffer of size len
|
||||
// now read the actual string
|
||||
while (i < len)
|
||||
value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros
|
||||
value[i++] = P_ReadChar(save_p); // read chars individually, including the embedded zeros
|
||||
lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros)
|
||||
free(value); // free the buffer
|
||||
break;
|
||||
}
|
||||
case ARCH_TABLE:
|
||||
{
|
||||
UINT16 tid = READUINT16(save_p);
|
||||
UINT16 tid = P_ReadUINT16(save_p);
|
||||
lua_rawgeti(gL, TABLESINDEX, tid);
|
||||
if (lua_isnil(gL, -1))
|
||||
{
|
||||
|
@ -1591,69 +1594,69 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
|
|||
break;
|
||||
}
|
||||
case ARCH_MOBJINFO:
|
||||
LUA_PushUserdata(gL, &mobjinfo[READUINT16(save_p)], META_MOBJINFO);
|
||||
LUA_PushUserdata(gL, &mobjinfo[P_ReadUINT16(save_p)], META_MOBJINFO);
|
||||
break;
|
||||
case ARCH_STATE:
|
||||
LUA_PushUserdata(gL, &states[READUINT16(save_p)], META_STATE);
|
||||
LUA_PushUserdata(gL, &states[P_ReadUINT16(save_p)], META_STATE);
|
||||
break;
|
||||
case ARCH_MOBJ:
|
||||
LUA_PushUserdata(gL, P_FindNewPosition(READUINT32(save_p)), META_MOBJ);
|
||||
LUA_PushUserdata(gL, P_FindNewPosition(P_ReadUINT32(save_p)), META_MOBJ);
|
||||
break;
|
||||
case ARCH_PLAYER:
|
||||
LUA_PushUserdata(gL, &players[READUINT8(save_p)], META_PLAYER);
|
||||
LUA_PushUserdata(gL, &players[P_ReadUINT8(save_p)], META_PLAYER);
|
||||
break;
|
||||
case ARCH_MAPTHING:
|
||||
LUA_PushUserdata(gL, &mapthings[READUINT16(save_p)], META_MAPTHING);
|
||||
LUA_PushUserdata(gL, &mapthings[P_ReadUINT16(save_p)], META_MAPTHING);
|
||||
break;
|
||||
case ARCH_VERTEX:
|
||||
LUA_PushUserdata(gL, &vertexes[READUINT16(save_p)], META_VERTEX);
|
||||
LUA_PushUserdata(gL, &vertexes[P_ReadUINT16(save_p)], META_VERTEX);
|
||||
break;
|
||||
case ARCH_LINE:
|
||||
LUA_PushUserdata(gL, &lines[READUINT16(save_p)], META_LINE);
|
||||
LUA_PushUserdata(gL, &lines[P_ReadUINT16(save_p)], META_LINE);
|
||||
break;
|
||||
case ARCH_SIDE:
|
||||
LUA_PushUserdata(gL, &sides[READUINT16(save_p)], META_SIDE);
|
||||
LUA_PushUserdata(gL, &sides[P_ReadUINT16(save_p)], META_SIDE);
|
||||
break;
|
||||
case ARCH_SUBSECTOR:
|
||||
LUA_PushUserdata(gL, &subsectors[READUINT16(save_p)], META_SUBSECTOR);
|
||||
LUA_PushUserdata(gL, &subsectors[P_ReadUINT16(save_p)], META_SUBSECTOR);
|
||||
break;
|
||||
case ARCH_SECTOR:
|
||||
LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_SECTOR);
|
||||
LUA_PushUserdata(gL, §ors[P_ReadUINT16(save_p)], META_SECTOR);
|
||||
break;
|
||||
#ifdef HAVE_LUA_SEGS
|
||||
case ARCH_SEG:
|
||||
LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG);
|
||||
LUA_PushUserdata(gL, &segs[P_ReadUINT16(save_p)], META_SEG);
|
||||
break;
|
||||
case ARCH_NODE:
|
||||
LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE);
|
||||
LUA_PushUserdata(gL, &nodes[P_ReadUINT16(save_p)], META_NODE);
|
||||
break;
|
||||
#endif
|
||||
case ARCH_FFLOOR:
|
||||
{
|
||||
sector_t *sector = §ors[READUINT16(save_p)];
|
||||
UINT16 id = READUINT16(save_p);
|
||||
sector_t *sector = §ors[P_ReadUINT16(save_p)];
|
||||
UINT16 id = P_ReadUINT16(save_p);
|
||||
ffloor_t *rover = P_GetFFloorByID(sector, id);
|
||||
if (rover)
|
||||
LUA_PushUserdata(gL, rover, META_FFLOOR);
|
||||
break;
|
||||
}
|
||||
case ARCH_POLYOBJ:
|
||||
LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ);
|
||||
LUA_PushUserdata(gL, &PolyObjects[P_ReadUINT16(save_p)], META_POLYOBJ);
|
||||
break;
|
||||
case ARCH_SLOPE:
|
||||
LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE);
|
||||
LUA_PushUserdata(gL, P_SlopeById(P_ReadUINT16(save_p)), META_SLOPE);
|
||||
break;
|
||||
case ARCH_MAPHEADER:
|
||||
LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER);
|
||||
LUA_PushUserdata(gL, mapheaderinfo[P_ReadUINT16(save_p)], META_MAPHEADER);
|
||||
break;
|
||||
case ARCH_SKINCOLOR:
|
||||
LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR);
|
||||
LUA_PushUserdata(gL, &skincolors[P_ReadUINT16(save_p)], META_SKINCOLOR);
|
||||
break;
|
||||
case ARCH_MOUSE:
|
||||
LUA_PushUserdata(gL, READUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE);
|
||||
LUA_PushUserdata(gL, P_ReadUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE);
|
||||
break;
|
||||
case ARCH_SKIN:
|
||||
LUA_PushUserdata(gL, skins[READUINT8(save_p)], META_SKIN);
|
||||
LUA_PushUserdata(gL, skins[P_ReadUINT8(save_p)], META_SKIN);
|
||||
break;
|
||||
case ARCH_TEND:
|
||||
return 1;
|
||||
|
@ -1661,10 +1664,10 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void UnArchiveExtVars(void *pointer)
|
||||
static void UnArchiveExtVars(save_t *save_p, void *pointer)
|
||||
{
|
||||
int TABLESINDEX;
|
||||
UINT16 field_count = READUINT16(save_p);
|
||||
UINT16 field_count = P_ReadUINT16(save_p);
|
||||
UINT16 i;
|
||||
char field[1024];
|
||||
|
||||
|
@ -1677,8 +1680,8 @@ static void UnArchiveExtVars(void *pointer)
|
|||
|
||||
for (i = 0; i < field_count; i++)
|
||||
{
|
||||
READSTRING(save_p, field);
|
||||
UnArchiveValue(TABLESINDEX);
|
||||
P_ReadString(save_p, field);
|
||||
UnArchiveValue(save_p, TABLESINDEX);
|
||||
lua_setfield(gL, -2, field);
|
||||
}
|
||||
|
||||
|
@ -1695,11 +1698,11 @@ static int NetUnArchive(lua_State *L)
|
|||
int TABLESINDEX = lua_upvalueindex(1);
|
||||
int i, n = lua_gettop(L);
|
||||
for (i = 1; i <= n; i++)
|
||||
UnArchiveValue(TABLESINDEX);
|
||||
UnArchiveValue(lua_save_p, TABLESINDEX);
|
||||
return n;
|
||||
}
|
||||
|
||||
static void UnArchiveTables(void)
|
||||
static void UnArchiveTables(save_t *save_p)
|
||||
{
|
||||
int TABLESINDEX;
|
||||
UINT16 i, n;
|
||||
|
@ -1716,13 +1719,13 @@ static void UnArchiveTables(void)
|
|||
lua_rawgeti(gL, TABLESINDEX, i);
|
||||
while (true)
|
||||
{
|
||||
UINT8 e = UnArchiveValue(TABLESINDEX); // read key
|
||||
UINT8 e = UnArchiveValue(save_p, TABLESINDEX); // read key
|
||||
if (e == 1) // End of table
|
||||
break;
|
||||
else if (e == 2) // Key contains a new table
|
||||
n++;
|
||||
|
||||
if (UnArchiveValue(TABLESINDEX) == 2) // read value
|
||||
if (UnArchiveValue(save_p, TABLESINDEX) == 2) // read value
|
||||
n++;
|
||||
|
||||
if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved)
|
||||
|
@ -1734,7 +1737,7 @@ static void UnArchiveTables(void)
|
|||
lua_rawset(gL, -3);
|
||||
}
|
||||
|
||||
metatableid = READUINT16(save_p);
|
||||
metatableid = P_ReadUINT16(save_p);
|
||||
if (metatableid)
|
||||
{
|
||||
// setmetatable(table, registry.metatables[metatableid])
|
||||
|
@ -1758,7 +1761,7 @@ void LUA_Step(void)
|
|||
lua_gc(gL, LUA_GCSTEP, 1);
|
||||
}
|
||||
|
||||
void LUA_Archive(void)
|
||||
void LUA_Archive(save_t *save_p)
|
||||
{
|
||||
INT32 i;
|
||||
thinker_t *th;
|
||||
|
@ -1771,7 +1774,7 @@ void LUA_Archive(void)
|
|||
if (!playeringame[i] && i > 0) // dedicated servers...
|
||||
continue;
|
||||
// all players in game will be archived, even if they just add a 0.
|
||||
ArchiveExtVars(&players[i], "player");
|
||||
ArchiveExtVars(save_p, &players[i], "player");
|
||||
}
|
||||
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
|
@ -1781,19 +1784,20 @@ void LUA_Archive(void)
|
|||
|
||||
// archive function will determine when to skip mobjs,
|
||||
// and write mobjnum in otherwise.
|
||||
ArchiveExtVars(th, "mobj");
|
||||
ArchiveExtVars(save_p, th, "mobj");
|
||||
}
|
||||
|
||||
WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
|
||||
P_WriteUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
|
||||
|
||||
lua_save_p = save_p;
|
||||
LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode
|
||||
ArchiveTables();
|
||||
ArchiveTables(save_p);
|
||||
|
||||
if (gL)
|
||||
lua_pop(gL, 1); // pop tables
|
||||
}
|
||||
|
||||
void LUA_UnArchive(void)
|
||||
void LUA_UnArchive(save_t *save_p)
|
||||
{
|
||||
UINT32 mobjnum;
|
||||
INT32 i;
|
||||
|
@ -1806,23 +1810,24 @@ void LUA_UnArchive(void)
|
|||
{
|
||||
if (!playeringame[i] && i > 0) // dedicated servers...
|
||||
continue;
|
||||
UnArchiveExtVars(&players[i]);
|
||||
UnArchiveExtVars(save_p, &players[i]);
|
||||
}
|
||||
|
||||
do {
|
||||
mobjnum = READUINT32(save_p); // read a mobjnum
|
||||
mobjnum = P_ReadUINT32(save_p); // read a mobjnum
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
|
||||
continue;
|
||||
UnArchiveExtVars(th); // apply variables
|
||||
UnArchiveExtVars(save_p, th); // apply variables
|
||||
}
|
||||
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
|
||||
|
||||
lua_save_p = save_p;
|
||||
LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode
|
||||
UnArchiveTables();
|
||||
UnArchiveTables(save_p);
|
||||
|
||||
if (gL)
|
||||
lua_pop(gL, 1); // pop tables
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#ifndef LUA_SCRIPT_H
|
||||
#define LUA_SCRIPT_H
|
||||
|
||||
#include "p_saveg.h"
|
||||
#include "m_fixed.h"
|
||||
#include "doomtype.h"
|
||||
#include "d_player.h"
|
||||
|
@ -52,8 +53,8 @@ void LUA_DumpFile(const char *filename);
|
|||
#endif
|
||||
fixed_t LUA_EvalMath(const char *word);
|
||||
void LUA_Step(void);
|
||||
void LUA_Archive(void);
|
||||
void LUA_UnArchive(void);
|
||||
void LUA_Archive(save_t *save_p);
|
||||
void LUA_UnArchive(save_t *save_p);
|
||||
int LUA_PushGlobals(lua_State *L, const char *word);
|
||||
int LUA_CheckGlobals(lua_State *L, const char *word);
|
||||
void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
|
||||
|
|
|
@ -4799,12 +4799,11 @@ static void Command_Togglemodified_f(void)
|
|||
modifiedgame = !modifiedgame;
|
||||
}
|
||||
|
||||
extern UINT8 *save_p;
|
||||
static void Command_Archivetest_f(void)
|
||||
{
|
||||
UINT8 *buf;
|
||||
UINT32 i, wrote;
|
||||
thinker_t *th;
|
||||
save_t savebuffer;
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
CONS_Printf("This command only works in-game, you dummy.\n");
|
||||
|
@ -4818,28 +4817,29 @@ static void Command_Archivetest_f(void)
|
|||
((mobj_t *)th)->mobjnum = i++;
|
||||
|
||||
// allocate buffer
|
||||
buf = save_p = ZZ_Alloc(1024);
|
||||
savebuffer.size = 1024;
|
||||
savebuffer.buf = malloc(savebuffer.size);
|
||||
savebuffer.pos = 0;
|
||||
|
||||
// test archive
|
||||
CONS_Printf("LUA_Archive...\n");
|
||||
LUA_Archive();
|
||||
WRITEUINT8(save_p, 0x7F);
|
||||
wrote = (UINT32)(save_p-buf);
|
||||
LUA_Archive(&savebuffer);
|
||||
P_WriteUINT8(&savebuffer, 0x7F);
|
||||
wrote = savebuffer.pos;
|
||||
|
||||
// clear Lua state, so we can really see what happens!
|
||||
CONS_Printf("Clearing state!\n");
|
||||
LUA_ClearExtVars();
|
||||
|
||||
// test unarchive
|
||||
save_p = buf;
|
||||
CONS_Printf("LUA_UnArchive...\n");
|
||||
LUA_UnArchive();
|
||||
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(&savebuffer);
|
||||
i = P_ReadUINT8(&savebuffer);
|
||||
if (i != 0x7F || wrote != (UINT32)(savebuffer.pos))
|
||||
CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(savebuffer.pos));
|
||||
|
||||
// free buffer
|
||||
Z_Free(buf);
|
||||
free(savebuffer.buf);
|
||||
CONS_Printf("Done. No crash.\n");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -54,30 +54,25 @@ boolean SV_ResendingSavegameToAnyone(void)
|
|||
void SV_SendSaveGame(INT32 node, boolean resending)
|
||||
{
|
||||
size_t length, compressedlen;
|
||||
UINT8 *savebuffer;
|
||||
save_t savebuffer;
|
||||
UINT8 *compressedsave;
|
||||
UINT8 *buffertosend;
|
||||
|
||||
// first save it in a malloced buffer
|
||||
savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!savebuffer)
|
||||
savebuffer.size = SAVEGAMESIZE;
|
||||
savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
|
||||
if (!savebuffer.buf)
|
||||
{
|
||||
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);
|
||||
savebuffer.pos = sizeof(UINT32);
|
||||
|
||||
P_SaveNetGame(resending);
|
||||
P_SaveNetGame(&savebuffer, resending);
|
||||
|
||||
length = save_p - savebuffer;
|
||||
if (length > SAVEGAMESIZE)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
I_Error("Savegame buffer overrun");
|
||||
}
|
||||
length = savebuffer.pos;
|
||||
|
||||
// Allocate space for compressed save: one byte fewer than for the
|
||||
// uncompressed data to ensure that the compression is worthwhile.
|
||||
|
@ -89,11 +84,11 @@ 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(savebuffer.buf + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1)))
|
||||
{
|
||||
// Compressing succeeded; send compressed data
|
||||
|
||||
free(savebuffer);
|
||||
free(savebuffer.buf);
|
||||
|
||||
// State that we're compressed.
|
||||
buffertosend = compressedsave;
|
||||
|
@ -107,12 +102,12 @@ void SV_SendSaveGame(INT32 node, boolean resending)
|
|||
free(compressedsave);
|
||||
|
||||
// State that we're not compressed
|
||||
buffertosend = savebuffer;
|
||||
WRITEUINT32(savebuffer, 0);
|
||||
buffertosend = savebuffer.buf;
|
||||
savebuffer.pos = 0;
|
||||
P_WriteUINT32(&savebuffer, 0);
|
||||
}
|
||||
|
||||
AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0);
|
||||
save_p = NULL;
|
||||
|
||||
// Remember when we started sending the savegame so we can handle timeouts
|
||||
netnodes[node].sendingsavegame = true;
|
||||
|
@ -125,8 +120,7 @@ static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SA
|
|||
|
||||
void SV_SavedGame(void)
|
||||
{
|
||||
size_t length;
|
||||
UINT8 *savebuffer;
|
||||
save_t savebuffer;
|
||||
char tmpsave[256];
|
||||
|
||||
if (!cv_dumpconsistency.value)
|
||||
|
@ -135,29 +129,22 @@ 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)
|
||||
savebuffer.size = SAVEGAMESIZE;
|
||||
savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
|
||||
if (!savebuffer.buf)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
|
||||
return;
|
||||
}
|
||||
savebuffer.pos = 0;
|
||||
|
||||
P_SaveNetGame(false);
|
||||
|
||||
length = save_p - savebuffer;
|
||||
if (length > SAVEGAMESIZE)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
I_Error("Savegame buffer overrun");
|
||||
}
|
||||
P_SaveNetGame(&savebuffer, false);
|
||||
|
||||
// then save it!
|
||||
if (!FIL_WriteFile(tmpsave, savebuffer, length))
|
||||
if (!FIL_WriteFile(tmpsave, savebuffer.buf, savebuffer.pos))
|
||||
CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave);
|
||||
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
free(savebuffer.pos);
|
||||
}
|
||||
|
||||
#undef TMPSAVENAME
|
||||
|
@ -167,33 +154,34 @@ void SV_SavedGame(void)
|
|||
|
||||
void CL_LoadReceivedSavegame(boolean reloading)
|
||||
{
|
||||
UINT8 *savebuffer = NULL;
|
||||
size_t length, decompressedlen;
|
||||
save_t savebuffer;
|
||||
size_t decompressedlen;
|
||||
char tmpsave[256];
|
||||
|
||||
FreeFileNeeded();
|
||||
|
||||
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
|
||||
|
||||
length = FIL_ReadFile(tmpsave, &savebuffer);
|
||||
savebuffer.size = FIL_ReadFile(tmpsave, &savebuffer.buf);
|
||||
savebuffer.pos = 0;
|
||||
|
||||
CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length));
|
||||
if (!length)
|
||||
CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(savebuffer.size));
|
||||
if (!savebuffer.size)
|
||||
{
|
||||
I_Error("Can't read savegame sent");
|
||||
return;
|
||||
}
|
||||
|
||||
save_p = savebuffer;
|
||||
|
||||
// Decompress saved game if necessary.
|
||||
decompressedlen = READUINT32(save_p);
|
||||
decompressedlen = P_ReadUINT32(&savebuffer);
|
||||
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(savebuffer.buf + sizeof(UINT32), savebuffer.size - sizeof(UINT32), decompressedbuffer, decompressedlen);
|
||||
Z_Free(savebuffer.buf);
|
||||
savebuffer.buf = decompressedbuffer;
|
||||
savebuffer.size = decompressedlen;
|
||||
savebuffer.pos = 0;
|
||||
}
|
||||
|
||||
paused = false;
|
||||
|
@ -203,7 +191,7 @@ void CL_LoadReceivedSavegame(boolean reloading)
|
|||
automapactive = false;
|
||||
|
||||
// load a base level
|
||||
if (P_LoadNetGame(reloading))
|
||||
if (P_LoadNetGame(&savebuffer, reloading))
|
||||
{
|
||||
const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
|
||||
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
|
||||
|
@ -219,8 +207,7 @@ void CL_LoadReceivedSavegame(boolean reloading)
|
|||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
Z_Free(savebuffer.buf);
|
||||
if (unlink(tmpsave) == -1)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
|
||||
consistancy[gametic%BACKUPTICS] = Consistancy();
|
||||
|
|
|
@ -539,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo);
|
|||
void P_PlayerZMovement(mobj_t *mo);
|
||||
void P_EmeraldManager(void);
|
||||
|
||||
mobj_t *P_FindNewPosition(UINT32 oldposition);
|
||||
|
||||
extern INT32 modulothing;
|
||||
|
||||
#define MAXHUNTEMERALDS 64
|
||||
|
|
3543
src/p_saveg.c
3543
src/p_saveg.c
File diff suppressed because it is too large
Load diff
|
@ -18,17 +18,24 @@
|
|||
#pragma interface
|
||||
#endif
|
||||
|
||||
#include "tables.h"
|
||||
|
||||
#define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility)
|
||||
|
||||
// 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);
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} save_t;
|
||||
|
||||
mobj_t *P_FindNewPosition(UINT32 oldposition);
|
||||
void P_SaveGame(save_t *save_p, INT16 mapnum);
|
||||
void P_SaveNetGame(save_t *save_p, boolean resending);
|
||||
boolean P_LoadGame(save_t *save_p, INT16 mapoverride);
|
||||
boolean P_LoadNetGame(save_t *save_p, boolean reloading);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -42,6 +49,37 @@ typedef struct
|
|||
} savedata_t;
|
||||
|
||||
extern savedata_t savedata;
|
||||
extern UINT8 *save_p;
|
||||
|
||||
void P_WriteUINT8(save_t *p, UINT8 v);
|
||||
void P_WriteSINT8(save_t *p, SINT8 v);
|
||||
void P_WriteUINT16(save_t *p, UINT16 v);
|
||||
void P_WriteINT16(save_t *p, INT16 v);
|
||||
void P_WriteUINT32(save_t *p, UINT32 v);
|
||||
void P_WriteINT32(save_t *p, INT32 v);
|
||||
void P_WriteChar(save_t *p, char v);
|
||||
void P_WriteFixed(save_t *p, fixed_t v);
|
||||
void P_WriteAngle(save_t *p, angle_t v);
|
||||
void P_WriteStringN(save_t *p, char const *s, size_t n);
|
||||
void P_WriteStringL(save_t *p, char const *s, size_t n);
|
||||
void P_WriteString(save_t *p, char const *s);
|
||||
void P_WriteMem(save_t *p, void const *s, size_t n);
|
||||
|
||||
void P_SkipStringN(save_t *p, size_t n);
|
||||
void P_SkipStringL(save_t *p, size_t n);
|
||||
void P_SkipString(save_t *p);
|
||||
|
||||
UINT8 P_ReadUINT8(save_t *p);
|
||||
SINT8 P_ReadSINT8(save_t *p);
|
||||
UINT16 P_ReadUINT16(save_t *p);
|
||||
INT16 P_ReadINT16(save_t *p);
|
||||
UINT32 P_ReadUINT32(save_t *p);
|
||||
INT32 P_ReadINT32(save_t *p);
|
||||
char P_ReadChar(save_t *p);
|
||||
fixed_t P_ReadFixed(save_t *p);
|
||||
angle_t P_ReadAngle(save_t *p);
|
||||
void P_ReadStringN(save_t *p, char *s, size_t n);
|
||||
void P_ReadStringL(save_t *p, char *s, size_t n);
|
||||
void P_ReadString(save_t *p, char *s);
|
||||
void P_ReadMem(save_t *p, void *s, size_t n);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue