diff --git a/src/cvars.cpp b/src/cvars.cpp index 112263f81..8668c27f4 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -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_update = Server("menujam_update", "Off").on_off(); 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); consvar_t cv_nettimeout = Server("nettimeout", "210").min_max(TICRATE/7, 60*TICRATE).onchange(NetTimeout_OnChange); diff --git a/src/doomdef.h b/src/doomdef.h index ffec260ef..21e8bdb4f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -548,6 +548,7 @@ typedef enum DBG_SETUP = 0x00000400, DBG_LUA = 0x00000800, DBG_RNG = 0x00001000, + DBG_DEMO = 0x00002000, } debugFlags_t; struct debugFlagNames_s diff --git a/src/g_demo.c b/src/g_demo.c index 4b51c85d7..b0f539f9c 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -734,6 +734,7 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim) void G_WriteAllGhostTics(void) { + boolean toobig = false; INT32 i, counter = leveltime; for (i = 0; i < MAXPLAYERS; i++) { @@ -750,12 +751,18 @@ void G_WriteAllGhostTics(void) WRITEUINT8(demobuf.p, 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); - // attention here for the ticcmd size! - // latest demos with mouse aiming byte in ticcmd - if (demobuf.p >= demobuf.end - (13 + 9 + 9)) + if (toobig) { G_CheckDemoStatus(); // no more space return; @@ -2088,16 +2095,13 @@ void G_WriteMetalTic(mobj_t *metal) // void G_RecordDemo(const char *name) { + extern consvar_t cv_netdemosize; + INT32 maxsize; strcpy(demoname, name); strcat(demoname, ".lmp"); - //@TODO make a maxdemosize cvar - // 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; + maxsize = 1024 * 1024 * cv_netdemosize.value; // if (demobuf.buffer) // Z_Free(demobuf.buffer); @@ -2109,6 +2113,21 @@ void G_RecordDemo(const char *name) demobuf.p = NULL; 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) @@ -3246,6 +3265,7 @@ void G_DoPlayDemo(const char *defdemoname) // read demo header gameaction = ga_nothing; demo.playback = true; + demo.buffer = &demobuf; if (memcmp(demobuf.p, DEMOHEADER, 12)) { snprintf(msg, 1024, M_GetText("%s is not a Ring Racers replay file.\n"), pdemoname); diff --git a/src/g_demo.h b/src/g_demo.h index f102e8517..e19f8f820 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -65,6 +65,8 @@ struct demovars_s { UINT8 numskins; democharlist_t *skinlist; UINT8 currentskinid[MAXPLAYERS]; + + const savebuffer_t *buffer; // debug, valid only if recording or playback }; extern struct demovars_s demo; diff --git a/src/k_menu.h b/src/k_menu.h index da1b68f61..a623aedb3 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -342,6 +342,7 @@ typedef enum dopt_replay, dopt_rprecord, dopt_rpsync, + dopt_rpsize, #ifdef HAVE_DISCORDRPC dopt_discord, dopt_drp, diff --git a/src/m_cheat.c b/src/m_cheat.c index f9eb97cd8..c623a8f1e 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -605,6 +605,8 @@ struct debugFlagNames_s const debug_flag_names[] = {"Music", DBG_MUSIC}, {"PwrLv", DBG_PWRLV}, {"PowerLevel", DBG_PWRLV}, // alt name + {"Demo", DBG_DEMO}, + {"Replay", DBG_DEMO}, // alt name {NULL, 0} }; diff --git a/src/menus/options-data-1.c b/src/menus/options-data-1.c index 97393948a..fd7f830d6 100644 --- a/src/menus/options-data-1.c +++ b/src/menus/options-data-1.c @@ -4,6 +4,8 @@ #include "../k_menu.h" #include "../discord.h" // discord rpc cvars +extern consvar_t cv_netdemosize; + // data options menu -- see dopt_e 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?", 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 {IT_HEADER, "Discord Rich Presence...", NULL, NULL, {NULL}, 0, 0}, diff --git a/src/st_stuff.c b/src/st_stuff.c index 50e3ba29f..8e2505ef5 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -448,6 +448,31 @@ static void ST_drawRenderDebug(INT32 *height) 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) { INT32 height = 192; @@ -547,6 +572,11 @@ void ST_drawDebugInfo(void) ST_drawRenderDebug(&height); } + if (cht_debug & DBG_DEMO) + { + ST_drawDemoDebug(&height); + } + if (cht_debug & DBG_MEMORY) V_DrawRightAlignedString(320, height, V_MONOSPACE, va("Heap used: %7sKB", sizeu1(Z_TagsUsage(0, INT32_MAX)>>10))); }