From 279dfcafc41788b27bbba298d7aa0cea481b1ede Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 28 May 2025 22:10:25 +0300 Subject: [PATCH 01/24] Expose S_FindMusicCredit and musiccredit_t to lua --- src/lua_infolib.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ src/lua_libs.h | 6 +++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 3ff2d97ae..08e26a48b 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -16,6 +16,7 @@ #include "dehacked.h" #include "p_mobj.h" #include "p_local.h" +#include "s_sound.h" #include "z_zone.h" #include "lua_script.h" @@ -1072,6 +1073,72 @@ static int sfxinfo_num(lua_State *L) return 1; } +enum musicdef_e { + musicdef_name = 0, + musicdef_usage, + musicdef_source, + musicdef_filename, + musicdef_title, + musicdef_alttitle, + musicdef_authors, +}; + +const char *const musicdef_opt[] = { + "name", + "usage", + "source", + "filename", + "title", + "alttitle", + "authors", + NULL +}; + +static int musicdef_fields_ref = LUA_NOREF; + +static int lib_sFindMusicCredit(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + LUA_PushUserdata(L, S_FindMusicCredit(name), META_MUSICDEF); + return 1; +} + +static int musicdef_get(lua_State *L) +{ + musicdef_t *musicdef = *((musicdef_t **)luaL_checkudata(L, 1, META_MUSICDEF)); + enum musicdef_e field = Lua_optoption(L, 2, -1, musicdef_fields_ref); + + I_Assert(musicdef != NULL); + + switch (field) + { + case musicdef_name: + lua_pushstring(L, musicdef->name); + return 1; + case musicdef_usage: + lua_pushstring(L, musicdef->usage); + return 1; + case musicdef_source: + lua_pushstring(L, musicdef->source); + return 1; + case musicdef_filename: + lua_pushstring(L, musicdef->filename); + return 1; + case musicdef_title: + lua_pushstring(L, musicdef->title); + return 1; + case musicdef_alttitle: + lua_pushstring(L, musicdef->alttitle); + return 1; + case musicdef_authors: + lua_pushstring(L, musicdef->authors); + return 1; + default: + return luaL_error(L, LUA_QL("musicdef_t") " has no field named " LUA_QS, lua_tostring(L, 2)); + } + return 0; +} + ////////////////////////////// // // Now push all these functions into the Lua state! @@ -1126,6 +1193,15 @@ int LUA_InfoLib(lua_State *L) sfxinfo_fields_ref = Lua_CreateFieldTable(L, sfxinfo_opt); + luaL_newmetatable(L, META_MUSICDEF); + lua_pushcfunction(L, musicdef_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + musicdef_fields_ref = Lua_CreateFieldTable(L, musicdef_opt); + + lua_register(L, "S_FindMusicCredit", lib_sFindMusicCredit); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getSprname); diff --git a/src/lua_libs.h b/src/lua_libs.h index c226c4714..729cea68d 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -10,6 +10,9 @@ /// \file lua_libs.h /// \brief libraries for Lua scripting +#include "doomtype.h" +#include "blua/lua.h" + extern lua_State *gL; #define LREG_VALID "VALID_USERDATA" @@ -20,6 +23,7 @@ extern lua_State *gL; #define META_STATE "STATE_T*" #define META_MOBJINFO "MOBJINFO_T*" #define META_SFXINFO "SFXINFO_T*" +#define META_MUSICDEF "MUSICDEF_T*" #define META_MOBJ "MOBJ_T*" #define META_MAPTHING "MAPTHING_T*" @@ -68,4 +72,4 @@ int LUA_SkinLib(lua_State *L); int LUA_ThinkerLib(lua_State *L); int LUA_MapLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); -int LUA_HudLib(lua_State *L); \ No newline at end of file +int LUA_HudLib(lua_State *L); -- 2.54.0 From ff474d18ee6a6c67ae315b55eba3b0177474f008 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 28 May 2025 21:42:13 +0200 Subject: [PATCH 02/24] remove this prob wrong assumption, our netcode sucks massive ass --- src/d_clisrv.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 98b4b1e55..712cf8dc8 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1687,13 +1687,7 @@ static void SV_SendPlayerInfo(INT32 node) for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++) { - if (i >= MAXPLAYERS) - { - netbuffer->u.playerinfo[i].node = 255; - continue; - } - - if (playernode[i] == UINT8_MAX || !playeringame[i]) + if ((i >= MAXPLAYERS) || !playeringame[i]) { netbuffer->u.playerinfo[i].node = 255; // This slot is empty. continue; -- 2.54.0 From a6898bd1cd8c091e356d22dd8fec91559c35f991 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 28 May 2025 22:11:46 +0200 Subject: [PATCH 03/24] this memset is incorrect and does nothing --- src/d_clisrv.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 712cf8dc8..4e5a1cd9a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1068,6 +1068,7 @@ static void SV_RequireResynch(INT32 node) // Initial setup memset(resynch_sent[node], 0, MAXPLAYERS); + for (i = 0; i < MAXPLAYERS; ++i) { if (!playeringame[i]) // Player not in game so just drop it from required synch @@ -1772,8 +1773,6 @@ static boolean SV_SendServerConfig(INT32 node) memset(netbuffer->u.servercfg.playerskins, 0xFF, sizeof(netbuffer->u.servercfg.playerskins)); memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor)); - memset(netbuffer->u.servercfg.adminplayers, -1, sizeof(netbuffer->u.servercfg.adminplayers)); - for (i = 0; i < MAXPLAYERS; i++) { netbuffer->u.servercfg.adminplayers[i] = (SINT8)adminplayers[i]; @@ -3269,7 +3268,7 @@ void CL_ClearPlayer(INT32 playernum) P_RemoveMobj(players[playernum].mo); } - memset(&players[playernum], 0, sizeof (player_t)); + memset(&players[playernum], 0, sizeof(player_t)); } // @@ -4278,14 +4277,14 @@ void SV_ResetServer(void) sprintf(player_names[i], "Player %d", i + 1); } - memset(player_name_changes, 0, sizeof player_name_changes); + memset(player_name_changes, 0, sizeof(player_name_changes)); - memset(playeringame, false, sizeof playeringame); - memset(playernode, UINT8_MAX, sizeof playernode); + memset(playeringame, false, sizeof(playeringame)); + memset(playernode, UINT8_MAX, sizeof(playernode)); pingmeasurecount = 1; - memset(realpingtable, 0, sizeof realpingtable); - memset(playerpingtable, 0, sizeof playerpingtable); + memset(realpingtable, 0, sizeof(realpingtable)); + memset(playerpingtable, 0, sizeof(playerpingtable)); ClearAdminPlayers(); -- 2.54.0 From 359befd85722f341e44822ad434e75741d09d541 Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 28 May 2025 23:27:30 +0300 Subject: [PATCH 04/24] Add MusicCredit lua hook --- src/lua_hook.h | 2 ++ src/lua_hooklib.c | 12 ++++++++++++ src/s_sound.c | 3 ++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 45237aa80..c31a58a67 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -55,6 +55,7 @@ X (PlayerQuit),\ X (PlayerThink),/* P_PlayerThink */\ X (MusicChange),\ + X (MusicCredit),\ X (ShouldSpin),/*SRB2KART*/\ X (ShouldExplode),/*SRB2KART*/\ X (ShouldSquish),/*SRB2KART*/\ @@ -130,6 +131,7 @@ int LUA_HookPlayerCanDamage(player_t *, mobj_t *); void LUA_HookPlayerQuit(player_t *, int); int LUA_HookPlayerCmd(player_t *, ticcmd_t *); int LUA_HookMusicChange(const char *oldname, struct MusicChange *); +int LUA_HookMusicCredit(musicdef_t *musicdef); int LUA_HookShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be spun out? int LUA_HookShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be exploded? diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index a0f795985..1ef02b886 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1065,6 +1065,18 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) return hook.status; } +int LUA_HookMusicCredit(musicdef_t *musicdef) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, HOOK(MusicCredit))) + { + LUA_PushUserdata(gL, musicdef, META_MUSICDEF); + call_hooks(&hook, 1, res_true); + } + + return hook.status; +} + static int kartdamage_hook ( player_t *player, diff --git a/src/s_sound.c b/src/s_sound.c index 922d864d5..ab9a1a2d7 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -32,6 +32,7 @@ #include "m_menu.h" // bird music stuff #include "lua_hook.h" // MusicChange hook +#include "lua_hud.h" // LUA_HudEnabled(hud_musiccredit) static boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo); static void SetChannelsNum(void); @@ -1452,7 +1453,7 @@ void S_ShowSpecifiedMusicCredit(const char *musname) def = S_FindMusicCredit(musname); - if (def) + if (def && !LUA_HookMusicCredit(def)) { cursongcredit.def = def; cursongcredit.anim = 5*TICRATE; -- 2.54.0 From fb9c459269aff534af9ef239bf62a19bb7af7c71 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 11:47:37 +0200 Subject: [PATCH 05/24] readd cubeapply check here --- src/v_video.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/v_video.c b/src/v_video.c index 0f3306696..7df5cacea 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -457,6 +457,9 @@ static void LoadPalette(const char *lumpname) #endif pLocalPalette[i].s.alpha = 0xFF; + if (!Cubeapply) + continue; + // lerp of colour cubing! if you want, make it smoother yourself V_CubeApply(&pLocalPalette[i].s.red, &pLocalPalette[i].s.green, &pLocalPalette[i].s.blue); } -- 2.54.0 From 5e532a76cfba090a8150d72c7ec0cb018cde4c39 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 11:49:43 +0200 Subject: [PATCH 06/24] reset the palette earlier during levelload generally make this behave like srb2/rr again --- src/p_setup.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index fe3a0d7fc..57894c074 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2807,6 +2807,10 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) CON_Drawer(); // let the user know what we are going to do I_FinishUpdate(); // page flip or blit buffer + // Reset the palette + if (rendermode != render_none) + V_SetPaletteLump("PLAYPAL"); + // Initialize sector node list. P_Initsecnode(); @@ -2878,10 +2882,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) // Reset the palette now all fades have been done if (rendermode != render_none) - { - //V_ResetPaletteCVars(); // dont carry over changed palettes - V_SetPaletteLump(GetPalette()); // Set the level palette - } + V_ReloadPalette(); // Set the level palette // Print "SPEEDING OFF TO [ZONE] [ACT 1]..." /*if (rendermode != render_none) -- 2.54.0 From e88093d9cf2a129a26ae05049a79c32294c84fb1 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 11:50:08 +0200 Subject: [PATCH 07/24] no need for an else here --- src/p_setup.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 57894c074..47327e3ca 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2872,12 +2872,9 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) F_WipeStartScreen(); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); F_WipeEndScreen(); - F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); - } - else //dedicated servers - { - F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); } + + F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); } // Reset the palette now all fades have been done -- 2.54.0 From a364068abbbe8f10316dc80f0c6cf6171e166363 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 13:26:52 +0200 Subject: [PATCH 08/24] add a bunch of checks for if G_BuildMapTitle returns NULL --- src/command.c | 1 - src/d_netcmd.c | 9 +++++++-- src/discord.c | 14 ++++++++++---- src/g_game.c | 11 +++++++---- src/m_menu.c | 52 +++++++++++++++++++++++++++++++++----------------- src/s_sound.c | 9 ++++++--- 6 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/command.c b/src/command.c index e7dd9cc01..4e43e2cb5 100644 --- a/src/command.c +++ b/src/command.c @@ -240,7 +240,6 @@ void COM_ImmedExecute(const char *ptext) while (i < strlen(ptext)) { - quotes = 0; for (j = 0; i < strlen(ptext); i++,j++) { diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 862ebb679..1970b5323 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2774,7 +2774,7 @@ static void Command_Map_f(void) // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer else { - if (!mapheaderinfo[newmapnum-1] || mapheaderinfo[newmapnum-1] == NULL) + if (!mapheaderinfo[newmapnum-1]) { CONS_Alert(CONS_WARNING, M_GetText("Invalid mapheaderinfo for Course %s (%s)\n"), realmapname, G_BuildMapName(newmapnum)); Z_Free(realmapname); @@ -3028,9 +3028,14 @@ static void Command_ReplayMarker(void) adjustedleveltime = 0; char *title = G_BuildMapTitle(gamemap); - snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername); + if (title) + { + snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername); Z_Free(title); + } + else + snprintf(demo.titlename, 64, "[%i:%02d/%.5s]", G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername); CONS_Printf("Replay will be saved!\n"); } diff --git a/src/discord.c b/src/discord.c index cd7dafa8f..207a249a6 100644 --- a/src/discord.c +++ b/src/discord.c @@ -388,7 +388,7 @@ static void DRPC_GotServerIP(UINT32 address) --------------------------------------------------*/ static const char *DRPC_GetServerIP(void) { - const char *address; + const char *address; // If you're connected if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL) @@ -489,7 +489,7 @@ void DRPC_UpdatePresence(void) { #endif discordPresence.state = "Private"; -#ifdef MASTERSERVER +#ifdef MASTERSERVER } #endif @@ -571,9 +571,15 @@ void DRPC_UpdatePresence(void) { // Map name on tool tip char *title = G_BuildMapTitle(gamemap); - snprintf(mapname, 48, "Map: %s", title); + if (title) + { + snprintf(mapname, 48, "Map: %s", title); + Z_Free(title); + } + else + snprintf(mapname, 48, "Map: UNKNOWN"); + discordPresence.largeImageText = mapname; - Z_Free(title); } if (gamestate == GS_LEVEL && Playing()) diff --git a/src/g_game.c b/src/g_game.c index 200ce7834..dd3823f8a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3998,7 +3998,6 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool } } - char *G_BuildMapTitle(INT32 mapnum) { char *title = NULL; @@ -6068,15 +6067,19 @@ void G_BeginRecording(void) char *title = G_BuildMapTitle(gamemap); // Print to a separate temp buffer instead of demo.titlename, so we can use it in M_TextInputSetString - snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername); + if (title) + { + snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername); + Z_Free(title); + } + else + snprintf(demotitlename, 64, "%s", modeattacking ? "Time Attack" : connectedservername); // Init just in case it isn't initialized already M_TextInputInit(&demo.titlenameinput, demo.titlename, sizeof(demo.titlename)); // This will indirectly assign to demo.titlename too M_TextInputSetString(&demo.titlenameinput, demotitlename); - - Z_Free(title); } // demo checksum diff --git a/src/m_menu.c b/src/m_menu.c index 2fb38a4d5..65dab3e6a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7167,8 +7167,11 @@ static void DrawReplayHutReplayInfo(void) if (mapheaderinfo[demolist[dir_on[menudepthleft]].map-1]) { char *title = G_BuildMapTitle(demolist[dir_on[menudepthleft]].map); - V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title); - Z_Free(title); + if (title) + { + V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title); + Z_Free(title); + } } else V_DrawString(x, y, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded."); @@ -8120,6 +8123,9 @@ UINT8 skyRoomMenuTranslations[MAXUNLOCKABLES]; static char *M_GetConditionString(condition_t cond) { + char *title = NULL; + char *response = NULL; + switch(cond.type) { case UC_PLAYTIME: @@ -8146,33 +8152,45 @@ static char *M_GetConditionString(condition_t cond) G_TicsToSeconds(cond.requirement)); case UC_MAPVISITED: { - char *title = G_BuildMapTitle(cond.requirement-1); - char *response = va("Visit %s", title); - Z_Free(title); + title = G_BuildMapTitle(cond.requirement-1); + if (title) + { + response = va("Visit %s", title); + Z_Free(title); + } return response; } case UC_MAPBEATEN: { - char *title = G_BuildMapTitle(cond.requirement-1); - char *response = va("Beat %s", title); - Z_Free(title); + title = G_BuildMapTitle(cond.requirement-1); + if (title) + { + response = va("Beat %s", title); + Z_Free(title); + } return response; } case UC_MAPALLEMERALDS: { - char *title = G_BuildMapTitle(cond.requirement-1); - char *response = va("Beat %s w/ all emeralds", title); - Z_Free(title); + title = G_BuildMapTitle(cond.requirement-1); + if (title) + { + response = va("Beat %s w/ all emeralds", title); + Z_Free(title); + } return response; } case UC_MAPTIME: { - char *title = G_BuildMapTitle(cond.extrainfo1-1); - char *response = va("Beat %s in %i:%02i.%02i", title, - G_TicsToMinutes(cond.requirement, true), - G_TicsToSeconds(cond.requirement), - G_TicsToCentiseconds(cond.requirement)); - Z_Free(title); + title = G_BuildMapTitle(cond.extrainfo1-1); + if (title) + { + response = va("Beat %s in %i:%02i.%02i", title, + G_TicsToMinutes(cond.requirement, true), + G_TicsToSeconds(cond.requirement), + G_TicsToCentiseconds(cond.requirement)); + Z_Free(title); + } return response; } case UC_TOTALEMBLEMS: diff --git a/src/s_sound.c b/src/s_sound.c index 922d864d5..cf75df56a 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2042,9 +2042,12 @@ static boolean S_SkipIntroMusic(void) char *maptitle = G_BuildMapTitle(gamemap); // Zzz... - // check if menu music is playing, otherwise it may continue playing - if (!stricmp(music.name, "titles") || (maptitle && (!stricmp(maptitle, "Wandering Falls")))) // wandering balls changes its song when the race starts Zzz... - skip = false; + if (maptitle) + { + // check if menu music is playing, otherwise it may continue playing + if (!stricmp(music.name, "titles") || (maptitle && (!stricmp(maptitle, "Wandering Falls")))) // wandering balls changes its song when the race starts Zzz... + skip = false; + } Z_Free(maptitle); -- 2.54.0 From cf42c35b9fda511217a4dc72c58d8275cb6b5742 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 13:29:25 +0200 Subject: [PATCH 09/24] add mo checks to automap stuff --- src/am_map.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index f91273e8b..11b3796b0 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -197,7 +197,7 @@ static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) static fixed_t scale_ftom; -static player_t *plr; // the player represented by an arrow +static player_t *plr = NULL; // the player represented by an arrow static boolean followplayer = true; // specifies whether to follow the player around @@ -237,7 +237,7 @@ static inline void AM_restoreScaleAndLoc(void) m_x = old_m_x; m_y = old_m_y; } - else + else if (plr && plr->mo) { m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2; m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2; @@ -318,7 +318,8 @@ static void AM_initVariables(void) break; plr = &players[pnum]; - if (plr != NULL && plr->mo != NULL) + + if (plr && plr->mo) { m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2; m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2; @@ -597,6 +598,9 @@ static inline void AM_changeWindowScale(void) static inline void AM_doFollowPlayer(void) { + if (!plr || !plr->mo) + return; + if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) { m_x = FTOM(MTOF(plr->mo->x >> FRACTOMAPBITS)) - m_w/2; -- 2.54.0 From eca9c60d9b8a9122fe9078462e615b8f9b3ba4dc Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 17:58:00 +0200 Subject: [PATCH 10/24] call HWR_LoadMapTextures in paletterender toggle callback from srb2 pr --- src/hardware/hw_batching.c | 2 +- src/hardware/hw_main.c | 4 ++-- src/st_stuff.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index 3655beb8a..b8490f4ed 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -124,7 +124,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt polygonArray[polygonArraySize].numVerts = iNumPts; polygonArray[polygonArraySize].polyFlags = PolyFlags; polygonArray[polygonArraySize].texture = current_texture; - polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target; + polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target; polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; polygonArraySize++; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 0f308017d..51f3346dc 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5764,7 +5764,7 @@ static void HWR_TogglePaletteRendering(void) // If the r_opengl "texture palette" stays the same during this switch, these textures // will not be cleared out. However they are still out of date since the // composite texture blending method has changed. Therefore they need to be cleared. - GL_ClearMipMapCache(); + HWR_LoadMapTextures(numtextures); } } else @@ -5778,7 +5778,7 @@ static void HWR_TogglePaletteRendering(void) // If the r_opengl "texture palette" stays the same during this switch, these textures // will not be cleared out. However they are still out of date since the // composite texture blending method has changed. Therefore they need to be cleared. - GL_ClearMipMapCache(); + HWR_LoadMapTextures(numtextures); } } } diff --git a/src/st_stuff.c b/src/st_stuff.c index 04523f577..4f5401aae 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -187,7 +187,7 @@ void ST_doPaletteStuff(void) #ifdef HWRENDER if (rendermode == render_opengl && !HWR_PalRenderFlashpal()) - palette = 0; // No flashpals here in OpenGL + palette = 0; // Don't set the palette to a flashpal in OpenGL's truecolor mode #endif palette = min(max(palette, 0), 13); -- 2.54.0 From bf44a054a1a614d1756813fec90311d6e708897c Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 18:17:07 +0200 Subject: [PATCH 11/24] move HWR_GetTexturePalette calls to after early returns/where they are used --- src/hardware/hw_cache.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 85e50465a..36f6a57a5 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -46,12 +46,16 @@ RGBA_t *HWR_GetTexturePalette(void) static INT32 format2bpp(GLTextureFormat_t format) { - if (format == GL_TEXFMT_RGBA) - return 4; - else if (format == GL_TEXFMT_ALPHA_INTENSITY_88 || format == GL_TEXFMT_AP_88) - return 2; - else - return 1; + switch (format) + { + case GL_TEXFMT_RGBA: + return 4; + case GL_TEXFMT_ALPHA_INTENSITY_88: + case GL_TEXFMT_AP_88: + return 2; + default: + return 1; + } } // This code was originally placed directly in HWR_DrawPatchInCache. @@ -221,8 +225,6 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, if (texture->width <= 0 || texture->height <= 0) return; - palette = HWR_GetTexturePalette(); - x1 = patch->originx; width = SHORT(realpatch->width); height = SHORT(realpatch->height); @@ -234,6 +236,8 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, if (patch->originy > texture->height || (patch->originy + height) < 0) return; // patch not located within texture's y bounds, ignore + palette = HWR_GetTexturePalette(); + // patch is actually inside the texture! // now check if texture is partly off-screen and adjust accordingly @@ -323,7 +327,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe boolean skyspecial = false; // poor hack for Legacy large skies.. RGBA_t *palette; - palette = HWR_GetTexturePalette(); texture = textures[texnum]; @@ -361,6 +364,8 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe INT32 j; RGBA_t col; + palette = HWR_GetTexturePalette(); + col = palette[HWR_CHROMAKEY_EQUIVALENTCOLORINDEX]; for (idx = 0, j = 0; j < blockheight; j++) -- 2.54.0 From fe682a80712a4bc9a4d78a46539f5d1af0682caa Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 18:57:36 +0200 Subject: [PATCH 12/24] only make screentexture for postprocess if we need to gives quite a neat perfboost on the gpu side --- src/hardware/hw_main.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 51f3346dc..af8a6e160 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -340,7 +340,6 @@ static void HWR_SetShaderState(void) GL_SetSpecialState(HWD_SET_SHADERS, HWR_UseShader() ? 1 : 0); } - static boolean HWR_IsWireframeMode(void) { return (cv_glwireframe.value /*&& cv_debug*/); @@ -4235,7 +4234,6 @@ static void *HWR_CreateDrawNode(gl_drawnode_type_t type) Z_Realloc(drawnodes, alloceddrawnodes * sizeof(gl_drawnode_t), PU_LEVEL, &drawnodes); } - drawnode = &drawnodes[numdrawnodes++]; drawnode->type = type; @@ -5889,7 +5887,6 @@ static void COM_HWR_glinfo(void) CONS_Printf("Unrecognized argument: %s\n", argv); return; } - } CONS_Printf("\x88OpenGL %s\x80\n", gl_version); @@ -5983,7 +5980,7 @@ static void HWR_DoPostProcessor(player_t *player) // Armageddon Blast Flash! // Could this even be considered postprocessor? - if (!HWR_PalRenderFlashpal() && player->flashcount) + if (player->flashcount && !HWR_PalRenderFlashpal()) { FOutVector v[4]; FSurfaceInfo Surf; @@ -6009,19 +6006,19 @@ static void HWR_DoPostProcessor(player_t *player) if (cv_glscreentextures.value != 2) // screen textures are needed for the rest of the effects return; - // Capture the screen for intermission and screen waving - if (gamestate != GS_INTERMISSION) - GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); - - if (splitscreen) // Not supported in splitscreen - someone want to add support? - return; - - //UINT8 viewnum = R_GetViewNumber(); // see above + //UINT8 viewnum = R_GetViewNumber(); // see below //camera_t *thiscam = &camera[viewnum]; camera_t *thiscam = &camera[0]; + // Not supported in splitscreen - someone want to add support? + const boolean screenwave = (!splitscreen && (thiscam->postimg & POSTIMG_WATER || thiscam->postimg & POSTIMG_HEAT)); + + // Capture the screen for intermission and screen waving + if ((lastdraw || screenwave) && gamestate != GS_INTERMISSION) + GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); + // Drunken vision! WooOOooo~ - if (thiscam->postimg & POSTIMG_WATER || thiscam->postimg & POSTIMG_HEAT) + if (screenwave) { // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; @@ -6055,6 +6052,7 @@ static void HWR_DoPostProcessor(player_t *player) v[x][y][1] = (y/((float)(SCREENVERTS-1.0f)/9.0f))-4.5f; } } + GL_PostImgRedraw(v); // Capture the screen again for screen waving on the intermission -- 2.54.0 From 57b2316c42074ce02eccfa2c71e06303fd98adfb Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 29 May 2025 18:59:27 +0200 Subject: [PATCH 13/24] didnt mean to change this lel --- src/hardware/hw_main.c | 2 +- src/hardware/hw_main.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index af8a6e160..e25364bee 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5980,7 +5980,7 @@ static void HWR_DoPostProcessor(player_t *player) // Armageddon Blast Flash! // Could this even be considered postprocessor? - if (player->flashcount && !HWR_PalRenderFlashpal()) + if (!HWR_PalRenderFlashpal() && player->flashcount) { FOutVector v[4]; FSurfaceInfo Surf; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 87b1faaf4..6dc0d23a6 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -225,7 +225,7 @@ FUNCINLINE static ATTRINLINE boolean HWR_ShouldUsePaletteRendering(void) FUNCINLINE static ATTRINLINE boolean HWR_PalRenderFlashpal(void) { - return (HWR_ShouldUsePaletteRendering() && cv_glflashpal.value); + return (cv_glflashpal.value && HWR_ShouldUsePaletteRendering()); } #endif -- 2.54.0 From 201c725dc7d2f90e8b636304767410df3f4043da Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 30 May 2025 02:19:13 +0200 Subject: [PATCH 14/24] cleanup d_main a little --- src/d_main.c | 247 ++++++++++++++++++++++++++------------------------- 1 file changed, 125 insertions(+), 122 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 728a1a760..d10ba05ab 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -197,12 +197,10 @@ static void D_PadMenuScrollInput(UINT8 input) // and pass it to the eventlist static void D_GamePadMenuScrollTicker(void) { + UINT8 i; static UINT8 menuInputDelayTimer = 0; - if (dedicated) - return; - - for (UINT8 i = 0; i < 4; i++) + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { if (dpadscrollstate[i]) { @@ -222,10 +220,10 @@ static void D_GamePadMenuScrollTicker(void) static void D_DeviceLEDTick(void) { UINT8 i; - static UINT16 color[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; - static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; + static UINT16 color[MAXSPLITSCREENPLAYERS] = {0}; + static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0}; - if (dedicated || numcontrollers == 0) + if (numcontrollers == 0) { return; } @@ -252,7 +250,6 @@ static void D_DeviceLEDTick(void) void D_ProcessEvents(void) { event_t *ev; - boolean eaten; for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) @@ -291,8 +288,10 @@ void D_ProcessEvents(void) // Demo input: if (demo.playback) + { if (M_DemoResponder(ev)) continue; // demo ate the event + } // console input #ifdef HAVE_THREADS @@ -317,6 +316,88 @@ void D_ProcessEvents(void) // draw current display, possibly wiping it from the previous // +static void D_Renderview(void) +{ + UINT8 i; + + if (automapactive) + return; + + R_ApplyLevelInterpolators(rendertimefrac); + + for (i = 0; i <= splitscreen; i++) + { + const boolean issplitscreen = (i > 0); + + if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD) + { + viewssnum = i; + + if (!issplitscreen) // Initialize for P1 + { + viewwindowy = viewwindowx = 0; + topleft = screens[0]; + objectsdrawn = 0; + } + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + HWR_RenderPlayerView(); + R_RestoreLevelInterpolators(); + return; + } +#endif + if (issplitscreen) // Splitscreen-specific + { + const INT32 len = viewheight*sizeof(ylookup[0]); + + switch (i) + { + case 1: + if (splitscreen > 1) + { + viewwindowx = viewwidth; + viewwindowy = 0; + } + else + { + viewwindowx = 0; + viewwindowy = viewheight; + } + M_Memcpy(ylookup, ylookup2, len); + break; + case 2: + viewwindowx = 0; + viewwindowy = viewheight; + M_Memcpy(ylookup, ylookup3, len); + break; + case 3: + viewwindowx = viewwidth; + viewwindowy = viewheight; + M_Memcpy(ylookup, ylookup4, len); + default: + break; + } + + topleft = screens[0] + viewwindowy*vid.width + viewwindowx; + } + + R_RenderPlayerView(&players[displayplayers[i]]); + + if (issplitscreen) + M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); + } + + if (!issplitscreen) + R_ApplyViewMorph(); + + V_DoPostProcessor(i, postimgparam[i]); + } + + R_RestoreLevelInterpolators(); +} + // wipegamestate can be set to -1 to force a wipe on the next draw // added comment : there is a wipe eatch change of the gamestate gamestate_t wipegamestate = GS_LEVEL; @@ -327,7 +408,6 @@ static boolean D_Display(void) boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; - UINT8 i; if (!dedicated) { @@ -366,6 +446,7 @@ static boolean D_Display(void) { // set for all later wipedefindex = gamestate; // wipe_xxx_toblack + if (gamestate == GS_TITLESCREEN && wipegamestate != GS_INTRO) wipedefindex = wipe_timeattack_toblack; else if (gamestate == GS_INTERMISSION) @@ -378,26 +459,28 @@ static boolean D_Display(void) if (!dedicated) { - // Fade to black first - if (gamestate != GS_LEVEL // fades to black on its own timing, always - && wipedefs[wipedefindex] != UINT8_MAX) + if (gamestate != GS_LEVEL) { - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK); - ranwipe = true; - } + // Fade to black first + if (wipedefs[wipedefindex] != UINT8_MAX) // fades to black on its own timing, always + { + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK); + ranwipe = true; + } - if (gamestate != GS_LEVEL && rendermode != render_none) - { - V_SetPaletteLump("PLAYPAL"); // Reset the palette - R_ReInitColormaps(0, LUMPERROR); + if (rendermode != render_none) + { + V_SetPaletteLump("PLAYPAL"); // Reset the palette + R_ReInitColormaps(0, LUMPERROR); + } } F_WipeStartScreen(); } - else //dedicated servers + else // dedicated servers { F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK); ranwipe = true; @@ -405,7 +488,7 @@ static boolean D_Display(void) } } - if (dedicated) //bail out after wipe logic + if (dedicated) // bail out after wipe logic return false; // do buffered drawing @@ -430,9 +513,6 @@ static boolean D_Display(void) HU_Drawer(); break; - case GS_TIMEATTACK: - break; - case GS_INTRO: F_IntroDrawer(); if (wipegamestate == (gamestate_t)-1) @@ -484,6 +564,7 @@ static boolean D_Display(void) HU_Erase(); HU_Drawer(); } + case GS_TIMEATTACK: case GS_DEDICATEDSERVER: case GS_NULL: break; @@ -492,89 +573,10 @@ static boolean D_Display(void) if (gamestate == GS_LEVEL) { // draw the view directly - if (cv_renderview.value && !automapactive) + if (cv_renderview.value) { PS_START_TIMING(ps_rendercalltime); - - R_ApplyLevelInterpolators(rendertimefrac); - - for (i = 0; i <= splitscreen; i++) - { - if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD) - { - viewssnum = i; - - if (i == 0) // Initialize for P1 - { - viewwindowy = 0; - viewwindowx = 0; - - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; - objectsdrawn = 0; - } - -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_RenderPlayerView(); - else -#endif - if (rendermode != render_none) - { - if (i > 0) // Splitscreen-specific - { - switch (i) - { - case 1: - if (splitscreen > 1) - { - viewwindowx = viewwidth; - viewwindowy = 0; - } - else - { - viewwindowx = 0; - viewwindowy = viewheight; - } - M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0])); - break; - case 2: - viewwindowx = 0; - viewwindowy = viewheight; - M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0])); - break; - case 3: - viewwindowx = viewwidth; - viewwindowy = viewheight; - M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0])); - default: - break; - } - - - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; - } - - R_RenderPlayerView(&players[displayplayers[i]]); - - if (i > 0) - M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); - } - } - } - - if (rendermode == render_soft) - { - if (!splitscreen) - R_ApplyViewMorph(); - - for (i = 0; i <= splitscreen; i++) - { - V_DoPostProcessor(i, postimgparam[i]); - } - } - - R_RestoreLevelInterpolators(); - + D_Renderview(); PS_STOP_TIMING(ps_rendercalltime); } @@ -584,6 +586,7 @@ static boolean D_Display(void) { VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); } + lastdraw = false; } @@ -606,13 +609,8 @@ static boolean D_Display(void) // draw pause pic if (paused && cv_showhud.value && !demo.playback) { - INT32 py; - patch_t *patch; - if (automapactive) - py = 4; - else - py = viewwindowy + 4; - patch = W_CachePatchName("M_PAUSE", PU_PATCH); + INT32 py = (automapactive) ? 4 : (viewwindowy + 4); + patch_t *patch = W_CachePatchName("M_PAUSE", PU_PATCH); V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, V_SNAPTOTOP, patch); } @@ -754,7 +752,7 @@ void D_SRB2Loop(void) // Casting the return value of a function is bad practice (apparently) double budget = ((R_GetFramerateCap() == 0) ? 0.0 : round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision())); - capbudget = (precise_t) budget; + capbudget = (precise_t)budget; boolean ranwipe = false; @@ -824,12 +822,15 @@ void D_SRB2Loop(void) doDisplay = true; } - if (menuactive) + if (!dedicated) { - D_GamePadMenuScrollTicker(); - } + if (menuactive) + { + D_GamePadMenuScrollTicker(); + } - D_DeviceLEDTick(); + D_DeviceLEDTick(); + } } if (interp) @@ -841,7 +842,9 @@ void D_SRB2Loop(void) ps_interp_frac.value.p = (precise_t)((FIXED_TO_FLOAT(g_time.timefrac)) * 1000.0f); ps_interp_lag.value.p = (precise_t)((deltasecs) * 1000.0f); - if (!(paused || P_AutoPause()) && deltatics < 1.0 && !hu_stopped) + const boolean lagging = ((deltatics >= 1.0) || hu_stopped); + + if (!(paused || P_AutoPause()) && !lagging) { rendertimefrac = g_time.timefrac; } @@ -850,7 +853,7 @@ void D_SRB2Loop(void) rendertimefrac = FRACUNIT; } - if ((deltatics < 1.0) && !hu_stopped) + if (!lagging) { rendertimefrac_unpaused = g_time.timefrac; } -- 2.54.0 From 7d68c0598c89f66d2774c9b29d8a5bdb5300a209 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 30 May 2025 02:54:34 +0200 Subject: [PATCH 15/24] Fix underflow in consistancy checking code https://git.srb2.org/Hanicef/SRB2Classic/-/commit/9f5686ef48956cd64ef92f737e59cbbaa27d8cf9 --- src/d_clisrv.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4e5a1cd9a..0135c76cd 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5388,7 +5388,7 @@ static void HandlePacketFromPlayer(SINT8 node) // Check player consistancy during the level if (gamestate == GS_LEVEL - && (realstart > gametic - TICQUEUE+1 && realstart <= gametic) + && (realstart <= gametic && realstart + TICQUEUE - 1 > gametic) && consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy) && (!UseSaturnSynch(node) || (!resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() && !SV_ResendingSavegameToAnyone()))) { @@ -5418,10 +5418,13 @@ static void HandlePacketFromPlayer(SINT8 node) } if (cv_blamecfail.value) + { CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), netconsole+1, player_names[netconsole], consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy)); + } + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", netconsole, realstart, consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy))); @@ -5693,7 +5696,7 @@ static void HandlePacketFromPlayer(SINT8 node) break; } - //Update client ping table from the server. + // Update client ping table from the server. if (client) { UINT8 i; @@ -6503,7 +6506,6 @@ static inline void PingUpdate(void) if (pingtimeout[i] > 0) pingtimeout[i]--; } - } //kick lagging players... unless everyone but the server's ping sucks. -- 2.54.0 From 6617382f54298869c7a557bf2c7c69e04412543d Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 30 May 2025 23:59:08 +0200 Subject: [PATCH 16/24] Revert "reset the palette earlier during levelload" This reverts commit 5e532a76cfba090a8150d72c7ec0cb018cde4c39. --- src/p_setup.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 47327e3ca..0459a03f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2807,10 +2807,6 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) CON_Drawer(); // let the user know what we are going to do I_FinishUpdate(); // page flip or blit buffer - // Reset the palette - if (rendermode != render_none) - V_SetPaletteLump("PLAYPAL"); - // Initialize sector node list. P_Initsecnode(); @@ -2879,7 +2875,10 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) // Reset the palette now all fades have been done if (rendermode != render_none) - V_ReloadPalette(); // Set the level palette + { + //V_ResetPaletteCVars(); // dont carry over changed palettes + V_SetPaletteLump(GetPalette()); // Set the level palette + } // Print "SPEEDING OFF TO [ZONE] [ACT 1]..." /*if (rendermode != render_none) -- 2.54.0 From 55c6ba6d12fb4222e6baf15cbc85ea8d7dd2b6d2 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 31 May 2025 15:57:03 +0200 Subject: [PATCH 17/24] fix awayview join crash player->awayviewmobj may not exist yet in some cases --- src/r_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index f16d138ee..15f17db9d 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1063,7 +1063,7 @@ static void R_SetupCommonFrame(player_t * player, sector_t * sector) static void R_SetupAimingFrame(player_t *player, camera_t *thiscam) { - if (player->awayviewtics) + if (player->awayviewtics && player->awayviewmobj) { newview->aim = player->awayviewaiming; newview->angle = player->awayviewmobj->angle; @@ -1169,7 +1169,7 @@ void R_SkyboxFrame(int s) { mapheader_t *mh = mapheaderinfo[gamemap-1]; - if (player->awayviewtics) + if (player->awayviewtics && player->awayviewmobj) { SETUPSKYVIEW(player->awayviewmobj, (player->awayviewmobj->z + 20*FRACUNIT)); } @@ -1226,7 +1226,7 @@ void R_SetupFrame(int s, boolean skybox) R_SetupAimingFrame(player, thiscam); - if (player->awayviewtics) // cut-away view stuff + if (player->awayviewtics && player->awayviewmobj) // cut-away view stuff { viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN I_Assert(viewmobj != NULL); @@ -1235,7 +1235,7 @@ void R_SetupFrame(int s, boolean skybox) newview->y = viewmobj->y; newview->z = viewmobj->z + 20*FRACUNIT; - if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector) + if (viewmobj->subsector && viewmobj->subsector->sector) sector = viewmobj->subsector->sector; R_SetupCommonFrame(player, sector); @@ -1253,7 +1253,7 @@ void R_SetupFrame(int s, boolean skybox) R_SetupCommonFrame(player, sector); } - else // use the player's eyes view + else if (player->mo) // use the player's eyes view { viewmobj = player->mo; I_Assert(viewmobj != NULL); @@ -1262,7 +1262,7 @@ void R_SetupFrame(int s, boolean skybox) newview->y = viewmobj->y; newview->z = player->viewz; - if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector) + if (viewmobj->subsector && viewmobj->subsector->sector) sector = viewmobj->subsector->sector; R_SetupCommonFrame(player, sector); -- 2.54.0 From 5c53a90eea949af6f5316b260e78d1e297e0d494 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 31 May 2025 16:20:58 +0200 Subject: [PATCH 18/24] hack: reset musiccredits when changing gamestate otherwise they may persist if theyve been currently displayed --- src/g_game.c | 5 +++++ src/s_sound.c | 5 +++++ src/s_sound.h | 1 + 3 files changed, 11 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index dd3823f8a..31eed2fd4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -8234,6 +8234,11 @@ boolean G_DemoTitleResponder(event_t *ev) void G_SetGamestate(gamestate_t newstate) { gamestate = newstate; + + //HACK: reset musiccredits whenever we change gamestate + // since we allow them to run everywhere now + S_ResetMusicCredit(); + #ifdef HAVE_DISCORDRPC DRPC_UpdatePresence(); #endif diff --git a/src/s_sound.c b/src/s_sound.c index cf75df56a..2f79e0540 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1436,6 +1436,11 @@ musicdef_t *S_FindMusicCredit(const char *musname) return NULL; } +void S_ResetMusicCredit(void) +{ + memset(&cursongcredit, 0, sizeof(cursongcredit)); +} + // // S_ShowSpecifiedMusicCredit // diff --git a/src/s_sound.h b/src/s_sound.h index 92e206e1b..eec99d802 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -206,6 +206,7 @@ void S_InitMTDefs(void); musicdef_t *S_FindMusicCredit(const char *musname); void S_ShowSpecifiedMusicCredit(const char *musname); void S_ShowMusicCredit(void); +void S_ResetMusicCredit(void); boolean S_PrepareSoundTest(void); -- 2.54.0 From 68ae8809791b1012e88724dc1ca3d8629ced02c0 Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 31 May 2025 18:04:08 +0300 Subject: [PATCH 19/24] Change the way how musicdefs are stored (preparing for exposing them to lua) --- src/m_menu.c | 38 ++++++++++---------- src/s_sound.c | 98 +++++++++++++++++++++++++++++---------------------- src/s_sound.h | 11 ++---- 3 files changed, 77 insertions(+), 70 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 2fb38a4d5..9e9fbe1c9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8458,7 +8458,7 @@ static void M_MusicTest(INT32 choice) { (void)choice; - if (!S_PrepareSoundTest()) + if (!nummusicdefs) { M_StartMessage(M_GetText("No selectable tracks found.\n"),NULL,MM_NOTHING); return; @@ -8537,33 +8537,33 @@ static void M_DrawMusicTest(void) { INT32 t, b, q, m = 128; - if (numsoundtestdefs <= 8) + if (nummusicdefs <= 8) { t = 0; - b = numsoundtestdefs - 1; + b = nummusicdefs - 1; i = 0; } else { q = m; - m = (5*m)/numsoundtestdefs; + m = (5*m)/nummusicdefs; if (st_sel < 3) { t = 0; b = 7; i = 0; } - else if (st_sel >= numsoundtestdefs-4) + else if (st_sel >= nummusicdefs-4) { - t = numsoundtestdefs - 8; - b = numsoundtestdefs - 1; + t = nummusicdefs - 8; + b = nummusicdefs - 1; i = q-m; } else { t = st_sel - 3; b = st_sel + 4; - i = (t * (q-m))/(numsoundtestdefs - 8); + i = (t * (q-m))/(nummusicdefs - 8); } } @@ -8572,7 +8572,7 @@ static void M_DrawMusicTest(void) if (t != 0) V_DrawString(20+280+4, 60+4 - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); - if (b != numsoundtestdefs - 1) + if (b != nummusicdefs - 1) V_DrawString(20+280+4, 60+128-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); x = 24; @@ -8586,8 +8586,9 @@ static void M_DrawMusicTest(void) V_DrawFill(20, y-4, 280-1, 16, 237); { + const musicdef_t *def = S_GetMusicCredit(t); const size_t MAXLENGTH = 34; - const char *songname = soundtestdefs[t]->title[0] ? soundtestdefs[t]->title : soundtestdefs[t]->source; + const char *songname = def->title[0] ? def->title : def->source; size_t namelength = strlen(songname); @@ -8600,7 +8601,7 @@ static void M_DrawMusicTest(void) buf[MAXLENGTH] = 0; V_DrawString(x, y, (t == st_sel ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE|V_MONOSPACE, buf); - if (curplaying == soundtestdefs[t]) + if (curplaying == def) { V_DrawFill(20+280-9, y-4, 8, 16, 230); } @@ -8618,7 +8619,7 @@ static void M_HandleMusicTest(INT32 choice) switch (choice) { case KEY_DOWNARROW: - if (st_sel++ >= numsoundtestdefs-1) + if (st_sel++ >= nummusicdefs-1) st_sel = 0; { S_StartSound(NULL, sfx_menu1); @@ -8627,18 +8628,18 @@ static void M_HandleMusicTest(INT32 choice) break; case KEY_UPARROW: if (!st_sel--) - st_sel = numsoundtestdefs-1; + st_sel = nummusicdefs-1; { S_StartSound(NULL, sfx_menu1); } st_musictime = 0; break; case KEY_PGDN: - if (st_sel < numsoundtestdefs-1) + if (st_sel < nummusicdefs-1) { st_sel += 3; - if (st_sel >= numsoundtestdefs-1) - st_sel = numsoundtestdefs-1; + if (st_sel >= nummusicdefs-1) + st_sel = nummusicdefs-1; S_StartSound(NULL, sfx_menu1); } st_musictime = 0; @@ -8672,7 +8673,7 @@ static void M_HandleMusicTest(INT32 choice) case KEY_ENTER: S_StopSounds(); S_StopMusic(); - curplaying = soundtestdefs[st_sel]; + curplaying = S_GetMusicCredit(st_sel); S_ChangeMusicInternal(curplaying->name, true); break; @@ -8681,9 +8682,6 @@ static void M_HandleMusicTest(INT32 choice) } if (exitmenu) { - Z_Free(soundtestdefs); - soundtestdefs = NULL; - if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); else diff --git a/src/s_sound.c b/src/s_sound.c index ab9a1a2d7..e4f15333f 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1203,8 +1203,58 @@ static consvar_t *music_refade_cv; /// Music Definitions /// ------------------------ -musicdef_t *musicdefstart = NULL; // First music definition -struct cursongcredit cursongcredit; // Currently displayed song credit info +// Similar system to vissprite allocation. Exists so external pointers to musicdefs are not invalidated +// when allocating more space for musicdefs +#define MUSICDEFCHUNKBITS 6 +#define MUSICDEFSPERCHUNK (1 << MUSICDEFCHUNKBITS) +#define MUSICDEFINDEXMASK (MUSICDEFSPERCHUNK - 1) +static musicdef_t **musicdefs = NULL; +static INT32 numchunks = 0; +INT32 nummusicdefs = 0; + +// +// S_GetMusicCredit +// +// Return music credit with given index. +// +musicdef_t *S_GetMusicCredit(INT32 i) +{ + if (i < 0 || i >= nummusicdefs) + return NULL; + + INT32 chunk = i >> MUSICDEFCHUNKBITS; + i &= MUSICDEFINDEXMASK; + + return &musicdefs[chunk][i]; +} + +// +// S_AddMusicCredit +// +// Return new music credit, allocates memory for it if needed. +// +static musicdef_t *S_AddMusicCredit(void) +{ + INT32 chunk = nummusicdefs >> MUSICDEFCHUNKBITS; + INT32 i = nummusicdefs & MUSICDEFINDEXMASK; + + // Allocate new chunk if needed. Other chunks stay valid + if (chunk == numchunks) + { + ++numchunks; + musicdefs = (musicdef_t**)Z_Realloc(musicdefs, sizeof(musicdef_t*)*numchunks, PU_STATIC, NULL); + musicdefs[chunk] = Z_Calloc(sizeof(musicdef_t)*MUSICDEFSPERCHUNK, PU_STATIC, NULL); + } + + // Store "id" of new musicdef (mostly exists only for lua) + musicdefs[chunk][i].num = nummusicdefs; + + ++nummusicdefs; + + return &musicdefs[chunk][i]; +} + +struct cursongcredit cursongcredit = {0}; // Currently displayed song credit info static boolean ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) @@ -1232,14 +1282,11 @@ ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) // Nothing found, add to the end. if (!def) { - def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); + def = S_AddMusicCredit(); STRBUFCPY(def->name, value); strlwr(def->name); def->hash = quickncasehash (def->name, 6); - - def->next = musicdefstart; - musicdefstart = def; } (*defp) = def; @@ -1424,8 +1471,10 @@ musicdef_t *S_FindMusicCredit(const char *musname) UINT32 hash = quickncasehash (musname, 6); musicdef_t *def; - for (def = musicdefstart; def; def = def->next) + for (INT32 i = 0; i < nummusicdefs; ++i) { + def = S_GetMusicCredit(i); + if (hash != def->hash) continue; if (stricmp(def->name, musname)) @@ -1472,41 +1521,6 @@ void S_ShowMusicCredit(void) S_ShowSpecifiedMusicCredit(music.name); } -musicdef_t **soundtestdefs = NULL; -INT32 numsoundtestdefs = 0; - -// -// S_PrepareSoundTest -// -// Prepare sound test. What am I, your butler? -// -boolean S_PrepareSoundTest(void) -{ - musicdef_t *def; - INT32 pos = numsoundtestdefs = 0; - - for (def = musicdefstart; def; def = def->next) - { - numsoundtestdefs++; - } - - if (!numsoundtestdefs) - return false; - - if (soundtestdefs) - Z_Free(soundtestdefs); - - if (!(soundtestdefs = Z_Malloc(numsoundtestdefs*sizeof(musicdef_t *), PU_STATIC, NULL))) - I_Error("S_PrepareSoundTest(): could not allocate soundtestdefs."); - - for (def = musicdefstart; def /*&& i < numsoundtestdefs*/; def = def->next) - { - soundtestdefs[pos++] = def; - } - - return true; -} - /// ------------------------ /// Music Status /// ------------------------ diff --git a/src/s_sound.h b/src/s_sound.h index 92e206e1b..d909bf63d 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -182,14 +182,9 @@ typedef struct musicdef_s char alttitle[256]; char authors[256]; boolean use_info; - struct musicdef_s *next; + size_t num; } musicdef_t; -extern musicdef_t *musicdefstart; -extern musicdef_t **soundtestdefs; -extern INT32 numsoundtestdefs; -extern UINT8 soundtestpage; - extern struct cursongcredit { musicdef_t *def; @@ -198,17 +193,17 @@ extern struct cursongcredit UINT8 trans; } cursongcredit; +extern INT32 nummusicdefs; void S_LoadMusicDefs(UINT16 wadnum); void S_InitMusicDefs(void); void S_LoadMTDefs(UINT16 wadnum); void S_InitMTDefs(void); +musicdef_t *S_GetMusicCredit(INT32 i); musicdef_t *S_FindMusicCredit(const char *musname); void S_ShowSpecifiedMusicCredit(const char *musname); void S_ShowMusicCredit(void); -boolean S_PrepareSoundTest(void); - // // Music Seeking // -- 2.54.0 From 0e9a825f63d989309ef75a540531259d86ae942e Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 30 May 2025 20:52:38 +0200 Subject: [PATCH 20/24] some crap from ceepeepeecheck --- src/g_game.c | 51 ++++++++++++++++++++++-------------------- src/g_input.c | 2 +- src/hardware/hw_main.c | 5 ++++- src/k_kart.c | 5 +++-- src/r_data.c | 21 ++++++++++++----- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 31eed2fd4..a872fc571 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5464,33 +5464,36 @@ void G_GhostTicker(void) break; } } - if (type == MT_GHOST) + if (type != -1) { - mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us - mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK); - mobj->sprite = states[mobjinfo[type].spawnstate].sprite; - mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<tics = -1; // nope. - mobj->color = g->mo->color; - if (g->mo->eflags & MFE_VERTICALFLIP) + if (type == MT_GHOST) { - mobj->flags2 |= MF2_OBJECTFLIP; - mobj->eflags |= MFE_VERTICALFLIP; + mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us + mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<mo->scale); - mobj->destscale = g->mo->scale; + else + { + mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK); + mobj->sprite = states[mobjinfo[type].spawnstate].sprite; + mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<tics = -1; // nope. + mobj->color = g->mo->color; + if (g->mo->eflags & MFE_VERTICALFLIP) + { + mobj->flags2 |= MF2_OBJECTFLIP; + mobj->eflags |= MFE_VERTICALFLIP; + } + P_SetScale(mobj, g->mo->scale); + mobj->destscale = g->mo->scale; + } + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z+mobj->height; + P_UnsetThingPosition(mobj); + mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... + P_SetThingPosition(mobj); + mobj->fuse = 8; + P_SetTarget(&mobj->target, g->mo); } - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_UnsetThingPosition(mobj); - mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... - P_SetThingPosition(mobj); - mobj->fuse = 8; - P_SetTarget(&mobj->target, g->mo); } if (ziptic & EZT_HIT) { // Spawn hit poofs for killing things! @@ -8143,7 +8146,7 @@ void G_SaveDemo(void) size_t i, strindex = 0; boolean dash = true; - for (i = 0; i < 127 && demo.titlename[i]; i++) + for (i = 0; demo.titlename[i] && i < 127; i++) { if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') || (demo.titlename[i] >= '0' && demo.titlename[i] <= '9')) diff --git a/src/g_input.c b/src/g_input.c index 43b7f48ca..8d5b38bf2 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1030,7 +1030,7 @@ INT32 G_KeyStringtoNum(const char *keystr) if (!keystr[0]) return 0; - if (!keystr[0] || (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z')) + if (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z') return keystr[0]; if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9') diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e25364bee..43cb25aed 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4464,7 +4464,10 @@ static void HWR_DrawModels(void) continue; } - if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + if (!spr->mobj) + continue; + + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { md2_t *md2; diff --git a/src/k_kart.c b/src/k_kart.c index c63433fb4..5589bdb6e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10525,11 +10525,12 @@ static void K_drawKartWanted(void) { INT32 x = basex+(splitscreen > 1 ? 13 : 8), y = basey+(splitscreen > 1 ? 16 : 21); fixed_t scale = FRACUNIT/2; - player_t *p = &players[battlewanted[i]]; if (battlewanted[i] == -1) break; + player_t *p = &players[battlewanted[i]]; + if (numwanted == 1) scale = FRACUNIT; else @@ -10540,7 +10541,7 @@ static void K_drawKartWanted(void) y += 16; } - if (players[battlewanted[i]].skincolor) + if (p->skincolor) { colormap = R_GetTranslationColormap(TC_RAINBOW, p->skincolor, GTC_CACHE); V_DrawFixedPatch(x<8) + + if (texturesTokenLength > 8) { I_Error("Error parsing TEXTURES lump: Patch name \"%s\" exceeds 8 characters",texturesToken); } @@ -713,10 +716,12 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) // Comma 1 Z_Free(texturesToken); texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName); } + if (strcmp(texturesToken,",")!=0) { I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken); @@ -725,14 +730,17 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) // XPos Z_Free(texturesToken); texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s x coordinate should be",patchName); } + endPos = NULL; #ifndef AVOID_ERRNO errno = 0; #endif + patchXPos = strtol(texturesToken,&endPos,10); (void)patchXPos; //unused for now if (endPos == texturesToken // Empty string @@ -748,10 +756,12 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) // Comma 2 Z_Free(texturesToken); texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName); } + if (strcmp(texturesToken,",")!=0) { I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken); @@ -760,6 +770,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) // YPos Z_Free(texturesToken); texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s y coordinate should be",patchName); @@ -1131,9 +1142,9 @@ static void R_InitExtraColormaps(void) lumpnum_t R_GetFlatNumForName(const char *name) { INT32 i; - lumpnum_t lump; - lumpnum_t start; - lumpnum_t end; + lumpnum_t lump = LUMPERROR; + lumpnum_t start = LUMPERROR; + lumpnum_t end = LUMPERROR; // Scan wad files backwards so patched flats take preference. for (i = numwadfiles - 1; i >= 0; i--) @@ -1608,7 +1619,7 @@ const char *R_ColormapNameForNum(INT32 num) if (num == -1) return "NONE"; - if (num < 0 || num > MAXCOLORMAPS) + if (num < 0 || num >= MAXCOLORMAPS) I_Error("R_ColormapNameForNum: num %d is invalid!\n", num); if (foundcolormaps[num] == LUMPERROR) -- 2.54.0 From f1f07822569149c6d94cd68c8c5c8b5f7ec2343d Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 30 May 2025 20:56:43 +0200 Subject: [PATCH 21/24] fix memoryleak in pk3 verify functions --- src/w_wad.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 0c7fdbaf0..305e4b3bd 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -2039,8 +2039,7 @@ static lumpchecklist_t folderblacklist[] = {NULL, 0}, }; -static int -W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) +static int W_VerifyPK3(FILE *fp, lumpchecklist_t *checklist, boolean status) { int verified = true; @@ -2082,7 +2081,10 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) char *cdir = (char*)(malloc(LONG(zend.cdirsize))); if (fread(cdir, 1, LONG(zend.cdirsize), fp) < (UINT32)(LONG(zend.cdirsize))) + { + free(cdir); return true; + } size_t offset = 0; @@ -2094,7 +2096,10 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) char* dotpos; if (memcmp(zentry->signature, pat_central, 4) != 0) + { + free(cdir); return true; + } if (verified == true) { @@ -2132,10 +2137,16 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) sizeof *zentry + SHORT(zentry->namelen) + SHORT(zentry->xtralen) + SHORT(zentry->commlen); if (fseek(fp, LONG(zentry->offset), SEEK_SET) != 0) + { + free(cdir); return true; + } if (fread(&zlentry, 1, sizeof(zlentry_t), fp) < sizeof (zlentry_t)) + { + free(cdir); return true; + } data_size += sizeof zlentry + SHORT(zlentry.namelen) + SHORT(zlentry.xtralen) + LONG(zlentry.compsize); @@ -2186,7 +2197,9 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, goodfile = W_VerifyWAD(handle, checklist, status); } } + fclose(handle); + return goodfile; } @@ -2341,7 +2354,10 @@ static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist) char *cdir = (char*)(malloc(LONG(zend.cdirsize))); if (fread(cdir, 1, LONG(zend.cdirsize), fp) < (UINT32)(LONG(zend.cdirsize))) + { + free(cdir); return true; + } size_t offset = 0; @@ -2353,7 +2369,10 @@ static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist) char* dotpos; if (memcmp(zentry->signature, pat_central, 4) != 0) + { + free(cdir); return false; + } fullname = (char*)(malloc(SHORT(zentry->namelen) + 1)); strlcpy(fullname, (char*)(zentry + 1), SHORT(zentry->namelen) + 1); @@ -2373,11 +2392,19 @@ static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist) strncpy(lumpname, trimname, min(8, dotpos - trimname)); if (W_NameStartsWith(lumpname, checklist)) + { + free(fullname); + free(cdir); return true; + } } if (W_NameStartsWith(fullname, checklist)) + { + free(fullname); + free(cdir); return true; + } free(fullname); @@ -2387,10 +2414,16 @@ static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist) sizeof *zentry + SHORT(zentry->namelen) + SHORT(zentry->xtralen) + SHORT(zentry->commlen); if (fseek(fp, LONG(zentry->offset), SEEK_SET) != 0) + { + free(cdir); return false; + } if (fread(&zlentry, 1, sizeof(zlentry_t), fp) < sizeof (zlentry_t)) + { + free(cdir); return false; + } data_size += sizeof zlentry + SHORT(zlentry.namelen) + SHORT(zlentry.xtralen) + LONG(zlentry.compsize); -- 2.54.0 From b29ca13916b4fe9ec5934f58a32925198e8af283 Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 31 May 2025 18:54:07 +0300 Subject: [PATCH 22/24] Add musicdefs table into lua --- src/lua_infolib.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 08e26a48b..0ac308bcb 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1103,6 +1103,33 @@ static int lib_sFindMusicCredit(lua_State *L) return 1; } +static int lib_getMusicDef(lua_State *L) +{ + musicdef_t *def = NULL; + + if (lua_isnumber(L, 2)) + def = S_GetMusicCredit(lua_tonumber(L, 2)); + else if (lua_isstring(L, 2)) + def = S_FindMusicCredit(lua_tostring(L, 2)); + else + return luaL_error(L, "musicdefs index must be number or string (got %s)", luaL_typename(L, 2)); + + LUA_PushUserdata(L, def, META_MUSICDEF); + + return 1; +} + +static int lib_setMusicDef(lua_State *L) +{ + return luaL_error(L, "musicdefs is read only"); +} + +static int lib_musicdefslen(lua_State *L) +{ + lua_pushinteger(L, nummusicdefs); + return 1; +} + static int musicdef_get(lua_State *L) { musicdef_t *musicdef = *((musicdef_t **)luaL_checkudata(L, 1, META_MUSICDEF)); @@ -1139,6 +1166,16 @@ static int musicdef_get(lua_State *L) return 0; } +static int musicdef_num(lua_State *L) +{ + musicdef_t *musicdef = *((musicdef_t **)luaL_checkudata(L, 1, META_MUSICDEF)); + + I_Assert(musicdef != NULL); + + lua_pushinteger(L, musicdef->num); + return 1; +} + ////////////////////////////// // // Now push all these functions into the Lua state! @@ -1196,6 +1233,9 @@ int LUA_InfoLib(lua_State *L) luaL_newmetatable(L, META_MUSICDEF); lua_pushcfunction(L, musicdef_get); lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, musicdef_num); + lua_setfield(L, -2, "__len"); lua_pop(L, 1); musicdef_fields_ref = Lua_CreateFieldTable(L, musicdef_opt); @@ -1252,5 +1292,19 @@ int LUA_InfoLib(lua_State *L) lua_pushvalue(L, -1); lua_setglobal(L, "S_sfx"); lua_setglobal(L, "sfxinfo"); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getMusicDef); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setMusicDef); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_musicdefslen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "musicdefs"); + return 0; } -- 2.54.0 From fab76353730f4c3b519ae5013b26bbdb6f0d65ec Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 31 May 2025 19:10:58 +0300 Subject: [PATCH 23/24] Add musicdef lua stuff into LUASTUFF.md --- LUASTUFF.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/LUASTUFF.md b/LUASTUFF.md index 8960fad48..3853f6e43 100644 --- a/LUASTUFF.md +++ b/LUASTUFF.md @@ -161,6 +161,32 @@ Duration is in milliseconds and is optional to set, default value is 84ms. Exactly same as P_CheckSight but uses cheaper algorithm, useful for things like nametags. Doesn't work exactly like P_CheckSight so don't use it for anything gameplay-related. +## musicdef_t + +Userdata structure representing a musicdef. Fields: + +`musicdef.name` - song identifier ("kmap01" for example). + +`musicdef.usage`, `musicdef.source` - fields from vanilla MUSICDEFS lump. + +`musicdef.filename` - unused for now. + +`musicdef.title`, `musicdef.alttitle`, `musicdef.authors` - fields from MUSCINFO lump. + +`#musicdef` - returns integer id for musicdef (which can be used as index in `musicdefs`). + +All fields are read-only. + +## S_FindMusicCredit(name) + +Returns musicdef corresponding to music with given identifier. For example, `S_FindMusicCredit("kmap01")` will return +musicdef for green hills music. + +## musicdefs + +Global table for all musicdefs, similar to mobjinfo, states, etc. Can take either integer indices, +from `0` to `#musicdefs-1`, or string indices (which is equal to calling `S_FindMusicCredit`). + # Other changes ## P_PlayRinglossSound(source, damager) -- 2.54.0 From 8fb17756062c14247f88ff63b60ad72e90ea877f Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 31 May 2025 19:15:04 +0300 Subject: [PATCH 24/24] Forgot MusicCredit hook --- LUASTUFF.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/LUASTUFF.md b/LUASTUFF.md index 3853f6e43..83ec76545 100644 --- a/LUASTUFF.md +++ b/LUASTUFF.md @@ -187,6 +187,11 @@ musicdef for green hills music. Global table for all musicdefs, similar to mobjinfo, states, etc. Can take either integer indices, from `0` to `#musicdefs-1`, or string indices (which is equal to calling `S_FindMusicCredit`). +## addHook("MusicCredit", function(musicdef)) + +Hook is called whenever `S_ShowMusicCredit` (either from game or mod) is called. Takes musicdef as only argument, returning true +will overwrite vanilla behavior (not show music credit), can be used to implement custom music credit pop-ups. + # Other changes ## P_PlayRinglossSound(source, damager) -- 2.54.0