mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-26 20:11:47 +00:00
Merge branch 'fix-demo-ghost-buffer-overrun' into 'master'
Large replay crash mitigation, replay buffer size option, debug command Closes #656 See merge request KartKrew/Kart!1885
This commit is contained in:
commit
8aeeae24c3
8 changed files with 71 additions and 9 deletions
|
|
@ -538,6 +538,7 @@ consvar_t cv_maxping = Server("maxdelay", "20").values(CV_Unsigned);
|
||||||
consvar_t cv_menujam = Server("menujam", "menu").values({{0, "menu"}, {1, "menu2"}, {2, "menu3"}});
|
consvar_t cv_menujam = Server("menujam", "menu").values({{0, "menu"}, {1, "menu2"}, {2, "menu3"}});
|
||||||
consvar_t cv_menujam_update = Server("menujam_update", "Off").on_off();
|
consvar_t cv_menujam_update = Server("menujam_update", "Off").on_off();
|
||||||
consvar_t cv_netdemosyncquality = Server("netdemo_syncquality", "1").min_max(1, 35);
|
consvar_t cv_netdemosyncquality = Server("netdemo_syncquality", "1").min_max(1, 35);
|
||||||
|
consvar_t cv_netdemosize = Server("netdemo_size", "6").values(CV_Natural);
|
||||||
|
|
||||||
void NetTimeout_OnChange(void);
|
void NetTimeout_OnChange(void);
|
||||||
consvar_t cv_nettimeout = Server("nettimeout", "210").min_max(TICRATE/7, 60*TICRATE).onchange(NetTimeout_OnChange);
|
consvar_t cv_nettimeout = Server("nettimeout", "210").min_max(TICRATE/7, 60*TICRATE).onchange(NetTimeout_OnChange);
|
||||||
|
|
|
||||||
|
|
@ -548,6 +548,7 @@ typedef enum
|
||||||
DBG_SETUP = 0x00000400,
|
DBG_SETUP = 0x00000400,
|
||||||
DBG_LUA = 0x00000800,
|
DBG_LUA = 0x00000800,
|
||||||
DBG_RNG = 0x00001000,
|
DBG_RNG = 0x00001000,
|
||||||
|
DBG_DEMO = 0x00002000,
|
||||||
} debugFlags_t;
|
} debugFlags_t;
|
||||||
|
|
||||||
struct debugFlagNames_s
|
struct debugFlagNames_s
|
||||||
|
|
|
||||||
38
src/g_demo.c
38
src/g_demo.c
|
|
@ -734,6 +734,7 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim)
|
||||||
|
|
||||||
void G_WriteAllGhostTics(void)
|
void G_WriteAllGhostTics(void)
|
||||||
{
|
{
|
||||||
|
boolean toobig = false;
|
||||||
INT32 i, counter = leveltime;
|
INT32 i, counter = leveltime;
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -750,12 +751,18 @@ void G_WriteAllGhostTics(void)
|
||||||
|
|
||||||
WRITEUINT8(demobuf.p, i);
|
WRITEUINT8(demobuf.p, i);
|
||||||
G_WriteGhostTic(players[i].mo, i);
|
G_WriteGhostTic(players[i].mo, i);
|
||||||
|
|
||||||
|
// attention here for the ticcmd size!
|
||||||
|
// latest demos with mouse aiming byte in ticcmd
|
||||||
|
if (demobuf.p >= demobuf.end - (13 + 9 + 9))
|
||||||
|
{
|
||||||
|
toobig = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WRITEUINT8(demobuf.p, 0xFF);
|
WRITEUINT8(demobuf.p, 0xFF);
|
||||||
|
|
||||||
// attention here for the ticcmd size!
|
if (toobig)
|
||||||
// latest demos with mouse aiming byte in ticcmd
|
|
||||||
if (demobuf.p >= demobuf.end - (13 + 9 + 9))
|
|
||||||
{
|
{
|
||||||
G_CheckDemoStatus(); // no more space
|
G_CheckDemoStatus(); // no more space
|
||||||
return;
|
return;
|
||||||
|
|
@ -2088,16 +2095,13 @@ void G_WriteMetalTic(mobj_t *metal)
|
||||||
//
|
//
|
||||||
void G_RecordDemo(const char *name)
|
void G_RecordDemo(const char *name)
|
||||||
{
|
{
|
||||||
|
extern consvar_t cv_netdemosize;
|
||||||
|
|
||||||
INT32 maxsize;
|
INT32 maxsize;
|
||||||
|
|
||||||
strcpy(demoname, name);
|
strcpy(demoname, name);
|
||||||
strcat(demoname, ".lmp");
|
strcat(demoname, ".lmp");
|
||||||
//@TODO make a maxdemosize cvar
|
maxsize = 1024 * 1024 * cv_netdemosize.value;
|
||||||
// NOPE. We are kicking this can HELLA down the road. -Tyron 2024-01-20
|
|
||||||
maxsize = 1024*1024*4;
|
|
||||||
|
|
||||||
if (M_CheckParm("-maxdemo") && M_IsNextParm())
|
|
||||||
maxsize = atoi(M_GetNextParm()) * 1024;
|
|
||||||
|
|
||||||
// if (demobuf.buffer)
|
// if (demobuf.buffer)
|
||||||
// Z_Free(demobuf.buffer);
|
// Z_Free(demobuf.buffer);
|
||||||
|
|
@ -2109,6 +2113,21 @@ void G_RecordDemo(const char *name)
|
||||||
demobuf.p = NULL;
|
demobuf.p = NULL;
|
||||||
|
|
||||||
demo.recording = true;
|
demo.recording = true;
|
||||||
|
demo.buffer = &demobuf;
|
||||||
|
|
||||||
|
/* FIXME: This whole file is in a wretched state. Take a
|
||||||
|
look at G_WriteAllGhostTics and G_WriteDemoTiccmd, they
|
||||||
|
write a lot of data. It's not realistic to refactor that
|
||||||
|
code in order to know exactly HOW MANY bytes it can write
|
||||||
|
out. So here's the deal. Reserve a decent block of memory
|
||||||
|
at the end of the buffer and never use it. Those bastard
|
||||||
|
functions will check if they overran the buffer, but it
|
||||||
|
should be safe enough because they'll think there's less
|
||||||
|
memory than there actually is and stop early. */
|
||||||
|
const size_t deadspace = 1024;
|
||||||
|
I_Assert(demobuf.size > deadspace);
|
||||||
|
demobuf.size -= deadspace;
|
||||||
|
demobuf.end -= deadspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_RecordMetal(void)
|
void G_RecordMetal(void)
|
||||||
|
|
@ -3246,6 +3265,7 @@ void G_DoPlayDemo(const char *defdemoname)
|
||||||
// read demo header
|
// read demo header
|
||||||
gameaction = ga_nothing;
|
gameaction = ga_nothing;
|
||||||
demo.playback = true;
|
demo.playback = true;
|
||||||
|
demo.buffer = &demobuf;
|
||||||
if (memcmp(demobuf.p, DEMOHEADER, 12))
|
if (memcmp(demobuf.p, DEMOHEADER, 12))
|
||||||
{
|
{
|
||||||
snprintf(msg, 1024, M_GetText("%s is not a Ring Racers replay file.\n"), pdemoname);
|
snprintf(msg, 1024, M_GetText("%s is not a Ring Racers replay file.\n"), pdemoname);
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ struct demovars_s {
|
||||||
UINT8 numskins;
|
UINT8 numskins;
|
||||||
democharlist_t *skinlist;
|
democharlist_t *skinlist;
|
||||||
UINT8 currentskinid[MAXPLAYERS];
|
UINT8 currentskinid[MAXPLAYERS];
|
||||||
|
|
||||||
|
const savebuffer_t *buffer; // debug, valid only if recording or playback
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct demovars_s demo;
|
extern struct demovars_s demo;
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,7 @@ typedef enum
|
||||||
dopt_replay,
|
dopt_replay,
|
||||||
dopt_rprecord,
|
dopt_rprecord,
|
||||||
dopt_rpsync,
|
dopt_rpsync,
|
||||||
|
dopt_rpsize,
|
||||||
#ifdef HAVE_DISCORDRPC
|
#ifdef HAVE_DISCORDRPC
|
||||||
dopt_discord,
|
dopt_discord,
|
||||||
dopt_drp,
|
dopt_drp,
|
||||||
|
|
|
||||||
|
|
@ -605,6 +605,8 @@ struct debugFlagNames_s const debug_flag_names[] =
|
||||||
{"Music", DBG_MUSIC},
|
{"Music", DBG_MUSIC},
|
||||||
{"PwrLv", DBG_PWRLV},
|
{"PwrLv", DBG_PWRLV},
|
||||||
{"PowerLevel", DBG_PWRLV}, // alt name
|
{"PowerLevel", DBG_PWRLV}, // alt name
|
||||||
|
{"Demo", DBG_DEMO},
|
||||||
|
{"Replay", DBG_DEMO}, // alt name
|
||||||
{NULL, 0}
|
{NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
#include "../k_menu.h"
|
#include "../k_menu.h"
|
||||||
#include "../discord.h" // discord rpc cvars
|
#include "../discord.h" // discord rpc cvars
|
||||||
|
|
||||||
|
extern consvar_t cv_netdemosize;
|
||||||
|
|
||||||
// data options menu -- see dopt_e
|
// data options menu -- see dopt_e
|
||||||
menuitem_t OPTIONS_Data[] =
|
menuitem_t OPTIONS_Data[] =
|
||||||
{
|
{
|
||||||
|
|
@ -26,6 +28,9 @@ menuitem_t OPTIONS_Data[] =
|
||||||
{IT_STRING | IT_CVAR, "Net Consistency Quality", "For filesize, how often do we write position data in online replays?",
|
{IT_STRING | IT_CVAR, "Net Consistency Quality", "For filesize, how often do we write position data in online replays?",
|
||||||
NULL, {.cvar = &cv_netdemosyncquality}, 0, 0},
|
NULL, {.cvar = &cv_netdemosyncquality}, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CVAR, "Buffer Size (MB)", "Lets replays last longer with more players. Uses more RAM.",
|
||||||
|
NULL, {.cvar = &cv_netdemosize}, 0, 0},
|
||||||
|
|
||||||
#ifdef HAVE_DISCORDRPC
|
#ifdef HAVE_DISCORDRPC
|
||||||
{IT_HEADER, "Discord Rich Presence...", NULL,
|
{IT_HEADER, "Discord Rich Presence...", NULL,
|
||||||
NULL, {NULL}, 0, 0},
|
NULL, {NULL}, 0, 0},
|
||||||
|
|
|
||||||
|
|
@ -448,6 +448,31 @@ static void ST_drawRenderDebug(INT32 *height)
|
||||||
ST_pushDebugString(height, va("Skybox Portals: %4s", sizeu1(i->skybox_portals)));
|
ST_pushDebugString(height, va("Skybox Portals: %4s", sizeu1(i->skybox_portals)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ST_drawDemoDebug(INT32 *height)
|
||||||
|
{
|
||||||
|
if (!demo.recording && !demo.playback)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t needle = demo.buffer->p - demo.buffer->buffer;
|
||||||
|
size_t size = demo.buffer->size;
|
||||||
|
double percent = (double)needle / size * 100.0;
|
||||||
|
double avg = (double)needle / leveltime;
|
||||||
|
|
||||||
|
ST_pushDebugString(height, va("%s/%s bytes", sizeu1(needle), sizeu2(size)));
|
||||||
|
ST_pushDebugString(height, va(
|
||||||
|
"%.2f/%.2f MB %5.2f%%",
|
||||||
|
needle / (1024.0 * 1024.0),
|
||||||
|
size / (1024.0 * 1024.0),
|
||||||
|
percent
|
||||||
|
));
|
||||||
|
ST_pushDebugString(height, va(
|
||||||
|
"%.2f KB/s (ETA %.2f minutes)",
|
||||||
|
avg * TICRATE / 1024.0,
|
||||||
|
(size - needle) / (avg * TICRATE * 60.0)
|
||||||
|
));
|
||||||
|
ST_pushDebugString(height, va("Demo (%s)", demo.recording ? "recording" : "playback"));
|
||||||
|
}
|
||||||
|
|
||||||
void ST_drawDebugInfo(void)
|
void ST_drawDebugInfo(void)
|
||||||
{
|
{
|
||||||
INT32 height = 192;
|
INT32 height = 192;
|
||||||
|
|
@ -547,6 +572,11 @@ void ST_drawDebugInfo(void)
|
||||||
ST_drawRenderDebug(&height);
|
ST_drawRenderDebug(&height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cht_debug & DBG_DEMO)
|
||||||
|
{
|
||||||
|
ST_drawDemoDebug(&height);
|
||||||
|
}
|
||||||
|
|
||||||
if (cht_debug & DBG_MEMORY)
|
if (cht_debug & DBG_MEMORY)
|
||||||
V_DrawRightAlignedString(320, height, V_MONOSPACE, va("Heap used: %7sKB", sizeu1(Z_TagsUsage(0, INT32_MAX)>>10)));
|
V_DrawRightAlignedString(320, height, V_MONOSPACE, va("Heap used: %7sKB", sizeu1(Z_TagsUsage(0, INT32_MAX)>>10)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue