From 9327e96e4d4f4d15421b71bbba8a9c44c4244951 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sat, 26 Dec 2020 17:19:14 -0600 Subject: [PATCH 01/49] Pause the console refresh while startup wads are loading. --- src/console.c | 13 +++++++++++++ src/console.h | 3 +++ src/d_main.c | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/src/console.c b/src/console.c index c7bfe0fe1..3785136af 100644 --- a/src/console.c +++ b/src/console.c @@ -484,6 +484,19 @@ void CON_Init(void) Unlock_state(); } } + +void CON_StartRefresh(void) +{ + if (con_startup) + con_refresh = true; +} + +void CON_StopRefresh(void) +{ + if (con_startup) + con_refresh = false; +} + // Console input initialization // static void CON_InputInit(void) diff --git a/src/console.h b/src/console.h index 0296f4f6e..db27d9358 100644 --- a/src/console.h +++ b/src/console.h @@ -16,6 +16,9 @@ void CON_Init(void); +void CON_StartRefresh(void); +void CON_StopRefresh(void); + boolean CON_Responder(event_t *ev); #ifdef HAVE_THREADS diff --git a/src/d_main.c b/src/d_main.c index a89f4ed2d..7d25208e7 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1275,10 +1275,14 @@ void D_SRB2Main(void) I_RegisterSysCommands(); + CON_StopRefresh(); // Temporarily stop refreshing the screen for wad loading + CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n"); W_InitMultipleFiles(startuppwads); D_CleanFile(startuppwads); + CON_StartRefresh(); // Restart the refresh! + CONS_Printf("HU_LoadGraphics()...\n"); HU_LoadGraphics(); From d35a1811d6a0fd94808a4fcb189a0ffe38bc7483 Mon Sep 17 00:00:00 2001 From: katsy Date: Fri, 16 Apr 2021 04:49:33 -0500 Subject: [PATCH 02/49] clean up bouncy fof code --- src/p_user.c | 46 +++++++--------------------------------------- 1 file changed, 7 insertions(+), 39 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 4413cc6cd..c7eecce9b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2772,16 +2772,9 @@ static void P_CheckBouncySectors(player_t *player) player->mo->momx = -FixedMul(player->mo->momx,bouncestrength); player->mo->momy = -FixedMul(player->mo->momy,bouncestrength); - if (player->pflags & PF_SPINNING) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); - player->pflags |= PF_THOKKED; - } } else { - fixed_t newmom; pslope_t *slope = (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) ? *rover->t_slope : *rover->b_slope; momentum.x = player->mo->momx; @@ -2791,53 +2784,28 @@ static void P_CheckBouncySectors(player_t *player) if (slope) P_ReverseQuantizeMomentumToSlope(&momentum, slope); - newmom = momentum.z = -FixedMul(momentum.z,bouncestrength)/2; + momentum.z = -FixedMul(momentum.z,bouncestrength)/2; - if (abs(newmom) < (bouncestrength*2)) + if (abs(momentum.z) < (bouncestrength*2)) goto bouncydone; - if (!(rover->master->flags & ML_BOUNCY)) - { - if (newmom > 0) - { - if (newmom < 8*FRACUNIT) - newmom = 8*FRACUNIT; - } - else if (newmom < 0) - { - if (newmom > -8*FRACUNIT) - newmom = -8*FRACUNIT; - } - } - - if (newmom > P_GetPlayerHeight(player)/2) - newmom = P_GetPlayerHeight(player)/2; - else if (newmom < -P_GetPlayerHeight(player)/2) - newmom = -P_GetPlayerHeight(player)/2; - - momentum.z = newmom*2; + if (momentum.z > FixedMul(24*FRACUNIT, player->mo->scale)) //half of the default player height + momentum.z = FixedMul(24*FRACUNIT, player->mo->scale); + else if (momentum.z < -FixedMul(24*FRACUNIT, player->mo->scale)) + momentum.z = -FixedMul(24*FRACUNIT, player->mo->scale); if (slope) P_QuantizeMomentumToSlope(&momentum, slope); player->mo->momx = momentum.x; player->mo->momy = momentum.y; - player->mo->momz = momentum.z/2; + player->mo->momz = momentum.z; if (player->pflags & PF_SPINNING) { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); player->pflags |= PF_THOKKED; } } - - if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<mo->scale) && player->mo->momz) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); - } - goto bouncydone; } } From 22272732f0e45d9cfa637880f8eb36b00bf838b3 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 26 Jun 2021 14:59:56 -0400 Subject: [PATCH 03/49] Exclude MT_BOXSPARKLE from Mario blocks --- src/p_floor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_floor.c b/src/p_floor.c index d81a022e5..e98670f17 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1062,6 +1062,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_HOOPCOLLIDE: case MT_NIGHTSCORE: case MT_NAMECHECK: // DEFINITELY not this, because it is client-side. + case MT_BOXSPARKLE: continue; default: break; From a5cd764772760583d55d4d116b3cbfdf09cafeaa Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 26 Jun 2021 15:42:41 -0400 Subject: [PATCH 04/49] move MT_BOXSPARKLE in the list --- src/p_floor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_floor.c b/src/p_floor.c index e98670f17..263644f70 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1042,6 +1042,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_THUNDERCOIN_ORB: case MT_IVSP: case MT_SUPERSPARK: + case MT_BOXSPARKLE: case MT_RAIN: case MT_SNOWFLAKE: case MT_SPLISH: @@ -1062,7 +1063,6 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_HOOPCOLLIDE: case MT_NIGHTSCORE: case MT_NAMECHECK: // DEFINITELY not this, because it is client-side. - case MT_BOXSPARKLE: continue; default: break; From 15b7221c7895d05103239a08c34ac1ff890ad000 Mon Sep 17 00:00:00 2001 From: litten Date: Thu, 12 Aug 2021 12:39:28 -0500 Subject: [PATCH 05/49] modified: debian-template/rules --- debian-template/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian-template/rules b/debian-template/rules index 0a77624cb..12ceaf98b 100644 --- a/debian-template/rules +++ b/debian-template/rules @@ -78,7 +78,7 @@ NONX86 = $(shell test "`echo $(CROSS_COMPILE_HOST) | grep 'i[3-6]86'`" || echo " MAKEARGS = $(OS) $(NONX86) $(PREFIX) EXENAME=$(EXENAME) DBGNAME=$(DBGNAME) NOOBJDUMP=1 # SDL_PKGCONFIG=sdl2 PNG_PKGCONFIG=libpng MENUFILE1 = ?package($(PACKAGE)):needs="X11" section="$(SECTION)" MENUFILE2 = title="$(TITLE)" command="/$(PKGDIR)/$(PACKAGE)" -BINDIR := $(DIR)/bin/Linux/Release +BINDIR := $(DIR)/bin/ # FIXME pkg-config dir hacks # Launchpad doesn't need this; it actually makes i386 builds fail due to cross-compile From 4a6acc2c8dcd7cd94305da19f15ff790fae277de Mon Sep 17 00:00:00 2001 From: SteelT Date: Sun, 22 Aug 2021 16:13:40 -0400 Subject: [PATCH 06/49] Fix metal recordings not being saved in srb2home --- src/g_demo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 701f930e5..e75c6a738 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2422,12 +2422,13 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill) { WRITEUINT8(demo_p, (kill) ? METALDEATH : DEMOMARKER); // add the demo end (or metal death) marker WriteDemoChecksum(); - saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. + sprintf(demoname, "%sMS.LMP", G_BuildMapName(gamemap)); + saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. } free(demobuffer); metalrecording = false; if (saved) - I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap)); + I_Error("Saved to %s", demoname); I_Error("Failed to save demo!"); } From cbc5cc3b2acd0f8f87a4616b8fadf57400dffbcb Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 3 Sep 2021 17:18:00 -0700 Subject: [PATCH 07/49] Fix GCC 11 array-bounds warning in P_SetupStateAnimation Removing inline here silences the warning somehow, it could be a GCC bug? --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 690842270..b77dbc42a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -78,7 +78,7 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum) // // P_SetupStateAnimation // -FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st) +static void P_SetupStateAnimation(mobj_t *mobj, state_t *st) { INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin) ? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1 From 0ac36b7ce1cc28af073fb157af4ab139571746e4 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 12 Sep 2021 19:07:40 -0700 Subject: [PATCH 08/49] Remove mixed code and declarations warning --- src/Makefile.d/versions.mk | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index d7d0c3dd1..f0b59658e 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -35,8 +35,6 @@ ifndef GCC295 WFLAGS+=-Wendif-labels endif ifdef GCC41 - WFLAGS+=-Wdeclaration-after-statement - WFLAGS+=-Wno-error=declaration-after-statement WFLAGS+=-Wshadow endif #WFLAGS+=-Wlarger-than-%len% From 3d2f9e6150ab7216d8beea232262850d9e669125 Mon Sep 17 00:00:00 2001 From: katsy Date: Mon, 13 Sep 2021 17:20:20 -0500 Subject: [PATCH 09/49] don't create the default patches if we have an interscreen --- src/y_inter.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 6e1bc2e61..1abe01792 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -239,12 +239,12 @@ void Y_LoadIntermissionData(void) } data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH); - // get background patches - bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + else // no interscreen? use default background + bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); break; } case int_spec: @@ -255,12 +255,11 @@ void Y_LoadIntermissionData(void) data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); - // get background tile - bgtile = W_CachePatchName("SPECTILE", PU_PATCH); - // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + else // no interscreen? use default background + bgtile = W_CachePatchName("SPECTILE", PU_PATCH); break; } case int_ctf: From 143a515445f1307b98dbd79a458f966f71601185 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 21 Sep 2021 02:15:11 -0700 Subject: [PATCH 10/49] Correct Big Wave Dave/InstantSonic credits --- src/f_finale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index aecf79fc2..dc736a720 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1167,8 +1167,8 @@ static const char *credits[] = { "Alexander \"DrTapeworm\" Moench-Ford", "Stefan \"Stuf\" Rimalia", "Shane Mychal Sexton", - "David \"Big Wave Dave\" Spencer Sr.", - "David \"Instant Sonic\" Spencer Jr.", + "Dave \"Big Wave Dave\" Spencer", + "David \"InstantSonic\" Spencer", "\"SSNTails\"", "", "\1Level Design", From d88eb7cc14c239dfb30fbfae3dc00ebdd1a8b388 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 21 Sep 2021 02:17:44 -0700 Subject: [PATCH 11/49] Missed the 'i' --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index dc736a720..47786bb60 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1168,7 +1168,7 @@ static const char *credits[] = { "Stefan \"Stuf\" Rimalia", "Shane Mychal Sexton", "Dave \"Big Wave Dave\" Spencer", - "David \"InstantSonic\" Spencer", + "David \"instantSonic\" Spencer", "\"SSNTails\"", "", "\1Level Design", From ed5942a0b6fb05c861384786f389f63d1fc528dc Mon Sep 17 00:00:00 2001 From: katsy Date: Wed, 22 Sep 2021 23:18:54 -0500 Subject: [PATCH 12/49] fix tailsbot controls --- src/g_game.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index de1a774f4..ce2aa41f5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1549,8 +1549,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // Note: Majority of botstuffs are handled in G_Ticker now. if (player->bot == BOT_2PHUMAN) //Player-controlled bot { - G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver - // Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy + // Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Strafe cmd->angleturn = (INT16)((localangle - *myangle) >> 16); } From 0f4074f22d6e1bab37fa6c4e138270ec95e72a04 Mon Sep 17 00:00:00 2001 From: SteelT Date: Thu, 23 Sep 2021 13:45:42 -0400 Subject: [PATCH 13/49] Remove unused I_GetMouseGrab function --- src/i_system.h | 4 ---- src/sdl/i_video.c | 5 ----- 2 files changed, 9 deletions(-) diff --git a/src/i_system.h b/src/i_system.h index e046fd620..a3790dca3 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -318,10 +318,6 @@ void I_RegisterSysCommands(void); */ void I_GetCursorPosition(INT32 *x, INT32 *y); -/** \brief Returns whether the mouse is grabbed -*/ -boolean I_GetMouseGrab(void); - /** \brief Sets whether the mouse is grabbed */ void I_SetMouseGrab(boolean grab); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 97e4a7214..ed766ff23 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -409,11 +409,6 @@ void I_UpdateMouseGrab(void) SDLdoGrabMouse(); } -boolean I_GetMouseGrab(void) -{ - return (boolean)SDL_GetWindowGrab(window); -} - void I_SetMouseGrab(boolean grab) { if (grab) From a8c6a652605b921d2accbf256c2ebbd27c9dd596 Mon Sep 17 00:00:00 2001 From: FlykeSpice Date: Mon, 11 Oct 2021 00:20:11 -0400 Subject: [PATCH 14/49] Fix visplanes getting allocated twice I guess that is legacy remnant stuff --- src/r_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_plane.c b/src/r_plane.c index d844048ae..45719ce58 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -318,7 +318,7 @@ static visplane_t *new_visplane(unsigned hash) visplane_t *check = freetail; if (!check) { - check = calloc(2, sizeof (*check)); + check = malloc(sizeof (*check)); if (check == NULL) I_Error("%s: Out of memory", "new_visplane"); // FIXME: ugly } else From 8110473643e6b6e541a7f8e8217bed45dd64d671 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Fri, 22 Oct 2021 18:31:37 -0500 Subject: [PATCH 15/49] Give userdata that needed names some names. --- src/lua_baselib.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 350c1585f..a0b5ff873 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -187,6 +187,8 @@ static const struct { {META_MAPHEADER, "mapheader_t"}, {META_POLYOBJ, "polyobj_t"}, + {META_POLYOBJVERTICES, "polyobj_t.vertices"}, + {META_POLYOBJLINES, "polyobj_t.lines"}, {META_CVAR, "consvar_t"}, @@ -216,6 +218,7 @@ static const struct { {META_LUABANKS, "luabanks[]"}, + {META_KEYEVENT, "keyevent_t"}, {META_MOUSE, "mouse_t"}, {NULL, NULL} }; From e10eddd11da065f0cb0955700055d09509bfd11a Mon Sep 17 00:00:00 2001 From: katsy <205-katsy@users.noreply.git.do.srb2.org> Date: Wed, 27 Oct 2021 17:52:29 +0000 Subject: [PATCH 16/49] Fix broken rain to rain weather switching --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 8ae0ec125..07410efa2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2040,7 +2040,7 @@ void P_SwitchWeather(INT32 weathernum) continue; // not a precipmobj thinker precipmobj = (precipmobj_t *)think; - if (weathernum == (PRECIP_RAIN || PRECIP_STORM || PRECIP_STORM_NOSTRIKES)) // Snow To Rain + if (weathernum == PRECIP_RAIN || weathernum == PRECIP_STORM || weathernum == PRECIP_STORM_NOSTRIKES) // Snow To Rain { precipmobj->flags = mobjinfo[MT_RAIN].flags; st = &states[mobjinfo[MT_RAIN].spawnstate]; From 77ecfb9cdc92faea474cb91b65edd45c32a4ff40 Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Mon, 25 Oct 2021 20:49:15 +0300 Subject: [PATCH 17/49] Perfstats averaging and refactor --- src/d_clisrv.c | 11 +- src/d_main.c | 14 +- src/d_netcmd.c | 12 +- src/d_netcmd.h | 2 + src/hardware/hw_batching.c | 31 +- src/hardware/hw_main.c | 70 +-- src/hardware/hw_main.h | 30 +- src/lua_hooklib.c | 4 +- src/m_perfstats.c | 1074 ++++++++++++++++++++++-------------- src/m_perfstats.h | 43 +- src/p_map.c | 2 +- src/p_tick.c | 20 +- src/r_bsp.c | 4 +- src/r_main.c | 49 +- src/r_main.h | 26 +- src/r_things.c | 2 +- src/z_zone.h | 1 + 17 files changed, 840 insertions(+), 555 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index b7071320c..61b855319 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4974,16 +4974,23 @@ void TryRunTics(tic_t realtics) // run the count * tics while (neededtic > gametic) { + boolean update_stats = !(paused || P_AutoPause()); + DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic)); - ps_tictime = I_GetPreciseTime(); + if (update_stats) + PS_START_TIMING(ps_tictime); G_Ticker((gametic % NEWTICRATERATIO) == 0); ExtraDataTicker(); gametic++; consistancy[gametic%BACKUPTICS] = Consistancy(); - ps_tictime = I_GetPreciseTime() - ps_tictime; + if (update_stats) + { + PS_STOP_TIMING(ps_tictime); + PS_UpdateTickStats(); + } // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) diff --git a/src/d_main.c b/src/d_main.c index b4b668f4b..3845f08bd 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -476,7 +476,7 @@ static void D_Display(void) if (!automapactive && !dedicated && cv_renderview.value) { - ps_rendercalltime = I_GetPreciseTime(); + PS_START_TIMING(ps_rendercalltime); if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) { topleft = screens[0] + viewwindowy*vid.width + viewwindowx; @@ -523,7 +523,7 @@ static void D_Display(void) if (postimgtype2) V_DoPostProcessor(1, postimgtype2, postimgparam2); } - ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime; + PS_STOP_TIMING(ps_rendercalltime); } if (lastdraw) @@ -537,7 +537,7 @@ static void D_Display(void) lastdraw = false; } - ps_uitime = I_GetPreciseTime(); + PS_START_TIMING(ps_uitime); if (gamestate == GS_LEVEL) { @@ -550,7 +550,7 @@ static void D_Display(void) } else { - ps_uitime = I_GetPreciseTime(); + PS_START_TIMING(ps_uitime); } } @@ -592,7 +592,7 @@ static void D_Display(void) CON_Drawer(); - ps_uitime = I_GetPreciseTime() - ps_uitime; + PS_STOP_TIMING(ps_uitime); // // wipe update @@ -678,9 +678,9 @@ static void D_Display(void) M_DrawPerfStats(); } - ps_swaptime = I_GetPreciseTime(); + PS_START_TIMING(ps_swaptime); I_FinishUpdate(); // page flip or blit buffer - ps_swaptime = I_GetPreciseTime() - ps_swaptime; + PS_STOP_TIMING(ps_swaptime); } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5eb360bef..9d32f1bb1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -47,6 +47,7 @@ #include "m_cond.h" #include "m_anigif.h" #include "md5.h" +#include "m_perfstats.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR @@ -374,7 +375,14 @@ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL) static CV_PossibleValue_t perfstats_cons_t[] = { {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; -consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL); +consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange); +static CV_PossibleValue_t ps_samplesize_cons_t[] = { + {1, "MIN"}, {1000, "MAX"}, {0, NULL}}; +consvar_t cv_ps_samplesize = CVAR_INIT ("ps_samplesize", "1", CV_CALL, ps_samplesize_cons_t, PS_SampleSize_OnChange); +static CV_PossibleValue_t ps_descriptor_cons_t[] = { + {1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}}; +consvar_t cv_ps_descriptor = CVAR_INIT ("ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL); + consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL); char timedemo_name[256]; @@ -867,6 +875,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_soundtest); CV_RegisterVar(&cv_perfstats); + CV_RegisterVar(&cv_ps_samplesize); + CV_RegisterVar(&cv_ps_descriptor); // ingame object placing COM_AddCommand("objectplace", Command_ObjectPlace_f); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index cae32643e..30b39c0eb 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -110,6 +110,8 @@ extern consvar_t cv_skipmapcheck; extern consvar_t cv_sleep; extern consvar_t cv_perfstats; +extern consvar_t cv_ps_samplesize; +extern consvar_t cv_ps_descriptor; extern char timedemo_name[256]; extern boolean timedemo_csv; diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index 0ac33d136..da0319bcc 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -245,13 +245,16 @@ void HWR_RenderBatches(void) currently_batching = false;// no longer collecting batches if (!polygonArraySize) { - ps_hw_numpolys = ps_hw_numcalls = ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 0; + ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i + = ps_hw_numtextures.value.i = ps_hw_numpolyflags.value.i + = ps_hw_numcolors.value.i = 0; return;// nothing to draw } // init stats vars - ps_hw_numpolys = polygonArraySize; - ps_hw_numcalls = ps_hw_numverts = 0; - ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 1; + ps_hw_numpolys.value.i = polygonArraySize; + ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0; + ps_hw_numshaders.value.i = ps_hw_numtextures.value.i + = ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1; // init polygonIndexArray for (i = 0; i < polygonArraySize; i++) { @@ -259,12 +262,12 @@ void HWR_RenderBatches(void) } // sort polygons - ps_hw_batchsorttime = I_GetPreciseTime(); + PS_START_TIMING(ps_hw_batchsorttime); if (cv_glshaders.value && gl_shadersavailable) qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); else qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); - ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime; + PS_STOP_TIMING(ps_hw_batchsorttime); // sort order // 1. shader // 2. texture @@ -272,7 +275,7 @@ void HWR_RenderBatches(void) // 4. colors + light level // not sure about what order of the last 2 should be, or if it even matters - ps_hw_batchdrawtime = I_GetPreciseTime(); + PS_START_TIMING(ps_hw_batchdrawtime); currentShader = polygonArray[polygonIndexArray[0]].shader; currentTexture = polygonArray[polygonIndexArray[0]].texture; @@ -408,8 +411,8 @@ void HWR_RenderBatches(void) // execute draw call HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); // update stats - ps_hw_numcalls++; - ps_hw_numverts += finalIndexWritePos; + ps_hw_numcalls.value.i++; + ps_hw_numverts.value.i += finalIndexWritePos; // reset write positions finalVertexWritePos = 0; finalIndexWritePos = 0; @@ -426,7 +429,7 @@ void HWR_RenderBatches(void) currentShader = nextShader; changeShader = false; - ps_hw_numshaders++; + ps_hw_numshaders.value.i++; } if (changeTexture) { @@ -435,21 +438,21 @@ void HWR_RenderBatches(void) currentTexture = nextTexture; changeTexture = false; - ps_hw_numtextures++; + ps_hw_numtextures.value.i++; } if (changePolyFlags) { currentPolyFlags = nextPolyFlags; changePolyFlags = false; - ps_hw_numpolyflags++; + ps_hw_numpolyflags.value.i++; } if (changeSurfaceInfo) { currentSurfaceInfo = nextSurfaceInfo; changeSurfaceInfo = false; - ps_hw_numcolors++; + ps_hw_numcolors.value.i++; } // and that should be it? } @@ -457,7 +460,7 @@ void HWR_RenderBatches(void) polygonArraySize = 0; unsortedVertexArraySize = 0; - ps_hw_batchdrawtime = I_GetPreciseTime() - ps_hw_batchdrawtime; + PS_STOP_TIMING(ps_hw_batchdrawtime); } diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e0851af85..9bade3d6f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -147,22 +147,22 @@ static angle_t gl_aimingangle; static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox); // Render stats -precise_t ps_hw_skyboxtime = 0; -precise_t ps_hw_nodesorttime = 0; -precise_t ps_hw_nodedrawtime = 0; -precise_t ps_hw_spritesorttime = 0; -precise_t ps_hw_spritedrawtime = 0; +ps_metric_t ps_hw_skyboxtime = {0}; +ps_metric_t ps_hw_nodesorttime = {0}; +ps_metric_t ps_hw_nodedrawtime = {0}; +ps_metric_t ps_hw_spritesorttime = {0}; +ps_metric_t ps_hw_spritedrawtime = {0}; // Render stats for batching -int ps_hw_numpolys = 0; -int ps_hw_numverts = 0; -int ps_hw_numcalls = 0; -int ps_hw_numshaders = 0; -int ps_hw_numtextures = 0; -int ps_hw_numpolyflags = 0; -int ps_hw_numcolors = 0; -precise_t ps_hw_batchsorttime = 0; -precise_t ps_hw_batchdrawtime = 0; +ps_metric_t ps_hw_numpolys = {0}; +ps_metric_t ps_hw_numverts = {0}; +ps_metric_t ps_hw_numcalls = {0}; +ps_metric_t ps_hw_numshaders = {0}; +ps_metric_t ps_hw_numtextures = {0}; +ps_metric_t ps_hw_numpolyflags = {0}; +ps_metric_t ps_hw_numcolors = {0}; +ps_metric_t ps_hw_batchsorttime = {0}; +ps_metric_t ps_hw_batchdrawtime = {0}; boolean gl_init = false; boolean gl_maploaded = false; @@ -3235,7 +3235,7 @@ static void HWR_Subsector(size_t num) } // for render stats - ps_numpolyobjects += numpolys; + ps_numpolyobjects.value.i += numpolys; // Sort polyobjects R_SortPolyObjects(sub); @@ -3343,7 +3343,7 @@ static void HWR_RenderBSPNode(INT32 bspnum) // Decide which side the view point is on INT32 side; - ps_numbspcalls++; + ps_numbspcalls.value.i++; // Found a subsector? if (bspnum & NF_SUBSECTOR) @@ -4718,7 +4718,7 @@ static void HWR_CreateDrawNodes(void) // that is already lying around. This should all be in some sort of linked list or lists. sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL); - ps_hw_nodesorttime = I_GetPreciseTime(); + PS_START_TIMING(ps_hw_nodesorttime); for (i = 0; i < numplanes; i++, p++) { @@ -4738,7 +4738,7 @@ static void HWR_CreateDrawNodes(void) sortindex[p] = p; } - ps_numdrawnodes = p; + ps_numdrawnodes.value.i = p; // p is the number of stuff to sort @@ -4773,9 +4773,9 @@ static void HWR_CreateDrawNodes(void) } } - ps_hw_nodesorttime = I_GetPreciseTime() - ps_hw_nodesorttime; + PS_STOP_TIMING(ps_hw_nodesorttime); - ps_hw_nodedrawtime = I_GetPreciseTime(); + PS_START_TIMING(ps_hw_nodedrawtime); // Okay! Let's draw it all! Woo! HWD.pfnSetTransform(&atransform); @@ -4812,7 +4812,7 @@ static void HWR_CreateDrawNodes(void) } } - ps_hw_nodedrawtime = I_GetPreciseTime() - ps_hw_nodedrawtime; + PS_STOP_TIMING(ps_hw_nodedrawtime); numwalls = 0; numplanes = 0; @@ -6095,10 +6095,10 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) if (viewnumber == 0) // Only do it if it's the first screen being rendered HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. - ps_hw_skyboxtime = I_GetPreciseTime(); + PS_START_TIMING(ps_hw_skyboxtime); if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind - ps_hw_skyboxtime = I_GetPreciseTime() - ps_hw_skyboxtime; + PS_STOP_TIMING(ps_hw_skyboxtime); { // do we really need to save player (is it not the same)? @@ -6208,9 +6208,9 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) // Reset the shader state. HWR_SetShaderState(); - ps_numbspcalls = 0; - ps_numpolyobjects = 0; - ps_bsptime = I_GetPreciseTime(); + ps_numbspcalls.value.i = 0; + ps_numpolyobjects.value.i = 0; + PS_START_TIMING(ps_bsptime); validcount++; @@ -6248,7 +6248,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) } #endif - ps_bsptime = I_GetPreciseTime() - ps_bsptime; + PS_STOP_TIMING(ps_bsptime); if (cv_glbatching.value) HWR_RenderBatches(); @@ -6263,22 +6263,22 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) #endif // Draw MD2 and sprites - ps_numsprites = gl_visspritecount; - ps_hw_spritesorttime = I_GetPreciseTime(); + ps_numsprites.value.i = gl_visspritecount; + PS_START_TIMING(ps_hw_spritesorttime); HWR_SortVisSprites(); - ps_hw_spritesorttime = I_GetPreciseTime() - ps_hw_spritesorttime; - ps_hw_spritedrawtime = I_GetPreciseTime(); + PS_STOP_TIMING(ps_hw_spritesorttime); + PS_START_TIMING(ps_hw_spritedrawtime); HWR_DrawSprites(); - ps_hw_spritedrawtime = I_GetPreciseTime() - ps_hw_spritedrawtime; + PS_STOP_TIMING(ps_hw_spritedrawtime); #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? HWR_DrawCoronas(); #endif - ps_numdrawnodes = 0; - ps_hw_nodesorttime = 0; - ps_hw_nodedrawtime = 0; + ps_numdrawnodes.value.i = 0; + ps_hw_nodesorttime.value.p = 0; + ps_hw_nodedrawtime.value.p = 0; if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything { HWR_CreateDrawNodes(); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index b751b2a6e..3f90f0ae1 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -20,6 +20,8 @@ #include "../d_player.h" #include "../r_defs.h" +#include "../m_perfstats.h" + // Startup & Shutdown the hardware mode renderer void HWR_Startup(void); void HWR_Switch(void); @@ -116,22 +118,22 @@ extern FTransform atransform; // Render stats -extern precise_t ps_hw_skyboxtime; -extern precise_t ps_hw_nodesorttime; -extern precise_t ps_hw_nodedrawtime; -extern precise_t ps_hw_spritesorttime; -extern precise_t ps_hw_spritedrawtime; +extern ps_metric_t ps_hw_skyboxtime; +extern ps_metric_t ps_hw_nodesorttime; +extern ps_metric_t ps_hw_nodedrawtime; +extern ps_metric_t ps_hw_spritesorttime; +extern ps_metric_t ps_hw_spritedrawtime; // Render stats for batching -extern int ps_hw_numpolys; -extern int ps_hw_numverts; -extern int ps_hw_numcalls; -extern int ps_hw_numshaders; -extern int ps_hw_numtextures; -extern int ps_hw_numpolyflags; -extern int ps_hw_numcolors; -extern precise_t ps_hw_batchsorttime; -extern precise_t ps_hw_batchdrawtime; +extern ps_metric_t ps_hw_numpolys; +extern ps_metric_t ps_hw_numverts; +extern ps_metric_t ps_hw_numcalls; +extern ps_metric_t ps_hw_numshaders; +extern ps_metric_t ps_hw_numtextures; +extern ps_metric_t ps_hw_numpolyflags; +extern ps_metric_t ps_hw_numcolors; +extern ps_metric_t ps_hw_batchsorttime; +extern ps_metric_t ps_hw_batchdrawtime; extern boolean gl_init; extern boolean gl_maploaded; diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 32b5e52fb..a72b22b5a 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -505,7 +505,7 @@ static int call_hooks calls += call_mobj_type_hooks(hook, MT_NULL); calls += call_mobj_type_hooks(hook, hook->mobj_type); - ps_lua_mobjhooks += calls; + ps_lua_mobjhooks.value.i += calls; } else calls += call_mapped(hook, &hookIds[hook->hook_type]); @@ -868,7 +868,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) LUA_PushUserdata(gL, line, META_LINE); LUA_PushUserdata(gL, mo, META_MOBJ); LUA_PushUserdata(gL, sector, META_SECTOR); - ps_lua_mobjhooks += call_hooks(&hook, 0, res_none); + ps_lua_mobjhooks.value.i += call_hooks(&hook, 0, res_none); } } diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 8a99312e6..9285b31be 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -22,46 +22,173 @@ #include "hardware/hw_main.h" #endif -struct perfstatcol; struct perfstatrow; -typedef struct perfstatcol perfstatcol_t; typedef struct perfstatrow perfstatrow_t; -struct perfstatcol { - INT32 lores_x; - INT32 hires_x; - INT32 color; - perfstatrow_t * rows; -}; - struct perfstatrow { - const char * lores_label; - const char * hires_label; - void * value; + const char * lores_label; + const char * hires_label; + ps_metric_t * metric; + UINT8 flags; }; -static precise_t ps_frametime = 0; +// perfstatrow_t flags -precise_t ps_tictime = 0; +#define PS_TIME 1 // metric measures time (uses precise_t instead of INT32) +#define PS_LEVEL 2 // metric is valid only when a level is active +#define PS_SW 4 // metric is valid only in software mode +#define PS_HW 8 // metric is valid only in opengl mode +#define PS_BATCHING 16 // metric is valid only when opengl batching is active +#define PS_HIDE_ZERO 32 // hide metric if its value is zero -precise_t ps_playerthink_time = 0; -precise_t ps_thinkertime = 0; +static ps_metric_t ps_frametime = {0}; -precise_t ps_thlist_times[NUM_THINKERLISTS]; +ps_metric_t ps_tictime = {0}; -int ps_checkposition_calls = 0; +ps_metric_t ps_playerthink_time = {0}; +ps_metric_t ps_thinkertime = {0}; -precise_t ps_lua_thinkframe_time = 0; -int ps_lua_mobjhooks = 0; +ps_metric_t ps_thlist_times[NUM_THINKERLISTS]; + +static ps_metric_t ps_thinkercount = {0}; +static ps_metric_t ps_polythcount = {0}; +static ps_metric_t ps_mainthcount = {0}; +static ps_metric_t ps_mobjcount = {0}; +static ps_metric_t ps_regularcount = {0}; +static ps_metric_t ps_scenerycount = {0}; +static ps_metric_t ps_nothinkcount = {0}; +static ps_metric_t ps_dynslopethcount = {0}; +static ps_metric_t ps_precipcount = {0}; +static ps_metric_t ps_removecount = {0}; + +ps_metric_t ps_checkposition_calls = {0}; + +ps_metric_t ps_lua_thinkframe_time = {0}; +ps_metric_t ps_lua_mobjhooks = {0}; + +ps_metric_t ps_otherlogictime = {0}; + +// Columns for perfstats pages. + +// Position on screen is determined separately in the drawing functions. + +// New columns must also be added to the drawing and update functions. +// Drawing functions: PS_DrawRenderStats, PS_DrawGameLogicStats, etc. +// Update functions: +// - PS_UpdateFrameStats for frame-dependent values +// - PS_UpdateTickStats for tick-dependent values + +// Rendering stats columns + +perfstatrow_t rendertime_rows[] = { + {"frmtime", "Frame time: ", &ps_frametime, PS_TIME}, + {"drwtime", "3d rendering: ", &ps_rendercalltime, PS_TIME|PS_LEVEL}, + +#ifdef HWRENDER + {" skybox ", " Skybox render: ", &ps_hw_skyboxtime, PS_TIME|PS_LEVEL|PS_HW}, + {" bsptime", " RenderBSPNode: ", &ps_bsptime, PS_TIME|PS_LEVEL|PS_HW}, + {" batsort", " Batch sort: ", &ps_hw_batchsorttime, PS_TIME|PS_LEVEL|PS_HW|PS_BATCHING}, + {" batdraw", " Batch render: ", &ps_hw_batchdrawtime, PS_TIME|PS_LEVEL|PS_HW|PS_BATCHING}, + {" sprsort", " Sprite sort: ", &ps_hw_spritesorttime, PS_TIME|PS_LEVEL|PS_HW}, + {" sprdraw", " Sprite render: ", &ps_hw_spritedrawtime, PS_TIME|PS_LEVEL|PS_HW}, + {" nodesrt", " Drwnode sort: ", &ps_hw_nodesorttime, PS_TIME|PS_LEVEL|PS_HW}, + {" nodedrw", " Drwnode render:", &ps_hw_nodedrawtime, PS_TIME|PS_LEVEL|PS_HW}, + {" other ", " Other: ", &ps_otherrendertime, PS_TIME|PS_LEVEL|PS_HW}, +#endif + + {" bsptime", " RenderBSPNode: ", &ps_bsptime, PS_TIME|PS_LEVEL|PS_SW}, + {" sprclip", " R_ClipSprites: ", &ps_sw_spritecliptime, PS_TIME|PS_LEVEL|PS_SW}, + {" portals", " Portals+Skybox:", &ps_sw_portaltime, PS_TIME|PS_LEVEL|PS_SW}, + {" planes ", " R_DrawPlanes: ", &ps_sw_planetime, PS_TIME|PS_LEVEL|PS_SW}, + {" masked ", " R_DrawMasked: ", &ps_sw_maskedtime, PS_TIME|PS_LEVEL|PS_SW}, + {" other ", " Other: ", &ps_otherrendertime, PS_TIME|PS_LEVEL|PS_SW}, + + {"ui ", "UI render: ", &ps_uitime, PS_TIME}, + {"finupdt", "I_FinishUpdate:", &ps_swaptime, PS_TIME}, + {0} +}; + +perfstatrow_t gamelogicbrief_row[] = { + {"logic ", "Game logic: ", &ps_tictime, PS_TIME}, + {0} +}; + +perfstatrow_t commoncounter_rows[] = { + {"bspcall", "BSP calls: ", &ps_numbspcalls, 0}, + {"sprites", "Sprites: ", &ps_numsprites, 0}, + {"drwnode", "Drawnodes: ", &ps_numdrawnodes, 0}, + {"plyobjs", "Polyobjects: ", &ps_numpolyobjects, 0}, + {0} +}; + +#ifdef HWRENDER +perfstatrow_t batchcount_rows[] = { + {"polygon", "Polygons: ", &ps_hw_numpolys, 0}, + {"vertex ", "Vertices: ", &ps_hw_numverts, 0}, + {0} +}; + +perfstatrow_t batchcalls_rows[] = { + {"drwcall", "Draw calls:", &ps_hw_numcalls, 0}, + {"shaders", "Shaders: ", &ps_hw_numshaders, 0}, + {"texture", "Textures: ", &ps_hw_numtextures, 0}, + {"polyflg", "Polyflags: ", &ps_hw_numpolyflags, 0}, + {"colors ", "Colors: ", &ps_hw_numcolors, 0}, + {0} +}; +#endif + +// Game logic stats columns + +perfstatrow_t gamelogic_rows[] = { + {"logic ", "Game logic: ", &ps_tictime, PS_TIME}, + {" plrthnk", " P_PlayerThink: ", &ps_playerthink_time, PS_TIME|PS_LEVEL}, + {" thnkers", " P_RunThinkers: ", &ps_thinkertime, PS_TIME|PS_LEVEL}, + {" plyobjs", " Polyobjects: ", &ps_thlist_times[THINK_POLYOBJ], PS_TIME|PS_LEVEL}, + {" main ", " Main: ", &ps_thlist_times[THINK_MAIN], PS_TIME|PS_LEVEL}, + {" mobjs ", " Mobjs: ", &ps_thlist_times[THINK_MOBJ], PS_TIME|PS_LEVEL}, + {" dynslop", " Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE], PS_TIME|PS_LEVEL}, + {" precip ", " Precipitation: ", &ps_thlist_times[THINK_PRECIP], PS_TIME|PS_LEVEL}, + {" lthinkf", " LUAh_ThinkFrame:", &ps_lua_thinkframe_time, PS_TIME|PS_LEVEL}, + {" other ", " Other: ", &ps_otherlogictime, PS_TIME|PS_LEVEL}, + {0} +}; + +perfstatrow_t thinkercount_rows[] = { + {"thnkers", "Thinkers: ", &ps_thinkercount, PS_LEVEL}, + {" plyobjs", " Polyobjects: ", &ps_polythcount, PS_LEVEL}, + {" main ", " Main: ", &ps_mainthcount, PS_LEVEL}, + {" mobjs ", " Mobjs: ", &ps_mobjcount, PS_LEVEL}, + {" regular", " Regular: ", &ps_regularcount, PS_LEVEL}, + {" scenery", " Scenery: ", &ps_scenerycount, PS_LEVEL}, + {" nothink", " Nothink: ", &ps_nothinkcount, PS_HIDE_ZERO|PS_LEVEL}, + {" dynslop", " Dynamic slopes: ", &ps_dynslopethcount, PS_LEVEL}, + {" precip ", " Precipitation: ", &ps_precipcount, PS_LEVEL}, + {" remove ", " Pending removal:", &ps_removecount, PS_LEVEL}, + {0} +}; + +perfstatrow_t misc_calls_rows[] = { + {"lmhook", "Lua mobj hooks: ", &ps_lua_mobjhooks, PS_LEVEL}, + {"chkpos", "P_CheckPosition:", &ps_checkposition_calls, PS_LEVEL}, + {0} +}; + +// Sample collection status for averaging. +// Maximum of these two is shown to user if nonzero to tell that +// the reported averages are not correct yet. +int ps_frame_samples_left = 0; +int ps_tick_samples_left = 0; +// History writing positions for frame and tick based metrics +int ps_frame_index = 0; +int ps_tick_index = 0; // dynamically allocated resizeable array for thinkframe hook stats ps_hookinfo_t *thinkframe_hooks = NULL; int thinkframe_hooks_length = 0; int thinkframe_hooks_capacity = 16; -static INT32 draw_row; - void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) { if (!thinkframe_hooks) @@ -76,506 +203,617 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) thinkframe_hooks = Z_Realloc(thinkframe_hooks, sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL); } - thinkframe_hooks[index].time_taken = time_taken; + thinkframe_hooks[index].time_taken.value.p = time_taken; memcpy(thinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char)); // since the values are set sequentially from begin to end, the last call should leave // the correct value to this variable thinkframe_hooks_length = index + 1; } -static void PS_SetFrameTime(void) -{ - precise_t currenttime = I_GetPreciseTime(); - ps_frametime = currenttime - ps_prevframetime; - ps_prevframetime = currenttime; -} - -static boolean M_HighResolution(void) +static boolean PS_HighResolution(void) { return (vid.width >= 640 && vid.height >= 400); } -enum { - PERF_TIME, - PERF_COUNT, -}; - -static void M_DrawPerfString(perfstatcol_t *col, int type) +static boolean PS_IsLevelActive(void) { - const boolean hires = M_HighResolution(); + return gamestate == GS_LEVEL || + (gamestate == GS_TITLESCREEN && titlemapinaction); +} - INT32 draw_flags = V_MONOSPACE | col->color; +// Is the row valid in the current context? +static boolean PS_IsRowValid(perfstatrow_t *row) +{ + return !((row->flags & PS_LEVEL && !PS_IsLevelActive()) || + (row->flags & PS_SW && rendermode != render_soft) || + (row->flags & PS_HW && rendermode != render_opengl) || + (row->flags & PS_BATCHING && !cv_glbatching.value)); +} +// Should the row be visible on the screen? +static boolean PS_IsRowVisible(perfstatrow_t *row) +{ + boolean value_is_zero; + + if (row->flags & PS_TIME) + value_is_zero = row->metric->value.p == 0; + else + value_is_zero = row->metric->value.i == 0; + + return !(!PS_IsRowValid(row) || + (row->flags & PS_HIDE_ZERO && value_is_zero)); +} + +static INT32 PS_GetMetricAverage(ps_metric_t *metric, boolean time_metric) +{ + char* history_read_pos = metric->history; // char* used for pointer arithmetic + INT64 sum = 0; + int i; + int value_size = time_metric ? sizeof(precise_t) : sizeof(INT32); + + for (i = 0; i < cv_ps_samplesize.value; i++) + { + if (time_metric) + sum += I_PreciseToMicros(*((precise_t*)history_read_pos)); + else + sum += *((INT32*)history_read_pos); + history_read_pos += value_size; + } + + return sum / cv_ps_samplesize.value; +} + +static INT32 PS_GetMetricMinOrMax(ps_metric_t *metric, boolean time_metric, boolean get_max) +{ + char* history_read_pos = metric->history; // char* used for pointer arithmetic + INT32 found_value = get_max ? INT32_MIN : INT32_MAX; + int i; + int value_size = time_metric ? sizeof(precise_t) : sizeof(INT32); + + for (i = 0; i < cv_ps_samplesize.value; i++) + { + INT32 value; + if (time_metric) + value = I_PreciseToMicros(*((precise_t*)history_read_pos)); + else + value = *((INT32*)history_read_pos); + + if ((get_max && value > found_value) || + (!get_max && value < found_value)) + { + found_value = value; + } + history_read_pos += value_size; + } + + return found_value; +} + +// Calculates the standard deviation for metric. +static INT32 PS_GetMetricSD(ps_metric_t *metric, boolean time_metric) +{ + char* history_read_pos = metric->history; // char* used for pointer arithmetic + INT64 sum = 0; + int i; + int value_size = time_metric ? sizeof(precise_t) : sizeof(INT32); + INT32 avg = PS_GetMetricAverage(metric, time_metric); + + for (i = 0; i < cv_ps_samplesize.value; i++) + { + INT64 value; + if (time_metric) + value = I_PreciseToMicros(*((precise_t*)history_read_pos)); + else + value = *((INT32*)history_read_pos); + + value -= avg; + sum += value * value; + + history_read_pos += value_size; + } + + return round(sqrt(sum / cv_ps_samplesize.value)); +} + +// Returns the value to show on screen for metric. +static INT32 PS_GetMetricScreenValue(ps_metric_t *metric, boolean time_metric) +{ + if (cv_ps_samplesize.value > 1 && metric->history) + { + if (cv_ps_descriptor.value == 1) + return PS_GetMetricAverage(metric, time_metric); + else if (cv_ps_descriptor.value == 2) + return PS_GetMetricSD(metric, time_metric); + else if (cv_ps_descriptor.value == 3) + return PS_GetMetricMinOrMax(metric, time_metric, false); + else + return PS_GetMetricMinOrMax(metric, time_metric, true); + } + else + { + if (time_metric) + return I_PreciseToMicros(metric->value.p); + else + return metric->value.i; + } +} + +static int PS_DrawPerfRows(int x, int y, int color, perfstatrow_t *rows) +{ + const boolean hires = PS_HighResolution(); + INT32 draw_flags = V_MONOSPACE | color; perfstatrow_t * row; - - int value; + int draw_y = y; if (hires) draw_flags |= V_ALLOWLOWERCASE; - for (row = col->rows; row->lores_label; ++row) + for (row = rows; row->lores_label; ++row) { - if (type == PERF_TIME) - value = I_PreciseToMicros(*(precise_t *)row->value); - else - value = *(int *)row->value; + const char *label; + INT32 value; + char *final_str; + + if (!PS_IsRowVisible(row)) + continue; + + label = hires ? row->hires_label : row->lores_label; + value = PS_GetMetricScreenValue(row->metric, !!(row->flags & PS_TIME)); + final_str = va("%s %d", label, value); if (hires) { - V_DrawSmallString(col->hires_x, draw_row, draw_flags, - va("%s %d", row->hires_label, value)); - - draw_row += 5; + V_DrawSmallString(x, draw_y, draw_flags, final_str); + draw_y += 5; } else { - V_DrawThinString(col->lores_x, draw_row, draw_flags, - va("%s %d", row->lores_label, value)); - - draw_row += 8; + V_DrawThinString(x, draw_y, draw_flags, final_str); + draw_y += 8; } } + + return draw_y; +} + +static void PS_UpdateMetricHistory(ps_metric_t *metric, boolean time_metric, boolean frame_metric, boolean set_user) +{ + int index = frame_metric ? ps_frame_index : ps_tick_index; + + if (!metric->history) + { + // allocate history table + int value_size = time_metric ? sizeof(precise_t) : sizeof(INT32); + void** memory_user = set_user ? &metric->history : NULL; + + metric->history = Z_Calloc(value_size * cv_ps_samplesize.value, PU_PERFSTATS, + memory_user); + + // reset "samples left" counter since this history table needs to be filled + if (frame_metric) + ps_frame_samples_left = cv_ps_samplesize.value; + else + ps_tick_samples_left = cv_ps_samplesize.value; + } + + if (time_metric) + { + precise_t *history = (precise_t*)metric->history; + history[index] = metric->value.p; + } + else + { + INT32 *history = (INT32*)metric->history; + history[index] = metric->value.i; + } } -static void M_DrawPerfTiming(perfstatcol_t *col) +static void PS_UpdateRowHistories(perfstatrow_t *rows, boolean frame_metric) { - M_DrawPerfString(col, PERF_TIME); -} - -static void M_DrawPerfCount(perfstatcol_t *col) -{ - M_DrawPerfString(col, PERF_COUNT); -} - -static void M_DrawRenderStats(void) -{ - const boolean hires = M_HighResolution(); - - const int half_row = hires ? 5 : 4; - - precise_t extrarendertime; - - perfstatrow_t frametime_row[] = { - {"frmtime", "Frame time: ", &ps_frametime}, - {0} - }; - - perfstatrow_t rendercalltime_row[] = { - {"drwtime", "3d rendering: ", &ps_rendercalltime}, - {0} - }; - - perfstatrow_t opengltime_row[] = { - {"skybox ", "Skybox render: ", &ps_hw_skyboxtime}, - {"bsptime", "RenderBSPNode: ", &ps_bsptime}, - {"nodesrt", "Drwnode sort: ", &ps_hw_nodesorttime}, - {"nodedrw", "Drwnode render:", &ps_hw_nodedrawtime}, - {"sprsort", "Sprite sort: ", &ps_hw_spritesorttime}, - {"sprdraw", "Sprite render: ", &ps_hw_spritedrawtime}, - {"other ", "Other: ", &extrarendertime}, - {0} - }; - - perfstatrow_t softwaretime_row[] = { - {"bsptime", "RenderBSPNode: ", &ps_bsptime}, - {"sprclip", "R_ClipSprites: ", &ps_sw_spritecliptime}, - {"portals", "Portals+Skybox:", &ps_sw_portaltime}, - {"planes ", "R_DrawPlanes: ", &ps_sw_planetime}, - {"masked ", "R_DrawMasked: ", &ps_sw_maskedtime}, - {"other ", "Other: ", &extrarendertime}, - {0} - }; - - perfstatrow_t uiswaptime_row[] = { - {"ui ", "UI render: ", &ps_uitime}, - {"finupdt", "I_FinishUpdate:", &ps_swaptime}, - {0} - }; - - perfstatrow_t tictime_row[] = { - {"logic ", "Game logic: ", &ps_tictime}, - {0} - }; - - perfstatrow_t rendercalls_row[] = { - {"bspcall", "BSP calls: ", &ps_numbspcalls}, - {"sprites", "Sprites: ", &ps_numsprites}, - {"drwnode", "Drawnodes: ", &ps_numdrawnodes}, - {"plyobjs", "Polyobjects: ", &ps_numpolyobjects}, - {0} - }; - - perfstatrow_t batchtime_row[] = { - {"batsort", "Batch sort: ", &ps_hw_batchsorttime}, - {"batdraw", "Batch render:", &ps_hw_batchdrawtime}, - {0} - }; - - perfstatrow_t batchcount_row[] = { - {"polygon", "Polygons: ", &ps_hw_numpolys}, - {"vertex ", "Vertices: ", &ps_hw_numverts}, - {0} - }; - - perfstatrow_t batchcalls_row[] = { - {"drwcall", "Draw calls:", &ps_hw_numcalls}, - {"shaders", "Shaders: ", &ps_hw_numshaders}, - {"texture", "Textures: ", &ps_hw_numtextures}, - {"polyflg", "Polyflags: ", &ps_hw_numpolyflags}, - {"colors ", "Colors: ", &ps_hw_numcolors}, - {0} - }; - - perfstatcol_t frametime_col = {20, 20, V_YELLOWMAP, frametime_row}; - perfstatcol_t rendercalltime_col = {20, 20, V_YELLOWMAP, rendercalltime_row}; - - perfstatcol_t opengltime_col = {24, 24, V_YELLOWMAP, opengltime_row}; - perfstatcol_t softwaretime_col = {24, 24, V_YELLOWMAP, softwaretime_row}; - - perfstatcol_t uiswaptime_col = {20, 20, V_YELLOWMAP, uiswaptime_row}; - perfstatcol_t tictime_col = {20, 20, V_GRAYMAP, tictime_row}; - - perfstatcol_t rendercalls_col = {90, 115, V_BLUEMAP, rendercalls_row}; - - perfstatcol_t batchtime_col = {90, 115, V_REDMAP, batchtime_row}; - - perfstatcol_t batchcount_col = {155, 200, V_PURPLEMAP, batchcount_row}; - perfstatcol_t batchcalls_col = {220, 200, V_PURPLEMAP, batchcalls_row}; - - - boolean rendering = ( - gamestate == GS_LEVEL || - (gamestate == GS_TITLESCREEN && titlemapinaction) - ); - - draw_row = 10; - M_DrawPerfTiming(&frametime_col); - - if (rendering) + perfstatrow_t *row; + for (row = rows; row->lores_label; row++) { - M_DrawPerfTiming(&rendercalltime_col); + if (PS_IsRowValid(row)) + PS_UpdateMetricHistory(row->metric, !!(row->flags & PS_TIME), frame_metric, true); + } +} +// Update all metrics that are calculated on every frame. +static void PS_UpdateFrameStats(void) +{ + // update frame time + precise_t currenttime = I_GetPreciseTime(); + ps_frametime.value.p = currenttime - ps_prevframetime; + ps_prevframetime = currenttime; + + // update 3d rendering stats + if (PS_IsLevelActive()) + { // Remember to update this calculation when adding more 3d rendering stats! - extrarendertime = ps_rendercalltime - ps_bsptime; + ps_otherrendertime.value.p = ps_rendercalltime.value.p - ps_bsptime.value.p; #ifdef HWRENDER if (rendermode == render_opengl) { - extrarendertime -= - ps_hw_skyboxtime + - ps_hw_nodesorttime + - ps_hw_nodedrawtime + - ps_hw_spritesorttime + - ps_hw_spritedrawtime; + ps_otherrendertime.value.p -= + ps_hw_skyboxtime.value.p + + ps_hw_nodesorttime.value.p + + ps_hw_nodedrawtime.value.p + + ps_hw_spritesorttime.value.p + + ps_hw_spritedrawtime.value.p; if (cv_glbatching.value) { - extrarendertime -= - ps_hw_batchsorttime + - ps_hw_batchdrawtime; + ps_otherrendertime.value.p -= + ps_hw_batchsorttime.value.p + + ps_hw_batchdrawtime.value.p; } - - M_DrawPerfTiming(&opengltime_col); } else #endif { - extrarendertime -= - ps_sw_spritecliptime + - ps_sw_portaltime + - ps_sw_planetime + - ps_sw_maskedtime; - - M_DrawPerfTiming(&softwaretime_col); + ps_otherrendertime.value.p -= + ps_sw_spritecliptime.value.p + + ps_sw_portaltime.value.p + + ps_sw_planetime.value.p + + ps_sw_maskedtime.value.p; } } - M_DrawPerfTiming(&uiswaptime_col); - - draw_row += half_row; - M_DrawPerfTiming(&tictime_col); - - if (rendering) + if (cv_ps_samplesize.value > 1) { - draw_row = 10; - M_DrawPerfCount(&rendercalls_col); + PS_UpdateRowHistories(rendertime_rows, true); + if (PS_IsLevelActive()) + PS_UpdateRowHistories(commoncounter_rows, true); #ifdef HWRENDER if (rendermode == render_opengl && cv_glbatching.value) { - draw_row += half_row; - M_DrawPerfTiming(&batchtime_col); - - draw_row = 10; - M_DrawPerfCount(&batchcount_col); - - if (hires) - draw_row += half_row; - else - draw_row = 10; - - M_DrawPerfCount(&batchcalls_col); + PS_UpdateRowHistories(batchcount_rows, true); + PS_UpdateRowHistories(batchcalls_rows, true); } #endif + + ps_frame_index++; + if (ps_frame_index >= cv_ps_samplesize.value) + ps_frame_index = 0; + if (ps_frame_samples_left) + ps_frame_samples_left--; } } -static void M_DrawTickStats(void) +// Update thinker counters by iterating the thinker lists. +static void PS_CountThinkers(void) { - int i = 0; + int i; thinker_t *thinker; - int thinkercount = 0; - int polythcount = 0; - int mainthcount = 0; - int mobjcount = 0; - int nothinkcount = 0; - int scenerycount = 0; - int regularcount = 0; - int dynslopethcount = 0; - int precipcount = 0; - int removecount = 0; - precise_t extratime = - ps_tictime - - ps_playerthink_time - - ps_thinkertime - - ps_lua_thinkframe_time; - - perfstatrow_t tictime_row[] = { - {"logic ", "Game logic: ", &ps_tictime}, - {0} - }; - - perfstatrow_t thinker_time_row[] = { - {"plrthnk", "P_PlayerThink: ", &ps_playerthink_time}, - {"thnkers", "P_RunThinkers: ", &ps_thinkertime}, - {0} - }; - - perfstatrow_t detailed_thinker_time_row[] = { - {"plyobjs", "Polyobjects: ", &ps_thlist_times[THINK_POLYOBJ]}, - {"main ", "Main: ", &ps_thlist_times[THINK_MAIN]}, - {"mobjs ", "Mobjs: ", &ps_thlist_times[THINK_MOBJ]}, - {"dynslop", "Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE]}, - {"precip ", "Precipitation: ", &ps_thlist_times[THINK_PRECIP]}, - {0} - }; - - perfstatrow_t extra_thinker_time_row[] = { - {"lthinkf", "LUAh_ThinkFrame:", &ps_lua_thinkframe_time}, - {"other ", "Other: ", &extratime}, - {0} - }; - - perfstatrow_t thinkercount_row[] = { - {"thnkers", "Thinkers: ", &thinkercount}, - {0} - }; - - perfstatrow_t detailed_thinkercount_row[] = { - {"plyobjs", "Polyobjects: ", &polythcount}, - {"main ", "Main: ", &mainthcount}, - {"mobjs ", "Mobjs: ", &mobjcount}, - {0} - }; - - perfstatrow_t mobjthinkercount_row[] = { - {"regular", "Regular: ", ®ularcount}, - {"scenery", "Scenery: ", &scenerycount}, - {0} - }; - - perfstatrow_t nothinkcount_row[] = { - {"nothink", "Nothink: ", ¬hinkcount}, - {0} - }; - - perfstatrow_t detailed_thinkercount_row2[] = { - {"dynslop", "Dynamic slopes: ", &dynslopethcount}, - {"precip ", "Precipitation: ", &precipcount}, - {"remove ", "Pending removal:", &removecount}, - {0} - }; - - perfstatrow_t misc_calls_row[] = { - {"lmhook", "Lua mobj hooks: ", &ps_lua_mobjhooks}, - {"chkpos", "P_CheckPosition:", &ps_checkposition_calls}, - {0} - }; - - perfstatcol_t tictime_col = {20, 20, V_YELLOWMAP, tictime_row}; - perfstatcol_t thinker_time_col = {24, 24, V_YELLOWMAP, thinker_time_row}; - perfstatcol_t detailed_thinker_time_col = {28, 28, V_YELLOWMAP, detailed_thinker_time_row}; - perfstatcol_t extra_thinker_time_col = {24, 24, V_YELLOWMAP, extra_thinker_time_row}; - - perfstatcol_t thinkercount_col = {90, 115, V_BLUEMAP, thinkercount_row}; - perfstatcol_t detailed_thinkercount_col = {94, 119, V_BLUEMAP, detailed_thinkercount_row}; - perfstatcol_t mobjthinkercount_col = {98, 123, V_BLUEMAP, mobjthinkercount_row}; - perfstatcol_t nothinkcount_col = {98, 123, V_BLUEMAP, nothinkcount_row}; - perfstatcol_t detailed_thinkercount_col2 = {94, 119, V_BLUEMAP, detailed_thinkercount_row2}; - perfstatcol_t misc_calls_col = {170, 216, V_PURPLEMAP, misc_calls_row}; + ps_thinkercount.value.i = 0; + ps_polythcount.value.i = 0; + ps_mainthcount.value.i = 0; + ps_mobjcount.value.i = 0; + ps_regularcount.value.i = 0; + ps_scenerycount.value.i = 0; + ps_nothinkcount.value.i = 0; + ps_dynslopethcount.value.i = 0; + ps_precipcount.value.i = 0; + ps_removecount.value.i = 0; for (i = 0; i < NUM_THINKERLISTS; i++) { for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next) { - thinkercount++; + ps_thinkercount.value.i++; if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - removecount++; + ps_removecount.value.i++; else if (i == THINK_POLYOBJ) - polythcount++; + ps_polythcount.value.i++; else if (i == THINK_MAIN) - mainthcount++; + ps_mainthcount.value.i++; else if (i == THINK_MOBJ) { if (thinker->function.acp1 == (actionf_p1)P_MobjThinker) { mobj_t *mobj = (mobj_t*)thinker; - mobjcount++; + ps_mobjcount.value.i++; if (mobj->flags & MF_NOTHINK) - nothinkcount++; + ps_nothinkcount.value.i++; else if (mobj->flags & MF_SCENERY) - scenerycount++; + ps_scenerycount.value.i++; else - regularcount++; + ps_regularcount.value.i++; } } else if (i == THINK_DYNSLOPE) - dynslopethcount++; + ps_dynslopethcount.value.i++; else if (i == THINK_PRECIP) - precipcount++; + ps_precipcount.value.i++; } } +} - draw_row = 10; - M_DrawPerfTiming(&tictime_col); - M_DrawPerfTiming(&thinker_time_col); - M_DrawPerfTiming(&detailed_thinker_time_col); - M_DrawPerfTiming(&extra_thinker_time_col); - - draw_row = 10; - M_DrawPerfCount(&thinkercount_col); - M_DrawPerfCount(&detailed_thinkercount_col); - M_DrawPerfCount(&mobjthinkercount_col); - - if (nothinkcount) - M_DrawPerfCount(¬hinkcount_col); - - M_DrawPerfCount(&detailed_thinkercount_col2); - - if (M_HighResolution()) +// Update all metrics that are calculated on every tick. +void PS_UpdateTickStats(void) +{ + if (cv_perfstats.value == 1 && cv_ps_samplesize.value > 1) { + PS_UpdateRowHistories(gamelogicbrief_row, false); + } + if (cv_perfstats.value == 2) + { + if (PS_IsLevelActive()) + { + ps_otherlogictime.value.p = + ps_tictime.value.p - + ps_playerthink_time.value.p - + ps_thinkertime.value.p - + ps_lua_thinkframe_time.value.p; + + PS_CountThinkers(); + } + + if (cv_ps_samplesize.value > 1) + { + PS_UpdateRowHistories(gamelogic_rows, false); + PS_UpdateRowHistories(thinkercount_rows, false); + PS_UpdateRowHistories(misc_calls_rows, false); + } + } + if (cv_perfstats.value == 3 && cv_ps_samplesize.value > 1 && PS_IsLevelActive()) + { + int i; + for (i = 0; i < thinkframe_hooks_length; i++) + { + PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false); + } + } + if (cv_perfstats.value && cv_ps_samplesize.value > 1) + { + ps_tick_index++; + if (ps_tick_index >= cv_ps_samplesize.value) + ps_tick_index = 0; + if (ps_tick_samples_left) + ps_tick_samples_left--; + } +} + +static void PS_DrawDescriptorHeader(void) +{ + if (cv_ps_samplesize.value > 1) + { + const char* descriptor_names[] = { + "average", + "standard deviation", + "minimum", + "maximum" + }; + const boolean hires = PS_HighResolution(); + char* str; + INT32 flags = V_MONOSPACE | V_ALLOWLOWERCASE; + int samples_left = max(ps_frame_samples_left, ps_tick_samples_left); + int x, y; + + if (cv_perfstats.value == 3) + { + x = 2; + y = 0; + } + else + { + x = 20; + y = hires ? 5 : 2; + } + + if (samples_left) + { + str = va("Samples needed for correct results: %d", samples_left); + flags |= V_REDMAP; + } + else + { + str = va("Showing the %s of %d samples.", + descriptor_names[cv_ps_descriptor.value - 1], cv_ps_samplesize.value); + flags |= V_GREENMAP; + } + + if (hires) + V_DrawSmallString(x, y, flags, str); + else + V_DrawThinString(x, y, flags, str); + } +} + +static void PS_DrawRenderStats(void) +{ + const boolean hires = PS_HighResolution(); + const int half_row = hires ? 5 : 4; + int x, y; + + PS_DrawDescriptorHeader(); + + y = PS_DrawPerfRows(20, 10, V_YELLOWMAP, rendertime_rows); + + PS_DrawPerfRows(20, y + half_row, V_GRAYMAP, gamelogicbrief_row); + + if (PS_IsLevelActive()) + { + x = hires ? 115 : 90; + PS_DrawPerfRows(x, 10, V_BLUEMAP, commoncounter_rows); + +#ifdef HWRENDER + if (rendermode == render_opengl && cv_glbatching.value) + { + x = hires ? 200 : 155; + y = PS_DrawPerfRows(x, 10, V_PURPLEMAP, batchcount_rows); + + x = hires ? 200 : 220; + y = hires ? y + half_row : 10; + PS_DrawPerfRows(x, y, V_PURPLEMAP, batchcalls_rows); + } +#endif + } +} + +static void PS_DrawGameLogicStats(void) +{ + const boolean hires = PS_HighResolution(); + int x, y; + + PS_DrawDescriptorHeader(); + + PS_DrawPerfRows(20, 10, V_YELLOWMAP, gamelogic_rows); + + x = hires ? 115 : 90; + PS_DrawPerfRows(x, 10, V_BLUEMAP, thinkercount_rows); + + if (hires) V_DrawSmallString(212, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, "Calls:"); - draw_row = 15; - } - else - { - draw_row = 10; - } + x = hires ? 216 : 170; + y = hires ? 15 : 10; + PS_DrawPerfRows(x, y, V_PURPLEMAP, misc_calls_rows); +} - M_DrawPerfCount(&misc_calls_col); +static void PS_DrawThinkFrameStats(void) +{ + char s[100]; + int i; + // text writing position + int x = 2; + int y = 4; + UINT32 text_color; + char tempbuffer[LUA_IDSIZE]; + char last_mod_name[LUA_IDSIZE]; + last_mod_name[0] = '\0'; + + PS_DrawDescriptorHeader(); + + for (i = 0; i < thinkframe_hooks_length; i++) + { + +#define NEXT_ROW() \ +y += 4; \ +if (y > 192) \ +{ \ + y = 4; \ + x += 106; \ + if (x > 214) \ + break; \ +} + + char* str = thinkframe_hooks[i].short_src; + char* tempstr = tempbuffer; + int len = (int)strlen(str); + char* str_ptr; + if (strcmp(".lua", str + len - 4) == 0) + { + str[len-4] = '\0'; // remove .lua at end + len -= 4; + } + // we locate the wad/pk3 name in the string and compare it to + // what we found on the previous iteration. + // if the name has changed, print it out on the screen + strcpy(tempstr, str); + str_ptr = strrchr(tempstr, '|'); + if (str_ptr) + { + *str_ptr = '\0'; + str = str_ptr + 1; // this is the name of the hook without the mod file name + str_ptr = strrchr(tempstr, PATHSEP[0]); + if (str_ptr) + tempstr = str_ptr + 1; + // tempstr should now point to the mod name, (wad/pk3) possibly truncated + if (strcmp(tempstr, last_mod_name) != 0) + { + strcpy(last_mod_name, tempstr); + len = (int)strlen(tempstr); + if (len > 25) + tempstr += len - 25; + snprintf(s, sizeof s - 1, "%s", tempstr); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + NEXT_ROW() + } + text_color = V_YELLOWMAP; + } + else + { + // probably a standalone lua file + // cut off the folder if it's there + str_ptr = strrchr(tempstr, PATHSEP[0]); + if (str_ptr) + str = str_ptr + 1; + text_color = 0; // white + } + len = (int)strlen(str); + if (len > 20) + str += len - 20; + snprintf(s, sizeof s - 1, "%20s: %d", str, + PS_GetMetricScreenValue(&thinkframe_hooks[i].time_taken, true)); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s); + NEXT_ROW() + +#undef NEXT_ROW + + } } void M_DrawPerfStats(void) { - char s[100]; - - PS_SetFrameTime(); - if (cv_perfstats.value == 1) // rendering { - M_DrawRenderStats(); + PS_UpdateFrameStats(); + PS_DrawRenderStats(); } else if (cv_perfstats.value == 2) // logic { - M_DrawTickStats(); + // PS_UpdateTickStats is called in TryRunTics, since otherwise it would miss + // tics when frame skips happen + PS_DrawGameLogicStats(); } else if (cv_perfstats.value == 3) // lua thinkframe { - if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + if (!PS_IsLevelActive()) return; - if (vid.width < 640 || vid.height < 400) // low resolution + if (!PS_HighResolution()) { - // it's not gonna fit very well.. - V_DrawThinString(30, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Not available for resolutions below 640x400"); + // Low resolutions can't really use V_DrawSmallString that is used by thinkframe stats. + // A low-res version using V_DrawThinString could be implemented, + // but it would have much less space for information. + V_DrawThinString(80, 92, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Perfstats 3 is not available"); + V_DrawThinString(80, 100, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "for resolutions below 640x400."); } - else // high resolution + else { - int i; - // text writing position - int x = 2; - int y = 4; - UINT32 text_color; - char tempbuffer[LUA_IDSIZE]; - char last_mod_name[LUA_IDSIZE]; - last_mod_name[0] = '\0'; - for (i = 0; i < thinkframe_hooks_length; i++) - { - char* str = thinkframe_hooks[i].short_src; - char* tempstr = tempbuffer; - int len = (int)strlen(str); - char* str_ptr; - if (strcmp(".lua", str + len - 4) == 0) - { - str[len-4] = '\0'; // remove .lua at end - len -= 4; - } - // we locate the wad/pk3 name in the string and compare it to - // what we found on the previous iteration. - // if the name has changed, print it out on the screen - strcpy(tempstr, str); - str_ptr = strrchr(tempstr, '|'); - if (str_ptr) - { - *str_ptr = '\0'; - str = str_ptr + 1; // this is the name of the hook without the mod file name - str_ptr = strrchr(tempstr, PATHSEP[0]); - if (str_ptr) - tempstr = str_ptr + 1; - // tempstr should now point to the mod name, (wad/pk3) possibly truncated - if (strcmp(tempstr, last_mod_name) != 0) - { - strcpy(last_mod_name, tempstr); - len = (int)strlen(tempstr); - if (len > 25) - tempstr += len - 25; - snprintf(s, sizeof s - 1, "%s", tempstr); - V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); - y += 4; // repeated code! - if (y > 192) - { - y = 4; - x += 106; - if (x > 214) - break; - } - } - text_color = V_YELLOWMAP; - } - else - { - // probably a standalone lua file - // cut off the folder if it's there - str_ptr = strrchr(tempstr, PATHSEP[0]); - if (str_ptr) - str = str_ptr + 1; - text_color = 0; // white - } - len = (int)strlen(str); - if (len > 20) - str += len - 20; - snprintf(s, sizeof s - 1, "%20s: %d", str, I_PreciseToMicros(thinkframe_hooks[i].time_taken)); - V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s); - y += 4; // repeated code! - if (y > 192) - { - y = 4; - x += 106; - if (x > 214) - break; - } - } + PS_DrawThinkFrameStats(); } } } + +// remove and unallocate history from all metrics +static void PS_ClearHistory(void) +{ + int i; + + Z_FreeTag(PU_PERFSTATS); + // thinkframe hook metric history pointers need to be cleared manually + for (i = 0; i < thinkframe_hooks_length; i++) + { + thinkframe_hooks[i].time_taken.history = NULL; + } + + ps_frame_index = ps_tick_index = 0; + // PS_UpdateMetricHistory will set these correctly when it runs + ps_frame_samples_left = ps_tick_samples_left = 0; +} + +void PS_PerfStats_OnChange(void) +{ + if (cv_perfstats.value && cv_ps_samplesize.value > 1) + PS_ClearHistory(); +} + +void PS_SampleSize_OnChange(void) +{ + if (cv_ps_samplesize.value > 1) + PS_ClearHistory(); +} diff --git a/src/m_perfstats.h b/src/m_perfstats.h index 71208fbc1..3ff0e6c6b 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -16,26 +16,45 @@ #include "lua_script.h" #include "p_local.h" -extern precise_t ps_tictime; - -extern precise_t ps_playerthink_time; -extern precise_t ps_thinkertime; - -extern precise_t ps_thlist_times[]; - -extern int ps_checkposition_calls; - -extern precise_t ps_lua_thinkframe_time; -extern int ps_lua_mobjhooks; +typedef struct +{ + union { + precise_t p; + INT32 i; + } value; + void *history; +} ps_metric_t; typedef struct { - precise_t time_taken; + ps_metric_t time_taken; char short_src[LUA_IDSIZE]; } ps_hookinfo_t; +#define PS_START_TIMING(metric) metric.value.p = I_GetPreciseTime() +#define PS_STOP_TIMING(metric) metric.value.p = I_GetPreciseTime() - metric.value.p + +extern ps_metric_t ps_tictime; + +extern ps_metric_t ps_playerthink_time; +extern ps_metric_t ps_thinkertime; + +extern ps_metric_t ps_thlist_times[]; + +extern ps_metric_t ps_checkposition_calls; + +extern ps_metric_t ps_lua_thinkframe_time; +extern ps_metric_t ps_lua_mobjhooks; + +extern ps_metric_t ps_otherlogictime; + void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); +void PS_UpdateTickStats(void); + void M_DrawPerfStats(void); +void PS_PerfStats_OnChange(void); +void PS_SampleSize_OnChange(void); + #endif diff --git a/src/p_map.c b/src/p_map.c index e55bebb9a..1d3197fab 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2029,7 +2029,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) subsector_t *newsubsec; boolean blockval = true; - ps_checkposition_calls++; + ps_checkposition_calls.value.i++; I_Assert(thing != NULL); #ifdef PARANOIA diff --git a/src/p_tick.c b/src/p_tick.c index d7357eb82..1cdea9ac6 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -323,7 +323,7 @@ static inline void P_RunThinkers(void) size_t i; for (i = 0; i < NUM_THINKERLISTS; i++) { - ps_thlist_times[i] = I_GetPreciseTime(); + PS_START_TIMING(ps_thlist_times[i]); for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) { #ifdef PARANOIA @@ -331,7 +331,7 @@ static inline void P_RunThinkers(void) #endif currentthinker->function.acp1(currentthinker); } - ps_thlist_times[i] = I_GetPreciseTime() - ps_thlist_times[i]; + PS_STOP_TIMING(ps_thlist_times[i]); } } @@ -653,16 +653,16 @@ void P_Ticker(boolean run) } } - ps_lua_mobjhooks = 0; - ps_checkposition_calls = 0; + ps_lua_mobjhooks.value.i = 0; + ps_checkposition_calls.value.i = 0; LUA_HOOK(PreThinkFrame); - ps_playerthink_time = I_GetPreciseTime(); + PS_START_TIMING(ps_playerthink_time); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerThink(&players[i]); - ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time; + PS_STOP_TIMING(ps_playerthink_time); } // Keep track of how long they've been playing! @@ -677,18 +677,18 @@ void P_Ticker(boolean run) if (run) { - ps_thinkertime = I_GetPreciseTime(); + PS_START_TIMING(ps_thinkertime); P_RunThinkers(); - ps_thinkertime = I_GetPreciseTime() - ps_thinkertime; + PS_STOP_TIMING(ps_thinkertime); // Run any "after all the other thinkers" stuff for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - ps_lua_thinkframe_time = I_GetPreciseTime(); + PS_START_TIMING(ps_lua_thinkframe_time); LUA_HookThinkFrame(); - ps_lua_thinkframe_time = I_GetPreciseTime() - ps_lua_thinkframe_time; + PS_STOP_TIMING(ps_lua_thinkframe_time); } // Run shield positioning diff --git a/src/r_bsp.c b/src/r_bsp.c index 5acd4e70c..b8559d39e 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -804,7 +804,7 @@ static void R_AddPolyObjects(subsector_t *sub) } // for render stats - ps_numpolyobjects += numpolys; + ps_numpolyobjects.value.i += numpolys; // sort polyobjects R_SortPolyObjects(sub); @@ -1239,7 +1239,7 @@ void R_RenderBSPNode(INT32 bspnum) node_t *bsp; INT32 side; - ps_numbspcalls++; + ps_numbspcalls.value.i++; while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? { diff --git a/src/r_main.c b/src/r_main.c index 17e124cb9..8729b5dcb 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -101,21 +101,22 @@ extracolormap_t *extra_colormaps = NULL; // Render stats precise_t ps_prevframetime = 0; -precise_t ps_rendercalltime = 0; -precise_t ps_uitime = 0; -precise_t ps_swaptime = 0; +ps_metric_t ps_rendercalltime = {0}; +ps_metric_t ps_otherrendertime = {0}; +ps_metric_t ps_uitime = {0}; +ps_metric_t ps_swaptime = {0}; -precise_t ps_bsptime = 0; +ps_metric_t ps_bsptime = {0}; -precise_t ps_sw_spritecliptime = 0; -precise_t ps_sw_portaltime = 0; -precise_t ps_sw_planetime = 0; -precise_t ps_sw_maskedtime = 0; +ps_metric_t ps_sw_spritecliptime = {0}; +ps_metric_t ps_sw_portaltime = {0}; +ps_metric_t ps_sw_planetime = {0}; +ps_metric_t ps_sw_maskedtime = {0}; -int ps_numbspcalls = 0; -int ps_numsprites = 0; -int ps_numdrawnodes = 0; -int ps_numpolyobjects = 0; +ps_metric_t ps_numbspcalls = {0}; +ps_metric_t ps_numsprites = {0}; +ps_metric_t ps_numdrawnodes = {0}; +ps_metric_t ps_numpolyobjects = {0}; static CV_PossibleValue_t drawdist_cons_t[] = { {256, "256"}, {512, "512"}, {768, "768"}, @@ -1496,11 +1497,11 @@ void R_RenderPlayerView(player_t *player) mytotal = 0; ProfZeroTimer(); #endif - ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0; - ps_bsptime = I_GetPreciseTime(); + ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; + PS_START_TIMING(ps_bsptime); R_RenderBSPNode((INT32)numnodes - 1); - ps_bsptime = I_GetPreciseTime() - ps_bsptime; - ps_numsprites = visspritecount; + PS_STOP_TIMING(ps_bsptime); + ps_numsprites.value.i = visspritecount; #ifdef TIMING RDMSR(0x10, &mycount); mytotal += mycount; // 64bit add @@ -1510,9 +1511,9 @@ void R_RenderPlayerView(player_t *player) //profile stuff --------------------------------------------------------- Mask_Post(&masks[nummasks - 1]); - ps_sw_spritecliptime = I_GetPreciseTime(); + PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(drawsegs, NULL); - ps_sw_spritecliptime = I_GetPreciseTime() - ps_sw_spritecliptime; + PS_STOP_TIMING(ps_sw_spritecliptime); // Add skybox portals caused by sky visplanes. @@ -1520,7 +1521,7 @@ void R_RenderPlayerView(player_t *player) Portal_AddSkyboxPortals(); // Portal rendering. Hijacks the BSP traversal. - ps_sw_portaltime = I_GetPreciseTime(); + PS_START_TIMING(ps_sw_portaltime); if (portal_base) { portal_t *portal; @@ -1560,17 +1561,17 @@ void R_RenderPlayerView(player_t *player) Portal_Remove(portal); } } - ps_sw_portaltime = I_GetPreciseTime() - ps_sw_portaltime; + PS_STOP_TIMING(ps_sw_portaltime); - ps_sw_planetime = I_GetPreciseTime(); + PS_START_TIMING(ps_sw_planetime); R_DrawPlanes(); - ps_sw_planetime = I_GetPreciseTime() - ps_sw_planetime; + PS_STOP_TIMING(ps_sw_planetime); // draw mid texture and sprite // And now 3D floors/sides! - ps_sw_maskedtime = I_GetPreciseTime(); + PS_START_TIMING(ps_sw_maskedtime); R_DrawMasked(masks, nummasks); - ps_sw_maskedtime = I_GetPreciseTime() - ps_sw_maskedtime; + PS_STOP_TIMING(ps_sw_maskedtime); free(masks); } diff --git a/src/r_main.h b/src/r_main.h index f81447c45..5f3bed980 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -17,6 +17,7 @@ #include "d_player.h" #include "r_data.h" #include "r_textures.h" +#include "m_perfstats.h" // ps_metric_t // // POV related. @@ -79,21 +80,22 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe // Render stats extern precise_t ps_prevframetime;// time when previous frame was rendered -extern precise_t ps_rendercalltime; -extern precise_t ps_uitime; -extern precise_t ps_swaptime; +extern ps_metric_t ps_rendercalltime; +extern ps_metric_t ps_otherrendertime; +extern ps_metric_t ps_uitime; +extern ps_metric_t ps_swaptime; -extern precise_t ps_bsptime; +extern ps_metric_t ps_bsptime; -extern precise_t ps_sw_spritecliptime; -extern precise_t ps_sw_portaltime; -extern precise_t ps_sw_planetime; -extern precise_t ps_sw_maskedtime; +extern ps_metric_t ps_sw_spritecliptime; +extern ps_metric_t ps_sw_portaltime; +extern ps_metric_t ps_sw_planetime; +extern ps_metric_t ps_sw_maskedtime; -extern int ps_numbspcalls; -extern int ps_numsprites; -extern int ps_numdrawnodes; -extern int ps_numpolyobjects; +extern ps_metric_t ps_numbspcalls; +extern ps_metric_t ps_numsprites; +extern ps_metric_t ps_numdrawnodes; +extern ps_metric_t ps_numpolyobjects; // // REFRESH - the actual rendering functions. diff --git a/src/r_things.c b/src/r_things.c index ea57e4086..bed71a6d7 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2745,7 +2745,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link) node->ffloor = NULL; node->sprite = NULL; - ps_numdrawnodes++; + ps_numdrawnodes.value.i++; return node; } diff --git a/src/z_zone.h b/src/z_zone.h index be55bf994..17f572a90 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -39,6 +39,7 @@ enum // Tags < PU_LEVEL are not purged until freed explicitly. PU_STATIC = 1, // static entire execution time PU_LUA = 2, // static entire execution time -- used by lua so it doesn't get caught in loops forever + PU_PERFSTATS = 3, // static between changes to ps_samplesize cvar PU_SOUND = 11, // static while playing PU_MUSIC = 12, // static while playing From 865c0a081da3292f9923216f0b31a3128b462c81 Mon Sep 17 00:00:00 2001 From: SMS Alfredo Date: Fri, 29 Oct 2021 10:40:25 +0000 Subject: [PATCH 18/49] Make Overlay objects account for player->drawangle --- src/p_enemy.c | 2 +- src/p_mobj.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 49907bdcc..0cada7f9f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5297,7 +5297,7 @@ void A_OverlayThink(mobj_t *actor) actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; else actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; - actor->angle = actor->target->angle + actor->movedir; + actor->angle = (actor->target->player ? actor->target->player->drawangle : actor->target->angle) + actor->movedir; actor->eflags = actor->target->eflags; actor->momx = actor->target->momx; diff --git a/src/p_mobj.c b/src/p_mobj.c index a1bb2d6ff..41377373d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6837,7 +6837,7 @@ void P_RunOverlays(void) mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP); mo->scale = mo->destscale = mo->target->scale; - mo->angle = mo->target->angle + mo->movedir; + mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir; if (!(mo->state->frame & FF_ANIMATE)) zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale); From c55e973364ab990afbd29f081c94aad245a13809 Mon Sep 17 00:00:00 2001 From: SteelT Date: Wed, 3 Nov 2021 17:13:34 -0400 Subject: [PATCH 19/49] MSYS2: Don't compile with dynamic base Resolves #671 --- src/Makefile.d/win32.mk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Makefile.d/win32.mk b/src/Makefile.d/win32.mk index 0c671b268..768133c15 100644 --- a/src/Makefile.d/win32.mk +++ b/src/Makefile.d/win32.mk @@ -8,6 +8,11 @@ else EXENAME?=srb2win64.exe endif +# disable dynamicbase if under msys2 +ifdef MSYSTEM +libs+=-Wl,--disable-dynamicbase +endif + sources+=win32/Srb2win.rc opts+=-DSTDC_HEADERS libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 From da33cb674e419eba5b4870c134f8dacab86ffb6f Mon Sep 17 00:00:00 2001 From: katsy Date: Fri, 5 Nov 2021 16:51:44 -0500 Subject: [PATCH 20/49] fix water fof height calculation on slopes --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index a1bb2d6ff..c5a84f333 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3236,8 +3236,8 @@ void P_MobjCheckWater(mobj_t *mobj) || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) continue; - topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y); - bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); + topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, sector); + bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, sector); if (mobj->eflags & MFE_VERTICALFLIP) { From 0ecfc38c468944b4de997199c0ece750cb39750f Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Sat, 6 Nov 2021 01:49:29 -0300 Subject: [PATCH 21/49] Remove misplaced line from R_DrawTiltedSplat_NPO2_8 --- src/r_draw8_npo2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 71ec99948..2433cb402 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -666,7 +666,6 @@ void R_DrawTiltedSplat_NPO2_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; // Lactozilla: Non-powers-of-two { fixed_t x = (((fixed_t)u) >> FRACBITS); From 9a5bb5980107050c1203276a72fcc4f23fd22e60 Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 7 Nov 2021 12:51:21 +0100 Subject: [PATCH 22/49] https://mb.srb2.org/threads/the-most-utterly-unimportant-typo-ever.27152 --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 47786bb60..0b2fe9741 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1219,7 +1219,7 @@ static const char *credits[] = { "Bill \"Tets\" Reed", "", "\1Special Thanks", - "iD Software", + "id Software", "Doom Legacy Project", "FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak "Kart Krew", From 270c7701b4c43faa59b642be5774a0a867a0f1ed Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Mon, 8 Nov 2021 01:17:30 +0200 Subject: [PATCH 23/49] Timestamp function for Lua --- src/i_system.h | 2 +- src/lua_baselib.c | 9 +++++++++ src/sdl/i_system.c | 8 +++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/i_system.h b/src/i_system.h index a3790dca3..a2dd81cca 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -50,7 +50,7 @@ tic_t I_GetTime(void); */ precise_t I_GetPreciseTime(void); -/** \brief Returns the difference between precise times as microseconds. +/** \brief Converts a precise_t to microseconds and casts it to a 32 bit integer. */ int I_PreciseToMicros(precise_t); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 350c1585f..61f0e43cb 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -31,6 +31,7 @@ #include "m_misc.h" // M_MapNumber #include "b_bot.h" // B_UpdateBotleader #include "d_clisrv.h" // CL_RemovePlayer +#include "i_system.h" // I_GetPreciseTime, I_PreciseToMicros #include "lua_script.h" #include "lua_libs.h" @@ -3876,6 +3877,12 @@ static int lib_gTicsToMilliseconds(lua_State *L) return 1; } +static int lib_iGetTimestamp(lua_State *L) +{ + lua_pushinteger(L, I_PreciseToMicros(I_GetPreciseTime())); + return 1; +} + static luaL_Reg lib[] = { {"print", lib_print}, {"chatprint", lib_chatprint}, @@ -4150,6 +4157,8 @@ static luaL_Reg lib[] = { {"G_TicsToCentiseconds",lib_gTicsToCentiseconds}, {"G_TicsToMilliseconds",lib_gTicsToMilliseconds}, + {"I_GetTimestamp",lib_iGetTimestamp}, + {NULL, NULL} }; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 2ec28ebc8..ccec37093 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2163,7 +2163,13 @@ precise_t I_GetPreciseTime(void) int I_PreciseToMicros(precise_t d) { - return (int)(d / (timer_frequency / 1000000.0)); + // d is going to be converted into a double. So remove the highest bits + // to avoid loss of precision in the lower bits, for the (probably rare) case + // that the higher bits are actually used. + d &= ((precise_t)1 << 53) - 1; // The mantissa of a double can handle 53 bits at most. + // The resulting double from the calculation is converted first to UINT64 to avoid overflow, + // which is undefined behaviour when converting floating point values to integers. + return (int)(UINT64)(d / (timer_frequency / 1000000.0)); } // From a14c008dee4e4841e5eb78df57429e59136027b7 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 8 Nov 2021 00:38:24 -0300 Subject: [PATCH 24/49] Fix #555 --- src/r_patchrotation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index a9b4a2b8f..dae3a7b53 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -227,8 +227,8 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle ox = (newwidth / 2) + (leftoffset - xpivot); oy = (newheight / 2) + (patch->topoffset - ypivot); - width = (maxx - minx); - height = (maxy - miny); + width = (maxx+1 - minx); + height = (maxy+1 - miny); if ((unsigned)(width * height) != size) { From 34b05efdf1fe548763901a49b0e20b80cc25d95c Mon Sep 17 00:00:00 2001 From: LZA <73-LZA@users.noreply.git.do.srb2.org> Date: Mon, 8 Nov 2021 03:40:53 +0000 Subject: [PATCH 25/49] Revert "Merge branch 'writable-colormaps' into 'next'" This reverts merge request !959 --- src/lua_hudlib.c | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index fca832053..0dd951efd 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -265,7 +265,7 @@ static int hudinfo_num(lua_State *L) static int colormap_get(lua_State *L) { - UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); + const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); UINT32 i = luaL_checkinteger(L, 2); if (i >= 256) return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255); @@ -273,23 +273,6 @@ static int colormap_get(lua_State *L) return 1; } -static int colormap_set(lua_State *L) -{ - UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); - UINT32 i = luaL_checkinteger(L, 2); - if (i >= 256) - return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255); - colormap[i] = (UINT8)luaL_checkinteger(L, 3); - return 0; -} - -static int colormap_free(lua_State *L) -{ - UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); - Z_Free(colormap); - return 0; -} - static int patch_get(lua_State *L) { patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); @@ -1057,7 +1040,7 @@ static int libd_getColormap(lua_State *L) // all was successful above, now we generate the colormap at last! - colormap = R_GetTranslationColormap(skinnum, color, 0); + colormap = R_GetTranslationColormap(skinnum, color, GTC_CACHE); LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use! return 1; } @@ -1066,14 +1049,10 @@ static int libd_getStringColormap(lua_State *L) { INT32 flags = luaL_checkinteger(L, 1); UINT8* colormap = NULL; - UINT8* lua_colormap = NULL; HUDONLY colormap = V_GetStringColormap(flags & V_CHARCOLORMASK); if (colormap) { - lua_colormap = Z_Malloc(256 * sizeof(UINT8), PU_LUA, NULL); - memcpy(lua_colormap, colormap, 256 * sizeof(UINT8)); - - LUA_PushUserdata(L, lua_colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use! + LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use! return 1; } return 0; @@ -1348,12 +1327,6 @@ int LUA_HudLib(lua_State *L) luaL_newmetatable(L, META_COLORMAP); lua_pushcfunction(L, colormap_get); lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, colormap_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, colormap_free); - lua_setfield(L, -2, "__gc"); lua_pop(L,1); luaL_newmetatable(L, META_PATCH); From 32a68f35c95d46f6bb2090d309a400814754476f Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 8 Nov 2021 01:11:51 -0300 Subject: [PATCH 26/49] Change my name --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 0b2fe9741..8dd03d44f 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1091,11 +1091,11 @@ static const char *credits[] = { "Kepa \"Nev3r\" Iceta", "Thomas \"Shadow Hog\" Igoe", "Iestyn \"Monster Iestyn\" Jealous", - "\"Jimita\"", "\"Kaito Sinclaire\"", "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog "Ronald \"Furyhunter\" Kinard", // The SDL2 port "\"Lat'\"", // SRB2-CHAT, the chat window from Kart + "\"LZA\"", "Matthew \"Shuffle\" Marsalko", "Steven \"StroggOnMeth\" McGranahan", "\"Morph\"", // For SRB2Morphed stuff From 1d7061b8921e348502a8b8569a0361a97a8fc76d Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 8 Nov 2021 01:34:03 -0300 Subject: [PATCH 27/49] Fix NONET compiling --- src/d_clisrv.c | 74 ++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index b7071320c..efe6473d4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1836,8 +1836,6 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif/*MASTERSERVER*/ } -#endif // ifndef NONET - static const char * InvalidServerReason (INT32 i) { #define EOT "\nPress ESC\n" @@ -1904,6 +1902,8 @@ static const char * InvalidServerReason (INT32 i) #undef EOT } +#endif // ifndef NONET + /** Called by CL_ServerConnectionTicker * * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. @@ -2932,6 +2932,34 @@ static void Command_Kick(void) else CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); } + +static void Command_ResendGamestate(void) +{ + SINT8 playernum; + + if (COM_Argc() == 1) + { + CONS_Printf(M_GetText("resendgamestate : resend the game state to a player\n")); + return; + } + else if (client) + { + CONS_Printf(M_GetText("Only the server can use this.\n")); + return; + } + + playernum = nametonum(COM_Argv(1)); + if (playernum == -1 || playernum == 0) + return; + + // Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + if (!HSendPacket(playernode[playernum], true, 0, 0)) + { + CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n")); + return; + } +} #endif static void Got_KickCmd(UINT8 **p, INT32 playernum) @@ -3139,34 +3167,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) CL_RemovePlayer(pnum, kickreason); } -static void Command_ResendGamestate(void) -{ - SINT8 playernum; - - if (COM_Argc() == 1) - { - CONS_Printf(M_GetText("resendgamestate : resend the game state to a player\n")); - return; - } - else if (client) - { - CONS_Printf(M_GetText("Only the server can use this.\n")); - return; - } - - playernum = nametonum(COM_Argv(1)); - if (playernum == -1 || playernum == 0) - return; - - // Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on - netbuffer->packettype = PT_WILLRESENDGAMESTATE; - if (!HSendPacket(playernode[playernum], true, 0, 0)) - { - CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n")); - return; - } -} - static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); @@ -3903,6 +3903,7 @@ static void HandleServerInfo(SINT8 node) static void PT_WillResendGamestate(void) { +#ifndef NONET char tmpsave[256]; if (server || cl_redownloadinggamestate) @@ -3925,10 +3926,12 @@ static void PT_WillResendGamestate(void) CL_PrepareDownloadSaveGame(tmpsave); cl_redownloadinggamestate = true; +#endif } static void PT_CanReceiveGamestate(SINT8 node) { +#ifndef NONET if (client || sendingsavegame[node]) return; @@ -3936,6 +3939,9 @@ static void PT_CanReceiveGamestate(SINT8 node) SV_SendSaveGame(node, true); // Resend a complete game state resendingsavegame[node] = true; +#else + (void)node; +#endif } /** Handles a packet received from a node that isn't in game @@ -4222,8 +4228,10 @@ static void HandlePacketFromPlayer(SINT8 node) // Check player consistancy during the level if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) - && !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() - && !SV_ResendingSavegameToAnyone()) +#ifndef NONET + && !SV_ResendingSavegameToAnyone() +#endif + && !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()) { if (cv_resynchattempts.value) { @@ -5127,9 +5135,11 @@ void NetUpdate(void) if (client) { +#ifndef NONET // If the client just finished redownloading the game state, load it if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND) CL_ReloadReceivedSavegame(); +#endif CL_SendClientCmd(); // Send tic cmd hu_redownloadinggamestate = cl_redownloadinggamestate; From 56c5a887c858aaf9e1def23327e56d09c546f333 Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Mon, 8 Nov 2021 20:28:35 +0200 Subject: [PATCH 28/49] Call the Lua timestamp function getTimeMicros --- src/lua_baselib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 61f0e43cb..29de7a05f 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3877,7 +3877,7 @@ static int lib_gTicsToMilliseconds(lua_State *L) return 1; } -static int lib_iGetTimestamp(lua_State *L) +static int lib_getTimeMicros(lua_State *L) { lua_pushinteger(L, I_PreciseToMicros(I_GetPreciseTime())); return 1; @@ -4157,7 +4157,7 @@ static luaL_Reg lib[] = { {"G_TicsToCentiseconds",lib_gTicsToCentiseconds}, {"G_TicsToMilliseconds",lib_gTicsToMilliseconds}, - {"I_GetTimestamp",lib_iGetTimestamp}, + {"getTimeMicros",lib_getTimeMicros}, {NULL, NULL} }; From cade6f3cf69cb3e4f3cbf7e4952706b317e7ea88 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Tue, 9 Nov 2021 16:59:49 +0100 Subject: [PATCH 29/49] Fix Ringslinger weapon ring penalty missplitment --- src/st_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 784666ad4..a1b9206b0 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2188,7 +2188,7 @@ static void ST_drawMatchHUD(void) { sprintf(penaltystr, "-%d", stplyr->ammoremoval); V_DrawString(offset + 8 + stplyr->ammoremovalweapon * 20, y, - V_REDMAP|V_SNAPTOBOTTOM, penaltystr); + V_REDMAP|V_SNAPTOBOTTOM|V_PERPLAYER, penaltystr); } } From 8136f5522b83d7328b20def28433ee274bd913cb Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Wed, 10 Nov 2021 01:55:31 +0200 Subject: [PATCH 30/49] Fix uninitialized history pointers in thinkframe_hooks array --- src/m_perfstats.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 9285b31be..439a9da1c 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -194,14 +194,18 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) if (!thinkframe_hooks) { // array needs to be initialized - thinkframe_hooks = Z_Malloc(sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL); + thinkframe_hooks = Z_Calloc(sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL); } if (index >= thinkframe_hooks_capacity) { // array needs more space, realloc with double size - thinkframe_hooks_capacity *= 2; + int new_capacity = thinkframe_hooks_capacity * 2; thinkframe_hooks = Z_Realloc(thinkframe_hooks, - sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL); + sizeof(ps_hookinfo_t) * new_capacity, PU_STATIC, NULL); + // initialize new memory with zeros so the pointers in the structs are null + memset(&thinkframe_hooks[thinkframe_hooks_capacity], 0, + sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity); + thinkframe_hooks_capacity = new_capacity; } thinkframe_hooks[index].time_taken.value.p = time_taken; memcpy(thinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char)); From a48c8826a1c5b1a8514632b9a3433161b3a35ebd Mon Sep 17 00:00:00 2001 From: sphere Date: Sat, 8 May 2021 18:13:35 +0200 Subject: [PATCH 31/49] Add modifiedgame warning to save select menu. --- src/m_menu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 7a82fd8fb..271936b0e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8652,6 +8652,12 @@ static void M_DrawLoad(void) loadgameoffset = 0; M_DrawLoadGameData(); + + if (modifiedgame && !savemoddata) + { + V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING: \x80The game is modified."); + V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved."); + } } // From d9fde5c39558248e43d8ec6f32a12c2a4c5d7cd3 Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 9 May 2021 16:47:52 +0200 Subject: [PATCH 32/49] Add emblem counter to the Extras checklist. --- src/m_menu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 271936b0e..8f956e9a7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7187,13 +7187,20 @@ static void M_HandleChecklist(INT32 choice) static void M_DrawChecklist(void) { - INT32 i = check_on, j = 0, y = currentMenu->y; + INT32 i = check_on, j = 0, y = currentMenu->y, emblems = numemblems+numextraemblems; UINT32 condnum, previd, maxcond; condition_t *cond; // draw title (or big pic) M_DrawMenuTitle(); + // draw emblem counter + if (emblems > 0) + { + V_DrawString(42, 20, (emblems == M_CountEmblems()) ? V_GREENMAP : 0, va("%d/%d", M_CountEmblems(), emblems)); + V_DrawSmallScaledPatch(28, 20, 0, W_CachePatchName("EMBLICON", PU_PATCH)); + } + if (check_on) V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A"); From 08e63fc822005bf061c004c8f6aaea37f56c4702 Mon Sep 17 00:00:00 2001 From: sphere Date: Fri, 8 Oct 2021 18:00:08 +0200 Subject: [PATCH 33/49] Show values on (float) sliders in the options menu. --- src/m_menu.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8f956e9a7..eeb51d0da 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4062,14 +4062,6 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) for (i = 1; i < SLIDER_RANGE; i++) V_DrawScaledPatch (x+i*8, y, 0,p); - if (ontop) - { - V_DrawCharacter(x - 6 - (skullAnimCounter/5), y, - '\x1C' | V_YELLOWMAP, false); - V_DrawCharacter(x+i*8 + 8 + (skullAnimCounter/5), y, - '\x1D' | V_YELLOWMAP, false); - } - p = W_CachePatchName("M_SLIDER", PU_PATCH); V_DrawScaledPatch(x+i*8, y, 0, p); @@ -4105,6 +4097,16 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) range = 100; V_DrawMappedPatch(x + 2 + (SLIDER_RANGE*8*range)/100, y, 0, p, yellowmap); + + if (ontop) + { + V_DrawCharacter(x - 6 - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(x + 80 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + V_DrawCenteredString(x + 40, y, V_30TRANS, + (cv->flags & CV_FLOAT) ? va("%.2f", FIXED_TO_FLOAT(cv->value)) : va("%d", cv->value)); + } } // From 4480af69c7dde61cb3d0a3e82dd9e1587e133157 Mon Sep 17 00:00:00 2001 From: spherallic Date: Fri, 26 Nov 2021 14:09:10 +0100 Subject: [PATCH 34/49] Only show Ultimate mode warning in unmodified vanilla gameplay. --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index eeb51d0da..b99ec186b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8968,7 +8968,7 @@ static void M_HandleLoadSave(INT32 choice) break; case KEY_ENTER: - if (ultimate_selectable && saveSlotSelected == NOSAVESLOT) + if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata && !modifiedgame) { loadgamescroll = 0; S_StartSound(NULL, sfx_skid); From cf79bc8382c414ae6973636b92cecb1403cd36c9 Mon Sep 17 00:00:00 2001 From: SMS Alfredo Date: Fri, 26 Nov 2021 14:11:09 +0000 Subject: [PATCH 35/49] Fix #214 (Crushstacean + Fireball Player Removal) --- src/p_enemy.c | 4 +--- src/p_inter.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 49907bdcc..8329b4f57 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3518,9 +3518,7 @@ void A_Scream(mobj_t *actor) if (LUA_CallAction(A_SCREAM, actor)) return; - if (actor->tracer && (actor->tracer->type == MT_SHELL || actor->tracer->type == MT_FIREBALL)) - S_StartScreamSound(actor, sfx_mario2); - else if (actor->info->deathsound) + if (actor->info->deathsound && !S_SoundPlaying(actor, sfx_mario2)) S_StartScreamSound(actor, actor->info->deathsound); } diff --git a/src/p_inter.c b/src/p_inter.c index 21e3bfa3d..4b958fb89 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2391,7 +2391,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget mobj_t *mo; if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL)) - P_SetTarget(&target->tracer, inflictor); + S_StartScreamSound(target, sfx_mario2); if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6) target->player->nightstime = 6; // Just let P_Ticker take care of the rest. From 6a6b292c730be21e492735ed8366a4c9f2ba5cb4 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 27 Nov 2021 14:22:21 +0100 Subject: [PATCH 36/49] Fix Flame Shield interactions in old-style special stages. --- src/p_tick.c | 2 +- src/st_stuff.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index d7357eb82..cee658953 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -487,7 +487,7 @@ static inline void P_DoSpecialStageStuff(void) continue; // If in water, deplete timer 6x as fast. - if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & SH_PROTECTWATER)) + if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & ((players[i].mo->eflags & MFE_TOUCHLAVA) ? SH_PROTECTFIRE : SH_PROTECTWATER))) players[i].nightstime -= 5; if (--players[i].nightstime > 6) { diff --git a/src/st_stuff.c b/src/st_stuff.c index a1b9206b0..a328d669e 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2037,9 +2037,8 @@ static void ST_drawNiGHTSHUD(void) else numbersize = 48/2; - if ((oldspecialstage && leveltime & 2) - && (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) - && !(stplyr->powers[pw_shield] & SH_PROTECTWATER)) + if ((oldspecialstage && leveltime & 2) && + (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(stplyr->powers[pw_shield] & ((stplyr->mo->eflags & MFE_TOUCHLAVA) ? SH_PROTECTFIRE : SH_PROTECTWATER)))) col = SKINCOLOR_ORANGE; ST_DrawNightsOverlayNum((160 + numbersize)< Date: Sat, 27 Nov 2021 14:23:02 +0100 Subject: [PATCH 37/49] Make Brak's electric barrier damage Elemental and Flame Shields. --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 4b958fb89..b37689fd8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3651,7 +3651,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return true; } - if (!force && inflictor && inflictor->flags & MF_FIRE) + if (!force && inflictor && inflictor->flags & MF_FIRE && !(damagetype && damagetype != DMG_FIRE)) { if (player->powers[pw_shield] & SH_PROTECTFIRE) return false; // Invincible to fire objects From 49e6e7a80f40b25e18faa99c54c121e0b2ac3b14 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 27 Nov 2021 16:19:04 +0100 Subject: [PATCH 38/49] Fix retracting spikes dealing typeless damage instead of spike damage. --- src/info.c | 4 ++-- src/p_map.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index efcf1c044..b9d088662 100644 --- a/src/info.c +++ b/src/info.c @@ -7974,7 +7974,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset - 4, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT, // flags @@ -8001,7 +8001,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16*FRACUNIT, // radius 14*FRACUNIT, // height 0, // display offset - 4, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags diff --git a/src/p_map.c b/src/p_map.c index e55bebb9a..c01c91e3c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1156,7 +1156,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale); if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, tmthing, tmthing, 1, 0); + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE); return true; } From d44ef91f6f86ff504b58799c9147b64199011da3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 28 Nov 2021 19:34:42 +0100 Subject: [PATCH 39/49] Re-add FF_BUSTUP to INT_CONST --- src/deh_tables.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index f2fd38059..f14eca6a9 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5226,6 +5226,7 @@ struct int_const_s const INT_CONST[] = { {"FF_CRUMBLE",FF_CRUMBLE}, ///< Falls 2 seconds after being stepped on, and randomly brings all touching crumbling 3dfloors down with it, providing their master sectors share the same tag (allows crumble platforms above or below, to also exist). {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. {"FF_MARIO",FF_MARIO}, ///< Acts like a question block when hit from underneath. Goodie spawned at top is determined by master sector. + {"FF_BUSTUP",FF_BUSTUP}, ///< You can spin through/punch this block and it will crumble! {"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand! {"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top. {"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. From 9bdfafc9dd3b274243c429a60ee7c14cceeeae2f Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 29 Nov 2021 19:25:30 +0100 Subject: [PATCH 40/49] Add DMG_FIRE to Pyrefly fire and lavafall objects. --- src/info.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index b9d088662..24c8f7bf7 100644 --- a/src/info.c +++ b/src/info.c @@ -5199,7 +5199,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 24*FRACUNIT, // radius 34*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_FIRE, // mass 0, // damage sfx_None, // activesound MF_NOGRAVITY|MF_NOBLOCKMAP|MF_FIRE|MF_PAIN, // flags @@ -13401,7 +13401,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 30*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_FIRE, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_PAIN|MF_NOGRAVITY|MF_FIRE, // flags @@ -13806,7 +13806,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset - 0, // mass + 0, // mass 0, // damage sfx_None, // activesound MF_NOGRAVITY|MF_PAIN, // flags From a5e1167ad2181a3b6278f6aeaa9e2cbb7d4dff97 Mon Sep 17 00:00:00 2001 From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com> Date: Tue, 30 Nov 2021 20:51:15 -0600 Subject: [PATCH 41/49] balls --- src/info.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index efcf1c044..1cd80f383 100644 --- a/src/info.c +++ b/src/info.c @@ -11430,7 +11430,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 17*FRACUNIT, // radius 34*FRACUNIT, // height 1, // display offset - 0, // mass + DMG_SPIKE, // mass 1, // damage sfx_s3kc9s, //sfx_mswing, -- activesound MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags @@ -11457,7 +11457,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 34*FRACUNIT, // radius 68*FRACUNIT, // height 1, // display offset - 0, // mass + DMG_SPIKE, // mass 1, // damage sfx_s3kc9s, //sfx_mswing, -- activesound MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags @@ -20380,7 +20380,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 18*FRACUNIT, // radius 28*FRACUNIT, // height 0, // display offset - 0, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_NOGRAVITY|MF_PAIN, // flags From aca0ba0f4b0175072dbd71f4b9cca4c2cbf17982 Mon Sep 17 00:00:00 2001 From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com> Date: Tue, 30 Nov 2021 22:46:51 -0600 Subject: [PATCH 42/49] wow --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index efcf1c044..4e991e81c 100644 --- a/src/info.c +++ b/src/info.c @@ -2069,7 +2069,7 @@ state_t states[NUMSTATES] = {SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL}, // S_FLAMEAURA_ICON2 {SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1 - {SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLERWAP_ICON2 + {SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLEWRAP_ICON2 {SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1 {SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL}, // S_THUNDERCOIN_ICON2 From c1c7607cb0a1e359cdce4db3cd252c1004e100ee Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 2 Dec 2021 01:52:45 +0100 Subject: [PATCH 43/49] Add toggle for linedef action 401 to not change the ceiling texture. --- extras/conf/SRB2-22.cfg | 7 ++++--- src/p_ceilng.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 0ca8a6715..4ed68e1ca 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -1992,7 +1992,7 @@ linedeftypes title = "Set Tagged Sector's Floor Height/Texture"; prefix = "(400)"; flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Keep floor flat"; + flags64text = "[6] Don't change floor texture"; } 401 @@ -2000,6 +2000,7 @@ linedeftypes title = "Set Tagged Sector's Ceiling Height/Texture"; prefix = "(401)"; flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't change ceiling texture"; } 402 @@ -2090,7 +2091,7 @@ linedeftypes prefix = "(403)"; flags2text = "[1] Trigger linedef executor"; flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Change floor flat"; + flags64text = "[6] Change floor texture"; } 404 @@ -2099,7 +2100,7 @@ linedeftypes prefix = "(404)"; flags2text = "[1] Trigger linedef executor"; flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Change ceiling flat"; + flags64text = "[6] Change ceiling texture"; } 405 diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 43f3cc1d5..e28f9b5b1 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -67,7 +67,8 @@ void T_MoveCeiling(ceiling_t *ceiling) switch (ceiling->type) { case instantMoveCeilingByFrontSector: - ceiling->sector->ceilingpic = ceiling->texture; + if (ceiling->texture > -1) + ceiling->sector->ceilingpic = ceiling->texture; ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; P_RemoveThinker(&ceiling->thinker); @@ -186,7 +187,8 @@ void T_MoveCeiling(ceiling_t *ceiling) break; case instantMoveCeilingByFrontSector: - ceiling->sector->ceilingpic = ceiling->texture; + if (ceiling->texture > -1) + ceiling->sector->ceilingpic = ceiling->texture; ceiling->sector->ceilingdata = NULL; ceiling->sector->ceilspeed = 0; P_RemoveThinker(&ceiling->thinker); @@ -512,7 +514,10 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) ceiling->direction = -1; ceiling->bottomheight = line->frontsector->ceilingheight; } - ceiling->texture = line->frontsector->ceilingpic; + if (line->flags & ML_NOCLIMB) + ceiling->texture = -1; + else + ceiling->texture = line->frontsector->ceilingpic; break; case moveCeilingByFrontTexture: From 443c51714a3e78eb47a1b10091f5852d86521b99 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 2 Dec 2021 21:02:54 +0100 Subject: [PATCH 44/49] Fix KeyUp hook being called when the console is open --- src/d_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index 679a596b3..99b3c3ebd 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -272,7 +272,7 @@ void D_ProcessEvents(void) if (eaten) continue; // ate the event - if (!hooked && G_LuaResponder(ev)) + if (!hooked && !CON_Ready() && G_LuaResponder(ev)) continue; G_Responder(ev); From 425d1f1b536dc634f81dd9d0a2473f03ab82a0a7 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 2 Dec 2021 21:03:16 +0100 Subject: [PATCH 45/49] Make all key identifiers lowercase --- src/g_input.c | 570 +++++++++++++++++++++++++------------------------- 1 file changed, 285 insertions(+), 285 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index cd4536bba..6383c3f00 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -233,323 +233,323 @@ typedef struct static keyname_t keynames[] = { - {KEY_SPACE, "SPACE"}, - {KEY_CAPSLOCK, "CAPS LOCK"}, - {KEY_ENTER, "ENTER"}, - {KEY_TAB, "TAB"}, - {KEY_ESCAPE, "ESCAPE"}, - {KEY_BACKSPACE, "BACKSPACE"}, + {KEY_SPACE, "space"}, + {KEY_CAPSLOCK, "caps lock"}, + {KEY_ENTER, "enter"}, + {KEY_TAB, "tab"}, + {KEY_ESCAPE, "escape"}, + {KEY_BACKSPACE, "backspace"}, - {KEY_NUMLOCK, "NUMLOCK"}, - {KEY_SCROLLLOCK, "SCROLLLOCK"}, + {KEY_NUMLOCK, "numlock"}, + {KEY_SCROLLLOCK, "scrolllock"}, // bill gates keys - {KEY_LEFTWIN, "LEFTWIN"}, - {KEY_RIGHTWIN, "RIGHTWIN"}, - {KEY_MENU, "MENU"}, + {KEY_LEFTWIN, "leftwin"}, + {KEY_RIGHTWIN, "rightwin"}, + {KEY_MENU, "menu"}, - {KEY_LSHIFT, "LSHIFT"}, - {KEY_RSHIFT, "RSHIFT"}, - {KEY_LSHIFT, "SHIFT"}, - {KEY_LCTRL, "LCTRL"}, - {KEY_RCTRL, "RCTRL"}, - {KEY_LCTRL, "CTRL"}, - {KEY_LALT, "LALT"}, - {KEY_RALT, "RALT"}, - {KEY_LALT, "ALT"}, + {KEY_LSHIFT, "lshift"}, + {KEY_RSHIFT, "rshift"}, + {KEY_LSHIFT, "shift"}, + {KEY_LCTRL, "lctrl"}, + {KEY_RCTRL, "rctrl"}, + {KEY_LCTRL, "ctrl"}, + {KEY_LALT, "lalt"}, + {KEY_RALT, "ralt"}, + {KEY_LALT, "alt"}, // keypad keys - {KEY_KPADSLASH, "KEYPAD /"}, - {KEY_KEYPAD7, "KEYPAD 7"}, - {KEY_KEYPAD8, "KEYPAD 8"}, - {KEY_KEYPAD9, "KEYPAD 9"}, - {KEY_MINUSPAD, "KEYPAD -"}, - {KEY_KEYPAD4, "KEYPAD 4"}, - {KEY_KEYPAD5, "KEYPAD 5"}, - {KEY_KEYPAD6, "KEYPAD 6"}, - {KEY_PLUSPAD, "KEYPAD +"}, - {KEY_KEYPAD1, "KEYPAD 1"}, - {KEY_KEYPAD2, "KEYPAD 2"}, - {KEY_KEYPAD3, "KEYPAD 3"}, - {KEY_KEYPAD0, "KEYPAD 0"}, - {KEY_KPADDEL, "KEYPAD ."}, + {KEY_KPADSLASH, "keypad /"}, + {KEY_KEYPAD7, "keypad 7"}, + {KEY_KEYPAD8, "keypad 8"}, + {KEY_KEYPAD9, "keypad 9"}, + {KEY_MINUSPAD, "keypad -"}, + {KEY_KEYPAD4, "keypad 4"}, + {KEY_KEYPAD5, "keypad 5"}, + {KEY_KEYPAD6, "keypad 6"}, + {KEY_PLUSPAD, "keypad +"}, + {KEY_KEYPAD1, "keypad 1"}, + {KEY_KEYPAD2, "keypad 2"}, + {KEY_KEYPAD3, "keypad 3"}, + {KEY_KEYPAD0, "keypad 0"}, + {KEY_KPADDEL, "keypad ."}, // extended keys (not keypad) - {KEY_HOME, "HOME"}, - {KEY_UPARROW, "UP ARROW"}, - {KEY_PGUP, "PGUP"}, - {KEY_LEFTARROW, "LEFT ARROW"}, - {KEY_RIGHTARROW, "RIGHT ARROW"}, - {KEY_END, "END"}, - {KEY_DOWNARROW, "DOWN ARROW"}, - {KEY_PGDN, "PGDN"}, - {KEY_INS, "INS"}, - {KEY_DEL, "DEL"}, + {KEY_HOME, "home"}, + {KEY_UPARROW, "up arrow"}, + {KEY_PGUP, "pgup"}, + {KEY_LEFTARROW, "left arrow"}, + {KEY_RIGHTARROW, "right arrow"}, + {KEY_END, "end"}, + {KEY_DOWNARROW, "down arrow"}, + {KEY_PGDN, "pgdn"}, + {KEY_INS, "ins"}, + {KEY_DEL, "del"}, // other keys - {KEY_F1, "F1"}, - {KEY_F2, "F2"}, - {KEY_F3, "F3"}, - {KEY_F4, "F4"}, - {KEY_F5, "F5"}, - {KEY_F6, "F6"}, - {KEY_F7, "F7"}, - {KEY_F8, "F8"}, - {KEY_F9, "F9"}, - {KEY_F10, "F10"}, - {KEY_F11, "F11"}, - {KEY_F12, "F12"}, + {KEY_F1, "f1"}, + {KEY_F2, "f2"}, + {KEY_F3, "f3"}, + {KEY_F4, "f4"}, + {KEY_F5, "f5"}, + {KEY_F6, "f6"}, + {KEY_F7, "f7"}, + {KEY_F8, "f8"}, + {KEY_F9, "f9"}, + {KEY_F10, "f10"}, + {KEY_F11, "f11"}, + {KEY_F12, "f12"}, // KEY_CONSOLE has an exception in the keyname code {'`', "TILDE"}, - {KEY_PAUSE, "PAUSE/BREAK"}, + {KEY_PAUSE, "pause/break"}, // virtual keys for mouse buttons and joystick buttons - {KEY_MOUSE1+0,"MOUSE1"}, - {KEY_MOUSE1+1,"MOUSE2"}, - {KEY_MOUSE1+2,"MOUSE3"}, - {KEY_MOUSE1+3,"MOUSE4"}, - {KEY_MOUSE1+4,"MOUSE5"}, - {KEY_MOUSE1+5,"MOUSE6"}, - {KEY_MOUSE1+6,"MOUSE7"}, - {KEY_MOUSE1+7,"MOUSE8"}, - {KEY_2MOUSE1+0,"SEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2 - {KEY_2MOUSE1+1,"SEC_MOUSE1"}, - {KEY_2MOUSE1+2,"SEC_MOUSE3"}, - {KEY_2MOUSE1+3,"SEC_MOUSE4"}, - {KEY_2MOUSE1+4,"SEC_MOUSE5"}, - {KEY_2MOUSE1+5,"SEC_MOUSE6"}, - {KEY_2MOUSE1+6,"SEC_MOUSE7"}, - {KEY_2MOUSE1+7,"SEC_MOUSE8"}, - {KEY_MOUSEWHEELUP, "Wheel 1 UP"}, - {KEY_MOUSEWHEELDOWN, "Wheel 1 Down"}, - {KEY_2MOUSEWHEELUP, "Wheel 2 UP"}, - {KEY_2MOUSEWHEELDOWN, "Wheel 2 Down"}, + {KEY_MOUSE1+0,"mouse1"}, + {KEY_MOUSE1+1,"mouse2"}, + {KEY_MOUSE1+2,"mouse3"}, + {KEY_MOUSE1+3,"mouse4"}, + {KEY_MOUSE1+4,"mouse5"}, + {KEY_MOUSE1+5,"mouse6"}, + {KEY_MOUSE1+6,"mouse7"}, + {KEY_MOUSE1+7,"mouse8"}, + {KEY_2MOUSE1+0,"sec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2 + {KEY_2MOUSE1+1,"sec_mouse1"}, + {KEY_2MOUSE1+2,"sec_mouse3"}, + {KEY_2MOUSE1+3,"sec_mouse4"}, + {KEY_2MOUSE1+4,"sec_mouse5"}, + {KEY_2MOUSE1+5,"sec_mouse6"}, + {KEY_2MOUSE1+6,"sec_mouse7"}, + {KEY_2MOUSE1+7,"sec_mouse8"}, + {KEY_MOUSEWHEELUP, "wheel 1 up"}, + {KEY_MOUSEWHEELDOWN, "wheel 1 down"}, + {KEY_2MOUSEWHEELUP, "wheel 2 up"}, + {KEY_2MOUSEWHEELDOWN, "wheel 2 down"}, - {KEY_JOY1+0, "JOY1"}, - {KEY_JOY1+1, "JOY2"}, - {KEY_JOY1+2, "JOY3"}, - {KEY_JOY1+3, "JOY4"}, - {KEY_JOY1+4, "JOY5"}, - {KEY_JOY1+5, "JOY6"}, - {KEY_JOY1+6, "JOY7"}, - {KEY_JOY1+7, "JOY8"}, - {KEY_JOY1+8, "JOY9"}, + {KEY_JOY1+0, "joy1"}, + {KEY_JOY1+1, "joy2"}, + {KEY_JOY1+2, "joy3"}, + {KEY_JOY1+3, "joy4"}, + {KEY_JOY1+4, "joy5"}, + {KEY_JOY1+5, "joy6"}, + {KEY_JOY1+6, "joy7"}, + {KEY_JOY1+7, "joy8"}, + {KEY_JOY1+8, "joy9"}, #if !defined (NOMOREJOYBTN_1S) // we use up to 32 buttons in DirectInput - {KEY_JOY1+9, "JOY10"}, - {KEY_JOY1+10, "JOY11"}, - {KEY_JOY1+11, "JOY12"}, - {KEY_JOY1+12, "JOY13"}, - {KEY_JOY1+13, "JOY14"}, - {KEY_JOY1+14, "JOY15"}, - {KEY_JOY1+15, "JOY16"}, - {KEY_JOY1+16, "JOY17"}, - {KEY_JOY1+17, "JOY18"}, - {KEY_JOY1+18, "JOY19"}, - {KEY_JOY1+19, "JOY20"}, - {KEY_JOY1+20, "JOY21"}, - {KEY_JOY1+21, "JOY22"}, - {KEY_JOY1+22, "JOY23"}, - {KEY_JOY1+23, "JOY24"}, - {KEY_JOY1+24, "JOY25"}, - {KEY_JOY1+25, "JOY26"}, - {KEY_JOY1+26, "JOY27"}, - {KEY_JOY1+27, "JOY28"}, - {KEY_JOY1+28, "JOY29"}, - {KEY_JOY1+29, "JOY30"}, - {KEY_JOY1+30, "JOY31"}, - {KEY_JOY1+31, "JOY32"}, + {KEY_JOY1+9, "joy10"}, + {KEY_JOY1+10, "joy11"}, + {KEY_JOY1+11, "joy12"}, + {KEY_JOY1+12, "joy13"}, + {KEY_JOY1+13, "joy14"}, + {KEY_JOY1+14, "joy15"}, + {KEY_JOY1+15, "joy16"}, + {KEY_JOY1+16, "joy17"}, + {KEY_JOY1+17, "joy18"}, + {KEY_JOY1+18, "joy19"}, + {KEY_JOY1+19, "joy20"}, + {KEY_JOY1+20, "joy21"}, + {KEY_JOY1+21, "joy22"}, + {KEY_JOY1+22, "joy23"}, + {KEY_JOY1+23, "joy24"}, + {KEY_JOY1+24, "joy25"}, + {KEY_JOY1+25, "joy26"}, + {KEY_JOY1+26, "joy27"}, + {KEY_JOY1+27, "joy28"}, + {KEY_JOY1+28, "joy29"}, + {KEY_JOY1+29, "joy30"}, + {KEY_JOY1+30, "joy31"}, + {KEY_JOY1+31, "joy32"}, #endif // the DOS version uses Allegro's joystick support - {KEY_HAT1+0, "HATUP"}, - {KEY_HAT1+1, "HATDOWN"}, - {KEY_HAT1+2, "HATLEFT"}, - {KEY_HAT1+3, "HATRIGHT"}, - {KEY_HAT1+4, "HATUP2"}, - {KEY_HAT1+5, "HATDOWN2"}, - {KEY_HAT1+6, "HATLEFT2"}, - {KEY_HAT1+7, "HATRIGHT2"}, - {KEY_HAT1+8, "HATUP3"}, - {KEY_HAT1+9, "HATDOWN3"}, - {KEY_HAT1+10, "HATLEFT3"}, - {KEY_HAT1+11, "HATRIGHT3"}, - {KEY_HAT1+12, "HATUP4"}, - {KEY_HAT1+13, "HATDOWN4"}, - {KEY_HAT1+14, "HATLEFT4"}, - {KEY_HAT1+15, "HATRIGHT4"}, + {KEY_HAT1+0, "hatup"}, + {KEY_HAT1+1, "hatdown"}, + {KEY_HAT1+2, "hatleft"}, + {KEY_HAT1+3, "hatright"}, + {KEY_HAT1+4, "hatup2"}, + {KEY_HAT1+5, "hatdown2"}, + {KEY_HAT1+6, "hatleft2"}, + {KEY_HAT1+7, "hatright2"}, + {KEY_HAT1+8, "hatup3"}, + {KEY_HAT1+9, "hatdown3"}, + {KEY_HAT1+10, "hatleft3"}, + {KEY_HAT1+11, "hatright3"}, + {KEY_HAT1+12, "hatup4"}, + {KEY_HAT1+13, "hatdown4"}, + {KEY_HAT1+14, "hatleft4"}, + {KEY_HAT1+15, "hatright4"}, - {KEY_DBLMOUSE1+0, "DBLMOUSE1"}, - {KEY_DBLMOUSE1+1, "DBLMOUSE2"}, - {KEY_DBLMOUSE1+2, "DBLMOUSE3"}, - {KEY_DBLMOUSE1+3, "DBLMOUSE4"}, - {KEY_DBLMOUSE1+4, "DBLMOUSE5"}, - {KEY_DBLMOUSE1+5, "DBLMOUSE6"}, - {KEY_DBLMOUSE1+6, "DBLMOUSE7"}, - {KEY_DBLMOUSE1+7, "DBLMOUSE8"}, - {KEY_DBL2MOUSE1+0, "DBLSEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2 - {KEY_DBL2MOUSE1+1, "DBLSEC_MOUSE1"}, - {KEY_DBL2MOUSE1+2, "DBLSEC_MOUSE3"}, - {KEY_DBL2MOUSE1+3, "DBLSEC_MOUSE4"}, - {KEY_DBL2MOUSE1+4, "DBLSEC_MOUSE5"}, - {KEY_DBL2MOUSE1+5, "DBLSEC_MOUSE6"}, - {KEY_DBL2MOUSE1+6, "DBLSEC_MOUSE7"}, - {KEY_DBL2MOUSE1+7, "DBLSEC_MOUSE8"}, + {KEY_DBLMOUSE1+0, "dblmouse1"}, + {KEY_DBLMOUSE1+1, "dblmouse2"}, + {KEY_DBLMOUSE1+2, "dblmouse3"}, + {KEY_DBLMOUSE1+3, "dblmouse4"}, + {KEY_DBLMOUSE1+4, "dblmouse5"}, + {KEY_DBLMOUSE1+5, "dblmouse6"}, + {KEY_DBLMOUSE1+6, "dblmouse7"}, + {KEY_DBLMOUSE1+7, "dblmouse8"}, + {KEY_DBL2MOUSE1+0, "dblsec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2 + {KEY_DBL2MOUSE1+1, "dblsec_mouse1"}, + {KEY_DBL2MOUSE1+2, "dblsec_mouse3"}, + {KEY_DBL2MOUSE1+3, "dblsec_mouse4"}, + {KEY_DBL2MOUSE1+4, "dblsec_mouse5"}, + {KEY_DBL2MOUSE1+5, "dblsec_mouse6"}, + {KEY_DBL2MOUSE1+6, "dblsec_mouse7"}, + {KEY_DBL2MOUSE1+7, "dblsec_mouse8"}, - {KEY_DBLJOY1+0, "DBLJOY1"}, - {KEY_DBLJOY1+1, "DBLJOY2"}, - {KEY_DBLJOY1+2, "DBLJOY3"}, - {KEY_DBLJOY1+3, "DBLJOY4"}, - {KEY_DBLJOY1+4, "DBLJOY5"}, - {KEY_DBLJOY1+5, "DBLJOY6"}, - {KEY_DBLJOY1+6, "DBLJOY7"}, - {KEY_DBLJOY1+7, "DBLJOY8"}, + {KEY_DBLJOY1+0, "dbljoy1"}, + {KEY_DBLJOY1+1, "dbljoy2"}, + {KEY_DBLJOY1+2, "dbljoy3"}, + {KEY_DBLJOY1+3, "dbljoy4"}, + {KEY_DBLJOY1+4, "dbljoy5"}, + {KEY_DBLJOY1+5, "dbljoy6"}, + {KEY_DBLJOY1+6, "dbljoy7"}, + {KEY_DBLJOY1+7, "dbljoy8"}, #if !defined (NOMOREJOYBTN_1DBL) - {KEY_DBLJOY1+8, "DBLJOY9"}, - {KEY_DBLJOY1+9, "DBLJOY10"}, - {KEY_DBLJOY1+10, "DBLJOY11"}, - {KEY_DBLJOY1+11, "DBLJOY12"}, - {KEY_DBLJOY1+12, "DBLJOY13"}, - {KEY_DBLJOY1+13, "DBLJOY14"}, - {KEY_DBLJOY1+14, "DBLJOY15"}, - {KEY_DBLJOY1+15, "DBLJOY16"}, - {KEY_DBLJOY1+16, "DBLJOY17"}, - {KEY_DBLJOY1+17, "DBLJOY18"}, - {KEY_DBLJOY1+18, "DBLJOY19"}, - {KEY_DBLJOY1+19, "DBLJOY20"}, - {KEY_DBLJOY1+20, "DBLJOY21"}, - {KEY_DBLJOY1+21, "DBLJOY22"}, - {KEY_DBLJOY1+22, "DBLJOY23"}, - {KEY_DBLJOY1+23, "DBLJOY24"}, - {KEY_DBLJOY1+24, "DBLJOY25"}, - {KEY_DBLJOY1+25, "DBLJOY26"}, - {KEY_DBLJOY1+26, "DBLJOY27"}, - {KEY_DBLJOY1+27, "DBLJOY28"}, - {KEY_DBLJOY1+28, "DBLJOY29"}, - {KEY_DBLJOY1+29, "DBLJOY30"}, - {KEY_DBLJOY1+30, "DBLJOY31"}, - {KEY_DBLJOY1+31, "DBLJOY32"}, + {KEY_DBLJOY1+8, "dbljoy9"}, + {KEY_DBLJOY1+9, "dbljoy10"}, + {KEY_DBLJOY1+10, "dbljoy11"}, + {KEY_DBLJOY1+11, "dbljoy12"}, + {KEY_DBLJOY1+12, "dbljoy13"}, + {KEY_DBLJOY1+13, "dbljoy14"}, + {KEY_DBLJOY1+14, "dbljoy15"}, + {KEY_DBLJOY1+15, "dbljoy16"}, + {KEY_DBLJOY1+16, "dbljoy17"}, + {KEY_DBLJOY1+17, "dbljoy18"}, + {KEY_DBLJOY1+18, "dbljoy19"}, + {KEY_DBLJOY1+19, "dbljoy20"}, + {KEY_DBLJOY1+20, "dbljoy21"}, + {KEY_DBLJOY1+21, "dbljoy22"}, + {KEY_DBLJOY1+22, "dbljoy23"}, + {KEY_DBLJOY1+23, "dbljoy24"}, + {KEY_DBLJOY1+24, "dbljoy25"}, + {KEY_DBLJOY1+25, "dbljoy26"}, + {KEY_DBLJOY1+26, "dbljoy27"}, + {KEY_DBLJOY1+27, "dbljoy28"}, + {KEY_DBLJOY1+28, "dbljoy29"}, + {KEY_DBLJOY1+29, "dbljoy30"}, + {KEY_DBLJOY1+30, "dbljoy31"}, + {KEY_DBLJOY1+31, "dbljoy32"}, #endif - {KEY_DBLHAT1+0, "DBLHATUP"}, - {KEY_DBLHAT1+1, "DBLHATDOWN"}, - {KEY_DBLHAT1+2, "DBLHATLEFT"}, - {KEY_DBLHAT1+3, "DBLHATRIGHT"}, - {KEY_DBLHAT1+4, "DBLHATUP2"}, - {KEY_DBLHAT1+5, "DBLHATDOWN2"}, - {KEY_DBLHAT1+6, "DBLHATLEFT2"}, - {KEY_DBLHAT1+7, "DBLHATRIGHT2"}, - {KEY_DBLHAT1+8, "DBLHATUP3"}, - {KEY_DBLHAT1+9, "DBLHATDOWN3"}, - {KEY_DBLHAT1+10, "DBLHATLEFT3"}, - {KEY_DBLHAT1+11, "DBLHATRIGHT3"}, - {KEY_DBLHAT1+12, "DBLHATUP4"}, - {KEY_DBLHAT1+13, "DBLHATDOWN4"}, - {KEY_DBLHAT1+14, "DBLHATLEFT4"}, - {KEY_DBLHAT1+15, "DBLHATRIGHT4"}, + {KEY_DBLHAT1+0, "dblhatup"}, + {KEY_DBLHAT1+1, "dblhatdown"}, + {KEY_DBLHAT1+2, "dblhatleft"}, + {KEY_DBLHAT1+3, "dblhatright"}, + {KEY_DBLHAT1+4, "dblhatup2"}, + {KEY_DBLHAT1+5, "dblhatdown2"}, + {KEY_DBLHAT1+6, "dblhatleft2"}, + {KEY_DBLHAT1+7, "dblhatright2"}, + {KEY_DBLHAT1+8, "dblhatup3"}, + {KEY_DBLHAT1+9, "dblhatdown3"}, + {KEY_DBLHAT1+10, "dblhatleft3"}, + {KEY_DBLHAT1+11, "dblhatright3"}, + {KEY_DBLHAT1+12, "dblhatup4"}, + {KEY_DBLHAT1+13, "dblhatdown4"}, + {KEY_DBLHAT1+14, "dblhatleft4"}, + {KEY_DBLHAT1+15, "dblhatright4"}, - {KEY_2JOY1+0, "SEC_JOY1"}, - {KEY_2JOY1+1, "SEC_JOY2"}, - {KEY_2JOY1+2, "SEC_JOY3"}, - {KEY_2JOY1+3, "SEC_JOY4"}, - {KEY_2JOY1+4, "SEC_JOY5"}, - {KEY_2JOY1+5, "SEC_JOY6"}, - {KEY_2JOY1+6, "SEC_JOY7"}, - {KEY_2JOY1+7, "SEC_JOY8"}, + {KEY_2JOY1+0, "sec_joy1"}, + {KEY_2JOY1+1, "sec_joy2"}, + {KEY_2JOY1+2, "sec_joy3"}, + {KEY_2JOY1+3, "sec_joy4"}, + {KEY_2JOY1+4, "sec_joy5"}, + {KEY_2JOY1+5, "sec_joy6"}, + {KEY_2JOY1+6, "sec_joy7"}, + {KEY_2JOY1+7, "sec_joy8"}, #if !defined (NOMOREJOYBTN_2S) // we use up to 32 buttons in DirectInput - {KEY_2JOY1+8, "SEC_JOY9"}, - {KEY_2JOY1+9, "SEC_JOY10"}, - {KEY_2JOY1+10, "SEC_JOY11"}, - {KEY_2JOY1+11, "SEC_JOY12"}, - {KEY_2JOY1+12, "SEC_JOY13"}, - {KEY_2JOY1+13, "SEC_JOY14"}, - {KEY_2JOY1+14, "SEC_JOY15"}, - {KEY_2JOY1+15, "SEC_JOY16"}, - {KEY_2JOY1+16, "SEC_JOY17"}, - {KEY_2JOY1+17, "SEC_JOY18"}, - {KEY_2JOY1+18, "SEC_JOY19"}, - {KEY_2JOY1+19, "SEC_JOY20"}, - {KEY_2JOY1+20, "SEC_JOY21"}, - {KEY_2JOY1+21, "SEC_JOY22"}, - {KEY_2JOY1+22, "SEC_JOY23"}, - {KEY_2JOY1+23, "SEC_JOY24"}, - {KEY_2JOY1+24, "SEC_JOY25"}, - {KEY_2JOY1+25, "SEC_JOY26"}, - {KEY_2JOY1+26, "SEC_JOY27"}, - {KEY_2JOY1+27, "SEC_JOY28"}, - {KEY_2JOY1+28, "SEC_JOY29"}, - {KEY_2JOY1+29, "SEC_JOY30"}, - {KEY_2JOY1+30, "SEC_JOY31"}, - {KEY_2JOY1+31, "SEC_JOY32"}, + {KEY_2JOY1+8, "sec_joy9"}, + {KEY_2JOY1+9, "sec_joy10"}, + {KEY_2JOY1+10, "sec_joy11"}, + {KEY_2JOY1+11, "sec_joy12"}, + {KEY_2JOY1+12, "sec_joy13"}, + {KEY_2JOY1+13, "sec_joy14"}, + {KEY_2JOY1+14, "sec_joy15"}, + {KEY_2JOY1+15, "sec_joy16"}, + {KEY_2JOY1+16, "sec_joy17"}, + {KEY_2JOY1+17, "sec_joy18"}, + {KEY_2JOY1+18, "sec_joy19"}, + {KEY_2JOY1+19, "sec_joy20"}, + {KEY_2JOY1+20, "sec_joy21"}, + {KEY_2JOY1+21, "sec_joy22"}, + {KEY_2JOY1+22, "sec_joy23"}, + {KEY_2JOY1+23, "sec_joy24"}, + {KEY_2JOY1+24, "sec_joy25"}, + {KEY_2JOY1+25, "sec_joy26"}, + {KEY_2JOY1+26, "sec_joy27"}, + {KEY_2JOY1+27, "sec_joy28"}, + {KEY_2JOY1+28, "sec_joy29"}, + {KEY_2JOY1+29, "sec_joy30"}, + {KEY_2JOY1+30, "sec_joy31"}, + {KEY_2JOY1+31, "sec_joy32"}, #endif // the DOS version uses Allegro's joystick support - {KEY_2HAT1+0, "SEC_HATUP"}, - {KEY_2HAT1+1, "SEC_HATDOWN"}, - {KEY_2HAT1+2, "SEC_HATLEFT"}, - {KEY_2HAT1+3, "SEC_HATRIGHT"}, - {KEY_2HAT1+4, "SEC_HATUP2"}, - {KEY_2HAT1+5, "SEC_HATDOWN2"}, - {KEY_2HAT1+6, "SEC_HATLEFT2"}, - {KEY_2HAT1+7, "SEC_HATRIGHT2"}, - {KEY_2HAT1+8, "SEC_HATUP3"}, - {KEY_2HAT1+9, "SEC_HATDOWN3"}, - {KEY_2HAT1+10, "SEC_HATLEFT3"}, - {KEY_2HAT1+11, "SEC_HATRIGHT3"}, - {KEY_2HAT1+12, "SEC_HATUP4"}, - {KEY_2HAT1+13, "SEC_HATDOWN4"}, - {KEY_2HAT1+14, "SEC_HATLEFT4"}, - {KEY_2HAT1+15, "SEC_HATRIGHT4"}, + {KEY_2HAT1+0, "sec_hatup"}, + {KEY_2HAT1+1, "sec_hatdown"}, + {KEY_2HAT1+2, "sec_hatleft"}, + {KEY_2HAT1+3, "sec_hatright"}, + {KEY_2HAT1+4, "sec_hatup2"}, + {KEY_2HAT1+5, "sec_hatdown2"}, + {KEY_2HAT1+6, "sec_hatleft2"}, + {KEY_2HAT1+7, "sec_hatright2"}, + {KEY_2HAT1+8, "sec_hatup3"}, + {KEY_2HAT1+9, "sec_hatdown3"}, + {KEY_2HAT1+10, "sec_hatleft3"}, + {KEY_2HAT1+11, "sec_hatright3"}, + {KEY_2HAT1+12, "sec_hatup4"}, + {KEY_2HAT1+13, "sec_hatdown4"}, + {KEY_2HAT1+14, "sec_hatleft4"}, + {KEY_2HAT1+15, "sec_hatright4"}, - {KEY_DBL2JOY1+0, "DBLSEC_JOY1"}, - {KEY_DBL2JOY1+1, "DBLSEC_JOY2"}, - {KEY_DBL2JOY1+2, "DBLSEC_JOY3"}, - {KEY_DBL2JOY1+3, "DBLSEC_JOY4"}, - {KEY_DBL2JOY1+4, "DBLSEC_JOY5"}, - {KEY_DBL2JOY1+5, "DBLSEC_JOY6"}, - {KEY_DBL2JOY1+6, "DBLSEC_JOY7"}, - {KEY_DBL2JOY1+7, "DBLSEC_JOY8"}, + {KEY_DBL2JOY1+0, "dblsec_joy1"}, + {KEY_DBL2JOY1+1, "dblsec_joy2"}, + {KEY_DBL2JOY1+2, "dblsec_joy3"}, + {KEY_DBL2JOY1+3, "dblsec_joy4"}, + {KEY_DBL2JOY1+4, "dblsec_joy5"}, + {KEY_DBL2JOY1+5, "dblsec_joy6"}, + {KEY_DBL2JOY1+6, "dblsec_joy7"}, + {KEY_DBL2JOY1+7, "dblsec_joy8"}, #if !defined (NOMOREJOYBTN_2DBL) - {KEY_DBL2JOY1+8, "DBLSEC_JOY9"}, - {KEY_DBL2JOY1+9, "DBLSEC_JOY10"}, - {KEY_DBL2JOY1+10, "DBLSEC_JOY11"}, - {KEY_DBL2JOY1+11, "DBLSEC_JOY12"}, - {KEY_DBL2JOY1+12, "DBLSEC_JOY13"}, - {KEY_DBL2JOY1+13, "DBLSEC_JOY14"}, - {KEY_DBL2JOY1+14, "DBLSEC_JOY15"}, - {KEY_DBL2JOY1+15, "DBLSEC_JOY16"}, - {KEY_DBL2JOY1+16, "DBLSEC_JOY17"}, - {KEY_DBL2JOY1+17, "DBLSEC_JOY18"}, - {KEY_DBL2JOY1+18, "DBLSEC_JOY19"}, - {KEY_DBL2JOY1+19, "DBLSEC_JOY20"}, - {KEY_DBL2JOY1+20, "DBLSEC_JOY21"}, - {KEY_DBL2JOY1+21, "DBLSEC_JOY22"}, - {KEY_DBL2JOY1+22, "DBLSEC_JOY23"}, - {KEY_DBL2JOY1+23, "DBLSEC_JOY24"}, - {KEY_DBL2JOY1+24, "DBLSEC_JOY25"}, - {KEY_DBL2JOY1+25, "DBLSEC_JOY26"}, - {KEY_DBL2JOY1+26, "DBLSEC_JOY27"}, - {KEY_DBL2JOY1+27, "DBLSEC_JOY28"}, - {KEY_DBL2JOY1+28, "DBLSEC_JOY29"}, - {KEY_DBL2JOY1+29, "DBLSEC_JOY30"}, - {KEY_DBL2JOY1+30, "DBLSEC_JOY31"}, - {KEY_DBL2JOY1+31, "DBLSEC_JOY32"}, + {KEY_DBL2JOY1+8, "dblsec_joy9"}, + {KEY_DBL2JOY1+9, "dblsec_joy10"}, + {KEY_DBL2JOY1+10, "dblsec_joy11"}, + {KEY_DBL2JOY1+11, "dblsec_joy12"}, + {KEY_DBL2JOY1+12, "dblsec_joy13"}, + {KEY_DBL2JOY1+13, "dblsec_joy14"}, + {KEY_DBL2JOY1+14, "dblsec_joy15"}, + {KEY_DBL2JOY1+15, "dblsec_joy16"}, + {KEY_DBL2JOY1+16, "dblsec_joy17"}, + {KEY_DBL2JOY1+17, "dblsec_joy18"}, + {KEY_DBL2JOY1+18, "dblsec_joy19"}, + {KEY_DBL2JOY1+19, "dblsec_joy20"}, + {KEY_DBL2JOY1+20, "dblsec_joy21"}, + {KEY_DBL2JOY1+21, "dblsec_joy22"}, + {KEY_DBL2JOY1+22, "dblsec_joy23"}, + {KEY_DBL2JOY1+23, "dblsec_joy24"}, + {KEY_DBL2JOY1+24, "dblsec_joy25"}, + {KEY_DBL2JOY1+25, "dblsec_joy26"}, + {KEY_DBL2JOY1+26, "dblsec_joy27"}, + {KEY_DBL2JOY1+27, "dblsec_joy28"}, + {KEY_DBL2JOY1+28, "dblsec_joy29"}, + {KEY_DBL2JOY1+29, "dblsec_joy30"}, + {KEY_DBL2JOY1+30, "dblsec_joy31"}, + {KEY_DBL2JOY1+31, "dblsec_joy32"}, #endif - {KEY_DBL2HAT1+0, "DBLSEC_HATUP"}, - {KEY_DBL2HAT1+1, "DBLSEC_HATDOWN"}, - {KEY_DBL2HAT1+2, "DBLSEC_HATLEFT"}, - {KEY_DBL2HAT1+3, "DBLSEC_HATRIGHT"}, - {KEY_DBL2HAT1+4, "DBLSEC_HATUP2"}, - {KEY_DBL2HAT1+5, "DBLSEC_HATDOWN2"}, - {KEY_DBL2HAT1+6, "DBLSEC_HATLEFT2"}, - {KEY_DBL2HAT1+7, "DBLSEC_HATRIGHT2"}, - {KEY_DBL2HAT1+8, "DBLSEC_HATUP3"}, - {KEY_DBL2HAT1+9, "DBLSEC_HATDOWN3"}, - {KEY_DBL2HAT1+10, "DBLSEC_HATLEFT3"}, - {KEY_DBL2HAT1+11, "DBLSEC_HATRIGHT3"}, - {KEY_DBL2HAT1+12, "DBLSEC_HATUP4"}, - {KEY_DBL2HAT1+13, "DBLSEC_HATDOWN4"}, - {KEY_DBL2HAT1+14, "DBLSEC_HATLEFT4"}, - {KEY_DBL2HAT1+15, "DBLSEC_HATRIGHT4"}, + {KEY_DBL2HAT1+0, "dblsec_hatup"}, + {KEY_DBL2HAT1+1, "dblsec_hatdown"}, + {KEY_DBL2HAT1+2, "dblsec_hatleft"}, + {KEY_DBL2HAT1+3, "dblsec_hatright"}, + {KEY_DBL2HAT1+4, "dblsec_hatup2"}, + {KEY_DBL2HAT1+5, "dblsec_hatdown2"}, + {KEY_DBL2HAT1+6, "dblsec_hatleft2"}, + {KEY_DBL2HAT1+7, "dblsec_hatright2"}, + {KEY_DBL2HAT1+8, "dblsec_hatup3"}, + {KEY_DBL2HAT1+9, "dblsec_hatdown3"}, + {KEY_DBL2HAT1+10, "dblsec_hatleft3"}, + {KEY_DBL2HAT1+11, "dblsec_hatright3"}, + {KEY_DBL2HAT1+12, "dblsec_hatup4"}, + {KEY_DBL2HAT1+13, "dblsec_hatdown4"}, + {KEY_DBL2HAT1+14, "dblsec_hatleft4"}, + {KEY_DBL2HAT1+15, "dblsec_hatright4"}, }; From 14403737efa4715ce49effd15a48fcb8c7384eb0 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 2 Dec 2021 23:15:55 +0100 Subject: [PATCH 46/49] Raise the file upload speed drastically --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index efe6473d4..5aab9c3cf 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3189,7 +3189,7 @@ consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_ consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); // Speed of file downloading (in packets per tic) -static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}}; consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); static void Got_AddPlayer(UINT8 **p, INT32 playernum); From ff037a81608eead67faa44fa4ea1bbbbeb46989c Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 2 Dec 2021 23:34:28 +0100 Subject: [PATCH 47/49] Remove downloadspeed cruft --- src/d_clisrv.c | 2 +- src/d_netfil.c | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5aab9c3cf..47733a3ee 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3189,7 +3189,7 @@ consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_ consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); // Speed of file downloading (in packets per tic) -static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); static void Got_AddPlayer(UINT8 **p, INT32 playernum); diff --git a/src/d_netfil.c b/src/d_netfil.c index 12c5ee6a2..daf6271bf 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -925,7 +925,6 @@ static void SV_EndFileSend(INT32 node) filestosend--; } -#define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH) #define FILEFRAGMENTSIZE (software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE)) /** Handles file transmission @@ -958,14 +957,7 @@ void FileSendTicker(void) if (!filestosend) // No file to send return; - if (cv_downloadspeed.value) // New behavior - packetsent = cv_downloadspeed.value; - else // Old behavior - { - packetsent = PACKETPERTIC; - if (!packetsent) - packetsent = 1; - } + packetsent = cv_downloadspeed.value; netbuffer->packettype = PT_FILEFRAGMENT; From a3353be0dce216dd7945a3c2f6af6ac24092e820 Mon Sep 17 00:00:00 2001 From: LZA <73-LZA@users.noreply.git.do.srb2.org> Date: Thu, 2 Dec 2021 22:50:44 +0000 Subject: [PATCH 48/49] Raise addon limit --- src/d_clisrv.c | 547 +++++++++++++++++++++++++++++++++++++------------ src/d_clisrv.h | 18 +- src/d_main.c | 102 +++++---- src/d_net.c | 2 + src/d_netcmd.c | 43 ++-- src/d_netcmd.h | 1 + src/d_netfil.c | 278 +++++++++++++++---------- src/d_netfil.h | 27 ++- src/doomdef.h | 3 + src/filesrch.c | 15 +- src/filesrch.h | 3 - src/m_menu.c | 11 +- src/w_wad.c | 74 ++----- src/w_wad.h | 20 +- 14 files changed, 768 insertions(+), 376 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index efe6473d4..36ced7f64 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -128,10 +128,14 @@ static UINT8 localtextcmd[MAXTEXTCMD]; static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen static tic_t neededtic; SINT8 servernode = 0; // the number of the server node + /// \brief do we accept new players? /// \todo WORK! boolean acceptnewnode = true; +static boolean serverisfull = false; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not +static tic_t firstconnectattempttime = 0; + // engine // Must be a power of two @@ -511,18 +515,24 @@ static INT16 Consistancy(void); typedef enum { CL_SEARCHING, + CL_CHECKFILES, CL_DOWNLOADFILES, CL_ASKJOIN, + CL_LOADFILES, CL_WAITJOINRESPONSE, CL_DOWNLOADSAVEGAME, CL_CONNECTED, - CL_ABORTED + CL_ABORTED, + CL_ASKFULLFILELIST, + CL_CONFIRMCONNECT } cl_mode_t; static void GetPackets(void); static cl_mode_t cl_mode = CL_SEARCHING; +static UINT16 cl_lastcheckedfilecount = 0; // used for full file list + #ifndef NONET #define SNAKE_SPEED 5 @@ -920,6 +930,8 @@ static void Snake_Draw(void) INT16 i; // Background + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + V_DrawFlatFill( SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE, @@ -1021,6 +1033,13 @@ static void Snake_Draw(void) ); } +static void CL_DrawConnectionStatusBox(void) +{ + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); + if (cl_mode != CL_CONFIRMCONNECT) + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); +} + // // CL_DrawConnectionStatus // @@ -1031,28 +1050,32 @@ static inline void CL_DrawConnectionStatus(void) INT32 ccstime = I_GetTime(); // Draw background fade - if (!menuactive) // menu already draws its own fade - V_DrawFadeScreen(0xFF00, 16); // force default + V_DrawFadeScreen(0xFF00, 16); // force default - // Draw the bottom box. - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); - - if (cl_mode != CL_DOWNLOADFILES) + if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES) { INT32 i, animtime = ((ccstime / 4) & 15) + 16; - UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96; - // 15 pal entries total. + UINT8 palstart; const char *cltext; + // Draw the bottom box. + CL_DrawConnectionStatusBox(); + + if (cl_mode == CL_SEARCHING) + palstart = 32; // Red + else if (cl_mode == CL_CONFIRMCONNECT) + palstart = 48; // Orange + else + palstart = 96; // Green + if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1)) - for (i = 0; i < 16; ++i) + for (i = 0; i < 16; ++i) // 15 pal entries total. V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15)); switch (cl_mode) { case CL_DOWNLOADSAVEGAME: - if (lastfilenum != -1) + if (fileneeded && lastfilenum != -1) { UINT32 currentsize = fileneeded[lastfilenum].currentsize; UINT32 totalsize = fileneeded[lastfilenum].totalsize; @@ -1076,9 +1099,22 @@ static inline void CL_DrawConnectionStatus(void) else cltext = M_GetText("Waiting to download game state..."); break; + case CL_ASKFULLFILELIST: + case CL_CHECKFILES: + cltext = M_GetText("Checking server addon list..."); + break; + case CL_CONFIRMCONNECT: + cltext = ""; + break; + case CL_LOADFILES: + cltext = M_GetText("Loading server addons..."); + break; case CL_ASKJOIN: case CL_WAITJOINRESPONSE: - cltext = M_GetText("Requesting to join..."); + if (serverisfull) + cltext = M_GetText("Server full, waiting for a slot..."); + else + cltext = M_GetText("Requesting to join..."); break; default: cltext = M_GetText("Connecting to server..."); @@ -1088,14 +1124,51 @@ static inline void CL_DrawConnectionStatus(void) } else { - if (lastfilenum != -1) + if (cl_mode == CL_LOADFILES) + { + INT32 totalfileslength; + INT32 loadcompletednum = 0; + INT32 i; + + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); + + //ima just count files here + if (fileneeded) + { + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_OPEN) + loadcompletednum++; + } + + // Loading progress + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, "Loading server addons..."); + totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256); + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, totalfileslength, 8, 96); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va(" %2u/%2u Files",loadcompletednum,fileneedednum)); + } + else if (lastfilenum != -1) { INT32 dldlength; static char tempname[28]; - fileneeded_t *file = &fileneeded[lastfilenum]; - char *filename = file->filename; + fileneeded_t *file; + char *filename; - Snake_Draw(); + if (snake) + Snake_Draw(); + + // Draw the bottom box. + CL_DrawConnectionStatusBox(); + + if (fileneeded) + { + file = &fileneeded[lastfilenum]; + filename = file->filename; + } + else + return; Net_GetNetStat(); dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); @@ -1128,20 +1201,32 @@ static inline void CL_DrawConnectionStatus(void) va("%3.1fK/s ", ((double)getbps)/1024)); } else + { + if (snake) + Snake_Draw(); + + CL_DrawConnectionStatusBox(); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, M_GetText("Waiting to download files...")); + } } } #endif +static boolean CL_AskFileList(INT32 firstfile) +{ + netbuffer->packettype = PT_TELLFILESNEEDED; + netbuffer->u.filesneedednum = firstfile; + + return HSendPacket(servernode, false, 0, sizeof (INT32)); +} + /** Sends a special packet to declare how many players in local * Used only in arbitratrenetstart() * Sends a PT_CLIENTJOIN packet to the server * * \return True if the packet was successfully sent * \todo Improve the description... - * Because to be honest, I have no idea what arbitratrenetstart is... - * Is it even used...? * */ static boolean CL_SendJoin(void) @@ -1240,7 +1325,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) sizeof netbuffer->u.serverinfo.gametypename); netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); - netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated; + netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0); strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, MAXSERVERNAME); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); @@ -1275,7 +1360,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) if (mapheaderinfo[gamemap-1]) netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum; - p = PutFileNeeded(); + p = PutFileNeeded(0); HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); } @@ -1526,6 +1611,8 @@ static void CL_LoadReceivedSavegame(boolean reloading) size_t length, decompressedlen; char tmpsave[256]; + FreeFileNeeded(); + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); length = FIL_ReadFile(tmpsave, &savebuffer); @@ -1836,12 +1923,164 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif/*MASTERSERVER*/ } -static const char * InvalidServerReason (INT32 i) +#endif // ifndef NONET + +static void M_ConfirmConnect(event_t *ev) +{ +#ifndef NONET + if (ev->type == ev_keydown) + { + if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER) + { + if (totalfilesrequestednum > 0) + { + if (CL_SendFileRequest()) + { + cl_mode = CL_DOWNLOADFILES; + Snake_Initialise(); + } + } + else + cl_mode = CL_LOADFILES; + + M_ClearMenus(true); + } + else if (ev->key == 'n' || ev->key == KEY_ESCAPE) + { + cl_mode = CL_ABORTED; + M_ClearMenus(true); + } + } +#else + (void)ev; +#endif +} + +static boolean CL_FinishedFileList(void) +{ + INT32 i; + char *downloadsize = NULL; + //CONS_Printf(M_GetText("Checking files...\n")); + i = CL_CheckFiles(); + if (i == 4) // still checking ... + { + return true; + } + else if (i == 3) // too many files + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have too many WAD files loaded\n" + "to add ones the server is using.\n" + "Please restart SRB2 before connecting.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 2) // cannot join for some reason + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have the wrong addons loaded.\n\n" + "To play on this server, restart\n" + "the game and don't load any addons.\n" + "SRB2 will automatically add\n" + "everything you need when you join.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 1) + { + if (serverisfull) + { + M_StartMessage(M_GetText( + "This server is full!\n" + "\n" + "You may load server addons (if any), and wait for a slot.\n" + "\n" + "Press ENTER to continue\nor ESC to cancel.\n\n" + ), M_ConfirmConnect, MM_EVENTHANDLER); + cl_mode = CL_CONFIRMCONNECT; + curfadevalue = 0; + } + else + cl_mode = CL_LOADFILES; + } + else + { + // must download something + // can we, though? + if (!CL_CheckDownloadable()) // nope! + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "An error occured when trying to\n" + "download missing addons.\n" + "(This is almost always a problem\n" + "with the server, not your game.)\n\n" + "See the console or log file\n" + "for additional details.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + +#ifndef NONET + downloadcompletednum = 0; + downloadcompletedsize = 0; + totalfilesrequestednum = 0; + totalfilesrequestedsize = 0; + + if (fileneeded == NULL) + I_Error("CL_FinishedFileList: fileneeded == NULL"); + + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) + { + totalfilesrequestednum++; + totalfilesrequestedsize += fileneeded[i].totalsize; + } + + if (totalfilesrequestedsize>>20 >= 100) + downloadsize = Z_StrDup(va("%uM",totalfilesrequestedsize>>20)); + else + downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10)); +#endif + + if (serverisfull) + M_StartMessage(va(M_GetText( + "This server is full!\n" + "Download of %s additional content\nis required to join.\n" + "\n" + "You may download, load server addons,\nand wait for a slot.\n" + "\n" + "Press ENTER to continue\nor ESC to cancel.\n" + ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); + else + M_StartMessage(va(M_GetText( + "Download of %s additional content\nis required to join.\n" + "\n" + "Press ENTER to continue\nor ESC to cancel.\n" + ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); + + Z_Free(downloadsize); + cl_mode = CL_CONFIRMCONNECT; + curfadevalue = 0; + } + return true; +} + +static const char * InvalidServerReason (serverinfo_pak *info) { #define EOT "\nPress ESC\n" - serverinfo_pak *info = &serverlist[i].info; - /* magic number for new packet format */ if (info->_255 != 255) { @@ -1902,8 +2141,6 @@ static const char * InvalidServerReason (INT32 i) #undef EOT } -#endif // ifndef NONET - /** Called by CL_ServerConnectionTicker * * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. @@ -1936,86 +2173,44 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) if (client) { - const char *reason = InvalidServerReason(i); + serverinfo_pak *info = &serverlist[i].info; - // Quit here rather than downloading files - // and being refused later. - if (reason) - { - char *message = Z_StrDup(reason); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(message, NULL, MM_NOTHING); - Z_Free(message); - return false; - } - - D_ParseFileneeded(serverlist[i].info.fileneedednum, - serverlist[i].info.fileneeded); - CONS_Printf(M_GetText("Checking files...\n")); - i = CL_CheckFiles(); - if (i == 3) // too many files - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have too many WAD files loaded\n" - "to add ones the server is using.\n" - "Please restart SRB2 before connecting.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - else if (i == 2) // cannot join for some reason - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have the wrong addons loaded.\n\n" - "To play on this server, restart\n" - "the game and don't load any addons.\n" - "SRB2 will automatically add\n" - "everything you need when you join.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - else if (i == 1) - cl_mode = CL_ASKJOIN; + if (info->refusereason == REFUSE_SLOTS_FULL) + serverisfull = true; else { - // must download something - // can we, though? - if (!CL_CheckDownloadable()) // nope! + const char *reason = InvalidServerReason(info); + + // Quit here rather than downloading files + // and being refused later. + if (reason) { + char *message = Z_StrDup(reason); D_QuitNetGame(); CL_Reset(); D_StartTitle(); - M_StartMessage(M_GetText( - "You cannot connect to this server\n" - "because you cannot download the files\n" - "that you are missing from the server.\n\n" - "See the console or log file for\n" - "more details.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); + M_StartMessage(message, NULL, MM_NOTHING); + Z_Free(message); return false; } - // no problem if can't send packet, we will retry later - if (CL_SendFileRequest()) - { - cl_mode = CL_DOWNLOADFILES; -#ifndef NONET - Snake_Initialise(); -#endif - } } + + D_ParseFileneeded(info->fileneedednum, info->fileneeded, 0); + + if (info->flags & SV_LOTSOFADDONS) + { + cl_mode = CL_ASKFULLFILELIST; + cl_lastcheckedfilecount = 0; + return true; + } + + cl_mode = CL_CHECKFILES; } else + { cl_mode = CL_ASKJOIN; // files need not be checked for the server. + *asksent = 0; + } return true; } @@ -2061,6 +2256,22 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic return false; break; + case CL_ASKFULLFILELIST: + if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved + cl_mode = CL_CHECKFILES; + else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent) + { + if (CL_AskFileList(fileneedednum)) + { + cl_lastcheckedfilecount = fileneedednum; + *asksent = I_GetTime() + NEWTICRATE; + } + } + break; + case CL_CHECKFILES: + if (!CL_FinishedFileList()) + return false; + break; case CL_DOWNLOADFILES: waitmore = false; for (i = 0; i < fileneedednum; i++) @@ -2081,21 +2292,51 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } #endif - cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now - /* FALLTHRU */ - + cl_mode = CL_LOADFILES; + break; + case CL_LOADFILES: + if (CL_LoadServerFiles()) + { + FreeFileNeeded(); + *asksent = 0; //This ensure the first join ask is right away + firstconnectattempttime = I_GetTime(); + cl_mode = CL_ASKJOIN; + } + break; case CL_ASKJOIN: - CL_LoadServerFiles(); + if (firstconnectattempttime + NEWTICRATE*300 < I_GetTime() && !server) + { + CONS_Printf(M_GetText("5 minute wait time exceeded.\n")); + CONS_Printf(M_GetText("Network game synchronization aborted.\n")); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "5 minute wait time exceeded.\n" + "You may retry connection.\n" + "\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } #ifndef NONET // prepare structures to save the file // WARNING: this can be useless in case of server not in GS_LEVEL // but since the network layer doesn't provide ordered packets... CL_PrepareDownloadSaveGame(tmpsave); #endif - if (CL_SendJoin()) + if (I_GetTime() >= *asksent && CL_SendJoin()) + { + *asksent = I_GetTime() + NEWTICRATE*3; cl_mode = CL_WAITJOINRESPONSE; + } + break; + case CL_WAITJOINRESPONSE: + if (I_GetTime() >= *asksent) + { + cl_mode = CL_ASKJOIN; + } break; - #ifndef NONET case CL_DOWNLOADSAVEGAME: // At this state, the first (and only) needed file is the gamestate @@ -2109,8 +2350,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic break; #endif - case CL_WAITJOINRESPONSE: case CL_CONNECTED: + case CL_CONFIRMCONNECT: //logic is handled by M_ConfirmConnect default: break; @@ -2118,7 +2359,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic case CL_ABORTED: cl_mode = CL_SEARCHING; return false; - } GetPackets(); @@ -2128,13 +2368,19 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic if (*oldtic != I_GetTime()) { I_OsPolling(); - for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) - G_MapEventsToControls(&events[eventtail]); - if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1]) + if (cl_mode == CL_CONFIRMCONNECT) + D_ProcessEvents(); //needed for menu system to receive inputs + else + { + for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) + G_MapEventsToControls(&events[eventtail]); + } + + if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1] || cl_mode == CL_ABORTED) { CONS_Printf(M_GetText("Network game synchronization aborted.\n")); -// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); + M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); #ifndef NONET if (snake) @@ -2167,13 +2413,20 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic #ifndef NONET if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) { - if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME) + if (!snake) { F_MenuPresTicker(true); // title sky F_TitleScreenTicker(true); F_TitleScreenDrawer(); } CL_DrawConnectionStatus(); +#ifdef HAVE_THREADS + I_lock_mutex(&m_menu_mutex); +#endif + M_Drawer(); //Needed for drawing messageboxes on the connection screen +#ifdef HAVE_THREADS + I_unlock_mutex(m_menu_mutex); +#endif I_UpdateNoVsync(); // page flip or blit buffer if (moviemode) M_SaveFrame(); @@ -2235,8 +2488,10 @@ static void CL_ConnectToServer(void) ClearAdminPlayers(); pnumnodes = 1; oldtic = I_GetTime() - 1; + #ifndef NONET asksent = (tic_t) - TICRATE; + firstconnectattempttime = I_GetTime(); i = SL_SearchServer(servernode); @@ -2676,8 +2931,16 @@ void CL_Reset(void) SV_ResetServer(); // make sure we don't leave any fileneeded gunk over from a failed join + FreeFileNeeded(); fileneedednum = 0; - memset(fileneeded, 0, sizeof(fileneeded)); + +#ifndef NONET + totalfilesrequestednum = 0; + totalfilesrequestedsize = 0; +#endif + firstconnectattempttime = 0; + serverisfull = false; + connectiontimeout = (tic_t)cv_nettimeout.value; //reset this temporary hack // D_StartTitle should get done now, but the calling function will handle it } @@ -3968,31 +4231,40 @@ static void HandlePacketFromAwayNode(SINT8 node) switch (netbuffer->packettype) { case PT_ASKINFOVIAMS: -#if 0 + Net_CloseConnection(node); + break; + + case PT_TELLFILESNEEDED: if (server && serverrunning) { - INT32 clientnode; - if (ms_RoomId < 0) // ignore if we're not actually on the MS right now - { - Net_CloseConnection(node); // and yes, close connection - return; - } - clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr); - if (clientnode != -1) - { - SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time)); - SV_SendPlayerInfo(clientnode); // Send extra info - Net_CloseConnection(clientnode); - // Don't close connection to MS... - } - else - Net_CloseConnection(node); // ...unless the IP address is not valid + UINT8 *p; + INT32 firstfile = netbuffer->u.filesneedednum; + + netbuffer->packettype = PT_MOREFILESNEEDED; + netbuffer->u.filesneededcfg.first = firstfile; + netbuffer->u.filesneededcfg.more = 0; + + p = PutFileNeeded(firstfile); + + HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); + } + else // Shouldn't get this if you aren't the server...? + Net_CloseConnection(node); + break; + + case PT_MOREFILESNEEDED: + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + SERVERONLY + if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum) + { + D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first); + if (!netbuffer->u.filesneededcfg.more) + cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list } - else - Net_CloseConnection(node); // you're not supposed to get it, so ignore it -#else - Net_CloseConnection(node); -#endif break; case PT_ASKINFO: @@ -4018,13 +4290,24 @@ static void HandlePacketFromAwayNode(SINT8 node) if (!reason) I_Error("Out of memory!\n"); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); + if (strstr(reason, "Maximum players reached")) + { + serverisfull = true; + //Special timeout for when refusing due to player cap. The client will wait 3 seconds between join requests when waiting for a slot, so we need this to be much longer + //We set it back to the value of cv_nettimeout.value in CL_Reset + connectiontimeout = NEWTICRATE*7; + cl_mode = CL_ASKJOIN; + free(reason); + break; + } M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"), reason), NULL, MM_NOTHING); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + free(reason); // Will be reset by caller. Signals refusal. diff --git a/src/d_clisrv.h b/src/d_clisrv.h index a89c054e1..8e75fb963 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -94,6 +94,9 @@ typedef enum PT_LOGIN, // Login attempt from the client. + PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?" + PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)" + PT_PING, // Packet sent to tell clients the other client's latency to server. NUMPACKETTYPE } packettype_t; @@ -198,6 +201,9 @@ typedef struct char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; } ATTRPACK clientconfig_pak; +#define SV_DEDICATED 0x40 // server is dedicated +#define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil + enum { REFUSE_JOINS_DISABLED = 1, REFUSE_SLOTS_FULL, @@ -225,7 +231,7 @@ typedef struct char gametypename[24]; UINT8 modifiedgame; UINT8 cheatsenabled; - UINT8 isdedicated; + UINT8 flags; UINT8 fileneedednum; tic_t time; tic_t leveltime; @@ -279,6 +285,14 @@ typedef struct UINT8 ctfteam; } ATTRPACK plrconfig; +typedef struct +{ + INT32 first; + UINT8 num; + UINT8 more; + UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) +} ATTRPACK filesneededconfig_pak; + // // Network packet data // @@ -308,6 +322,8 @@ typedef struct msaskinfo_pak msaskinfo; // 22 bytes plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) + INT32 filesneedednum; // 4 bytes + filesneededconfig_pak filesneededcfg; // ??? bytes UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; diff --git a/src/d_main.c b/src/d_main.c index 679a596b3..15f85f2e8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -65,7 +65,7 @@ #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" -#include "filesrch.h" // refreshdirmenu, mainwadstally +#include "filesrch.h" // refreshdirmenu #include "g_input.h" // tutorial mode control scheming #include "m_perfstats.h" @@ -96,11 +96,8 @@ int SUBVERSION; // platform independant focus loss UINT8 window_notinfocus = false; -// -// DEMO LOOP -// -static char *startupwadfiles[MAX_WADFILES]; -static char *startuppwads[MAX_WADFILES]; +static addfilelist_t startupwadfiles; +static addfilelist_t startuppwads; boolean devparm = false; // started game with -devparm @@ -119,6 +116,9 @@ boolean midi_disabled = false; boolean sound_disabled = false; boolean digital_disabled = false; +// +// DEMO LOOP +// boolean advancedemo; #ifdef DEBUGFILE INT32 debugload = 0; @@ -923,51 +923,68 @@ void D_StartTitle(void) tutorialmode = false; } -// -// D_AddFile -// -static void D_AddFile(char **list, const char *file) -{ - size_t pnumwadfiles; - char *newfile; +#define REALLOC_FILE_LIST \ + if (list->files == NULL) \ + { \ + list->files = calloc(sizeof(list->files), 2); \ + list->numfiles = 1; \ + } \ + else \ + { \ + index = list->numfiles; \ + list->files = realloc(list->files, sizeof(list->files) * ((++list->numfiles) + 1)); \ + if (list->files == NULL) \ + I_Error("%s: No more free memory to add file %s", __FUNCTION__, file); \ + } - for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++) - ; +static void D_AddFile(addfilelist_t *list, const char *file) +{ + char *newfile; + size_t index = 0; + + REALLOC_FILE_LIST newfile = malloc(strlen(file) + 1); if (!newfile) - I_Error("No more free memory to AddFile %s",file); + I_Error("D_AddFile: No more free memory to add file %s", file); strcpy(newfile, file); - list[pnumwadfiles] = newfile; + list->files[index] = newfile; } -static void D_AddFolder(char **list, const char *file) +static void D_AddFolder(addfilelist_t *list, const char *file) { - size_t pnumwadfiles; char *newfile; + size_t index = 0; - for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++) - ; + REALLOC_FILE_LIST newfile = malloc(strlen(file) + 2); // Path delimiter + NULL terminator if (!newfile) - I_Error("No more free memory to AddFolder %s",file); + I_Error("D_AddFolder: No more free memory to add folder %s", file); strcpy(newfile, file); strcat(newfile, PATHSEP); - list[pnumwadfiles] = newfile; + list->files[index] = newfile; } -static inline void D_CleanFile(char **list) +#undef REALLOC_FILE_LIST + +static inline void D_CleanFile(addfilelist_t *list) { - size_t pnumwadfiles; - for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++) + if (list->files) { - free(list[pnumwadfiles]); - list[pnumwadfiles] = NULL; + size_t pnumwadfiles = 0; + + for (; pnumwadfiles < list->numfiles; pnumwadfiles++) + free(list->files[pnumwadfiles]); + + free(list->files); + list->files = NULL; } + + list->numfiles = 0; } ///\brief Checks if a netgame URL is being handled, and changes working directory to the EXE's if so. @@ -1051,7 +1068,7 @@ static void IdentifyVersion(void) // Load the IWAD if (srb2wad != NULL && FIL_ReadFileOK(srb2wad)) - D_AddFile(startupwadfiles, srb2wad); + D_AddFile(&startupwadfiles, srb2wad); else I_Error("srb2.pk3 not found! Expected in %s, ss file: %s\n", srb2waddir, srb2wad); @@ -1062,14 +1079,14 @@ static void IdentifyVersion(void) // checking in D_SRB2Main // Add the maps - D_AddFile(startupwadfiles, va(pandf,srb2waddir,"zones.pk3")); + D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "zones.pk3")); // Add the players - D_AddFile(startupwadfiles, va(pandf,srb2waddir, "player.dta")); + D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "player.dta")); #ifdef USE_PATCH_DTA // Add our crappy patches to fix our bugs - D_AddFile(startupwadfiles, va(pandf,srb2waddir,"patch.pk3")); + D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "patch.pk3")); #endif #if !defined (HAVE_SDL) || defined (HAVE_MIXER) @@ -1079,7 +1096,7 @@ static void IdentifyVersion(void) const char *musicpath = va(pandf,srb2waddir,str);\ int ms = W_VerifyNMUSlumps(musicpath, false); \ if (ms == 1) \ - D_AddFile(startupwadfiles, musicpath); \ + D_AddFile(&startupwadfiles, musicpath); \ else if (ms == 0) \ I_Error("File "str" has been modified with non-music/sound lumps"); \ } @@ -1269,9 +1286,9 @@ void D_SRB2Main(void) else if (myargv[i][0] == '-' || myargv[i][0] == '+') addontype = 0; else if (addontype == 1) - D_AddFile(startuppwads, myargv[i]); + D_AddFile(&startuppwads, myargv[i]); else if (addontype == 2) - D_AddFolder(startuppwads, myargv[i]); + D_AddFolder(&startuppwads, myargv[i]); } } @@ -1310,8 +1327,8 @@ void D_SRB2Main(void) // load wad, including the main wad file CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); - W_InitMultipleFiles(startupwadfiles); - D_CleanFile(startupwadfiles); + W_InitMultipleFiles(&startupwadfiles); + D_CleanFile(&startupwadfiles); #ifndef DEVELOP // md5s last updated 22/02/20 (ddmmyy) @@ -1326,8 +1343,6 @@ void D_SRB2Main(void) // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. #endif //ifndef DEVELOP - mainwadstally = packetsizetally; // technically not accurate atm, remember to port the two-stage -file process from kart in 2.2.x - cht_Init(); //---------------------------------------------------- READY SCREEN @@ -1360,9 +1375,12 @@ void D_SRB2Main(void) CON_StopRefresh(); // Temporarily stop refreshing the screen for wad loading - CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n"); - W_InitMultipleFiles(startuppwads); - D_CleanFile(startuppwads); + if (startuppwads.numfiles) + { + CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n"); + W_InitMultipleFiles(&startuppwads); + D_CleanFile(&startuppwads); + } CON_StartRefresh(); // Restart the refresh! diff --git a/src/d_net.c b/src/d_net.c index 9e5abe24a..3a4746002 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -815,6 +815,8 @@ static const char *packettypename[NUMPACKETTYPE] = "CLIENTJOIN", "NODETIMEOUT", "LOGIN", + "TELLFILESNEEDED", + "MOREFILESNEEDED", "PING" }; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5eb360bef..7024e64fb 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3223,7 +3223,7 @@ static void Command_RunSOC(void) static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) { char filename[256]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { @@ -3347,10 +3347,9 @@ static void Command_Addfile(void) break; ++p; - // check total packet size and no of files currently loaded - // See W_InitFile in w_wad.c - if ((numwadfiles >= MAX_WADFILES) - || ((packetsizetally + nameonlylength(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8))) + // check no of files currently loaded + // See W_LoadWadFile in w_wad.c + if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); return; @@ -3379,6 +3378,9 @@ static void Command_Addfile(void) for (i = 0; i < numwadfiles; i++) { + if (wadfiles[i]->type == RET_FOLDER) + continue; + if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) { CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); @@ -3469,10 +3471,9 @@ static void Command_Addfolder(void) continue; } - // check total packet size and no of files currently loaded - // See W_InitFile in w_wad.c - if ((numwadfiles >= MAX_WADFILES) - || ((packetsizetally + strlen(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8))) + // check no of files currently loaded + // See W_LoadWadFile in w_wad.c + if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); return; @@ -3534,7 +3535,7 @@ static void Command_Addfolder(void) static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) { char filename[241]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; UINT8 md5sum[16]; boolean kick = false; boolean toomany = false; @@ -3559,9 +3560,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) return; } - // See W_InitFile in w_wad.c - if ((numwadfiles >= MAX_WADFILES) - || ((packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8))) + if (numwadfiles >= MAX_WADFILES) toomany = true; else ncs = findfile(filename,md5sum,true); @@ -3594,7 +3593,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum) { char path[241]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; boolean kick = false; boolean toomany = false; INT32 i,j; @@ -3619,9 +3618,7 @@ static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum) return; } - // See W_InitFile in w_wad.c - if ((numwadfiles >= MAX_WADFILES) - || ((packetsizetally + strlen(path) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8))) + if (numwadfiles >= MAX_WADFILES) toomany = true; else ncs = findfolder(path); @@ -3652,7 +3649,7 @@ static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum) static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) { char filename[241]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; UINT8 md5sum[16]; READSTRINGN(*cp, filename, 240); @@ -3700,7 +3697,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum) { char path[241]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; READSTRINGN(*cp, path, 240); @@ -3744,7 +3741,13 @@ static void Command_ListWADS_f(void) { INT32 i = numwadfiles; char *tempname; - CONS_Printf(M_GetText("There are %d wads loaded:\n"),numwadfiles); + +#ifdef ENFORCE_WAD_LIMIT + CONS_Printf(M_GetText("There are %d/%d files loaded:\n"),numwadfiles,MAX_WADFILES); +#else + CONS_Printf(M_GetText("There are %d files loaded:\n"),numwadfiles); +#endif + for (i--; i >= 0; i--) { nameonly(tempname = va("%s", wadfiles[i]->filename)); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index cae32643e..efe00552a 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -73,6 +73,7 @@ extern consvar_t cv_teamscramble; extern consvar_t cv_scrambleonchange; extern consvar_t cv_netstat; +extern consvar_t cv_nettimeout; extern consvar_t cv_countdowntime; extern consvar_t cv_runscripts; diff --git a/src/d_netfil.c b/src/d_netfil.c index 12c5ee6a2..a1dd02eeb 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -52,7 +52,7 @@ #include // Prototypes -static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid); +static boolean AddFileToSendQueue(INT32 node, UINT8 fileid); // Sender structure typedef struct filetx_s @@ -87,7 +87,7 @@ static filetran_t transfer[MAXNETNODES]; // Receiver structure INT32 fileneedednum; // Number of files needed to join the server -fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files +fileneeded_t *fileneeded; // List of needed files static tic_t lasttimeackpacketsent = 0; char downloaddir[512] = "DOWNLOAD"; @@ -105,6 +105,10 @@ static pauseddownload_t *pauseddownload = NULL; #ifndef NONET // for cl loading screen INT32 lastfilenum = -1; +INT32 downloadcompletednum = 0; +UINT32 downloadcompletedsize = 0; +INT32 totalfilesrequestednum = 0; +UINT32 totalfilesrequestedsize = 0; #endif luafiletransfer_t *luafiletransfers = NULL; @@ -113,25 +117,62 @@ boolean waitingforluafilecommand = false; char luafiledir[256 + 16] = "luafiles"; +static UINT16 GetWadNumFromFileNeededId(UINT8 id) +{ + UINT16 wadnum; + + for (wadnum = mainwads; wadnum < numwadfiles; wadnum++) + { + if (!wadfiles[wadnum]->important) + continue; + if (id == 0) + return wadnum; + id--; + } + + return UINT16_MAX; +} + /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. * Used to have size limiting built in - now handled via W_InitFile in w_wad.c * */ -UINT8 *PutFileNeeded(void) +UINT8 *PutFileNeeded(UINT16 firstfile) { - size_t i, count = 0; - UINT8 *p = netbuffer->u.serverinfo.fileneeded; + size_t i; + UINT8 count = 0; + UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded; + UINT8 *p = p_start; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus, folder; - for (i = 0; i < numwadfiles; i++) + for (i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad { // If it has only music/sound lumps, don't put it in the list if (!wadfiles[i]->important) continue; + if (firstfile) + { // Skip files until we reach the first file. + firstfile--; + continue; + } + + nameonly(strcpy(wadfilename, wadfiles[i]->filename)); + + // Look below at the WRITE macros to understand what these numbers mean. + if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED) + { + // Too many files to send all at once + if (netbuffer->packettype == PT_MOREFILESNEEDED) + netbuffer->u.filesneededcfg.more = 1; + else + netbuffer->u.serverinfo.flags |= SV_LOTSOFADDONS; + break; + } + filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS folder = (wadfiles[i]->type == RET_FOLDER); @@ -148,32 +189,53 @@ UINT8 *PutFileNeeded(void) count++; WRITEUINT32(p, wadfiles[i]->filesize); - nameonly(strcpy(wadfilename, wadfiles[i]->filename)); WRITESTRINGN(p, wadfilename, MAX_WADPATH); WRITEMEM(p, wadfiles[i]->md5sum, 16); } - netbuffer->u.serverinfo.fileneedednum = (UINT8)count; + + if (netbuffer->packettype == PT_MOREFILESNEEDED) + netbuffer->u.filesneededcfg.num = count; + else + netbuffer->u.serverinfo.fileneedednum = count; return p; } +void AllocFileNeeded(INT32 size) +{ + if (fileneeded == NULL) + fileneeded = Z_Calloc(sizeof(fileneeded_t) * size, PU_STATIC, NULL); + else + fileneeded = Z_Realloc(fileneeded, sizeof(fileneeded_t) * size, PU_STATIC, NULL); +} + +void FreeFileNeeded(void) +{ + Z_Free(fileneeded); + fileneeded = NULL; +} + /** Parses the serverinfo packet and fills the fileneeded table on client * * \param fileneedednum_parm The number of files needed to join the server * \param fileneededstr The memory block containing the list of needed files * */ -void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) +void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile) { INT32 i; UINT8 *p; UINT8 filestatus; - fileneedednum = fileneedednum_parm; + fileneedednum = firstfile + fileneedednum_parm; p = (UINT8 *)fileneededstr; - for (i = 0; i < fileneedednum; i++) + + AllocFileNeeded(fileneedednum); + + for (i = firstfile; i < fileneedednum; i++) { - fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet + fileneeded[i].type = FILENEEDED_WAD; + fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet fileneeded[i].justdownloaded = false; filestatus = READUINT8(p); // The first byte is the file status fileneeded[i].folder = READUINT8(p); // The second byte is the folder flag @@ -191,7 +253,11 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave) lastfilenum = -1; #endif + FreeFileNeeded(); + AllocFileNeeded(1); + fileneedednum = 1; + fileneeded[0].type = FILENEEDED_SAVEGAME; fileneeded[0].status = FS_REQUESTED; fileneeded[0].justdownloaded = false; fileneeded[0].totalsize = UINT32_MAX; @@ -322,14 +388,18 @@ boolean CL_SendFileRequest(void) if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) { totalfreespaceneeded += fileneeded[i].totalsize; - nameonly(fileneeded[i].filename); + WRITEUINT8(p, i); // fileid - WRITESTRINGN(p, fileneeded[i].filename, MAX_WADPATH); + // put it in download dir + nameonly(fileneeded[i].filename); strcatbf(fileneeded[i].filename, downloaddir, "/"); + fileneeded[i].status = FS_REQUESTED; } + WRITEUINT8(p, 0xFF); + I_GetDiskFreeSpace(&availablefreespace); if (totalfreespaceneeded > availablefreespace) I_Error("To play on this server you must download %s KB,\n" @@ -345,21 +415,22 @@ boolean CL_SendFileRequest(void) // returns false if a requested file was not found or cannot be sent boolean PT_RequestFile(INT32 node) { - char wad[MAX_WADPATH+1]; UINT8 *p = netbuffer->u.textcmd; UINT8 id; + while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow { id = READUINT8(p); if (id == 0xFF) break; - READSTRINGN(p, wad, MAX_WADPATH); - if (!AddFileToSendQueue(node, wad, id)) + + if (!AddFileToSendQueue(node, id)) { SV_AbortSendFiles(node); return false; // don't read the rest of the files } } + return true; // no problems with any files } @@ -368,23 +439,16 @@ boolean PT_RequestFile(INT32 node) * \return 0 if some files are missing * 1 if all files exist * 2 if some already loaded files are not requested or are in a different order + * 3 too many files, over WADLIMIT + * 4 still checking, continuing next tic * */ INT32 CL_CheckFiles(void) { INT32 i, j; char wadfilename[MAX_WADPATH]; - INT32 ret = 1; - size_t packetsize = 0; - size_t filestoget = 0; - -// if (M_CheckParm("-nofiles")) -// return 1; - - // the first is the iwad (the main wad file) - // we don't care if it's called srb2.pk3 or not. - // Never download the IWAD, just assume it's there and identical - fileneeded[0].status = FS_OPEN; + size_t filestoload = 0; + boolean downloadrequired = false; // Modified game handling -- check for an identical file list // must be identical in files loaded AND in order @@ -392,7 +456,7 @@ INT32 CL_CheckFiles(void) if (modifiedgame) { CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); - for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;) + for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;) { if (j < numwadfiles && !wadfiles[j]->important) { @@ -419,15 +483,21 @@ INT32 CL_CheckFiles(void) return 1; } - // See W_InitFile in w_wad.c - packetsize = packetsizetally; - - for (i = 1; i < fileneedednum; i++) + for (i = 0; i < fileneedednum; i++) { + if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) + downloadrequired = true; + + if (fileneeded[i].status != FS_OPEN) + filestoload++; + + if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics + continue; + CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files - for (j = 1; wadfiles[j]; j++) + for (j = mainwads; wadfiles[j]; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && @@ -435,43 +505,34 @@ INT32 CL_CheckFiles(void) { CONS_Debug(DBG_NETPLAY, "already loaded\n"); fileneeded[i].status = FS_OPEN; - break; + return 4; } } - if (fileneeded[i].status != FS_NOTFOUND) - continue; - - if (fileneeded[i].folder) - packetsize += strlen(fileneeded[i].filename) + FILENEEDEDSIZE; - else - packetsize += nameonlylength(fileneeded[i].filename) + FILENEEDEDSIZE; - - if ((numwadfiles+filestoget >= MAX_WADFILES) - || (packetsize > MAXFILENEEDED*sizeof(UINT8))) - return 3; - - filestoget++; if (fileneeded[i].folder) fileneeded[i].status = findfolder(fileneeded[i].filename); else fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); + CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status); - if (fileneeded[i].status != FS_FOUND) - ret = 0; + return 4; } - return ret; + + //now making it here means we've checked the entire list and no FS_NOTCHECKED files remain + if (numwadfiles+filestoload > MAX_WADFILES) + return 3; + else if (downloadrequired) + return 0; //some stuff is FS_NOTFOUND, needs download + else + return 1; //everything is FS_OPEN or FS_FOUND, proceed to loading } // Load it now -void CL_LoadServerFiles(void) +boolean CL_LoadServerFiles(void) { INT32 i; -// if (M_CheckParm("-nofiles")) -// return; - - for (i = 1; i < fileneedednum; i++) + for (i = 0; i < fileneedednum; i++) { if (fileneeded[i].status == FS_OPEN) continue; // Already loaded @@ -483,6 +544,7 @@ void CL_LoadServerFiles(void) P_AddWadFile(fileneeded[i].filename); G_SetGameModified(true); fileneeded[i].status = FS_OPEN; + return false; } else if (fileneeded[i].status == FS_MD5SUMBAD) I_Error("Wrong version of file %s", fileneeded[i].filename); @@ -508,6 +570,7 @@ void CL_LoadServerFiles(void) fileneeded[i].status, s); } } + return true; } void AddLuaFileTransfer(const char *filename, const char *mode) @@ -689,7 +752,11 @@ void CL_PrepareDownloadLuaFile(void) netbuffer->packettype = PT_ASKLUAFILE; HSendPacket(servernode, true, 0, 0); + FreeFileNeeded(); + AllocFileNeeded(1); + fileneedednum = 1; + fileneeded[0].type = FILENEEDED_LUAFILE; fileneeded[0].status = FS_REQUESTED; fileneeded[0].justdownloaded = false; fileneeded[0].totalsize = UINT32_MAX; @@ -716,15 +783,11 @@ static INT32 filestosend = 0; * \sa AddLuaFileToSendQueue * */ -static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid) +static boolean AddFileToSendQueue(INT32 node, UINT8 fileid) { filetx_t **q; // A pointer to the "next" field of the last file in the list filetx_t *p; // The new file request - INT32 i; - char wadfilename[MAX_WADPATH]; - - if (cv_noticedownload.value) - CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node)); + UINT16 wadnum; // Find the last file in the list and set a pointer to its "next" field q = &transfer[node].txlist; @@ -744,51 +807,43 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid if (!p->id.filename) I_Error("AddFileToSendQueue: No more memory\n"); - // Set the file name and get rid of the path - strlcpy(p->id.filename, filename, MAX_WADPATH); - nameonly(p->id.filename); - - // Look for the requested file through all loaded files - for (i = 0; wadfiles[i]; i++) - { - strlcpy(wadfilename, wadfiles[i]->filename, MAX_WADPATH); - nameonly(wadfilename); - if (!stricmp(wadfilename, p->id.filename)) - { - // Copy file name with full path - strlcpy(p->id.filename, wadfiles[i]->filename, MAX_WADPATH); - break; - } - } + // Find the wad the ID refers to + wadnum = GetWadNumFromFileNeededId(fileid); // Handle non-loaded file requests - if (!wadfiles[i]) + if (wadnum == UINT16_MAX) { - DEBFILE(va("%s not found in wadfiles\n", filename)); + DEBFILE(va("fileneeded %d not found in wadfiles\n", fileid)); // This formerly checked if (!findfile(p->id.filename, NULL, true)) // Not found // Don't inform client - DEBFILE(va("Client %d request %s: not found\n", node, filename)); + DEBFILE(va("Client %d request fileneeded %d: not found\n", node, fileid)); free(p->id.filename); free(p); *q = NULL; return false; // cancel the rest of the requests } + // Set the file name and get rid of the path + strlcpy(p->id.filename, wadfiles[wadnum]->filename, MAX_WADPATH); + // Handle huge file requests (i.e. bigger than cv_maxsend.value KB) - if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024) + if (wadfiles[wadnum]->filesize > (UINT32)cv_maxsend.value * 1024) { // Too big // Don't inform client (client sucks, man) - DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename)); + DEBFILE(va("Client %d request %s: file too big, not sending\n", node, p->id.filename)); free(p->id.filename); free(p); *q = NULL; return false; // cancel the rest of the requests } - DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node)); + if (cv_noticedownload.value) + CONS_Printf("Sending file \"%s\" to node %d (%s)\n", p->id.filename, node, I_GetNodeAddress(node)); + + DEBFILE(va("Sending file %s (id=%d) to %d\n", p->id.filename, fileid, node)); p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it p->fileid = fileid; p->next = NULL; // End of list @@ -1242,6 +1297,9 @@ void PT_FileFragment(void) UINT16 boundedfragmentsize = doomcom->datalength - BASEPACKETSIZE - sizeof(netbuffer->u.filetxpak); char *filename; + if (!file) + return; + filename = va("%s", file->filename); nameonly(filename); @@ -1353,6 +1411,7 @@ void PT_FileFragment(void) // Tell the server we have received the file netbuffer->packettype = PT_HASLUAFILE; HSendPacket(servernode, true, 0, 0); + FreeFileNeeded(); } } } @@ -1423,32 +1482,37 @@ void CloseNetFile(void) SV_AbortSendFiles(i); // Receiving a file? - for (i = 0; i < MAX_WADFILES; i++) - if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file) - { - fclose(fileneeded[i].file); - free(fileneeded[i].ackpacket); - - if (!pauseddownload && i != 0) // 0 is either srb2.srb or the gamestate... + if (fileneeded) + { + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file) { - // Don't remove the file, save it for later in case we resume the download - pauseddownload = malloc(sizeof(*pauseddownload)); - if (!pauseddownload) - I_Error("CloseNetFile: No more memory\n"); + fclose(fileneeded[i].file); + free(fileneeded[i].ackpacket); - strcpy(pauseddownload->filename, fileneeded[i].filename); - memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16); - pauseddownload->currentsize = fileneeded[i].currentsize; - pauseddownload->receivedfragments = fileneeded[i].receivedfragments; - pauseddownload->fragmentsize = fileneeded[i].fragmentsize; + if (!pauseddownload && (fileneeded[i].type == FILENEEDED_WAD || i != 0)) // 0 is the gamestate... + { + // Don't remove the file, save it for later in case we resume the download + pauseddownload = malloc(sizeof(*pauseddownload)); + if (!pauseddownload) + I_Error("CloseNetFile: No more memory\n"); + + strcpy(pauseddownload->filename, fileneeded[i].filename); + memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16); + pauseddownload->currentsize = fileneeded[i].currentsize; + pauseddownload->receivedfragments = fileneeded[i].receivedfragments; + pauseddownload->fragmentsize = fileneeded[i].fragmentsize; + } + else + { + // File is not complete, delete it. + free(fileneeded[i].receivedfragments); + remove(fileneeded[i].filename); + } } - else - { - free(fileneeded[i].receivedfragments); - // File is not complete delete it - remove(fileneeded[i].filename); - } - } + } + + FreeFileNeeded(); } void Command_Downloads_f(void) diff --git a/src/d_netfil.h b/src/d_netfil.h index 70b721bf7..3d713c150 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -27,6 +27,7 @@ typedef enum typedef enum { + FS_NOTCHECKED, FS_NOTFOUND, FS_FOUND, FS_REQUESTED, @@ -35,13 +36,21 @@ typedef enum FS_MD5SUMBAD } filestatus_t; +typedef enum +{ + FILENEEDED_WAD, + FILENEEDED_SAVEGAME, + FILENEEDED_LUAFILE +} fileneededtype_t; + typedef struct { - UINT8 willsend; // Is the server willing to send it? - UINT8 folder; // File is a folder char filename[MAX_WADPATH]; UINT8 md5sum[16]; filestatus_t status; // The value returned by recsearch + UINT8 willsend; // Is the server willing to send it? + UINT8 folder; // File is a folder + fileneededtype_t type; boolean justdownloaded; // To prevent late fragments from causing an I_Error // Used only for download @@ -58,19 +67,25 @@ typedef struct #define FILENEEDEDSIZE 23 extern INT32 fileneedednum; -extern fileneeded_t fileneeded[MAX_WADFILES]; +extern fileneeded_t *fileneeded; extern char downloaddir[512]; #ifndef NONET extern INT32 lastfilenum; +extern INT32 downloadcompletednum; +extern UINT32 downloadcompletedsize; +extern INT32 totalfilesrequestednum; +extern UINT32 totalfilesrequestedsize; #endif -UINT8 *PutFileNeeded(void); -void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr); +void AllocFileNeeded(INT32 size); +void FreeFileNeeded(void); +UINT8 *PutFileNeeded(UINT16 firstfile); +void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile); void CL_PrepareDownloadSaveGame(const char *tmpsave); INT32 CL_CheckFiles(void); -void CL_LoadServerFiles(void); +boolean CL_LoadServerFiles(void); void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid); diff --git a/src/doomdef.h b/src/doomdef.h index 37edca896..7e7e35599 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -152,6 +152,9 @@ extern char logfilename[1024]; // Comment or uncomment this as necessary. #define USE_PATCH_DTA +// Enforce a limit of loaded WAD files. +//#define ENFORCE_WAD_LIMIT + // Use .kart extension addons //#define USE_KART diff --git a/src/filesrch.c b/src/filesrch.c index b4039e526..ec095518e 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -338,9 +338,6 @@ size_t dir_on[menudepth]; UINT8 refreshdirmenu = 0; char *refreshdirname = NULL; -size_t packetsizetally = 0; -size_t mainwadstally = 0; - #define dirpathlen 1024 #define maxdirdepth 48 @@ -830,7 +827,7 @@ char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) pl #endif "\5.pk3", "\5.soc", "\5.lua"}; // addfile -char filenamebuf[MAX_WADFILES][MAX_WADPATH]; +static char (*filenamebuf)[MAX_WADPATH]; static boolean filemenucmp(char *haystack, char *needle) { @@ -1102,6 +1099,10 @@ boolean preparefilemenu(boolean samedepth) if (ext >= EXT_LOADSTART) { size_t i; + + if (filenamebuf == NULL) + filenamebuf = calloc(sizeof(char) * MAX_WADPATH, numwadfiles); + for (i = 0; i < numwadfiles; i++) { if (!filenamebuf[i][0]) @@ -1151,6 +1152,12 @@ boolean preparefilemenu(boolean samedepth) } } + if (filenamebuf) + { + free(filenamebuf); + filenamebuf = NULL; + } + closedir(dirhandle); if ((menudepthleft != menudepth-1) // now for UP... entry diff --git a/src/filesrch.h b/src/filesrch.h index 9d5f31bbb..59ef5269b 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -53,9 +53,6 @@ extern size_t dir_on[menudepth]; extern UINT8 refreshdirmenu; extern char *refreshdirname; -extern size_t packetsizetally; -extern size_t mainwadstally; - typedef enum { EXT_FOLDER = 0, diff --git a/src/m_menu.c b/src/m_menu.c index 7a82fd8fb..d5fa5e95b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3215,7 +3215,7 @@ boolean M_Responder(event_t *ev) if (gamestate == GS_TITLESCREEN && finalecount < TICRATE) return false; - if (CON_Ready()) + if (CON_Ready() && gamestate != GS_WAITINGPLAYERS) return false; if (noFurtherInput) @@ -6410,6 +6410,7 @@ static void M_Addons(INT32 choice) M_SetupNextMenu(&MISC_AddonsDef); } +#ifdef ENFORCE_WAD_LIMIT #define width 4 #define vpadding 27 #define h (BASEVIDHEIGHT-(2*vpadding)) @@ -6457,6 +6458,7 @@ static void M_DrawTemperature(INT32 x, fixed_t t) #undef vpadding #undef h #undef NUMCOLOURS +#endif static char *M_AddonsHeaderPath(void) { @@ -6550,21 +6552,20 @@ static void M_DrawAddons(void) V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, LOCATIONSTRING1); // (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1) +#ifdef ENFORCE_WAD_LIMIT if (numwadfiles <= mainwads+1) y = 0; else if (numwadfiles >= MAX_WADFILES) y = FRACUNIT; else { - x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< y) - y = x; + y = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< FRACUNIT) // happens because of how we're shrinkin' it a little y = FRACUNIT; } M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y); +#endif // DRAW MENU x = currentMenu->x; diff --git a/src/w_wad.c b/src/w_wad.c index 3ff301117..e49e0ce82 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -105,7 +105,7 @@ static UINT16 lumpnumcacheindex = 0; // GLOBALS //=========================================================================== UINT16 numwadfiles; // number of active wadfiles -wadfile_t *wadfiles[MAX_WADFILES]; // 0 to numwadfiles-1 are valid +wadfile_t **wadfiles; // 0 to numwadfiles-1 are valid // W_Shutdown // Closes all of the WAD files before quitting @@ -134,6 +134,8 @@ void W_Shutdown(void) Z_Free(wad->lumpinfo); Z_Free(wad); } + + Z_Free(wadfiles); } //=========================================================================== @@ -844,7 +846,6 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) #ifndef NOMD5 size_t i; #endif - size_t packetsize; UINT8 md5sum[16]; int important; @@ -862,9 +863,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) refreshdirname = NULL; //CONS_Debug(DBG_SETUP, "Loading %s\n", filename); - // - // check if limit of active wadfiles - // + + // Check if the game reached the limit of active wadfiles. if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); @@ -884,24 +884,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) return INT16_MAX; } - // Check if wad files will overflow fileneededbuffer. Only the filename part - // is send in the packet; cf. - // see PutFileNeeded in d_netfil.c - if ((important = !important)) - { - packetsize = packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE; - - if (packetsize > MAXFILENEEDED*sizeof(UINT8)) - { - CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); - refreshdirmenu |= REFRESHDIR_MAX; - if (handle) - fclose(handle); - return W_InitFileError(filename, startup); - } - - packetsizetally = packetsize; - } + important = !important; #ifndef NOMD5 // @@ -913,11 +896,12 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) for (i = 0; i < numwadfiles; i++) { + if (wadfiles[i]->type == RET_FOLDER) + continue; + if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) { CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); - if (important) - packetsizetally -= nameonlylength(filename) + FILENEEDEDSIZE; if (handle) fclose(handle); return W_InitFileError(filename, false); @@ -984,6 +968,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) // add the wadfile // CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps); + wadfiles = Z_Realloc(wadfiles, sizeof(wadfile_t) * (numwadfiles + 1), PU_STATIC, NULL); wadfiles[numwadfiles] = wadfile; numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded @@ -1046,22 +1031,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup) return W_InitFileError(path, startup); } - important = 0; // ??? - - /// \todo Implement a W_VerifyFolder. - if ((important = !important)) - { - size_t packetsize = packetsizetally + strlen(path) + FILENEEDEDSIZE; - - if (packetsize > MAXFILENEEDED*sizeof(UINT8)) - { - CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); - refreshdirmenu |= REFRESHDIR_MAX; - return W_InitFileError(path, startup); - } - - packetsizetally = packetsize; - } + important = 0; /// \todo Implement a W_VerifyFolder. // Remove path delimiters. p = path + (strlen(path) - 1); @@ -1132,8 +1102,6 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup) if (samepaths(wadfiles[i]->path, fullpath) > 0) { CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), path); - if (important) - packetsizetally -= strlen(path) + FILENEEDEDSIZE; Z_Free(fn); Z_Free(fullpath); return W_InitFileError(path, false); @@ -1197,11 +1165,13 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup) * * \param filenames A null-terminated list of files to use. */ -void W_InitMultipleFiles(char **filenames) +void W_InitMultipleFiles(addfilelist_t *list) { - for (; *filenames; filenames++) + size_t i = 0; + + for (; i < list->numfiles; i++) { - const char *fn = (*filenames); + const char *fn = list->files[i]; char pathsep = fn[strlen(fn) - 1]; boolean mainfile = (numwadfiles < mainwads); @@ -1219,7 +1189,7 @@ void W_InitMultipleFiles(char **filenames) */ static boolean TestValidLump(UINT16 wad, UINT16 lump) { - I_Assert(wad < MAX_WADFILES); + I_Assert(wad < numwadfiles); if (!wadfiles[wad]) // make sure the wad file exists return false; @@ -1636,7 +1606,7 @@ size_t W_LumpLength(lumpnum_t lumpnum) // // W_IsLumpWad -// Is the lump a WAD? (presumably in a PK3) +// Is the lump a WAD? (presumably not in a WAD) // boolean W_IsLumpWad(lumpnum_t lumpnum) { @@ -1649,12 +1619,12 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) return !strnicmp(lumpfullName + strlen(lumpfullName) - 4, ".wad", 4); } - return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned + return false; // WADs should never be inside WADs as far as SRB2 is concerned } // // W_IsLumpFolder -// Is the lump a folder? (in a PK3 obviously) +// Is the lump a folder? (not in a WAD obviously) // boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) { @@ -1665,7 +1635,7 @@ boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) return (name[strlen(name)-1] == '/'); // folders end in '/' } - return false; // non-PK3s don't have folders + return false; // WADs don't have folders } #ifdef HAVE_ZLIB @@ -2217,7 +2187,7 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) #else I_Error #endif - (M_GetText("File is old, is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); + (M_GetText("File is old, is corrupt or has been modified:\n%s\nFound MD5: %s\nWanted MD5: %s\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); } #endif } diff --git a/src/w_wad.h b/src/w_wad.h index 949bab9fe..a41ba1724 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -97,9 +97,15 @@ virtlump_t* vres_Find(const virtres_t*, const char*); // DYNAMIC WAD LOADING // ========================================================================= +// Maximum of files that can be loaded +// (there is a max of simultaneous open files anyway) +#ifdef ENFORCE_WAD_LIMIT +#define MAX_WADFILES 2048 // This cannot be any higher than UINT16_MAX. +#else +#define MAX_WADFILES UINT16_MAX +#endif + #define MAX_WADPATH 512 -#define MAX_WADFILES 48 // maximum of wad files used at the same time -// (there is a max of simultaneous open files anyway, and this should be plenty) #define lumpcache_t void * @@ -134,7 +140,13 @@ typedef struct wadfile_s #define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad extern UINT16 numwadfiles; -extern wadfile_t *wadfiles[MAX_WADFILES]; +extern wadfile_t **wadfiles; + +typedef struct +{ + char **files; + size_t numfiles; +} addfilelist_t; // ========================================================================= @@ -148,7 +160,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup); UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup); // W_InitMultipleFiles exits if a file was not found, but not if all is okay. -void W_InitMultipleFiles(char **filenames); +void W_InitMultipleFiles(addfilelist_t *list); #define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER) From 6dc49042deb1f27217fd1d5107726732c2fd9bf8 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 3 Dec 2021 18:48:16 +0100 Subject: [PATCH 49/49] Port katsy's bouncy FOF cleanup --- extras/conf/SRB2-22.cfg | 1 - extras/conf/udb/Includes/SRB222_linedefs.cfg | 6 --- src/deh_tables.c | 10 ++-- src/lua_maplib.c | 8 +-- src/p_mobj.c | 6 +-- src/p_setup.c | 2 - src/p_spec.c | 33 +++++------- src/p_user.c | 54 ++++---------------- src/r_defs.h | 14 ++--- 9 files changed, 39 insertions(+), 95 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index fd12b5c81..3f345da4f 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -776,7 +776,6 @@ linedeftypes { title = "Make FOF Bouncy"; prefix = "(76)"; - flags16384text = "[14] Dampen"; } } diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index d4f24e4ab..068fc2c8c 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1733,12 +1733,6 @@ udmf { title = "Bounce strength"; } - arg2 - { - title = "Dampen?"; - type = 11; - enum = "noyes"; - } } } diff --git a/src/deh_tables.c b/src/deh_tables.c index ff2639a74..438ff2090 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5230,12 +5230,10 @@ struct int_const_s const INT_CONST[] = { {"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players {"FF_SPLAT",FF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible) - // FOF special flags - {"FS_PUSHABLES",FS_PUSHABLES}, - {"FS_EXECUTOR",FS_EXECUTOR}, - {"FS_ONLYBOTTOM",FS_ONLYBOTTOM}, - {"FS_BUSTMASK",FS_BUSTMASK}, - {"FS_DAMPEN",FS_DAMPEN}, + // FOF bustable flags + {"FB_PUSHABLES",FB_PUSHABLES}, + {"FB_EXECUTOR",FB_EXECUTOR}, + {"FB_ONLYBOTTOM",FB_ONLYBOTTOM}, // Bustable FOF type {"BT_TOUCH",BT_TOUCH}, diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 534ef9a07..b54924cdf 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -196,7 +196,7 @@ enum ffloor_e { ffloor_next, ffloor_prev, ffloor_alpha, - ffloor_specialflags, + ffloor_bustflags, ffloor_busttype, ffloor_busttag, ffloor_sinkspeed, @@ -220,7 +220,7 @@ static const char *const ffloor_opt[] = { "next", "prev", "alpha", - "specialflags", + "bustflags", "busttype", "busttag", "sinkspeed", @@ -1819,8 +1819,8 @@ static int ffloor_get(lua_State *L) case ffloor_alpha: lua_pushinteger(L, ffloor->alpha); return 1; - case ffloor_specialflags: - lua_pushinteger(L, ffloor->specialflags); + case ffloor_bustflags: + lua_pushinteger(L, ffloor->bustflags); return 1; case ffloor_busttype: lua_pushinteger(L, ffloor->busttype); diff --git a/src/p_mobj.c b/src/p_mobj.c index 86c237f4a..268881811 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1688,7 +1688,7 @@ static void P_PushableCheckBustables(mobj_t *mo) if (!(rover->flags & FF_BUSTUP)) continue; - if (!(rover->specialflags & FS_PUSHABLES)) + if (!(rover->bustflags & FB_PUSHABLES)) continue; if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) @@ -1698,7 +1698,7 @@ static void P_PushableCheckBustables(mobj_t *mo) bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); // Height checks - if (rover->specialflags & FS_ONLYBOTTOM) + if (rover->bustflags & FB_ONLYBOTTOM) { if (mo->z + mo->momz + mo->height < bottomheight) continue; @@ -1740,7 +1740,7 @@ static void P_PushableCheckBustables(mobj_t *mo) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->specialflags & FS_EXECUTOR) + if (rover->bustflags & FB_EXECUTOR) P_LinedefExecute(rover->busttag, mo, node->m_sector); goto bustupdone; diff --git a/src/p_setup.c b/src/p_setup.c index 17d71a8bf..83a5fe26c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3084,8 +3084,6 @@ static void P_ConvertBinaryMap(void) case 76: //Make FOF bouncy lines[i].args[0] = tag; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; - if (lines[i].flags & ML_BOUNCY) - lines[i].args[2] = 1; break; case 100: //FOF: solid, opaque, shadowcasting case 101: //FOF: solid, opaque, non-shadowcasting diff --git a/src/p_spec.c b/src/p_spec.c index f1c3e10ad..508c340b0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6089,10 +6089,6 @@ static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline) rover->flags |= FF_BOUNCY; rover->spawnflags |= FF_BOUNCY; rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100; - if (paramline->args[2]) - rover->specialflags |= FS_DAMPEN; - else - rover->specialflags &= ~FS_DAMPEN; CheckForBouncySector = true; break; } @@ -6739,7 +6735,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 254: // Bustable block { UINT8 busttype = BT_REGULAR; - ffloorspecialflags_e bustflags = 0; + ffloorbustflags_e bustflags = 0; ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; @@ -6762,15 +6758,15 @@ void P_SpawnSpecials(boolean fromnetsave) //Flags if (lines[i].args[3] & TMFB_PUSHABLES) - bustflags |= FS_PUSHABLES; + bustflags |= FB_PUSHABLES; if (lines[i].args[3] & TMFB_EXECUTOR) - bustflags |= FS_EXECUTOR; + bustflags |= FB_EXECUTOR; if (lines[i].args[3] & TMFB_ONLYBOTTOM) - bustflags |= FS_ONLYBOTTOM; + bustflags |= FB_ONLYBOTTOM; if (lines[i].args[3] & TMFB_SPLAT) ffloorflags |= FF_SPLAT; - if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM) + if (busttype != BT_TOUCH || bustflags & FB_ONLYBOTTOM) ffloorflags |= FF_BLOCKPLAYER; TAG_ITER_SECTORS(lines[i].args[0], s) @@ -6778,8 +6774,8 @@ void P_SpawnSpecials(boolean fromnetsave) ffloor_t *fflr = P_AddFakeFloor(§ors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); if (!fflr) continue; + fflr->bustflags = bustflags; fflr->busttype = busttype; - fflr->specialflags = bustflags; fflr->busttag = lines[i].args[4]; } break; @@ -6839,12 +6835,12 @@ void P_SpawnSpecials(boolean fromnetsave) } if (lines[i].args[3] & TMFB_ONLYBOTTOM) - fflr->specialflags |= FS_ONLYBOTTOM; + fflr->bustflags |= FB_ONLYBOTTOM; if (lines[i].flags & ML_EFFECT4) - fflr->specialflags |= FS_PUSHABLES; + fflr->bustflags |= FB_PUSHABLES; if (lines[i].flags & ML_EFFECT5) { - fflr->specialflags |= FS_EXECUTOR; + fflr->bustflags |= FB_EXECUTOR; fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; } } @@ -7176,7 +7172,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 74: // Make FOF bustable { UINT8 busttype = BT_REGULAR; - ffloorspecialflags_e bustflags = 0; + ffloorbustflags_e bustflags = 0; if (!udmf) break; @@ -7198,11 +7194,11 @@ void P_SpawnSpecials(boolean fromnetsave) } if (lines[i].args[2] & TMFB_PUSHABLES) - bustflags |= FS_PUSHABLES; + bustflags |= FB_PUSHABLES; if (lines[i].args[2] & TMFB_EXECUTOR) - bustflags |= FS_EXECUTOR; + bustflags |= FB_EXECUTOR; if (lines[i].args[2] & TMFB_ONLYBOTTOM) - bustflags |= FS_ONLYBOTTOM; + bustflags |= FB_ONLYBOTTOM; TAG_ITER_LINES(lines[i].args[0], l) { @@ -7220,9 +7216,8 @@ void P_SpawnSpecials(boolean fromnetsave) rover->flags |= FF_BUSTUP; rover->spawnflags |= FF_BUSTUP; + rover->bustflags = bustflags; rover->busttype = busttype; - rover->specialflags &= ~FS_BUSTMASK; - rover->specialflags |= bustflags; rover->busttag = lines[i].args[3]; CheckForBustableBlocks = true; break; diff --git a/src/p_user.c b/src/p_user.c index 048f2f1f9..6466a5316 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2656,7 +2656,7 @@ static void P_CheckBustableBlocks(player_t *player) } // Height checks - if (rover->specialflags & FS_ONLYBOTTOM) + if (rover->bustflags & FB_ONLYBOTTOM) { if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) continue; @@ -2710,7 +2710,7 @@ static void P_CheckBustableBlocks(player_t *player) EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? - if (rover->specialflags & FS_EXECUTOR) + if (rover->bustflags & FB_EXECUTOR) P_LinedefExecute(rover->busttag, player->mo, node->m_sector); goto bustupdone; @@ -2766,10 +2766,6 @@ static void P_CheckBouncySectors(player_t *player) { rover->flags |= FF_BOUNCY; rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; - if (rover->master->flags & ML_BOUNCY) - rover->specialflags |= FS_DAMPEN; - else - rover->specialflags &= ~FS_DAMPEN; } if (!(rover->flags & FF_BOUNCY)) @@ -2789,17 +2785,9 @@ static void P_CheckBouncySectors(player_t *player) { player->mo->momx = -FixedMul(player->mo->momx,rover->bouncestrength); player->mo->momy = -FixedMul(player->mo->momy,rover->bouncestrength); - - if (player->pflags & PF_SPINNING) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); - player->pflags |= PF_THOKKED; - } } else { - fixed_t newmom; pslope_t *slope = (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) ? *rover->t_slope : *rover->b_slope; momentum.x = player->mo->momx; @@ -2809,53 +2797,29 @@ static void P_CheckBouncySectors(player_t *player) if (slope) P_ReverseQuantizeMomentumToSlope(&momentum, slope); - newmom = momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2; + momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2; - if (abs(newmom) < (rover->bouncestrength*2)) + if (abs(momentum.z) < (rover->bouncestrength*2)) goto bouncydone; - if (!(rover->specialflags & FS_DAMPEN)) - { - if (newmom > 0) - { - if (newmom < 8*FRACUNIT) - newmom = 8*FRACUNIT; - } - else if (newmom < 0) - { - if (newmom > -8*FRACUNIT) - newmom = -8*FRACUNIT; - } - } - - if (newmom > P_GetPlayerHeight(player)/2) - newmom = P_GetPlayerHeight(player)/2; - else if (newmom < -P_GetPlayerHeight(player)/2) - newmom = -P_GetPlayerHeight(player)/2; - - momentum.z = newmom*2; + if (momentum.z > FixedMul(24*FRACUNIT, player->mo->scale)) //half of the default player height + momentum.z = FixedMul(24*FRACUNIT, player->mo->scale); + else if (momentum.z < -FixedMul(24*FRACUNIT, player->mo->scale)) + momentum.z = -FixedMul(24*FRACUNIT, player->mo->scale); if (slope) P_QuantizeMomentumToSlope(&momentum, slope); player->mo->momx = momentum.x; player->mo->momy = momentum.y; - player->mo->momz = momentum.z/2; + player->mo->momz = momentum.z; if (player->pflags & PF_SPINNING) { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); player->pflags |= PF_THOKKED; } } - if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<mo->scale) && player->mo->momz) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= P_GetJumpFlags(player); - } - goto bouncydone; } } diff --git a/src/r_defs.h b/src/r_defs.h index cb21d5043..4cc7d2e96 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -154,12 +154,10 @@ typedef enum typedef enum { - FS_PUSHABLES = 0x1, // FF_BUSTABLE: Bustable by pushables - FS_EXECUTOR = 0x2, // FF_BUSTABLE: Trigger linedef executor - FS_ONLYBOTTOM = 0x4, // FF_BUSTABLE: Only bustable from below - FS_BUSTMASK = 0x7, - FS_DAMPEN = 0x8, // FF_BOUNCY: Dampen bounce -} ffloorspecialflags_e; + FB_PUSHABLES = 0x1, // Bustable by pushables + FB_EXECUTOR = 0x2, // Trigger linedef executor + FB_ONLYBOTTOM = 0x4, // Only bustable from below +} ffloorbustflags_e; typedef enum { @@ -201,10 +199,8 @@ typedef struct ffloor_s INT32 alpha; tic_t norender; // for culling - // Flags that are only relevant for special ffloor types - ffloorspecialflags_e specialflags; - // Only relevant for FF_BUSTUP + ffloorbustflags_e bustflags; UINT8 busttype; INT16 busttag;