move savegame buffer size check to saveg_write* functions (#2235)

* Inline `saveg_write*` and `saveg_read*` functions for minor speedup.

* Simplify save buffer size checks.
This commit is contained in:
Roman Fomin 2025-04-04 13:42:30 +07:00 committed by GitHub
parent bea52a7cf9
commit 4b8e9f7cd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 129 additions and 193 deletions

View File

@ -99,7 +99,7 @@
#define SAVEGAMESIZE 0x20000 #define SAVEGAMESIZE 0x20000
#define SAVESTRINGSIZE 24 #define SAVESTRINGSIZE 24
static size_t savegamesize = SAVEGAMESIZE; // killough size_t savegamesize = SAVEGAMESIZE; // killough
static char *demoname = NULL; static char *demoname = NULL;
// the original name of the demo, without "-00000" and file extension // the original name of the demo, without "-00000" and file extension
static char *demoname_orig = NULL; static char *demoname_orig = NULL;
@ -2311,16 +2311,6 @@ void G_SaveGame(int slot, char *description)
sendsave = true; sendsave = true;
} }
// Check for overrun and realloc if necessary -- Lee Killough 1/22/98
void CheckSaveGame(size_t size)
{
size_t pos = save_p - savebuffer;
size += 1024; // breathing room
if (pos+size > savegamesize)
save_p = (savebuffer = Z_Realloc(savebuffer,
savegamesize += (size+1023) & ~1023, PU_STATIC, 0)) + pos;
}
// killough 3/22/98: form savegame name in one location // killough 3/22/98: form savegame name in one location
// (previously code was scattered around in multiple places) // (previously code was scattered around in multiple places)
@ -2412,7 +2402,7 @@ static void DoSaveGame(char *name)
save_p = savebuffer = Z_Malloc(savegamesize, PU_STATIC, 0); save_p = savebuffer = Z_Malloc(savegamesize, PU_STATIC, 0);
CheckSaveGame(SAVESTRINGSIZE+VERSIONSIZE+sizeof(uint64_t)); saveg_buffer_size(SAVESTRINGSIZE + VERSIONSIZE);
memcpy (save_p, description, SAVESTRINGSIZE); memcpy (save_p, description, SAVESTRINGSIZE);
save_p += SAVESTRINGSIZE; save_p += SAVESTRINGSIZE;
memset (name2,0,sizeof(name2)); memset (name2,0,sizeof(name2));
@ -2424,14 +2414,14 @@ static void DoSaveGame(char *name)
memcpy (save_p, name2, VERSIONSIZE); memcpy (save_p, name2, VERSIONSIZE);
save_p += VERSIONSIZE; save_p += VERSIONSIZE;
*save_p++ = demo_version; saveg_write8(demo_version);
// killough 2/14/98: save old compatibility flag: // killough 2/14/98: save old compatibility flag:
*save_p++ = compatibility; saveg_write8(compatibility);
*save_p++ = gameskill; saveg_write8(gameskill);
*save_p++ = gameepisode; saveg_write8(gameepisode);
*save_p++ = gamemap; saveg_write8(gamemap);
{ // killough 3/16/98, 12/98: store lump name checksum { // killough 3/16/98, 12/98: store lump name checksum
uint64_t checksum = G_Signature(gameepisode, gamemap); uint64_t checksum = G_Signature(gameepisode, gamemap);
@ -2444,29 +2434,28 @@ static void DoSaveGame(char *name)
for (*save_p = 0, i = 0; i < array_size(wadfiles); i++) for (*save_p = 0, i = 0; i < array_size(wadfiles); i++)
{ {
const char *basename = M_BaseName(wadfiles[i]); const char *basename = M_BaseName(wadfiles[i]);
CheckSaveGame(strlen(basename)+2); saveg_buffer_size(strlen(basename)+2);
strcat(strcat((char *) save_p, basename), "\n"); strcat(strcat((char *) save_p, basename), "\n");
} }
save_p += strlen((char *) save_p)+1; save_p += strlen((char *) save_p)+1;
} }
CheckSaveGame(G_GameOptionSize()+MIN_MAXPLAYERS+10);
for (i=0 ; i<MAXPLAYERS ; i++) for (i=0 ; i<MAXPLAYERS ; i++)
*save_p++ = playeringame[i]; saveg_write8(playeringame[i]);
for (;i<MIN_MAXPLAYERS;i++) // killough 2/28/98 for (;i<MIN_MAXPLAYERS;i++) // killough 2/28/98
*save_p++ = 0; saveg_write8(0);
*save_p++ = idmusnum; // jff 3/17/98 save idmus state saveg_write8(idmusnum); // jff 3/17/98 save idmus state
saveg_buffer_size(G_GameOptionSize());
save_p = G_WriteOptions(save_p); // killough 3/1/98: save game options save_p = G_WriteOptions(save_p); // killough 3/1/98: save game options
// [FG] fix copy size and pointer progression // [FG] fix copy size and pointer progression
saveg_write32(leveltime); //killough 11/98: save entire word saveg_write32(leveltime); //killough 11/98: save entire word
// killough 11/98: save revenant tracer state // killough 11/98: save revenant tracer state
*save_p++ = (gametic-basetic) & 255; saveg_write8((gametic-basetic) & 255);
P_ArchivePlayers(); P_ArchivePlayers();
P_ArchiveWorld(); P_ArchiveWorld();
@ -2475,14 +2464,13 @@ static void DoSaveGame(char *name)
P_ArchiveRNG(); // killough 1/18/98: save RNG information P_ArchiveRNG(); // killough 1/18/98: save RNG information
P_ArchiveMap(); // killough 1/22/98: save automap information P_ArchiveMap(); // killough 1/22/98: save automap information
*save_p++ = 0xe6; // consistancy marker saveg_write8(0xe6); // consistancy marker
// [FG] save total time for all completed levels // [FG] save total time for all completed levels
CheckSaveGame(sizeof totalleveltimes);
saveg_write32(totalleveltimes); saveg_write32(totalleveltimes);
// save lump name for current MUSINFO item // save lump name for current MUSINFO item
CheckSaveGame(8); saveg_buffer_size(8);
if (musinfo.current_item > 0) if (musinfo.current_item > 0)
memcpy(save_p, lumpinfo[musinfo.current_item].name, 8); memcpy(save_p, lumpinfo[musinfo.current_item].name, 8);
else else
@ -2490,11 +2478,10 @@ static void DoSaveGame(char *name)
save_p += 8; save_p += 8;
// save max_kill_requirement // save max_kill_requirement
CheckSaveGame(sizeof(max_kill_requirement));
saveg_write32(max_kill_requirement); saveg_write32(max_kill_requirement);
// [FG] save snapshot // [FG] save snapshot
CheckSaveGame(MN_SnapshotDataSize()); saveg_buffer_size(MN_SnapshotDataSize());
MN_WriteSnapshot(save_p); MN_WriteSnapshot(save_p);
save_p += MN_SnapshotDataSize(); save_p += MN_SnapshotDataSize();

View File

@ -47,85 +47,9 @@ byte *save_p;
saveg_compat_t saveg_compat = saveg_woof510; saveg_compat_t saveg_compat = saveg_woof510;
// Endian-safe integer read/write functions
byte saveg_read8(void)
{
return *save_p++;
}
void saveg_write8(byte value)
{
*save_p++ = value;
}
static short saveg_read16(void)
{
int result;
result = saveg_read8();
result |= saveg_read8() << 8;
return result;
}
static void saveg_write16(short value)
{
saveg_write8(value & 0xff);
saveg_write8((value >> 8) & 0xff);
}
int saveg_read32(void)
{
int result;
result = saveg_read8();
result |= saveg_read8() << 8;
result |= saveg_read8() << 16;
result |= saveg_read8() << 24;
return result;
}
void saveg_write32(int value)
{
saveg_write8(value & 0xff);
saveg_write8((value >> 8) & 0xff);
saveg_write8((value >> 16) & 0xff);
saveg_write8((value >> 24) & 0xff);
}
int64_t saveg_read64(void)
{
int64_t result;
result = (int64_t)(saveg_read8());
result |= (int64_t)(saveg_read8()) << 8;
result |= (int64_t)(saveg_read8()) << 16;
result |= (int64_t)(saveg_read8()) << 24;
result |= (int64_t)(saveg_read8()) << 32;
result |= (int64_t)(saveg_read8()) << 40;
result |= (int64_t)(saveg_read8()) << 48;
result |= (int64_t)(saveg_read8()) << 56;
return result;
}
void saveg_write64(int64_t value)
{
saveg_write8(value & 0xff);
saveg_write8((value >> 8) & 0xff);
saveg_write8((value >> 16) & 0xff);
saveg_write8((value >> 24) & 0xff);
saveg_write8((value >> 32) & 0xff);
saveg_write8((value >> 40) & 0xff);
saveg_write8((value >> 48) & 0xff);
saveg_write8((value >> 56) & 0xff);
}
// Pad to 4-byte boundaries // Pad to 4-byte boundaries
static void saveg_read_pad(void) inline static void saveg_read_pad(void)
{ {
int padding; int padding;
int i; int i;
@ -138,28 +62,29 @@ static void saveg_read_pad(void)
} }
} }
static void saveg_write_pad(void) inline static void saveg_write_pad(void)
{ {
int padding; int padding;
int i; int i;
padding = (4 - ((intptr_t)save_p & 3)) & 3; padding = (4 - ((intptr_t)save_p & 3)) & 3;
saveg_buffer_size(padding);
for (i=0; i<padding; ++i) for (i=0; i<padding; ++i)
{ {
saveg_write8(0); savep_putbyte(0);
} }
} }
// Pointers // Pointers
static void *saveg_readp(void) inline static void *saveg_readp(void)
{ {
return (void *) (intptr_t) saveg_read32(); return (void *) (intptr_t) saveg_read32();
} }
static void saveg_writep(const void *p) inline static void saveg_writep(const void *p)
{ {
saveg_write32((intptr_t) p); saveg_write32((intptr_t) p);
} }
@ -2047,7 +1972,6 @@ void P_ArchivePlayers (void)
{ {
int i; int i;
CheckSaveGame(sizeof(player_t) * MAXPLAYERS); // killough
for (i=0 ; i<MAXPLAYERS ; i++) for (i=0 ; i<MAXPLAYERS ; i++)
if (playeringame[i]) if (playeringame[i])
{ {
@ -2088,28 +2012,6 @@ void P_ArchiveWorld (void)
const line_t *li; const line_t *li;
const side_t *si; const side_t *si;
// killough 3/22/98: fix bug caused by hoisting save_p too early
// killough 10/98: adjust size for changes below
size_t size =
(sizeof(short)*5 + sizeof sec->floorheight + sizeof sec->ceilingheight
+ sizeof(sec->floor_xoffs) + sizeof(sec->floor_yoffs)
+ sizeof(sec->ceiling_xoffs) + sizeof(sec->ceiling_yoffs)
+ sizeof(sec->ceiling_rotation) + sizeof(sec->floor_rotation)) * numsectors
+ (sizeof(short) * 3 + sizeof(li->angle) + sizeof(li->frontmusic)
+ sizeof(li->backmusic) + sizeof(short)) * numlines + 4;
for (i=0; i<numlines; i++)
{
if (lines[i].sidenum[0] != NO_INDEX)
size +=
sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
if (lines[i].sidenum[1] != NO_INDEX)
size +=
sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
}
CheckSaveGame(size); // killough
saveg_write_pad(); // killough 3/22/98 saveg_write_pad(); // killough 3/22/98
// do sectors // do sectors
@ -2282,7 +2184,7 @@ void P_ArchiveThinkers (void)
size_t size = 0; size_t size = 0;
mobj_t tmp; mobj_t tmp;
CheckSaveGame(sizeof brain); // killough 3/26/98: Save boss brain state // killough 3/26/98: Save boss brain state
saveg_write32(brain.easy); saveg_write32(brain.easy);
saveg_write32(brain.targeton); saveg_write32(brain.targeton);
@ -2294,9 +2196,6 @@ void P_ArchiveThinkers (void)
if (th->function.p1 == (actionf_p1)P_MobjThinker) if (th->function.p1 == (actionf_p1)P_MobjThinker)
th->prev = (thinker_t *) ++size; th->prev = (thinker_t *) ++size;
// check that enough room is available in savegame buffer
CheckSaveGame(size*(sizeof(mobj_t)+4)); // killough 2/14/98
// save off the current thinkers // save off the current thinkers
for (th = thinkercap.next ; th != &thinkercap ; th=th->next) for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
@ -2357,7 +2256,6 @@ void P_ArchiveThinkers (void)
// killough 9/14/98: save soundtargets // killough 9/14/98: save soundtargets
{ {
int i; int i;
CheckSaveGame(numsectors * sizeof(mobj_t *)); // killough 9/14/98
for (i = 0; i < numsectors; i++) for (i = 0; i < numsectors; i++)
{ {
mobj_t *target = sectors[i].soundtarget; mobj_t *target = sectors[i].soundtarget;
@ -2560,46 +2458,6 @@ enum {
void P_ArchiveSpecials (void) void P_ArchiveSpecials (void)
{ {
thinker_t *th; thinker_t *th;
size_t size = 0; // killough
// save off the current thinkers (memory size calculation -- killough)
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
if (!th->function.v)
{
platlist_t *pl;
ceilinglist_t *cl; //jff 2/22/98 need this for ceilings too now
for (pl=activeplats; pl; pl=pl->next)
if (pl->plat == (plat_t *) th) // killough 2/14/98
{
size += 4+sizeof(plat_t);
goto end;
}
for (cl=activeceilings; cl; cl=cl->next) // search for activeceiling
if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
{
size += 4+sizeof(ceiling_t);
goto end;
}
end:;
}
else
size +=
th->function.p1==(actionf_p1)T_MoveCeiling ? 4+sizeof(ceiling_t) :
th->function.p1==(actionf_p1)T_VerticalDoor ? 4+sizeof(vldoor_t) :
th->function.p1==(actionf_p1)T_MoveFloor ? 4+sizeof(floormove_t):
th->function.p1==(actionf_p1)T_PlatRaise ? 4+sizeof(plat_t) :
th->function.p1==(actionf_p1)T_LightFlash ? 4+sizeof(lightflash_t):
th->function.p1==(actionf_p1)T_StrobeFlash ? 4+sizeof(strobe_t) :
th->function.p1==(actionf_p1)T_Glow ? 4+sizeof(glow_t) :
th->function.p1==(actionf_p1)T_MoveElevator ? 4+sizeof(elevator_t):
th->function.p1==(actionf_p1)T_Scroll ? 4+sizeof(scroll_t) :
th->function.p1==(actionf_p1)T_Pusher ? 4+sizeof(pusher_t) :
th->function.p1==(actionf_p1)T_FireFlicker ? 4+sizeof(fireflicker_t) :
th->function.p1==(actionf_p1)T_Friction ? 4+sizeof(friction_t) :
0;
CheckSaveGame(size); // killough
// save off the current thinkers // save off the current thinkers
for (th=thinkercap.next; th!=&thinkercap; th=th->next) for (th=thinkercap.next; th!=&thinkercap; th=th->next)
@ -2728,8 +2586,6 @@ void P_ArchiveSpecials (void)
} }
} }
CheckSaveGame(MAXBUTTONS * sizeof(button_t));
for (int i = 0; i < MAXBUTTONS; i++) for (int i = 0; i < MAXBUTTONS; i++)
{ {
if (buttonlist[i].btimer != 0) if (buttonlist[i].btimer != 0)
@ -2915,7 +2771,6 @@ void P_UnArchiveSpecials (void)
void P_ArchiveRNG(void) void P_ArchiveRNG(void)
{ {
CheckSaveGame(sizeof rng);
saveg_write_rng_t(&rng); saveg_write_rng_t(&rng);
} }
@ -2927,10 +2782,6 @@ void P_UnArchiveRNG(void)
// killough 2/22/98: Save/restore automap state // killough 2/22/98: Save/restore automap state
void P_ArchiveMap(void) void P_ArchiveMap(void)
{ {
CheckSaveGame(sizeof followplayer + sizeof markpointnum +
markpointnum * sizeof *markpoints +
sizeof automapactive + sizeof viewactive);
saveg_write32(automapactive); saveg_write32(automapactive);
saveg_write32(viewactive); saveg_write32(viewactive);
saveg_write32(followplayer); saveg_write32(followplayer);

View File

@ -21,6 +21,7 @@
#define __P_SAVEG__ #define __P_SAVEG__
#include "doomtype.h" #include "doomtype.h"
#include "z_zone.h"
// Persistent storage/archiving. // Persistent storage/archiving.
// These are the load / save game routines. // These are the load / save game routines.
@ -41,15 +42,112 @@ void P_UnArchiveRNG(void);
void P_ArchiveMap(void); void P_ArchiveMap(void);
void P_UnArchiveMap(void); void P_UnArchiveMap(void);
extern byte *save_p; extern byte *save_p, *savebuffer;
void CheckSaveGame(size_t); // killough extern size_t savegamesize;
byte saveg_read8(void); // Check for overrun and realloc if necessary -- Lee Killough 1/22/98
void saveg_write8(byte value); inline static void saveg_buffer_size(size_t size)
int saveg_read32(void); {
void saveg_write32(int value); size_t offset = save_p - savebuffer;
int64_t saveg_read64(void);
void saveg_write64(int64_t value); if (offset + size <= savegamesize)
{
return;
}
while (offset + size > savegamesize)
{
savegamesize *= 2;
}
savebuffer = Z_Realloc(savebuffer, savegamesize, PU_STATIC, NULL);
save_p = savebuffer + offset;
}
// Endian-safe integer read/write functions
inline static void savep_putbyte(byte value)
{
*save_p++ = value;
}
inline static void saveg_write8(byte value)
{
saveg_buffer_size(sizeof(byte));
savep_putbyte(value);
}
inline static void saveg_write16(short value)
{
saveg_buffer_size(sizeof(int16_t));
savep_putbyte(value & 0xff);
savep_putbyte((value >> 8) & 0xff);
}
inline static void saveg_write32(int value)
{
saveg_buffer_size(sizeof(int32_t));
savep_putbyte(value & 0xff);
savep_putbyte((value >> 8) & 0xff);
savep_putbyte((value >> 16) & 0xff);
savep_putbyte((value >> 24) & 0xff);
}
inline static void saveg_write64(int64_t value)
{
saveg_buffer_size(sizeof(int64_t));
savep_putbyte(value & 0xff);
savep_putbyte((value >> 8) & 0xff);
savep_putbyte((value >> 16) & 0xff);
savep_putbyte((value >> 24) & 0xff);
savep_putbyte((value >> 32) & 0xff);
savep_putbyte((value >> 40) & 0xff);
savep_putbyte((value >> 48) & 0xff);
savep_putbyte((value >> 56) & 0xff);
}
inline static byte saveg_read8(void)
{
return *save_p++;
}
inline static short saveg_read16(void)
{
int result;
result = saveg_read8();
result |= saveg_read8() << 8;
return result;
}
inline static int saveg_read32(void)
{
int result;
result = saveg_read8();
result |= saveg_read8() << 8;
result |= saveg_read8() << 16;
result |= saveg_read8() << 24;
return result;
}
inline static int64_t saveg_read64(void)
{
int64_t result;
result = (int64_t)(saveg_read8());
result |= (int64_t)(saveg_read8()) << 8;
result |= (int64_t)(saveg_read8()) << 16;
result |= (int64_t)(saveg_read8()) << 24;
result |= (int64_t)(saveg_read8()) << 32;
result |= (int64_t)(saveg_read8()) << 40;
result |= (int64_t)(saveg_read8()) << 48;
result |= (int64_t)(saveg_read8()) << 56;
return result;
}
typedef enum typedef enum
{ {