From b0cbc8ab2a59cd863c5c59f7593215fc1cd316a0 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 2 Mar 2016 23:47:06 -0600 Subject: [PATCH 01/93] Lua slope manipulation stuff! Warning: Incomplete. Very prone to crashing and I might not have handled some things properly. Use with caution. --- src/dehacked.c | 6 ++ src/lua_libs.h | 1 + src/lua_maplib.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++- src/p_slopes.c | 2 +- src/p_slopes.h | 1 + 5 files changed, 220 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index d6a1881e..d8847fd3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7230,6 +7230,12 @@ struct { {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. + // Slope flags + {"SL_NOPHYSICS",SL_NOPHYSICS}, // Don't do momentum adjustment with this slope + {"SL_NODYNAMIC",SL_NODYNAMIC}, // Slope will never need to move during the level, so don't fuss with recalculating it + {"SL_ANCHORVERTEX",SL_ANCHORVERTEX},// Slope is using a Slope Vertex Thing to anchor its position + {"SL_VERTEXSLOPE",SL_VERTEXSLOPE}, // Slope is built from three Slope Vertex Things + // Angles {"ANG1",ANG1>>16}, {"ANG2",ANG2>>16}, diff --git a/src/lua_libs.h b/src/lua_libs.h index d19ad885..893f5668 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -38,6 +38,7 @@ extern lua_State *gL; #define META_SUBSECTOR "SUBSECTOR_T*" #define META_SECTOR "SECTOR_T*" #define META_FFLOOR "FFLOOR_T*" +#define META_SLOPE "PSLOPE_T*" #define META_MAPHEADER "MAPHEADER_T*" #define META_CVAR "CONSVAR_T*" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 16d05dac..a6ebf1ab 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -16,6 +16,8 @@ #include "p_local.h" #include "p_setup.h" #include "z_zone.h" +#include "p_slopes.h" +#include "r_main.h" #include "lua_script.h" #include "lua_libs.h" @@ -37,7 +39,10 @@ enum sector_e { sector_thinglist, sector_heightsec, sector_camsec, - sector_ffloors + sector_ffloors, + sector_fslope, + sector_cslope, + sector_hasslope }; static const char *const sector_opt[] = { @@ -53,6 +58,9 @@ static const char *const sector_opt[] = { "heightsec", "camsec", "ffloors", + "f_slope", + "c_slope", + "hasslope", NULL}; enum subsector_e { @@ -158,6 +166,8 @@ enum ffloor_e { ffloor_toplightlevel, ffloor_bottomheight, ffloor_bottompic, + ffloor_tslope, + ffloor_bslope, ffloor_sector, ffloor_flags, ffloor_master, @@ -174,6 +184,8 @@ static const char *const ffloor_opt[] = { "toplightlevel", "bottomheight", "bottompic", + "t_slope", + "b_slope", "sector", // secnum pushed as control sector userdata "flags", "master", // control linedef @@ -183,6 +195,32 @@ static const char *const ffloor_opt[] = { "alpha", NULL}; +enum slope_e { + slope_valid = 0, + slope_o, + slope_d, + slope_zdelta, + slope_normal, + slope_zangle, + slope_xydirection, + slope_sourceline, + slope_refpos, + slope_flags +}; + +static const char *const slope_opt[] = { + "valid", + "o", + "d", + "zdelta", + "normal", + "zangle", + "xydirection", + "sourceline", + "refpos", + "flags", + NULL}; + static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -330,6 +368,15 @@ static int sector_get(lua_State *L) LUA_PushUserdata(L, sector->ffloors, META_FFLOOR); lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateFFloors and sector->ffloors as upvalues for the function return 1; + case sector_fslope: // f_slope + LUA_PushUserdata(L, sector->f_slope, META_SLOPE); + return 1; + case sector_cslope: // c_slope + LUA_PushUserdata(L, sector->c_slope, META_SLOPE); + return 1; + case sector_hasslope: // hasslope + lua_pushboolean(L, sector->hasslope); + return 1; } return 0; } @@ -392,6 +439,9 @@ static int sector_set(lua_State *L) case sector_heightsec: // heightsec case sector_camsec: // camsec case sector_ffloors: // ffloors + case sector_fslope: // f_slope + case sector_cslope: // c_slope + case sector_hasslope: // hasslope default: return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); case sector_floorheight: { // floorheight @@ -1026,6 +1076,12 @@ static int ffloor_get(lua_State *L) lua_pushlstring(L, levelflat->name, 8); return 1; } + case ffloor_tslope: + LUA_PushUserdata(L, *ffloor->t_slope, META_SLOPE); + return 1; + case ffloor_bslope: + LUA_PushUserdata(L, *ffloor->b_slope, META_SLOPE); + return 1; case ffloor_sector: LUA_PushUserdata(L, §ors[ffloor->secnum], META_SECTOR); return 1; @@ -1065,6 +1121,8 @@ static int ffloor_set(lua_State *L) switch(field) { case ffloor_valid: // valid + case ffloor_tslope: // t_slope + case ffloor_bslope: // b_slope case ffloor_sector: // sector case ffloor_master: // master case ffloor_target: // target @@ -1125,6 +1183,150 @@ static int ffloor_set(lua_State *L) return 0; } +static int slope_get(lua_State *L) +{ + pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); + enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + + if (!slope) + { + if (field == slope_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed pslope_t doesn't exist anymore."); + } + + switch(field) + { + case slope_valid: // valid + lua_pushboolean(L, 1); + return 1; + case slope_o: // o + lua_createtable(L, 0, 3); + lua_pushfixed(L, slope->o.x); + lua_setfield(L, -2, "x"); + lua_pushfixed(L, slope->o.y); + lua_setfield(L, -2, "y"); + lua_pushfixed(L, slope->o.z); + lua_setfield(L, -2, "z"); + return 1; + case slope_d: // d + lua_createtable(L, 0, 2); + lua_pushfixed(L, slope->o.x); + lua_setfield(L, -2, "x"); + lua_pushfixed(L, slope->o.y); + lua_setfield(L, -2, "y"); + return 1; + case slope_zdelta: // zdelta + lua_pushfixed(L, slope->zdelta); + return 1; + case slope_normal: // normal + lua_createtable(L, 0, 2); + lua_pushfixed(L, slope->o.x); + lua_setfield(L, -2, "x"); + lua_pushfixed(L, slope->o.y); + lua_setfield(L, -2, "y"); + return 1; + case slope_zangle: // zangle + lua_pushangle(L, slope->zangle); + return 1; + case slope_xydirection: // xydirection + lua_pushangle(L, slope->xydirection); + return 1; + case slope_sourceline: // source linedef + LUA_PushUserdata(L, slope->sourceline, META_LINE); + return 1; + case slope_refpos: // refpos + lua_pushinteger(L, slope->refpos); + return 1; + case slope_flags: // flags + lua_pushinteger(L, slope->flags); + return 1; + } + return 0; +} + +static int slope_set(lua_State *L) +{ + pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); + enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + + if (!slope) + return luaL_error(L, "accessed pslope_t doesn't exist anymore."); + + if (hud_running) + return luaL_error(L, "Do not alter pslope_t in HUD rendering code!"); + + switch(field) // todo: reorganize this shit + { + case slope_valid: // valid + case slope_sourceline: // sourceline + case slope_d: // d + case slope_flags: // flags + case slope_normal: // normal + case slope_refpos: // refpos + default: + return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]); + case slope_o: { // o + luaL_checktype(L, 3, LUA_TTABLE); + + lua_getfield(L, 3, "x"); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_rawgeti(L, 3, 1); + } + if (!lua_isnil(L, -1)) + slope->o.x = luaL_checkfixed(L, -1); + else + slope->o.x = 0; + lua_pop(L, 1); + + lua_getfield(L, 3, "y"); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_rawgeti(L, 3, 2); + } + if (!lua_isnil(L, -1)) + slope->o.y = luaL_checkfixed(L, -1); + else + slope->o.y = 0; + lua_pop(L, 1); + + lua_getfield(L, 3, "z"); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_rawgeti(L, 3, 3); + } + if (!lua_isnil(L, -1)) + slope->o.z = luaL_checkfixed(L, -1); + else + slope->o.z = 0; + lua_pop(L, 1); + break; + } + case slope_zdelta: { // zdelta, this is temp until i figure out wtf to do + slope->zdelta = luaL_checkfixed(L, 3); + slope->zangle = R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta); + P_CalculateSlopeNormal(slope); + break; + } + case slope_zangle: // zangle + slope->zangle = luaL_checkangle(L, 3); + slope->zdelta = FINETANGENT(slope->zangle); + P_CalculateSlopeNormal(slope); + break; + case slope_xydirection: // xydirection + slope->xydirection = luaL_checkangle(L, 3); + P_CalculateSlopeNormal(slope); + break; + } + return 0; +} + static int lib_getMapheaderinfo(lua_State *L) { // i -> mapheaderinfo[i-1] @@ -1293,6 +1495,14 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + luaL_newmetatable(L, META_SLOPE); + lua_pushcfunction(L, slope_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, slope_set); + lua_setfield(L, -2, "__newindex"); + lua_pop(L, 1); + luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); lua_setfield(L, -2, "__index"); diff --git a/src/p_slopes.c b/src/p_slopes.c index 2d55cf19..b51b2a4d 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -46,7 +46,7 @@ static pslope_t *slopelist = NULL; static UINT16 slopecount = 0; // Calculate line normal -static void P_CalculateSlopeNormal(pslope_t *slope) { +void P_CalculateSlopeNormal(pslope_t *slope) { slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT); slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x); slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y); diff --git a/src/p_slopes.h b/src/p_slopes.h index 8d82632f..7898302e 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -29,6 +29,7 @@ #define P_SLOPES_H__ #ifdef ESLOPE +void P_CalculateSlopeNormal(pslope_t *slope); void P_ResetDynamicSlopes(void); void P_RunDynamicSlopes(void); // P_SpawnSlope_Line From b3d842e8590938de3e4ac6cfea61a7df3023f4cc Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 3 Mar 2016 14:43:42 +0000 Subject: [PATCH 02/93] Fix accidental copy+paste of o to d and normal in slope_get code --- src/lua_maplib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index a6ebf1ab..218f26e1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1213,9 +1213,9 @@ static int slope_get(lua_State *L) return 1; case slope_d: // d lua_createtable(L, 0, 2); - lua_pushfixed(L, slope->o.x); + lua_pushfixed(L, slope->d.x); lua_setfield(L, -2, "x"); - lua_pushfixed(L, slope->o.y); + lua_pushfixed(L, slope->d.y); lua_setfield(L, -2, "y"); return 1; case slope_zdelta: // zdelta @@ -1223,9 +1223,9 @@ static int slope_get(lua_State *L) return 1; case slope_normal: // normal lua_createtable(L, 0, 2); - lua_pushfixed(L, slope->o.x); + lua_pushfixed(L, slope->normal.x); lua_setfield(L, -2, "x"); - lua_pushfixed(L, slope->o.y); + lua_pushfixed(L, slope->normal.y); lua_setfield(L, -2, "y"); return 1; case slope_zangle: // zangle From ad0069676a4cbc1201dbf3bfef35f28052df303b Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Thu, 3 Mar 2016 20:47:05 -0600 Subject: [PATCH 03/93] slope->normal is vector3_t, not vector2_t --- src/lua_maplib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 218f26e1..f584ce4c 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1222,11 +1222,13 @@ static int slope_get(lua_State *L) lua_pushfixed(L, slope->zdelta); return 1; case slope_normal: // normal - lua_createtable(L, 0, 2); + lua_createtable(L, 0, 3); lua_pushfixed(L, slope->normal.x); lua_setfield(L, -2, "x"); lua_pushfixed(L, slope->normal.y); lua_setfield(L, -2, "y"); + lua_pushfixed(L, slope->normal.z); + lua_setfield(L, -2, "z"); return 1; case slope_zangle: // zangle lua_pushangle(L, slope->zangle); From cb62f08364d4d53e51d4770198e2b65b3547e62b Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Thu, 20 Oct 2016 22:23:50 -0400 Subject: [PATCH 04/93] "PlayerQuit" hook --- src/lua_hook.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_hook.h b/src/lua_hook.h index 804d99e1..240fdaec 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -43,6 +43,7 @@ enum hook { hook_PlayerMsg, hook_HurtMsg, hook_PlayerSpawn, + hook_PlayerQuit, hook_MAX // last hook }; @@ -77,5 +78,6 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer +boolean LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting #endif From cfb2feff8ef4344130bed3456937ecb9609c593a Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Thu, 20 Oct 2016 22:25:11 -0400 Subject: [PATCH 05/93] "PlayerQuit" hook --- src/lua_hooklib.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 1b965257..be3f8b0e 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -54,6 +54,7 @@ const char *const hookNames[hook_MAX+1] = { "PlayerMsg", "HurtMsg", "PlayerSpawn", + "PlayerQuit", NULL }; @@ -798,4 +799,41 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc) // stack: tables } +boolean LUAh_PlayerQuit(player_t *plr, int reason) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) + return false; + + lua_settop(gL, 0); + + for (hookp = roothook; hookp; hookp = hookp->next) + if (hookp->type == hook_PlayerQuit) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + #endif From 89e8766b77f0176e9680522cd4a9b325a2e1b33c Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Thu, 20 Oct 2016 22:30:11 -0400 Subject: [PATCH 06/93] "PlayerQuit" hook --- src/d_clisrv.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c0f81ba3..973564a9 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2208,7 +2208,7 @@ void CL_ClearPlayer(INT32 playernum) // // Removes a player from the current game // -static void CL_RemovePlayer(INT32 playernum) +static void CL_RemovePlayer(INT32 playernum, INT32 reason) { // Sanity check: exceptional cases (i.e. c-fails) can cause multiple // kick commands to be issued for the same player. @@ -2262,6 +2262,10 @@ static void CL_RemovePlayer(INT32 playernum) } } } + +#ifdef HAVE_BLUA + LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting +#endif // Reset player data CL_ClearPlayer(playernum); @@ -2513,6 +2517,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) INT32 pnum, msg; XBOXSTATIC char buf[3 + MAX_REASONLENGTH]; char *reason = buf; + INT32 kickreason = 1; pnum = READUINT8(*p); msg = READUINT8(*p); @@ -2593,14 +2598,17 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) { case KICK_MSG_GO_AWAY: CONS_Printf(M_GetText("has been kicked (Go away)\n")); + kickreason = 1; break; #ifdef NEWPING case KICK_MSG_PING_HIGH: CONS_Printf(M_GetText("left the game (Broke ping limit)\n")); + kickreason = 2; break; #endif case KICK_MSG_CON_FAIL: CONS_Printf(M_GetText("left the game (Synch failure)\n")); + kickreason = 3; if (M_CheckParm("-consisdump")) // Helps debugging some problems { @@ -2637,21 +2645,26 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) break; case KICK_MSG_TIMEOUT: CONS_Printf(M_GetText("left the game (Connection timeout)\n")); + kickreason = 4; break; case KICK_MSG_PLAYER_QUIT: if (netgame) // not splitscreen/bots CONS_Printf(M_GetText("left the game\n")); + kickreason = 6; break; case KICK_MSG_BANNED: CONS_Printf(M_GetText("has been banned (Don't come back)\n")); + kickreason = 5; break; case KICK_MSG_CUSTOM_KICK: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); CONS_Printf(M_GetText("has been kicked (%s)\n"), reason); + kickreason = 1; break; case KICK_MSG_CUSTOM_BAN: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); CONS_Printf(M_GetText("has been banned (%s)\n"), reason); + kickreason = 5; break; } @@ -2679,7 +2692,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING); } else - CL_RemovePlayer(pnum); + CL_RemovePlayer(pnum, kickreason); } consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; From fcf2fe79e00dae735cf383ce04422a6548fe4288 Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Thu, 20 Oct 2016 23:25:47 -0400 Subject: [PATCH 07/93] Oops; PlayerQuit isn't a boolean! --- src/lua_hook.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 240fdaec..94b934f3 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -78,6 +78,6 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer -boolean LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting +void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting #endif From defc7c164545eeae8db8f81de5c8ca46eff9af14 Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Thu, 20 Oct 2016 23:26:41 -0400 Subject: [PATCH 08/93] Oops; PlayerQuit isn't a boolean! --- src/lua_hooklib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index be3f8b0e..5ac77da9 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -799,12 +799,12 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc) // stack: tables } -boolean LUAh_PlayerQuit(player_t *plr, int reason) +void LUAh_PlayerQuit(player_t *plr, int reason) { hook_p hookp; boolean hooked = false; if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) - return false; + return; lua_settop(gL, 0); From 673315265107da0740372f2ba1917cb89396c208 Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Fri, 21 Oct 2016 16:16:54 -0400 Subject: [PATCH 09/93] No more magic numbers --- src/d_clisrv.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 973564a9..cfe0c1cd 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2517,7 +2517,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) INT32 pnum, msg; XBOXSTATIC char buf[3 + MAX_REASONLENGTH]; char *reason = buf; - INT32 kickreason = 1; + kickreason_t kickreason = KR_KICK; pnum = READUINT8(*p); msg = READUINT8(*p); @@ -2598,17 +2598,17 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) { case KICK_MSG_GO_AWAY: CONS_Printf(M_GetText("has been kicked (Go away)\n")); - kickreason = 1; + kickreason = KR_KICK; break; #ifdef NEWPING case KICK_MSG_PING_HIGH: CONS_Printf(M_GetText("left the game (Broke ping limit)\n")); - kickreason = 2; + kickreason = KR_PINGLIMIT; break; #endif case KICK_MSG_CON_FAIL: CONS_Printf(M_GetText("left the game (Synch failure)\n")); - kickreason = 3; + kickreason = KR_SYNCH; if (M_CheckParm("-consisdump")) // Helps debugging some problems { @@ -2645,26 +2645,26 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) break; case KICK_MSG_TIMEOUT: CONS_Printf(M_GetText("left the game (Connection timeout)\n")); - kickreason = 4; + kickreason = KR_TIMEOUT; break; case KICK_MSG_PLAYER_QUIT: if (netgame) // not splitscreen/bots CONS_Printf(M_GetText("left the game\n")); - kickreason = 6; + kickreason = KR_LEAVE; break; case KICK_MSG_BANNED: CONS_Printf(M_GetText("has been banned (Don't come back)\n")); - kickreason = 5; + kickreason = KR_BAN; break; case KICK_MSG_CUSTOM_KICK: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); CONS_Printf(M_GetText("has been kicked (%s)\n"), reason); - kickreason = 1; + kickreason = KR_KICK; break; case KICK_MSG_CUSTOM_BAN: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); CONS_Printf(M_GetText("has been banned (%s)\n"), reason); - kickreason = 5; + kickreason = KR_BAN; break; } From c38457f23c70509cef3fd131e380332c2e43ab4f Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Fri, 21 Oct 2016 16:25:07 -0400 Subject: [PATCH 10/93] No more magic numbers --- src/d_clisrv.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 14b59092..cd726d9b 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -436,6 +436,17 @@ extern consvar_t cv_playbackspeed; #define KICK_MSG_CUSTOM_KICK 7 #define KICK_MSG_CUSTOM_BAN 8 +typedef enum +{ + KR_KICK = 1, //Kicked by server + KR_PINGLIMIT = 2, //Broke Ping Limit + KR_SYNCH = 3, //Synch Failure + KR_TIMEOUT = 4, //Connection Timeout + KR_BAN = 5, //Banned by server + KR_LEAVE = 6, //Quit the game + +} kickreason_t; + extern boolean server; extern boolean dedicated; // for dedicated server extern UINT16 software_MAXPACKETLENGTH; From b5988e082cd012555e532d7c0a25b73818ec6566 Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Fri, 21 Oct 2016 16:27:15 -0400 Subject: [PATCH 11/93] No more magic numbers --- src/dehacked.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index f03dd73b..62a7ad81 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -31,6 +31,7 @@ #include "fastcmp.h" #include "lua_script.h" #include "lua_hook.h" +#include "d_clisrv.h" #include "m_cond.h" @@ -7392,6 +7393,14 @@ struct { {"V_CHARCOLORSHIFT",V_CHARCOLORSHIFT}, {"V_ALPHASHIFT",V_ALPHASHIFT}, + + //Kick Reasons + {"KR_KICK",KR_KICK}, + {"KR_PINGLIMIT",KR_PINGLIMIT}, + {"KR_SYNCH",KR_SYNCH}, + {"KR_TIMEOUT",KR_TIMEOUT}, + {"KR_BAN",KR_BAN}, + {"KR_LEAVE",KR_LEAVE}, #endif {NULL,0} From b1ce5896aa97509268589cbcba26431c08f8adf9 Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Tue, 8 Nov 2016 10:30:01 -0500 Subject: [PATCH 12/93] Remove boolean remnants --- src/lua_hooklib.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 5ac77da9..16f8c55d 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -802,7 +802,6 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc) void LUAh_PlayerQuit(player_t *plr, int reason) { hook_p hookp; - boolean hooked = false; if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) return; @@ -811,29 +810,16 @@ void LUAh_PlayerQuit(player_t *plr, int reason) for (hookp = roothook; hookp; hookp = hookp->next) if (hookp->type == hook_PlayerQuit) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit - lua_pushinteger(gL, reason); // Reason for quitting - } + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); lua_pushvalue(gL, -3); lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_Call(gL, 2); } lua_settop(gL, 0); - return hooked; } #endif From d788cb7676e8832147d9e6ae911b10005987a85c Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Fri, 25 Nov 2016 15:20:41 -0500 Subject: [PATCH 13/93] Keeping the lua_gettop(gL) thing, otherwise the player/reason values will be pushed once to the stack each for every hook. Thanks MonsterIestyn! --- src/lua_hooklib.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 16f8c55d..7c10b7e3 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -810,7 +810,11 @@ void LUAh_PlayerQuit(player_t *plr, int reason) for (hookp = roothook; hookp; hookp = hookp->next) if (hookp->type == hook_PlayerQuit) { - LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + } lua_pushinteger(gL, reason); // Reason for quitting lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); From dd13df230831debbfb08a447800ea8cc18bd4abf Mon Sep 17 00:00:00 2001 From: Prisima the Fox Date: Sat, 3 Dec 2016 18:18:16 -0500 Subject: [PATCH 14/93] Whoops, didn't see the duplicate line. --- src/lua_hooklib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 7c10b7e3..273264d7 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -815,7 +815,6 @@ void LUAh_PlayerQuit(player_t *plr, int reason) LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit lua_pushinteger(gL, reason); // Reason for quitting } - lua_pushinteger(gL, reason); // Reason for quitting lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); lua_pushvalue(gL, -3); From 602701d6ddb42b85cb4779f7dacf1be81852c89a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 11 Jan 2018 16:55:42 +0000 Subject: [PATCH 15/93] G_DoPlayDemo: prepend srb2home to the demo name (if an external file) so that demos in custom home paths can be loaded --- src/d_netcmd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3696dd97..0d174548 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1452,7 +1452,12 @@ static void Command_Playdemo_f(void) CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name); - G_DoPlayDemo(name); + // Internal if no extension, external if one exists + // If external, convert the file name to a path in SRB2's home directory + if (FIL_CheckExtension(name)) + G_DoPlayDemo(va("%s"PATHSEP"%s", srb2home, name)) + else + G_DoPlayDemo(name); } static void Command_Timedemo_f(void) From f1b8e122a20b61289844013786a68dfddd349330 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 12 Jan 2018 20:05:09 +0000 Subject: [PATCH 16/93] Fix missing semicolon --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0d174548..82d2a33a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1455,7 +1455,7 @@ static void Command_Playdemo_f(void) // Internal if no extension, external if one exists // If external, convert the file name to a path in SRB2's home directory if (FIL_CheckExtension(name)) - G_DoPlayDemo(va("%s"PATHSEP"%s", srb2home, name)) + G_DoPlayDemo(va("%s"PATHSEP"%s", srb2home, name)); else G_DoPlayDemo(name); } From 0ef7aff5c0a847a46147ef525695c4361f12e8ac Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 16 Jan 2018 15:21:49 +0000 Subject: [PATCH 17/93] Prevent SV_SpawnPlayer from being able to freeze the game if gametic is 0. Additionally add a sanity check to prevent the loop going on more than necessary anyway This commit fixes -playdemo and -timedemo params for command line, allowing them to actually work again --- src/d_clisrv.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d48f223c..378b23f9 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4445,6 +4445,7 @@ static void Local_Maketic(INT32 realtics) void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) { tic_t tic; + UINT8 numadjust = 0; (void)x; (void)y; @@ -4454,7 +4455,21 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) // spawning, but will be applied afterwards. for (tic = server ? maketic : (neededtic - 1); tic >= gametic; tic--) + { + if (numadjust++ == BACKUPTICS) + { + DEBFILE(va("SV_SpawnPlayer: All netcmds for player %d adjusted!\n", playernum)); + // We already adjusted them all, waste of time doing the same thing over and over + // This shouldn't happen normally though, either gametic was 0 (which is handled now anyway) + // or maketic >= gametic + BACKUPTICS + // -- Monster Iestyn 16/01/18 + break; + } netcmds[tic%BACKUPTICS][playernum].angleturn = (INT16)((angle>>16) | TICCMD_RECEIVED); + + if (!tic) // failsafe for gametic == 0 -- Monster Iestyn 16/01/18 + break; + } } // create missed tic From fa3998e942ca6600919ec5e594b11d1d1c2485ac Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 20 Jan 2018 21:18:16 +0000 Subject: [PATCH 18/93] Some fixes to prevent bad table key types causing Lua panic errors for joining players in netgames: * ArchiveTables: print an error if invalid key, to alert script author potentially * UnArchiveTables: if the key is found to be nil after reading key and value, print an error and don't set them in the table --- src/lua_script.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index 167e4a0b..ce0f19c1 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -767,11 +767,19 @@ static void ArchiveTables(void) lua_pushnil(gL); while (lua_next(gL, -2)) { - ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. + // Write key + e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. + if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise) + { + lua_pushvalue(gL, -2); + CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -1), luaL_typename(gL, -1), i); + lua_pop(gL, 1); + } + // Write value e = ArchiveValue(TABLESINDEX, -1); if (e == 1) n++; // the table contained a new table we'll have to archive. :( - else if (e == 2) + else if (e == 2) // invalid value type { lua_pushvalue(gL, -2); CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1)); @@ -912,11 +920,17 @@ static void UnArchiveTables(void) lua_rawgeti(gL, TABLESINDEX, i); while (true) { - if (UnArchiveValue(TABLESINDEX) == 1) + if (UnArchiveValue(TABLESINDEX) == 1) // read key break; - if (UnArchiveValue(TABLESINDEX) == 2) + if (UnArchiveValue(TABLESINDEX) == 2) // read value n++; - lua_rawset(gL, -3); + if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved) + { + CONS_Alert(CONS_ERROR, "A nil key in table %d was found! (Invalid key type or corrupted save?)\n", i); + lua_pop(gL, 2); // pop key and value instead of setting them in the table, to prevent Lua panic errors + } + else + lua_rawset(gL, -3); } lua_pop(gL, 1); } From ad8c51ab8f9dd7117b303c137e46d93ee754ec09 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 21 Feb 2018 22:45:51 +0000 Subject: [PATCH 19/93] removing stupid dumb useless code fish --- src/dehacked.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index b7e874b1..36524108 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1860,7 +1860,6 @@ static void readframe(MYFILE *f, INT32 num) char *word1; char *word2 = NULL; char *tmp; - INT32 j; do { @@ -1875,16 +1874,6 @@ static void readframe(MYFILE *f, INT32 num) if (s == tmp) continue; // Skip comment lines, but don't break. - for (j = 0; s[j] != '\n'; j++) - { - if (s[j] == '=') - { - j += 2; - j = atoi(&s[j]); - break; - } - } - word1 = strtok(s, " "); if (word1) strupr(word1); From 29e80c53005ee3fe2e9cf4cd07ebfdacaf294aa8 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 8 May 2018 18:14:39 -0400 Subject: [PATCH 20/93] Don't increment totalplaytime if a demo is playing. --- src/p_tick.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_tick.c b/src/p_tick.c index f4bc5932..e81d0e5b 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -607,6 +607,7 @@ void P_Ticker(boolean run) } // Keep track of how long they've been playing! + if (!demoplayback) // Don't incerment if a demo is playing. totalplaytime++; if (!useNightsSS && G_IsSpecialStage(gamemap)) From 9ff491dd78f295412170832ff268d0b5aec24c99 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 8 May 2018 18:36:47 -0400 Subject: [PATCH 21/93] Add indentation --- src/p_tick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index e81d0e5b..aaf44f5e 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -608,7 +608,7 @@ void P_Ticker(boolean run) // Keep track of how long they've been playing! if (!demoplayback) // Don't incerment if a demo is playing. - totalplaytime++; + totalplaytime++; if (!useNightsSS && G_IsSpecialStage(gamemap)) P_DoSpecialStageStuff(); From a1d696b38e650e4f2e05d01a50d63756200782b9 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 8 May 2018 18:38:28 -0400 Subject: [PATCH 22/93] Fix small typo --- src/p_tick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_tick.c b/src/p_tick.c index aaf44f5e..4c59f8b4 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -607,7 +607,7 @@ void P_Ticker(boolean run) } // Keep track of how long they've been playing! - if (!demoplayback) // Don't incerment if a demo is playing. + if (!demoplayback) // Don't increment if a demo is playing. totalplaytime++; if (!useNightsSS && G_IsSpecialStage(gamemap)) From 4f75ae3a6819b68b476542abce497eea213a168e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 11 May 2018 20:35:46 +0100 Subject: [PATCH 23/93] Fix both Bouncy FOF and Space Countdown sector specials working on FOFs without the FF_EXISTS flag Also move the Bouncy FOF sector special check above the FOF heights checking in P_CheckBouncySectors, because it means not having to waste time calculating FOF heights only for it not to be bouncy anyway :P --- src/p_user.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 7abf8534..da8e19ca 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1621,6 +1621,9 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space for (rover = sector->ffloors; rover; rover = rover->next) { + if (!(rover->flags & FF_EXISTS)) + continue; + if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL) continue; #ifdef ESLOPE @@ -1835,6 +1838,12 @@ static void P_CheckBouncySectors(player_t *player) for (rover = node->m_sector->ffloors; rover; rover = rover->next) { + if (!(rover->flags & FF_EXISTS)) + continue; // FOFs should not be bouncy if they don't even "exist" + + if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 15) + continue; // this sector type is required for FOFs to be bouncy + topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); @@ -1848,7 +1857,6 @@ static void P_CheckBouncySectors(player_t *player) && oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL)) top = false; - if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 15) { fixed_t linedist; From f061ffa00ebb6bf748505666c98623794e588df3 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 21 May 2018 20:02:30 +0100 Subject: [PATCH 24/93] Stop Each Time trigger linedefs and object-carrying scrollers from doing anything with FOFs without FF_EXISTS --- src/p_floor.c | 14 ++++++++++++++ src/p_spec.c | 27 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/p_floor.c b/src/p_floor.c index 35c743a0..f3063765 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2103,6 +2103,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) boolean floortouch = false; fixed_t bottomheight, topheight; msecnode_t *node; + ffloor_t *rover; for (i = 0; i < MAXPLAYERS; i++) { @@ -2150,6 +2151,19 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) { targetsec = §ors[targetsecnum]; + // Find the FOF corresponding to the control linedef + for (rover = targetsec->ffloors; rover; rover = rover->next) + { + if (rover->master == sec->lines[i]) + break; + } + + if (!rover) // This should be impossible, but don't complain if it is the case somehow + continue; + + if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there + continue; + for (j = 0; j < MAXPLAYERS; j++) { if (!playeringame[j]) diff --git a/src/p_spec.c b/src/p_spec.c index c62c3b20..d308a9b3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6628,6 +6628,7 @@ void T_Scroll(scroll_t *s) line_t *line; size_t i; INT32 sect; + ffloor_t *rover; case sc_side: // scroll wall texture side = sides + s->affectee; @@ -6669,6 +6670,19 @@ void T_Scroll(scroll_t *s) sector_t *psec; psec = sectors + sect; + // Find the FOF corresponding to the control linedef + for (rover = psec->ffloors; rover; rover = rover->next) + { + if (rover->master == sec->lines[i]) + break; + } + + if (!rover) // This should be impossible, but don't complain if it is the case somehow + continue; + + if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there + continue; + for (node = psec->touching_thinglist; node; node = node->m_thinglist_next) { thing = node->m_thing; @@ -6732,6 +6746,19 @@ void T_Scroll(scroll_t *s) sector_t *psec; psec = sectors + sect; + // Find the FOF corresponding to the control linedef + for (rover = psec->ffloors; rover; rover = rover->next) + { + if (rover->master == sec->lines[i]) + break; + } + + if (!rover) // This should be impossible, but don't complain if it is the case somehow + continue; + + if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there + continue; + for (node = psec->touching_thinglist; node; node = node->m_thinglist_next) { thing = node->m_thing; From 2738f3a537fc57aba5e40d529bc11222b0cf9e72 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 5 Aug 2018 22:02:20 +0100 Subject: [PATCH 25/93] Rewrite archiving/unarchiving of Lua strings for netgames. This now means: * Lua strings longer than 1024 chars can now be read properly without awful crashes * Lua strings with embedded zeros can be written/read without truncating anything (hopefully) --- src/lua_script.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index 67ce77c5..5561094a 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -526,9 +526,23 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) break; } case LUA_TSTRING: + { + UINT16 len = (UINT16)lua_objlen(gL, myindex); // get length of string, including embedded zeros + const char *s = lua_tostring(gL, myindex); + UINT16 i = 0; WRITEUINT8(save_p, ARCH_STRING); - WRITESTRING(save_p, lua_tostring(gL, myindex)); + // if you're wondering why we're writing a string to save_p this way, + // it turns out that Lua can have embedded zeros ('\0') in the strings, + // so we can't use WRITESTRING as that cuts off when it finds a '\0'. + // Saving the size of the string also allows us to get the size of the string on the other end, + // fixing the awful crashes previously encountered for reading strings longer than 1024 + // (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?) + // -- Monster Iestyn 05/08/18 + WRITEUINT16(save_p, len); // save size of string + while (i < len) + WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros break; + } case LUA_TTABLE: { boolean found = false; @@ -809,9 +823,19 @@ static UINT8 UnArchiveValue(int TABLESINDEX) break; case ARCH_STRING: { - char value[1024]; - READSTRING(save_p, value); - lua_pushstring(gL, value); + UINT16 len = READUINT16(save_p); // length of string, including embedded zeros + char *value; + UINT16 i = 0; + // See my comments in the ArchiveValue function; + // it's much the same for reading strings as writing them! + // (i.e. we can't use READSTRING either) + // -- Monster Iestyn 05/08/18 + value = malloc(len); // make temp buffer of size len + // now read the actual string + while (i < len) + value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros + lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros) + free(value); // free the buffer break; } case ARCH_TABLE: From c703bc2fd7823c170ec5c40e7f89b40b8c6b2c80 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 6 Aug 2018 22:37:44 +0100 Subject: [PATCH 26/93] Trim off any extra null bytes off the end of sector floorpic/ceiling when you access them in Lua --- src/lua_maplib.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 208aebe3..4e9dbd5a 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -327,6 +327,7 @@ static int sector_get(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt); + INT16 i; if (!sector) { @@ -349,11 +350,23 @@ static int sector_get(lua_State *L) lua_pushfixed(L, sector->ceilingheight); return 1; case sector_floorpic: // floorpic - lua_pushlstring(L, levelflats[sector->floorpic].name, 8); + { + levelflat_t *levelflat = &levelflats[sector->floorpic]; + for (i = 0; i < 8; i++) + if (!levelflat->name[i]) + break; + lua_pushlstring(L, levelflat->name, i); return 1; + } case sector_ceilingpic: // ceilingpic - lua_pushlstring(L, levelflats[sector->ceilingpic].name, 8); + { + levelflat_t *levelflat = &levelflats[sector->ceilingpic]; + for (i = 0; i < 8; i++) + if (!levelflat->name[i]) + break; + lua_pushlstring(L, levelflat->name, i); return 1; + } case sector_lightlevel: lua_pushinteger(L, sector->lightlevel); return 1; From 0f5d685d1f61c3db55b820dc56f3c46f4b2fecc8 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 30 Aug 2018 18:32:26 -0400 Subject: [PATCH 27/93] Only do this if the admin player isn't the server host also. --- src/d_netcmd.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index bf26ca61..74212400 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2697,6 +2697,12 @@ static void Command_Login_f(void) XBOXSTATIC UINT8 finalmd5[16]; const char *pw; + if (!netgame) + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + // If the server uses login, it will effectively just remove admin privileges // from whoever has them. This is good. if (COM_Argc() != 2) @@ -2764,6 +2770,12 @@ static void Command_Verify_f(void) return; } + if (!netgame) + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + if (COM_Argc() != 2) { CONS_Printf(M_GetText("verify : give admin privileges to a node\n")); @@ -3075,7 +3087,7 @@ static void Command_Addfile(void) WRITEMEM(buf_p, md5sum, 16); } - if (adminplayer == consoleplayer) // Request to add file + if (adminplayer == consoleplayer && (!server)) // Request to add file SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); else SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); From 24aafa6dacaa03a73674ef049ceeae102693438f Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 15:43:36 +0100 Subject: [PATCH 28/93] UDP_Socket: Add missing limit checks for s, for client and broadcast addresses --- src/i_tcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 6488e984..5c660666 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1044,7 +1044,7 @@ static boolean UDP_Socket(void) if (gaie == 0) { runp = ai; - while (runp != NULL) + while (runp != NULL && s < MAXNETNODES+1) { memcpy(&clientaddress[s], runp->ai_addr, runp->ai_addrlen); s++; @@ -1064,7 +1064,7 @@ static boolean UDP_Socket(void) if (gaie == 0) { runp = ai; - while (runp != NULL) + while (runp != NULL && s < MAXNETNODES+1) { memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen); s++; @@ -1087,7 +1087,7 @@ static boolean UDP_Socket(void) if (gaie == 0) { runp = ai; - while (runp != NULL) + while (runp != NULL && s < MAXNETNODES+1) { memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen); s++; From 846bddfdcf9514e8164bd1157c58ab2ac614ae8a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 15:52:22 +0100 Subject: [PATCH 29/93] SOCK_Send: Fix what appears to be a mistaken use of i instead of j --- src/i_tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 5c660666..3b609914 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -707,10 +707,10 @@ static void SOCK_Send(void) { if (myfamily[i] == broadcastaddress[j].any.sa_family) { - if (broadcastaddress[i].any.sa_family == AF_INET) + if (broadcastaddress[j].any.sa_family == AF_INET) d = d4; #ifdef HAVE_IPV6 - else if (broadcastaddress[i].any.sa_family == AF_INET6) + else if (broadcastaddress[j].any.sa_family == AF_INET6) d = d6; #endif else From 7b083f07cd306ca8790427b0257ca1f06f7d3a3e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 15:56:02 +0100 Subject: [PATCH 30/93] UDP_Socket: I doubt client addresses are meant to be included in the total for broadcast addresses --- src/i_tcp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i_tcp.c b/src/i_tcp.c index 3b609914..d11be428 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1059,6 +1059,9 @@ static boolean UDP_Socket(void) clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip s++; } + + s = 0; + // setup broadcast adress to BROADCASTADDR entry gaie = I_getaddrinfo("255.255.255.255", "0", &hints, &ai); if (gaie == 0) From ea06e8a62b42d4e85112742ca668a7a6495beaf9 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 3 Sep 2018 20:53:40 +0100 Subject: [PATCH 31/93] SOCK_Send: Split the actual sending data parts into a new function, SOCK_SendToAddr, to make everything look a bit neater in general --- src/i_tcp.c | 59 ++++++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index d11be428..16e7bf2f 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -686,14 +686,29 @@ static boolean SOCK_CanGet(void) #endif #ifndef NONET -static void SOCK_Send(void) +static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr) { - ssize_t c = ERRSOCKET; socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); #ifdef HAVE_IPV6 socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6); #endif socklen_t d, da = (socklen_t)sizeof(mysockaddr_t); + + switch (sockaddr->any.sa_family) + { + case AF_INET: d = d4; break; +#ifdef HAVE_IPV6 + case AF_INET6: d = d6; break; +#endif + default: d = da; break; + } + + return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); +} + +static void SOCK_Send(void) +{ + ssize_t c = ERRSOCKET; size_t i, j; if (!nodeconnected[doomcom->remotenode]) @@ -706,19 +721,7 @@ static void SOCK_Send(void) for (j = 0; j < broadcastaddresses; j++) { if (myfamily[i] == broadcastaddress[j].any.sa_family) - { - if (broadcastaddress[j].any.sa_family == AF_INET) - d = d4; -#ifdef HAVE_IPV6 - else if (broadcastaddress[j].any.sa_family == AF_INET6) - d = d6; -#endif - else - d = da; - - c = sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0, - &broadcastaddress[j].any, d); - } + SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); } } return; @@ -728,35 +731,13 @@ static void SOCK_Send(void) for (i = 0; i < mysocketses; i++) { if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) - { - if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET) - d = d4; -#ifdef HAVE_IPV6 - else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6) - d = d6; -#endif - else - d = da; - - sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0, - &clientaddress[doomcom->remotenode].any, d); - } + SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); } return; } else { - if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET) - d = d4; -#ifdef HAVE_IPV6 - else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6) - d = d6; -#endif - else - d = da; - - c = sendto(nodesocket[doomcom->remotenode], (char *)&doomcom->data, doomcom->datalength, 0, - &clientaddress[doomcom->remotenode].any, d); + c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], &clientaddress[doomcom->remotenode]); } if (c == ERRSOCKET && errno != ECONNREFUSED && errno != EWOULDBLOCK) From c32c72c401b16d15184b1821cb52ff9e80717910 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 7 Sep 2018 18:14:52 -0400 Subject: [PATCH 32/93] Thwomp fix: Don't trigger (look for players) when ~FF_EXISTS --- src/p_floor.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index f3063765..f3dda23b 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1818,6 +1818,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) #define ceilingwasheight vars[5] fixed_t thwompx, thwompy; sector_t *actionsector; + ffloor_t *rover = NULL; INT32 secnum; // If you just crashed down, wait a second before coming back up. @@ -1832,7 +1833,16 @@ void T_ThwompSector(levelspecthink_t *thwomp) secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); if (secnum > 0) + { actionsector = §ors[secnum]; + + // Look for thwomp FFloor + for (rover = actionsector->ffloors; rover; rover = rover->next) + { + if (rover->master == thwomp->sourceline) + break; + } + } else return; // Bad bad bad! @@ -1921,10 +1931,13 @@ void T_ThwompSector(levelspecthink_t *thwomp) { mobj_t *mp = (void *)&actionsector->soundorg; - if (thwomp->sourceline->flags & ML_EFFECT4) - S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); - else - S_StartSound(mp, sfx_thwomp); + if (!rover || (rover->flags & FF_EXISTS)) + { + if (thwomp->sourceline->flags & ML_EFFECT4) + S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); + else + S_StartSound(mp, sfx_thwomp); + } thwomp->direction = 1; // start heading back up thwomp->distance = TICRATE; // but only after a small delay @@ -1938,18 +1951,21 @@ void T_ThwompSector(levelspecthink_t *thwomp) thinker_t *th; mobj_t *mo; - // scan the thinkers to find players! - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (!rover || (rover->flags & FF_EXISTS)) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight - && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) + // scan the thinkers to find players! + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - thwomp->direction = -1; - break; + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo = (mobj_t *)th; + if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight + && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) + { + thwomp->direction = -1; + break; + } } } From 89a6694d6743375e3dbaaabfec48f7e12d1f9cfb Mon Sep 17 00:00:00 2001 From: Digiku Date: Thu, 13 Sep 2018 11:30:00 -0400 Subject: [PATCH 33/93] Don't trigger thwomp on spectators --- src/p_floor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_floor.c b/src/p_floor.c index f3dda23b..e613b5ed 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1960,7 +1960,8 @@ void T_ThwompSector(levelspecthink_t *thwomp) continue; mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->z <= thwomp->sector->ceilingheight + if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator + && mo->z <= thwomp->sector->ceilingheight && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) { thwomp->direction = -1; From f8834b02019b03c9bead2414a28f790d6ce933f9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 25 Mar 2018 19:07:21 -0400 Subject: [PATCH 34/93] MT_NIGHTSBUMPER Spawn: Don't reset mthing->options (cherry picked from commit dc9fd6f02ed4b681ed4982d119672f07cc91e585) --- src/p_mobj.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5f85474c..1e2fe4f8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9194,9 +9194,6 @@ ML_NOCLIMB : Direction not controllable // the bumper in 30 degree increments. mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc P_SetMobjState(mobj, mobj->info->spawnstate+mobj->threshold); - - // you can shut up now, OBJECTFLIP. And all of the other options, for that matter. - mthing->options &= ~0xF; break; case MT_EGGCAPSULE: if (mthing->angle <= 0) From b666fa3131ec391f85dfc1cc56de047ebaf53ec2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 25 Mar 2018 19:42:46 -0400 Subject: [PATCH 35/93] P_SpawnMapThing: Ignore MTF_ flags if MT_NIGHTSBUMPER (cherry picked from commit d85f108997bfeca3e0b1731c1aad70617456400b) --- src/p_mobj.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1e2fe4f8..a146027b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9381,6 +9381,14 @@ ML_NOCLIMB : Direction not controllable } } + // ignore MTF_ flags and return early + if (i == MT_NIGHTSBUMPER) + { + mobj->angle = FixedAngle(mthing->angle*FRACUNIT); + mthing->mobj = mobj; + return; + } + mobj->angle = FixedAngle(mthing->angle*FRACUNIT); if ((mthing->options & MTF_AMBUSH) From ba7d97733dc9dd3529689ee81ce21afe63fb3e9d Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 26 Mar 2018 00:33:17 -0400 Subject: [PATCH 36/93] Fix NiGHTS drone loop detection by using pl->flyangle (cherry picked from commit 67e438128435aca992e2d45aa1f35603c5501984) --- src/p_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index f319acea..acaa2a99 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -777,14 +777,14 @@ static boolean PIT_CheckThing(mobj_t *thing) // not (your direction) xor (stored direction) // In other words, you can't u-turn and respawn rings near the drone. if (pl->bonustime && (pl->pflags & PF_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && ( - !(pl->anotherflyangle >= 90 && pl->anotherflyangle <= 270) + !(pl->flyangle >= 90 && pl->flyangle <= 270) ^ (droneobj->extravalue1 >= 90 && droneobj->extravalue1 <= 270) )) { // Reload all the fancy ring stuff! P_ReloadRings(); } - droneobj->extravalue1 = pl->anotherflyangle; + droneobj->extravalue1 = pl->flyangle; droneobj->extravalue2 = (INT32)leveltime + TICRATE; } From 25361713dc2841e0e4ef22923489faf9364bf200 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 26 Mar 2018 01:04:02 -0400 Subject: [PATCH 37/93] NiGHTS drone loop: Change flyangle comparison to fix detection from vertical angles Use > 90 && < 270 instead of >= 90 && <= 270. Fixes a bug where if you fly directly up (flyangle 90) or directly down (flyangle 270), that registers as a backwards direction, so you trigger the loop detection by flying BACKWARDS, not FORWARDS. This edge case (only possible via JUMPTOAXIS) should default to FORWARDS looping. (cherry picked from commit ce215195f89bf52e5c2e2ddd7d5444685edf835d) --- src/p_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index acaa2a99..28c6045c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -777,8 +777,8 @@ static boolean PIT_CheckThing(mobj_t *thing) // not (your direction) xor (stored direction) // In other words, you can't u-turn and respawn rings near the drone. if (pl->bonustime && (pl->pflags & PF_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && ( - !(pl->flyangle >= 90 && pl->flyangle <= 270) - ^ (droneobj->extravalue1 >= 90 && droneobj->extravalue1 <= 270) + !(pl->flyangle > 90 && pl->flyangle < 270) + ^ (droneobj->extravalue1 > 90 && droneobj->extravalue1 < 270) )) { // Reload all the fancy ring stuff! From 546fa383c1c74499552e031b11020ed71a6d8561 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 14 Sep 2018 21:01:07 +0100 Subject: [PATCH 38/93] Make sure that T_MarioBlockChecker is synced in netgames, so that the textures of Mario Blocks can change when there are no more items --- src/p_saveg.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index d1ec8e5a..6e0c704f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -950,6 +950,7 @@ typedef enum tc_bouncecheese, tc_startcrumble, tc_marioblock, + tc_marioblockchecker, tc_spikesector, tc_floatsector, tc_bridgethinker, @@ -1774,6 +1775,11 @@ static void P_NetArchiveThinkers(void) SaveSpecialLevelThinker(th, tc_marioblock); continue; } + else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) + { + SaveSpecialLevelThinker(th, tc_marioblockchecker); + continue; + } else if (th->function.acp1 == (actionf_p1)T_SpikeSector) { SaveSpecialLevelThinker(th, tc_spikesector); @@ -2730,6 +2736,10 @@ static void P_NetUnArchiveThinkers(void) LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3); break; + case tc_marioblockchecker: + LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0); + break; + case tc_spikesector: LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0); break; From 20c4702986f6f3f99d30bf3efe19a10bc13141cc Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 17 Sep 2018 14:12:16 -0400 Subject: [PATCH 39/93] Line exec trigger netsync: Save var2s in addition to vars --- src/p_saveg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 6e0c704f..6010a1d2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1260,7 +1260,10 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type) size_t i; WRITEUINT8(save_p, type); for (i = 0; i < 16; i++) + { WRITEFIXED(save_p, ht->vars[i]); //var[16] + WRITEFIXED(save_p, ht->var2s[i]); //var[16] + } WRITEUINT32(save_p, SaveLine(ht->sourceline)); WRITEUINT32(save_p, SaveSector(ht->sector)); } @@ -2163,7 +2166,10 @@ static void LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling) size_t i; ht->thinker.function.acp1 = thinker; for (i = 0; i < 16; i++) + { ht->vars[i] = READFIXED(save_p); //var[16] + ht->var2s[i] = READFIXED(save_p); //var[16] + } ht->sourceline = LoadLine(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p)); From 800b3bb2407f793730b88f2b6c70c583f3a2f8a8 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 30 Sep 2018 22:18:48 +0100 Subject: [PATCH 40/93] Move player + player mobj existence checks to top of P_MoveChaseCamera. This is the only place it makes sense to even check them tbh. While I'm at it, let's also use the "mo" variable instead of player->mo throughout the function (to be consistent) --- src/p_user.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index da8e19ca..91b5feb8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7853,7 +7853,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; fixed_t f1, f2; - cameranoclip = (player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) || (player->mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! + // We probably shouldn't move the camera if there is no player or player mobj somehow + if (!player || !player->mo) + return true; + + mo = player->mo; + + cameranoclip = (player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) || (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! if (!(player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD)) { @@ -7874,7 +7880,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else if (player == &players[secondarydisplayplayer]) focusangle = localangle2; else - focusangle = player->mo->angle; + focusangle = mo->angle; if (thiscam == &camera) camrotate = cv_cam_rotate.value; else if (thiscam == &camera2) @@ -7886,17 +7892,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall return true; } - if (!player || !player->mo) - return true; - - mo = player->mo; - thiscam->radius = FixedMul(20*FRACUNIT, mo->scale); thiscam->height = FixedMul(16*FRACUNIT, mo->scale); - if (!mo) - return true; - // Don't run while respawning from a starpost // Inu 4/8/13 Why not?! // if (leveltime > 0 && timeinmap <= 0) @@ -7904,7 +7902,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->pflags & PF_NIGHTSMODE) { - focusangle = player->mo->angle; + focusangle = mo->angle; focusaiming = 0; } else if (player == &players[consoleplayer]) @@ -7919,7 +7917,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } else { - focusangle = player->mo->angle; + focusangle = mo->angle; focusaiming = player->aiming; } @@ -7966,12 +7964,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall angle = R_PointToAngle2(player->axis1->x, player->axis1->y, player->axis2->x, player->axis2->y); angle += ANGLE_90; } - else if (player->mo->target) + else if (mo->target) { - if (player->mo->target->flags & MF_AMBUSH) - angle = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y); + if (mo->target->flags & MF_AMBUSH) + angle = R_PointToAngle2(mo->target->x, mo->target->y, mo->x, mo->y); else - angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->target->x, player->mo->target->y); + angle = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y); } } else if (P_AnalogMove(player)) // Analog @@ -8066,7 +8064,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (twodlevel || (mo->flags2 & MF2_TWOD)) { // Camera doesn't ALWAYS need to move, only when running... - if (abs(player->mo->momx) > 10) + if (abs(mo->momx) > 10) { // Move the camera all smooth-like, not jerk it around... if (mo->momx > 0) @@ -8384,13 +8382,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall vy = thiscam->y; } - if (P_AproxDistance(vx - player->mo->x, vy - player->mo->y) < FixedMul(48*FRACUNIT, mo->scale)) - player->mo->flags2 |= MF2_SHADOW; + if (P_AproxDistance(vx - mo->x, vy - mo->y) < FixedMul(48*FRACUNIT, mo->scale)) + mo->flags2 |= MF2_SHADOW; else - player->mo->flags2 &= ~MF2_SHADOW; + mo->flags2 &= ~MF2_SHADOW; } else - player->mo->flags2 &= ~MF2_SHADOW; + mo->flags2 &= ~MF2_SHADOW; /* if (!resetcalled && (player->pflags & PF_NIGHTSMODE && player->exiting)) { From c1d5c711a940fc2e66cbfe53571be01f8bee9420 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 19 Apr 2017 20:00:19 +0100 Subject: [PATCH 41/93] Be gone ye old texture hack --- src/r_data.c | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index f2c9b146..ee9144b7 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -472,40 +472,22 @@ void R_LoadTextures(void) } else { - UINT16 patchcount = 1; //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); - if (SHORT(patchlump->width) == 64 - && SHORT(patchlump->height) == 64) - { // 64x64 patch - const column_t *column; - for (k = 0; k < SHORT(patchlump->width); k++) - { // Find use of transparency. - column = (const column_t *)((const UINT8 *)patchlump + LONG(patchlump->columnofs[k])); - if (column->length != SHORT(patchlump->height)) - break; - } - if (k == SHORT(patchlump->width)) - patchcount = 2; // No transparency? 64x128 texture. - } - texture = textures[i] = Z_Calloc(sizeof(texture_t) + (sizeof(texpatch_t) * patchcount), PU_STATIC, NULL); + texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); // Set texture properties. M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name)); texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height)*patchcount; - texture->patchcount = patchcount; + texture->height = SHORT(patchlump->height); + texture->patchcount = 1; texture->holes = false; // Allocate information for the texture's patches. - for (k = 0; k < patchcount; k++) - { - patch = &texture->patches[k]; + patch = &texture->patches[0]; - patch->originx = 0; - patch->originy = (INT16)(k*patchlump->height); - patch->wad = (UINT16)w; - patch->lump = texstart + j; - } + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; Z_Unlock(patchlump); From 31f3f8b8e787f41e4c22ac2d84130f0a02861912 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 18 May 2017 16:54:58 +0100 Subject: [PATCH 42/93] Moved Y_EndGame from y_inter.c/h to g_game.c/h, renamed it to G_EndGame --- src/f_finale.c | 4 ++-- src/g_game.c | 34 +++++++++++++++++++++++++++++++++- src/g_game.h | 1 + src/y_inter.c | 33 +-------------------------------- src/y_inter.h | 1 - 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index a8b27bb8..0a448692 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1733,7 +1733,7 @@ static void F_AdvanceToNextScene(void) void F_EndCutScene(void) { - cutsceneover = true; // do this first, just in case Y_EndGame or something wants to turn it back false later + cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later if (runningprecutscene) { if (server) @@ -1748,7 +1748,7 @@ void F_EndCutScene(void) else if (nextmap < 1100-1) G_NextLevel(); else - Y_EndGame(); + G_EndGame(); } } diff --git a/src/g_game.c b/src/g_game.c index 4f1c49b4..25730ce7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2911,7 +2911,7 @@ void G_AfterIntermission(void) if (nextmap < 1100-1) G_NextLevel(); else - Y_EndGame(); + G_EndGame(); } } @@ -2997,6 +2997,38 @@ static void G_DoContinued(void) gameaction = ga_nothing; } +// +// G_EndGame (formerly Y_EndGame) +// Franky this function fits better in g_game.c than it does in y_inter.c +// +// ...Gee, (why) end the game? +// Because Y_FollowIntermission and F_EndCutscene would +// both do this exact same thing *in different ways* otherwise, +// which made it so that you could only unlock Ultimate mode +// if you had a cutscene after the final level and crap like that. +// This function simplifies it so only one place has to be updated +// when something new is added. +void G_EndGame(void) +{ + // Only do evaluation and credits in coop games. + if (gametype == GT_COOP) + { + if (nextmap == 1102-1) // end game with credits + { + F_StartCredits(); + return; + } + if (nextmap == 1101-1) // end game with evaluation + { + F_StartGameEvaluation(); + return; + } + } + + // 1100 or competitive multiplayer, so go back to title screen. + D_StartTitle(); +} + // // G_LoadGameSettings // diff --git a/src/g_game.h b/src/g_game.h index ada82404..196ba2ea 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -171,6 +171,7 @@ void G_NextLevel(void); void G_Continue(void); void G_UseContinue(void); void G_AfterIntermission(void); +void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); diff --git a/src/y_inter.c b/src/y_inter.c index e7df165b..37c59730 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1794,37 +1794,6 @@ void Y_EndIntermission(void) usebuffer = false; } -// -// Y_EndGame -// -// Why end the game? -// Because Y_FollowIntermission and F_EndCutscene would -// both do this exact same thing *in different ways* otherwise, -// which made it so that you could only unlock Ultimate mode -// if you had a cutscene after the final level and crap like that. -// This function simplifies it so only one place has to be updated -// when something new is added. -void Y_EndGame(void) -{ - // Only do evaluation and credits in coop games. - if (gametype == GT_COOP) - { - if (nextmap == 1102-1) // end game with credits - { - F_StartCredits(); - return; - } - if (nextmap == 1101-1) // end game with evaluation - { - F_StartGameEvaluation(); - return; - } - } - - // 1100 or competitive multiplayer, so go back to title screen. - D_StartTitle(); -} - // // Y_FollowIntermission // @@ -1850,7 +1819,7 @@ static void Y_FollowIntermission(void) return; } - Y_EndGame(); + G_EndGame(); } #define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL diff --git a/src/y_inter.h b/src/y_inter.h index 9fe95fcc..26f7dc39 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -15,7 +15,6 @@ void Y_IntermissionDrawer(void); void Y_Ticker(void); void Y_StartIntermission(void); void Y_EndIntermission(void); -void Y_EndGame(void); typedef enum { From 2bb7df5f49d90ac9f8c4d80ec5bbfeb11c9a064e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 18 May 2017 17:10:44 +0100 Subject: [PATCH 43/93] G_ExitLevel tweak: Use HU_ClearCEcho() instead of HU_DoCEcho(""), the latter causes an empty line to appear in log.txt --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 25730ce7..d145fcbe 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2615,7 +2615,7 @@ void G_ExitLevel(void) CONS_Printf(M_GetText("The round has ended.\n")); // Remove CEcho text on round end. - HU_DoCEcho(""); + HU_ClearCEcho(); } } From feceaf6d30144e19ef64e773705b637b242c7b05 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 18 May 2017 17:23:19 +0100 Subject: [PATCH 44/93] Removed all code in Y_FollowIntermission that's already handled in G_AfterIntermission Only real difference here is that CEcho messages will always be cleared when going to credits/evaluation, but that's hardly a loss tbh. --- src/g_game.c | 4 ++-- src/y_inter.c | 19 ++++--------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d145fcbe..b8df32f9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2999,10 +2999,10 @@ static void G_DoContinued(void) // // G_EndGame (formerly Y_EndGame) -// Franky this function fits better in g_game.c than it does in y_inter.c +// Frankly this function fits better in g_game.c than it does in y_inter.c // // ...Gee, (why) end the game? -// Because Y_FollowIntermission and F_EndCutscene would +// Because G_AfterIntermission and F_EndCutscene would // both do this exact same thing *in different ways* otherwise, // which made it so that you could only unlock Ultimate mode // if you had a cutscene after the final level and crap like that. diff --git a/src/y_inter.c b/src/y_inter.c index 37c59730..9d41caf3 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1805,21 +1805,10 @@ static void Y_FollowIntermission(void) return; } - if (nextmap < 1100-1) - { - // normal level - G_AfterIntermission(); - return; - } - - // Start a custom cutscene if there is one. - if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking) - { - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); - return; - } - - G_EndGame(); + // This handles whether to play a post-level cutscene, end the game, + // or simply go to the next level. + // No need to duplicate the code here! + G_AfterIntermission(); } #define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL From 61fa7026a107e30688bf836e0fc7c6a7c9f77861 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 20 Oct 2018 19:00:37 +0100 Subject: [PATCH 45/93] add vector2 and vector3 userdata types to simplify getting a slope's o/d/normal --- src/lua_libs.h | 2 ++ src/lua_maplib.c | 82 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/lua_libs.h b/src/lua_libs.h index bf7fe03e..a9c82bce 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -39,6 +39,8 @@ extern lua_State *gL; #define META_SECTOR "SECTOR_T*" #define META_FFLOOR "FFLOOR_T*" #define META_SLOPE "PSLOPE_T*" +#define META_VECTOR2 "VECTOR2_T" +#define META_VECTOR3 "VECTOR3_T" #define META_MAPHEADER "MAPHEADER_T*" #define META_CVAR "CONSVAR_T*" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 7a94060e..e769a00d 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -223,6 +223,19 @@ static const char *const slope_opt[] = { "flags", NULL}; +// shared by both vector2_t and vector3_t +enum vector_e { + vector_x = 0, + vector_y, + vector_z +}; + +static const char *const vector_opt[] = { + "x", + "y", + "z", + NULL}; + static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -1232,32 +1245,16 @@ static int slope_get(lua_State *L) lua_pushboolean(L, 1); return 1; case slope_o: // o - lua_createtable(L, 0, 3); - lua_pushfixed(L, slope->o.x); - lua_setfield(L, -2, "x"); - lua_pushfixed(L, slope->o.y); - lua_setfield(L, -2, "y"); - lua_pushfixed(L, slope->o.z); - lua_setfield(L, -2, "z"); + LUA_PushUserdata(L, &slope->o, META_VECTOR3); return 1; case slope_d: // d - lua_createtable(L, 0, 2); - lua_pushfixed(L, slope->d.x); - lua_setfield(L, -2, "x"); - lua_pushfixed(L, slope->d.y); - lua_setfield(L, -2, "y"); + LUA_PushUserdata(L, &slope->d, META_VECTOR2); return 1; case slope_zdelta: // zdelta lua_pushfixed(L, slope->zdelta); return 1; case slope_normal: // normal - lua_createtable(L, 0, 3); - lua_pushfixed(L, slope->normal.x); - lua_setfield(L, -2, "x"); - lua_pushfixed(L, slope->normal.y); - lua_setfield(L, -2, "y"); - lua_pushfixed(L, slope->normal.z); - lua_setfield(L, -2, "z"); + LUA_PushUserdata(L, &slope->normal, META_VECTOR3); return 1; case slope_zangle: // zangle lua_pushangle(L, slope->zangle); @@ -1358,6 +1355,43 @@ static int slope_set(lua_State *L) return 0; } +static int vector2_get(lua_State *L) +{ + vector2_t *vec = *((vector2_t **)luaL_checkudata(L, 1, META_VECTOR2)); + enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt); + + if (!vec) + return luaL_error(L, "accessed vector2_t doesn't exist anymore."); + + switch(field) + { + case vector_x: lua_pushfixed(L, vec->x); return 1; + case vector_y: lua_pushfixed(L, vec->y); return 1; + default: break; + } + + return 0; +} + +static int vector3_get(lua_State *L) +{ + vector3_t *vec = *((vector3_t **)luaL_checkudata(L, 1, META_VECTOR3)); + enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt); + + if (!vec) + return luaL_error(L, "accessed vector3_t doesn't exist anymore."); + + switch(field) + { + case vector_x: lua_pushfixed(L, vec->x); return 1; + case vector_y: lua_pushfixed(L, vec->y); return 1; + case vector_z: lua_pushfixed(L, vec->z); return 1; + default: break; + } + + return 0; +} + static int lib_getMapheaderinfo(lua_State *L) { // i -> mapheaderinfo[i-1] @@ -1542,6 +1576,16 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + luaL_newmetatable(L, META_VECTOR2); + lua_pushcfunction(L, vector2_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_VECTOR3); + lua_pushcfunction(L, vector3_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); lua_setfield(L, -2, "__index"); From 4edeeb69539267dce61e9841c564632dc6cad20d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 20 Oct 2018 21:08:59 +0100 Subject: [PATCH 46/93] Add P_GetZAt to Lua --- src/lua_baselib.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e8e8fd02..f60756f1 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -14,6 +14,9 @@ #ifdef HAVE_BLUA #include "p_local.h" #include "p_setup.h" // So we can have P_SetupLevelSky +#ifdef ESLOPE +#include "p_slopes.h" // P_GetZAt +#endif #include "z_zone.h" #include "r_main.h" #include "r_things.h" @@ -1547,6 +1550,24 @@ static int lib_evCrumbleChain(lua_State *L) return 0; } +#ifdef ESLOPE +// P_SLOPES +//////////// + +static int lib_pGetZAt(lua_State *L) +{ + pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + //HUDSAFE + if (!slope) + return LUA_ErrInvalid(L, "pslope_t"); + + lua_pushfixed(L, P_GetZAt(slope, x, y)); + return 1; +} +#endif + // R_DEFS //////////// @@ -2113,6 +2134,11 @@ static luaL_Reg lib[] = { {"P_StartQuake",lib_pStartQuake}, {"EV_CrumbleChain",lib_evCrumbleChain}, +#ifdef ESLOPE + // p_slopes + {"P_GetZAt",lib_pGetZAt}, +#endif + // r_defs {"R_PointToAngle",lib_rPointToAngle}, {"R_PointToAngle2",lib_rPointToAngle2}, From 9296aaa28c720057b4b0752c82256701ee0ae6ac Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 20 Oct 2018 23:36:06 +0100 Subject: [PATCH 47/93] zangle should be shifted down by ANGLETOFINESHIFT if we're to use FINETANGENT on it --- src/lua_maplib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index e769a00d..7635ded1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1344,7 +1344,7 @@ static int slope_set(lua_State *L) } case slope_zangle: // zangle slope->zangle = luaL_checkangle(L, 3); - slope->zdelta = FINETANGENT(slope->zangle); + slope->zdelta = FINETANGENT(slope->zangle>>ANGLETOFINESHIFT); P_CalculateSlopeNormal(slope); break; case slope_xydirection: // xydirection From 2ec4f2024f784af6bc5562cbd0e5f62d5d722d1a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 21 Oct 2018 15:00:07 +0100 Subject: [PATCH 48/93] Added support for pslope_t userdata variables in Lua archive/unarchive code --- src/lua_script.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index ddfbf5c7..0440efd5 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -22,6 +22,9 @@ #include "byteptr.h" #include "p_saveg.h" #include "p_local.h" +#ifdef ESLOPE +#include "p_slopes.h" // for P_SlopeById +#endif #ifdef LUA_ALLOW_BYTECODE #include "d_netfil.h" // for LUA_DumpFile #endif @@ -457,6 +460,9 @@ enum ARCH_SIDE, ARCH_SUBSECTOR, ARCH_SECTOR, +#ifdef ESLOPE + ARCH_SLOPE, +#endif ARCH_MAPHEADER, ARCH_TEND=0xFF, @@ -476,6 +482,9 @@ static const struct { {META_SIDE, ARCH_SIDE}, {META_SUBSECTOR,ARCH_SUBSECTOR}, {META_SECTOR, ARCH_SECTOR}, +#ifdef ESLOPE + {META_SLOPE, ARCH_SLOPE}, +#endif {META_MAPHEADER, ARCH_MAPHEADER}, {NULL, ARCH_NULL} }; @@ -680,6 +689,19 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } +#ifdef ESLOPE + case ARCH_SLOPE: + { + pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); + if (!slope) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_SLOPE); + WRITEUINT16(save_p, slope->id); + } + break; + } +#endif case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); @@ -884,6 +906,11 @@ static UINT8 UnArchiveValue(int TABLESINDEX) case ARCH_SECTOR: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_SECTOR); break; +#ifdef ESLOPE + case ARCH_SLOPE: + LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE); + break; +#endif case ARCH_MAPHEADER: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_MAPHEADER); break; From efff869e6e1e15b616f425ba84ce4d339e7052e3 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 21 Oct 2018 15:12:51 +0100 Subject: [PATCH 49/93] Add mobj.standingslope to Lua --- src/lua_mobjlib.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 6bb1388f..05091f12 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -80,7 +80,12 @@ enum mobj_e { mobj_extravalue1, mobj_extravalue2, mobj_cusval, +#ifdef ESLOPE + mobj_cvmem, + mobj_standingslope +#else mobj_cvmem +#endif }; static const char *const mobj_opt[] = { @@ -140,6 +145,9 @@ static const char *const mobj_opt[] = { "extravalue2", "cusval", "cvmem", +#ifdef ESLOPE + "standingslope", +#endif NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -343,6 +351,11 @@ static int mobj_get(lua_State *L) case mobj_cvmem: lua_pushinteger(L, mo->cvmem); break; +#ifdef ESLOPE + case mobj_standingslope: + LUA_PushUserdata(L, mo->standingslope, META_SLOPE); + break; +#endif default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -634,6 +647,10 @@ static int mobj_set(lua_State *L) case mobj_cvmem: mo->cvmem = luaL_checkinteger(L, 3); break; +#ifdef ESLOPE + case mobj_standingslope: + return NOSET; +#endif default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); From e15ed742c124f556ebebd4983e9f09136fa7cca3 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 21 Oct 2018 16:27:54 +0100 Subject: [PATCH 50/93] add ESLOPE ifdef checks around all the Lua slope support code that was there before I was involved --- src/dehacked.c | 2 ++ src/lua_libs.h | 2 ++ src/lua_maplib.c | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 251b0532..d470c7fa 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7261,11 +7261,13 @@ struct { {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. +#ifdef ESLOPE // Slope flags {"SL_NOPHYSICS",SL_NOPHYSICS}, // Don't do momentum adjustment with this slope {"SL_NODYNAMIC",SL_NODYNAMIC}, // Slope will never need to move during the level, so don't fuss with recalculating it {"SL_ANCHORVERTEX",SL_ANCHORVERTEX},// Slope is using a Slope Vertex Thing to anchor its position {"SL_VERTEXSLOPE",SL_VERTEXSLOPE}, // Slope is built from three Slope Vertex Things +#endif // Angles {"ANG1",ANG1}, diff --git a/src/lua_libs.h b/src/lua_libs.h index a9c82bce..15d988ef 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -38,9 +38,11 @@ extern lua_State *gL; #define META_SUBSECTOR "SUBSECTOR_T*" #define META_SECTOR "SECTOR_T*" #define META_FFLOOR "FFLOOR_T*" +#ifdef ESLOPE #define META_SLOPE "PSLOPE_T*" #define META_VECTOR2 "VECTOR2_T" #define META_VECTOR3 "VECTOR3_T" +#endif #define META_MAPHEADER "MAPHEADER_T*" #define META_CVAR "CONSVAR_T*" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 7635ded1..d8363429 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -40,10 +40,14 @@ enum sector_e { sector_heightsec, sector_camsec, sector_lines, +#ifdef ESLOPE sector_ffloors, sector_fslope, sector_cslope, sector_hasslope +#else + sector_ffloors +#endif }; static const char *const sector_opt[] = { @@ -60,9 +64,11 @@ static const char *const sector_opt[] = { "camsec", "lines", "ffloors", +#ifdef ESLOPE "f_slope", "c_slope", "hasslope", +#endif NULL}; enum subsector_e { @@ -168,8 +174,10 @@ enum ffloor_e { ffloor_toplightlevel, ffloor_bottomheight, ffloor_bottompic, +#ifdef ESLOPE ffloor_tslope, ffloor_bslope, +#endif ffloor_sector, ffloor_flags, ffloor_master, @@ -186,8 +194,10 @@ static const char *const ffloor_opt[] = { "toplightlevel", "bottomheight", "bottompic", +#ifdef ESLOPE "t_slope", "b_slope", +#endif "sector", // secnum pushed as control sector userdata "flags", "master", // control linedef @@ -197,6 +207,7 @@ static const char *const ffloor_opt[] = { "alpha", NULL}; +#ifdef ESLOPE enum slope_e { slope_valid = 0, slope_o, @@ -235,6 +246,7 @@ static const char *const vector_opt[] = { "y", "z", NULL}; +#endif static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -450,6 +462,7 @@ static int sector_get(lua_State *L) LUA_PushUserdata(L, sector->ffloors, META_FFLOOR); lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateFFloors and sector->ffloors as upvalues for the function return 1; +#ifdef ESLOPE case sector_fslope: // f_slope LUA_PushUserdata(L, sector->f_slope, META_SLOPE); return 1; @@ -459,6 +472,7 @@ static int sector_get(lua_State *L) case sector_hasslope: // hasslope lua_pushboolean(L, sector->hasslope); return 1; +#endif } return 0; } @@ -481,9 +495,11 @@ static int sector_set(lua_State *L) case sector_heightsec: // heightsec case sector_camsec: // camsec case sector_ffloors: // ffloors +#ifdef ESLOPE case sector_fslope: // f_slope case sector_cslope: // c_slope case sector_hasslope: // hasslope +#endif default: return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); case sector_floorheight: { // floorheight @@ -1118,12 +1134,14 @@ static int ffloor_get(lua_State *L) lua_pushlstring(L, levelflat->name, 8); return 1; } +#ifdef ESLOPE case ffloor_tslope: LUA_PushUserdata(L, *ffloor->t_slope, META_SLOPE); return 1; case ffloor_bslope: LUA_PushUserdata(L, *ffloor->b_slope, META_SLOPE); return 1; +#endif case ffloor_sector: LUA_PushUserdata(L, §ors[ffloor->secnum], META_SECTOR); return 1; @@ -1163,8 +1181,10 @@ static int ffloor_set(lua_State *L) switch(field) { case ffloor_valid: // valid +#ifdef ESLOPE case ffloor_tslope: // t_slope case ffloor_bslope: // b_slope +#endif case ffloor_sector: // sector case ffloor_master: // master case ffloor_target: // target @@ -1225,6 +1245,7 @@ static int ffloor_set(lua_State *L) return 0; } +#ifdef ESLOPE static int slope_get(lua_State *L) { pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); @@ -1391,6 +1412,7 @@ static int vector3_get(lua_State *L) return 0; } +#endif static int lib_getMapheaderinfo(lua_State *L) { @@ -1568,6 +1590,7 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); +#ifdef ESLOPE luaL_newmetatable(L, META_SLOPE); lua_pushcfunction(L, slope_get); lua_setfield(L, -2, "__index"); @@ -1585,6 +1608,7 @@ int LUA_MapLib(lua_State *L) lua_pushcfunction(L, vector3_get); lua_setfield(L, -2, "__index"); lua_pop(L, 1); +#endif luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); From 3ec8743c1bbdec71ecaa7d4d4cd41a3f00f1516c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 21 Oct 2018 17:32:53 +0100 Subject: [PATCH 51/93] Fix up the ability to edit slope zdelta and zangle with Lua (zangle is untested as of writing) --- src/lua_maplib.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index d8363429..975ea1cb 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1359,15 +1359,19 @@ static int slope_set(lua_State *L) } case slope_zdelta: { // zdelta, this is temp until i figure out wtf to do slope->zdelta = luaL_checkfixed(L, 3); - slope->zangle = R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta); + slope->zangle = R_PointToAngle2(0, 0, FRACUNIT, -slope->zdelta); P_CalculateSlopeNormal(slope); break; } - case slope_zangle: // zangle - slope->zangle = luaL_checkangle(L, 3); - slope->zdelta = FINETANGENT(slope->zangle>>ANGLETOFINESHIFT); + case slope_zangle: { // zangle + angle_t zangle = luaL_checkangle(L, 3); + if (zangle == ANGLE_90 || zangle == ANGLE_270) + return luaL_error(L, "invalid zangle for slope!"); + slope->zangle = zangle; + slope->zdelta = -FINETANGENT(((slope->zangle+ANGLE_90)>>ANGLETOFINESHIFT) & 4095); P_CalculateSlopeNormal(slope); break; + } case slope_xydirection: // xydirection slope->xydirection = luaL_checkangle(L, 3); P_CalculateSlopeNormal(slope); From 772004d3fd8032f6397b43221227af488e82cfd4 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 21 Oct 2018 18:25:13 +0100 Subject: [PATCH 52/93] Fix editing slope xydirection with Lua --- src/lua_maplib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 975ea1cb..2ccb3b5f 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1374,6 +1374,8 @@ static int slope_set(lua_State *L) } case slope_xydirection: // xydirection slope->xydirection = luaL_checkangle(L, 3); + slope->d.x = -FINECOSINE((slope->xydirection>>ANGLETOFINESHIFT) & FINEMASK); + slope->d.y = -FINESINE((slope->xydirection>>ANGLETOFINESHIFT) & FINEMASK); P_CalculateSlopeNormal(slope); break; } From e95b54e64f2cbb13b79ac46b13b8e104f17f5517 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 21 Oct 2018 20:35:14 +0100 Subject: [PATCH 53/93] missed this ESLOPE-needed area from a few commits ago apparently :V --- src/lua_maplib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 2ccb3b5f..b59c3c17 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -16,7 +16,9 @@ #include "p_local.h" #include "p_setup.h" #include "z_zone.h" +#ifdef ESLOPE #include "p_slopes.h" +#endif #include "r_main.h" #include "lua_script.h" From a0495142dfa0b9510079cc398eff90960f2561e8 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 30 Oct 2018 19:40:59 +0100 Subject: [PATCH 54/93] Small hud library additions --- src/lua_hudlib.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 60cbbe50..89353496 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -560,6 +560,15 @@ static int libd_renderer(lua_State *L) return 1; } +// 30/10/18 Lat': Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int +// Could as well be thrown in global vars for ease of access but I guess it makes sense for it to be a HUD fn +static int libd_getlocaltransflag(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, (10-cv_translucenthud.value)*V_10TRANS); // A bit weird that it's called "translucenthud" yet 10 is fully opaque :V + return 1; +} + static luaL_Reg lib_draw[] = { {"patchExists", libd_patchExists}, {"cachePatch", libd_cachePatch}, @@ -576,6 +585,7 @@ static luaL_Reg lib_draw[] = { {"dupx", libd_dupx}, {"dupy", libd_dupy}, {"renderer", libd_renderer}, + {"localTransFlag", libd_getlocaltransflag}, {NULL, NULL} }; @@ -599,6 +609,20 @@ static int lib_huddisable(lua_State *L) return 0; } +// 30/10/18: Lat': How come this wasn't here before? +static int lib_hudenabled(lua_State *L) +{ + enum hud option = luaL_checkoption(L, 1, NULL, hud_disable_options); + lua_settop(L, 2); + if (!gL || hud_enabled[option/8] & (1<<(option%8))) + lua_pushboolean(L, true); + else + lua_pushboolean(L, false); + + return 1; +} + + // add a HUD element for rendering static int lib_hudadd(lua_State *L) { @@ -623,6 +647,7 @@ static int lib_hudadd(lua_State *L) static luaL_Reg lib_hud[] = { {"enable", lib_hudenable}, {"disable", lib_huddisable}, + {"enabled", lib_hudenabled}, {"add", lib_hudadd}, {NULL, NULL} }; From 799d8d2749250218bd557d09c9727df3658f7a9f Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 30 Oct 2018 22:29:28 +0100 Subject: [PATCH 55/93] remove gL check --- src/lua_hudlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 89353496..2ba6c8a6 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -614,7 +614,7 @@ static int lib_hudenabled(lua_State *L) { enum hud option = luaL_checkoption(L, 1, NULL, hud_disable_options); lua_settop(L, 2); - if (!gL || hud_enabled[option/8] & (1<<(option%8))) + if (hud_enabled[option/8] & (1<<(option%8))) lua_pushboolean(L, true); else lua_pushboolean(L, false); From 68414585469fbb4e1c739253e9561b430dcaf0eb Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Tue, 30 Oct 2018 22:51:05 +0100 Subject: [PATCH 56/93] got rid of the settop as well --- src/lua_hudlib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 2ba6c8a6..bc9423be 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -613,7 +613,6 @@ static int lib_huddisable(lua_State *L) static int lib_hudenabled(lua_State *L) { enum hud option = luaL_checkoption(L, 1, NULL, hud_disable_options); - lua_settop(L, 2); if (hud_enabled[option/8] & (1<<(option%8))) lua_pushboolean(L, true); else From e9ea1b47d5ec8f2d04452426341aa9c13e00ce2d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 31 Oct 2018 19:26:29 +0000 Subject: [PATCH 57/93] Fix the game crashing if you put params with no "=" for some reason in some of the SOC blocks, just stop going through the lines if that happens --- src/dehacked.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 36524108..97e1965e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1035,7 +1035,10 @@ static void readlevelheader(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -1616,7 +1619,10 @@ static void readhuditem(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2118,7 +2124,10 @@ static void reademblemdata(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2258,7 +2267,10 @@ static void readextraemblemdata(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2342,7 +2354,10 @@ static void readunlockable(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2629,7 +2644,10 @@ static void readconditionset(MYFILE *f, UINT8 setnum) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2874,7 +2892,10 @@ static void readmaincfg(MYFILE *f) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -3113,7 +3134,10 @@ static void readwipes(MYFILE *f) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after From a3bc7ddfa0bca4d52b8de2a7151095ecc6968e04 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Tue, 6 Nov 2018 18:09:45 -0600 Subject: [PATCH 58/93] Add Lua Ultimate Mode global variable so people can use it. --- src/dehacked.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 97e1965e..212715dd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8217,6 +8217,9 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"maptol")) { lua_pushinteger(L, maptol); return 1; + } else if (fastcmp(word,"ultimatemode")) { + lua_pushboolean(L, ultimatemode != 0); + return 1; } else if (fastcmp(word,"mariomode")) { lua_pushboolean(L, mariomode != 0); return 1; From 82c738ea4b7ee4b1c03de261d26387107da9dd3c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 8 Nov 2018 21:13:58 +0000 Subject: [PATCH 59/93] Remove hasslope, per colette's warning about it potentially causing desyncs --- src/lua_maplib.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index b59c3c17..37dae5fa 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -46,7 +46,6 @@ enum sector_e { sector_ffloors, sector_fslope, sector_cslope, - sector_hasslope #else sector_ffloors #endif @@ -69,7 +68,6 @@ static const char *const sector_opt[] = { #ifdef ESLOPE "f_slope", "c_slope", - "hasslope", #endif NULL}; @@ -471,9 +469,6 @@ static int sector_get(lua_State *L) case sector_cslope: // c_slope LUA_PushUserdata(L, sector->c_slope, META_SLOPE); return 1; - case sector_hasslope: // hasslope - lua_pushboolean(L, sector->hasslope); - return 1; #endif } return 0; @@ -500,7 +495,6 @@ static int sector_set(lua_State *L) #ifdef ESLOPE case sector_fslope: // f_slope case sector_cslope: // c_slope - case sector_hasslope: // hasslope #endif default: return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); From 98fd9f8e426e40cc70d6248bf7c5a42bf13f25f1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 8 Nov 2018 21:22:45 +0000 Subject: [PATCH 60/93] WHY DID I FORGET THIS --- src/lua_maplib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 37dae5fa..1886d7d1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -45,7 +45,7 @@ enum sector_e { #ifdef ESLOPE sector_ffloors, sector_fslope, - sector_cslope, + sector_cslope #else sector_ffloors #endif From 2da335a1c4cb9af38fbba79c4aadeeb4facf0093 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 10 Nov 2018 13:08:26 +0000 Subject: [PATCH 61/93] Place limit on the amount of alias recursion allowed, to prevent cycles or otherwise excessive recursion --- src/command.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/command.c b/src/command.c index f77fb5a4..8971d42f 100644 --- a/src/command.c +++ b/src/command.c @@ -63,6 +63,7 @@ CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; #define COM_BUF_SIZE 8192 // command buffer size +#define MAX_ALIAS_RECURSION 100 // max recursion allowed for aliases static INT32 com_wait; // one command per frame (for cmd sequences) @@ -485,6 +486,7 @@ static void COM_ExecuteString(char *ptext) { xcommand_t *cmd; cmdalias_t *a; + static INT32 recursion = 0; // detects recursion and stops it if it goes too far COM_TokenizeString(ptext); @@ -497,6 +499,7 @@ static void COM_ExecuteString(char *ptext) { if (!stricmp(com_argv[0], cmd->name)) //case insensitive now that we have lower and uppercase! { + recursion = 0; cmd->function(); return; } @@ -507,11 +510,20 @@ static void COM_ExecuteString(char *ptext) { if (!stricmp(com_argv[0], a->name)) { + if (recursion > MAX_ALIAS_RECURSION) + { + CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n")); + recursion = 0; + return; + } + recursion++; COM_BufInsertText(a->value); return; } } + recursion = 0; + // check cvars // Hurdler: added at Ebola's request ;) // (don't flood the console in software mode with bad gr_xxx command) From 63ba59341b63a47bef3a07dc9788f328de5e80f9 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 12 Nov 2018 16:23:59 +0000 Subject: [PATCH 62/93] Fix monitors (and other objects) on a floating, bobbing FOF being stuck slightly above said FOF after it has finished bobbing --- src/p_floor.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/p_floor.c b/src/p_floor.c index e613b5ed..8af2ee7b 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -811,6 +811,8 @@ void T_BounceCheese(levelspecthink_t *bouncer) { bouncer->sector->ceilingheight = actionsector->ceilingheight; bouncer->sector->floorheight = bouncer->sector->ceilingheight - (halfheight*2); + T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling + T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor P_RecalcPrecipInSector(actionsector); bouncer->sector->ceilingdata = NULL; bouncer->sector->floordata = NULL; @@ -825,6 +827,8 @@ void T_BounceCheese(levelspecthink_t *bouncer) { bouncer->sector->ceilingheight = floorheight + (halfheight << 1); bouncer->sector->floorheight = floorheight; + T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling + T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor P_RecalcPrecipInSector(actionsector); bouncer->sector->ceilingdata = NULL; bouncer->sector->floordata = NULL; @@ -841,9 +845,9 @@ void T_BounceCheese(levelspecthink_t *bouncer) } T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight - - 70*FRACUNIT, 0, 1, -1); // move floor + 70*FRACUNIT, 0, 1, -1); // move ceiling T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT, - 0, 0, -1); // move ceiling + 0, 0, -1); // move floor bouncer->sector->floorspeed = -bouncer->speed/2; bouncer->sector->ceilspeed = 42; @@ -893,6 +897,8 @@ void T_BounceCheese(levelspecthink_t *bouncer) { bouncer->sector->floorheight = bouncer->floorwasheight; bouncer->sector->ceilingheight = bouncer->ceilingwasheight; + T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling + T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor bouncer->sector->ceilingdata = NULL; bouncer->sector->floordata = NULL; bouncer->sector->floorspeed = 0; From 9029cf5d9cc7c5dcbfcaa9f12446396745e9ca48 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 12 Nov 2018 22:35:22 -0500 Subject: [PATCH 63/93] Fix skybox disappearing after using objectplace command --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index c621378e..86931b78 100644 --- a/src/info.c +++ b/src/info.c @@ -12733,7 +12733,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 10, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, From d14f87b8c6c02447d00ea86c2c92f77da5bffb62 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Wed, 14 Nov 2018 10:54:33 -0500 Subject: [PATCH 64/93] Cleanup whitespace --- src/d_clisrv.c | 2 +- src/d_clisrv.h | 4 ++-- src/dehacked.c | 2 +- src/p_floor.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a5a0b1ab..036ed0e0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2393,7 +2393,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) } } } - + #ifdef HAVE_BLUA LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting #endif diff --git a/src/d_clisrv.h b/src/d_clisrv.h index c067a3ad..f49eeffc 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -449,10 +449,10 @@ typedef enum KR_KICK = 1, //Kicked by server KR_PINGLIMIT = 2, //Broke Ping Limit KR_SYNCH = 3, //Synch Failure - KR_TIMEOUT = 4, //Connection Timeout + KR_TIMEOUT = 4, //Connection Timeout KR_BAN = 5, //Banned by server KR_LEAVE = 6, //Quit the game - + } kickreason_t; extern boolean server; diff --git a/src/dehacked.c b/src/dehacked.c index da7240c8..dd75fce4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7417,7 +7417,7 @@ struct { {"V_CHARCOLORSHIFT",V_CHARCOLORSHIFT}, {"V_ALPHASHIFT",V_ALPHASHIFT}, - + //Kick Reasons {"KR_KICK",KR_KICK}, {"KR_PINGLIMIT",KR_PINGLIMIT}, diff --git a/src/p_floor.c b/src/p_floor.c index 8af2ee7b..40ce9acc 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1966,7 +1966,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) continue; mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator + if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator && mo->z <= thwomp->sector->ceilingheight && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) { From de5b6265205b816611a4e6174eee9e457af45162 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Wed, 14 Nov 2018 11:06:45 -0500 Subject: [PATCH 65/93] Fix misleading indentation --- 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 036ed0e0..fabd59be 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2808,7 +2808,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) case KICK_MSG_PLAYER_QUIT: if (netgame) // not splitscreen/bots CONS_Printf(M_GetText("left the game\n")); - kickreason = KR_LEAVE; + kickreason = KR_LEAVE; break; case KICK_MSG_BANNED: CONS_Printf(M_GetText("has been banned (Don't come back)\n")); From 2a5ae054f99138293a2d1e5541dc498175afc1c4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 22 Nov 2018 10:41:21 -0500 Subject: [PATCH 66/93] Make movement controls consistent with 2.2 --- src/g_input.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index b004384c..7385b41a 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1154,10 +1154,8 @@ void G_Controldefault(void) #else void G_Controldefault(void) { - gamecontrol[gc_forward ][0] = KEY_UPARROW; - gamecontrol[gc_forward ][1] = 'w'; - gamecontrol[gc_backward ][0] = KEY_DOWNARROW; - gamecontrol[gc_backward ][1] = 's'; + gamecontrol[gc_forward ][0] = 'w'; + gamecontrol[gc_backward ][0] = 's'; gamecontrol[gc_strafeleft ][0] = 'a'; gamecontrol[gc_straferight][0] = 'd'; gamecontrol[gc_turnleft ][0] = KEY_LEFTARROW; @@ -1178,19 +1176,18 @@ void G_Controldefault(void) gamecontrol[gc_fire ][1] = KEY_MOUSE1+0; gamecontrol[gc_firenormal ][0] = 'c'; gamecontrol[gc_tossflag ][0] = '\''; - gamecontrol[gc_use ][0] = 'x'; + gamecontrol[gc_use ][0] = KEY_LSHIFT; gamecontrol[gc_camtoggle ][0] = 'v'; gamecontrol[gc_camleft ][0] = '['; gamecontrol[gc_camright ][0] = ']'; gamecontrol[gc_camreset ][0] = 'r'; - gamecontrol[gc_lookup ][0] = KEY_PGUP; - gamecontrol[gc_lookdown ][0] = KEY_PGDN; + gamecontrol[gc_lookup ][0] = KEY_UPARROW; + gamecontrol[gc_lookdown ][0] = KEY_DOWNARROW; gamecontrol[gc_centerview ][0] = KEY_END; gamecontrol[gc_talkkey ][0] = 't'; gamecontrol[gc_teamkey ][0] = 'y'; gamecontrol[gc_scores ][0] = KEY_TAB; - gamecontrol[gc_jump ][0] = 'z'; - gamecontrol[gc_jump ][1] = KEY_MOUSE1+1; + gamecontrol[gc_jump ][0] = KEY_SPACE; gamecontrol[gc_console ][0] = KEY_CONSOLE; gamecontrol[gc_pause ][0] = KEY_PAUSE; #ifdef WMINPUT From 4b5246d5b74b84424c63e0e5bebec60101b6c9c9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 22 Nov 2018 14:13:28 -0500 Subject: [PATCH 67/93] Adjust menu for movement and camera controls --- src/m_menu.c | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index c9adbfb9..c7ab8bbe 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -270,7 +270,7 @@ static void M_SetupMultiPlayer2(INT32 choice); // Split into multiple parts due to size // Controls menu_t OP_ControlsDef, OP_ControlListDef, OP_MoveControlsDef; -menu_t OP_MPControlsDef, OP_CameraControlsDef, OP_MiscControlsDef; +menu_t OP_MPControlsDef, OP_MiscControlsDef; menu_t OP_P1ControlsDef, OP_P2ControlsDef, OP_MouseOptionsDef; menu_t OP_Mouse2OptionsDef, OP_Joystick1Def, OP_Joystick2Def; static void M_VideoModeMenu(INT32 choice); @@ -1024,20 +1024,30 @@ static menuitem_t OP_ControlListMenu[] = { {IT_SUBMENU | IT_STRING, NULL, "Movement Controls...", &OP_MoveControlsDef, 10}, {IT_SUBMENU | IT_STRING, NULL, "Multiplayer Controls...", &OP_MPControlsDef, 20}, - {IT_SUBMENU | IT_STRING, NULL, "Camera Controls...", &OP_CameraControlsDef, 30}, - {IT_SUBMENU | IT_STRING, NULL, "Miscellaneous Controls...", &OP_MiscControlsDef, 40}, + {IT_SUBMENU | IT_STRING, NULL, "Miscellaneous Controls...", &OP_MiscControlsDef, 30}, }; static menuitem_t OP_MoveControlsMenu[] = { - {IT_CALL | IT_STRING2, NULL, "Forward", M_ChangeControl, gc_forward }, - {IT_CALL | IT_STRING2, NULL, "Reverse", M_ChangeControl, gc_backward }, - {IT_CALL | IT_STRING2, NULL, "Turn Left", M_ChangeControl, gc_turnleft }, - {IT_CALL | IT_STRING2, NULL, "Turn Right", M_ChangeControl, gc_turnright }, - {IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, gc_jump }, - {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_use }, - {IT_CALL | IT_STRING2, NULL, "Strafe Left", M_ChangeControl, gc_strafeleft }, - {IT_CALL | IT_STRING2, NULL, "Strafe Right", M_ChangeControl, gc_straferight}, + {IT_HEADER, NULL, " Movement", NULL, 0}, + {IT_CALL | IT_STRING2, NULL, "Move Forward", M_ChangeControl, gc_forward }, + {IT_CALL | IT_STRING2, NULL, "Move Backward", M_ChangeControl, gc_backward }, + {IT_CALL | IT_STRING2, NULL, "Move Left", M_ChangeControl, gc_strafeleft }, + {IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, gc_straferight }, + {IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, gc_jump }, + {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_use }, + {IT_HEADER, NULL, " Camera", NULL, 0}, + {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup }, + {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown }, + {IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, gc_turnleft }, + {IT_CALL | IT_STRING2, NULL, "Look Right", M_ChangeControl, gc_turnright }, + {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview }, + {IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming }, + {IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle}, + {IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, + {IT_HEADER, NULL, " Advanced", NULL, 0}, + {IT_CALL | IT_STRING2, NULL, "Rotate Camera L", M_ChangeControl, gc_camleft }, + {IT_CALL | IT_STRING2, NULL, "Rotate Camera R", M_ChangeControl, gc_camright }, }; static menuitem_t OP_MPControlsMenu[] = @@ -1059,18 +1069,6 @@ static menuitem_t OP_MPControlsMenu[] = {IT_CALL | IT_STRING2, NULL, "Ring Toss Normal", M_ChangeControl, gc_firenormal }, }; -static menuitem_t OP_CameraControlsMenu[] = -{ - {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup }, - {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown }, - {IT_CALL | IT_STRING2, NULL, "Rotate Camera L", M_ChangeControl, gc_camleft }, - {IT_CALL | IT_STRING2, NULL, "Rotate Camera R", M_ChangeControl, gc_camright }, - {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview }, - {IT_CALL | IT_STRING2, NULL, "Mouselook", M_ChangeControl, gc_mouseaiming }, - {IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, - {IT_CALL | IT_STRING2, NULL, "Toggle Chasecam", M_ChangeControl, gc_camtoggle }, -}; - static menuitem_t OP_MiscControlsMenu[] = { {IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 }, @@ -1659,7 +1657,6 @@ menu_t OP_ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlsMenu, &OP_MainDe menu_t OP_ControlListDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlListMenu, &OP_ControlsDef, 60, 30); menu_t OP_MoveControlsDef = CONTROLMENUSTYLE(OP_MoveControlsMenu, &OP_ControlListDef); menu_t OP_MPControlsDef = CONTROLMENUSTYLE(OP_MPControlsMenu, &OP_ControlListDef); -menu_t OP_CameraControlsDef = CONTROLMENUSTYLE(OP_CameraControlsMenu, &OP_ControlListDef); menu_t OP_MiscControlsDef = CONTROLMENUSTYLE(OP_MiscControlsMenu, &OP_ControlListDef); menu_t OP_P1ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P1ControlsMenu, &OP_ControlsDef, 60, 30); menu_t OP_P2ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P2ControlsMenu, &OP_ControlsDef, 60, 30); From f926774ee11438173e456c4c98829120f3860f61 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 20 Nov 2018 23:43:05 -0500 Subject: [PATCH 68/93] Hardcode Pause/Break key and change Pause default; show prompt in menu about Pause key --- src/g_game.c | 3 ++- src/g_input.c | 2 +- src/m_menu.c | 28 +++++++++++++++++++++++++--- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index d6ce01dc..c48dc615 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1814,7 +1814,8 @@ boolean G_Responder(event_t *ev) { case ev_keydown: if (ev->data1 == gamecontrol[gc_pause][0] - || ev->data1 == gamecontrol[gc_pause][1]) + || ev->data1 == gamecontrol[gc_pause][1] + || ev->data1 == KEY_PAUSE) { if (!pausedelay) { diff --git a/src/g_input.c b/src/g_input.c index 7385b41a..c337e561 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1189,7 +1189,7 @@ void G_Controldefault(void) gamecontrol[gc_scores ][0] = KEY_TAB; gamecontrol[gc_jump ][0] = KEY_SPACE; gamecontrol[gc_console ][0] = KEY_CONSOLE; - gamecontrol[gc_pause ][0] = KEY_PAUSE; + gamecontrol[gc_pause ][0] = 'p'; #ifdef WMINPUT gamecontrol[gc_forward ][0] = KEY_JOY1+02; //UP gamecontrol[gc_backward ][0] = KEY_JOY1+03; //DOWN diff --git a/src/m_menu.c b/src/m_menu.c index c7ab8bbe..2e1b833d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6856,6 +6856,7 @@ static void M_DrawControl(void) } static INT32 controltochange; +static char controltochangetext[55]; static void M_ChangecontrolResponse(event_t *ev) { @@ -6863,8 +6864,8 @@ static void M_ChangecontrolResponse(event_t *ev) INT32 found; INT32 ch = ev->data1; - // ESCAPE cancels - if (ch != KEY_ESCAPE) + // ESCAPE cancels; dummy out PAUSE + if (ch != KEY_ESCAPE && ch != KEY_PAUSE) { switch (ev->type) @@ -6923,8 +6924,28 @@ static void M_ChangecontrolResponse(event_t *ev) G_CheckDoubleUsage(ch); setupcontrols[control][found] = ch; } - + S_StartSound(NULL, sfx_strpst); } + else if (ch == KEY_PAUSE) + { + static char tmp[155]; + menu_t *prev = currentMenu->prevMenu; + + if (controltochange == gc_pause) + sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nyou may select another key. \n\nHit another key for\n%s\nESC for Cancel"), + controltochangetext); + else + sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit is not configurable. \n\nHit another key for\n%s\nESC for Cancel"), + controltochangetext); + + M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER); + currentMenu->prevMenu = prev; + + S_StartSound(NULL, sfx_s3k42); + return; + } + else + S_StartSound(NULL, sfx_skid); M_StopMessage(0); } @@ -6936,6 +6957,7 @@ static void M_ChangeControl(INT32 choice) controltochange = currentMenu->menuitems[choice].alphaKey; sprintf(tmp, M_GetText("Hit the new key for\n%s\nESC for Cancel"), currentMenu->menuitems[choice].text); + strncpy(controltochangetext, currentMenu->menuitems[choice].text, 55); M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER); } From 7075cdbfa8feb1b112de9afd744a3a143d0fc5c8 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Wed, 21 Nov 2018 11:21:17 -0500 Subject: [PATCH 69/93] Don't accept KEY_PAUSE for control console command --- src/g_input.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/g_input.c b/src/g_input.c index c337e561..45ab29e0 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1327,6 +1327,8 @@ static void setcontrol(INT32 (*gc)[2], INT32 na) return; } keynum = G_KeyStringtoNum(COM_Argv(2)); + if (keynum == KEY_PAUSE) // fail silently; pause is hardcoded + return; G_CheckDoubleUsage(keynum); gc[numctrl][0] = keynum; From a8e01ee69b02e127bbb343006af6a704df3eecd4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 22 Nov 2018 14:47:01 -0500 Subject: [PATCH 70/93] Smarter pause/break rejection for setcontrol --- src/g_input.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index 45ab29e0..add7c2fc 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1327,13 +1327,31 @@ static void setcontrol(INT32 (*gc)[2], INT32 na) return; } keynum = G_KeyStringtoNum(COM_Argv(2)); + if (keynum == KEY_PAUSE) // fail silently; pause is hardcoded - return; + { + if (na == 4) + { + na--; + keynum = G_KeyStringtoNum(COM_Argv(3)); + if (keynum == KEY_PAUSE) + return; + } + else + return; + } + G_CheckDoubleUsage(keynum); gc[numctrl][0] = keynum; if (na == 4) - gc[numctrl][1] = G_KeyStringtoNum(COM_Argv(3)); + { + keynum = G_KeyStringtoNum(COM_Argv(3)); + if (keynum != KEY_PAUSE) + gc[numctrl][1] = keynum; + else + gc[numctrl][1] = 0; + } else gc[numctrl][1] = 0; } From 17ff7e69a0cd4eef872d28d08b78a051ac5450f5 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 22 Nov 2018 17:04:24 -0500 Subject: [PATCH 71/93] Add chasefreelook to separate third and first person mouselook --- src/d_netcmd.c | 2 ++ src/g_game.c | 14 +++++++++----- src/g_game.h | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3a7c5499..6520e973 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -674,6 +674,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_crosshair2); CV_RegisterVar(&cv_alwaysfreelook); CV_RegisterVar(&cv_alwaysfreelook2); + CV_RegisterVar(&cv_chasefreelook); + CV_RegisterVar(&cv_chasefreelook2); // g_input.c CV_RegisterVar(&cv_sideaxis); diff --git a/src/g_game.c b/src/g_game.c index c48dc615..f9d26c85 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -350,11 +350,13 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_alwaysfreelook = {"alwaysmlook", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_invertmouse2 = {"invertmouse2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_alwaysfreelook = {"alwaysmlook", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_alwaysfreelook2 = {"alwaysmlook2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mousemove = {"mousemove", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mousemove2 = {"mousemove2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chasefreelook = {"chasemlook", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chasefreelook2 = {"chasemlook2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mousemove = {"mousemove", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mousemove2 = {"mousemove2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_analog = {"analog", "Off", CV_CALL, CV_OnOff, Analog_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_analog2 = {"analog2", "Off", CV_CALL, CV_OnOff, Analog2_OnChange, 0, NULL, NULL, 0, 0, NULL}; #ifdef DC @@ -979,7 +981,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) turnright = PLAYER1INPUTDOWN(gc_turnright); turnleft = PLAYER1INPUTDOWN(gc_turnleft); - mouseaiming = (PLAYER1INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook.value; + mouseaiming = (PLAYER1INPUTDOWN(gc_mouseaiming)) ^ + (cv_chasecam.value ? cv_chasefreelook.value : cv_alwaysfreelook.value); analogjoystickmove = cv_usejoystick.value && !Joystick.bGamepadStyle; gamepadjoystickmove = cv_usejoystick.value && Joystick.bGamepadStyle; @@ -1270,7 +1273,8 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) turnright = PLAYER2INPUTDOWN(gc_turnright); turnleft = PLAYER2INPUTDOWN(gc_turnleft); - mouseaiming = (PLAYER2INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook2.value; + mouseaiming = (PLAYER2INPUTDOWN(gc_mouseaiming)) ^ + (cv_chasecam2.value ? cv_chasefreelook2.value : cv_alwaysfreelook2.value); analogjoystickmove = cv_usejoystick2.value && !Joystick2.bGamepadStyle; gamepadjoystickmove = cv_usejoystick2.value && Joystick2.bGamepadStyle; diff --git a/src/g_game.h b/src/g_game.h index ba414269..f22a2e18 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -55,8 +55,8 @@ extern INT16 rw_maximums[NUM_WEAPONS]; // used in game menu extern consvar_t cv_crosshair, cv_crosshair2; -extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove; -extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_mousemove2; +extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove; +extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2; extern consvar_t cv_useranalog, cv_useranalog2; extern consvar_t cv_analog, cv_analog2; extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_fireaxis,cv_firenaxis; From edd98842d544acc45d759eb29a43d8116daeda14 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 22 Nov 2018 17:32:03 -0500 Subject: [PATCH 72/93] Added chasefreecam to menu --- src/m_menu.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 2e1b833d..a24447e2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1117,13 +1117,14 @@ static menuitem_t OP_MouseOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Use Mouse", &cv_usemouse, 10}, - {IT_STRING | IT_CVAR, NULL, "Always MouseLook", &cv_alwaysfreelook, 30}, - {IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove, 40}, - {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse, 50}, + {IT_STRING | IT_CVAR, NULL, "First-Person MouseLook", &cv_alwaysfreelook, 30}, + {IT_STRING | IT_CVAR, NULL, "Third-Person MouseLook", &cv_chasefreelook, 40}, + {IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove, 50}, + {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse, 60}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse X Speed", &cv_mousesens, 60}, + NULL, "Mouse X Speed", &cv_mousesens, 70}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse Y Speed", &cv_mouseysens, 70}, + NULL, "Mouse Y Speed", &cv_mouseysens, 80}, }; static menuitem_t OP_Mouse2OptionsMenu[] = @@ -1131,13 +1132,14 @@ static menuitem_t OP_Mouse2OptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Use Mouse 2", &cv_usemouse2, 10}, {IT_STRING | IT_CVAR, NULL, "Second Mouse Serial Port", &cv_mouse2port, 20}, - {IT_STRING | IT_CVAR, NULL, "Always MouseLook", &cv_alwaysfreelook2, 30}, - {IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove2, 40}, - {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse2, 50}, + {IT_STRING | IT_CVAR, NULL, "First-Person MouseLook", &cv_alwaysfreelook2, 30}, + {IT_STRING | IT_CVAR, NULL, "Third-Person MouseLook", &cv_chasefreelook2, 40}, + {IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove2, 50}, + {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse2, 60}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse X Speed", &cv_mousesens2, 60}, + NULL, "Mouse X Speed", &cv_mousesens2, 70}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse Y Speed", &cv_mouseysens2, 70}, + NULL, "Mouse Y Speed", &cv_mouseysens2, 80}, }; static menuitem_t OP_VideoOptionsMenu[] = From c548aaa347a1af92759fd014055deddedc5e392b Mon Sep 17 00:00:00 2001 From: Nev3r Date: Fri, 23 Nov 2018 16:58:16 +0100 Subject: [PATCH 73/93] Backported PK3 support to 2.1 Hopefully I'm not missing anything. Signed-off-by: Nev3r --- src/d_netcmd.c | 4 +- src/d_netfil.c | 4 +- src/lua_script.c | 22 +- src/p_saveg.c | 26 +- src/p_setup.c | 439 ++++++++++++++++++++++----------- src/p_setup.h | 2 +- src/r_data.c | 109 +++++++-- src/r_things.c | 35 +-- src/w_wad.c | 617 +++++++++++++++++++++++++++++++++++++++-------- src/w_wad.h | 42 +++- 10 files changed, 1008 insertions(+), 292 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3a7c5499..213dafd1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3005,7 +3005,7 @@ static void Command_Addfile(void) // Add file on your client directly if it is trivial, or you aren't in a netgame. if (!(netgame || multiplayer) || musiconly) { - P_AddWadFile(fn, NULL); + P_AddWadFile(fn); return; } @@ -3237,7 +3237,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) ncs = findfile(filename,md5sum,true); - if (ncs != FS_FOUND || !P_AddWadFile(filename, NULL)) + if (ncs != FS_FOUND || !P_AddWadFile(filename)) { Command_ExitGame_f(); if (ncs == FS_FOUND) diff --git a/src/d_netfil.c b/src/d_netfil.c index adbc8d77..284b9169 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -444,7 +444,7 @@ void CL_LoadServerFiles(void) continue; // Already loaded else if (fileneeded[i].status == FS_FOUND) { - P_AddWadFile(fileneeded[i].filename, NULL); + P_AddWadFile(fileneeded[i].filename); G_SetGameModified(true); fileneeded[i].status = FS_OPEN; } @@ -463,7 +463,7 @@ void CL_LoadServerFiles(void) fileneeded[i].filename); // Okay, NOW we know it's safe. Whew. - P_AddWadFile(fileneeded[i].filename, NULL); + P_AddWadFile(fileneeded[i].filename); if (fileneeded[i].important) G_SetGameModified(true); fileneeded[i].status = FS_OPEN; diff --git a/src/lua_script.c b/src/lua_script.c index 9b87f0c2..6564f258 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -170,6 +170,7 @@ static inline void LUA_LoadFile(MYFILE *f, char *name) LUA_ClearState(); lua_pushinteger(gL, f->wad); lua_setfield(gL, LUA_REGISTRYINDEX, "WAD"); + if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, 0, 0)) { CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); lua_pop(gL,1); @@ -182,21 +183,24 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump) { MYFILE f; char *name; - size_t len; f.wad = wad; f.size = W_LumpLengthPwad(wad, lump); f.data = Z_Malloc(f.size, PU_LUA, NULL); W_ReadLumpPwad(wad, lump, f.data); f.curpos = f.data; - len = strlen(wadfiles[wad]->filename); - name = malloc(len+10); - strcpy(name, wadfiles[wad]->filename); - if (!fasticmp(&name[len - 4], ".lua")) { - // If it's not a .lua file, copy the lump name in too. - name[len] = '|'; - M_Memcpy(name+len+1, wadfiles[wad]->lumpinfo[lump].name, 8); - name[len+9] = '\0'; + if (wadfiles[wad]->type == RET_LUA) + { + name = malloc(strlen(wadfiles[wad]->filename)+1); + strcpy(name, wadfiles[wad]->filename); + } + else // If it's not a .lua file, copy the lump name in too. + { + lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump]; + size_t length = strlen(wadfiles[wad]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name + name = malloc(length + 1); + sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->name2); + name[length] = '\0'; } LUA_LoadFile(&f, name); diff --git a/src/p_saveg.c b/src/p_saveg.c index 17d28302..aa0f6af2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -489,16 +489,34 @@ static void P_NetArchiveWorld(void) UINT8 *put; // reload the map just to see difference - const mapsector_t *ms; - const mapsidedef_t *msd; - const maplinedef_t *mld; + mapsector_t *ms; + mapsidedef_t *msd; + maplinedef_t *mld; const sector_t *ss = sectors; UINT8 diff, diff2; WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; - ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE); + if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 + { // HACK: Open wad file rather quickly so we can get the data from the relevant lumps + UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); + filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); +#define retrieve_mapdata(d, f)\ + d = Z_Malloc((f)->size, PU_CACHE, NULL); \ + M_Memcpy(d, wadData + (f)->filepos, (f)->size) + retrieve_mapdata(ms, fileinfo + ML_SECTORS); + retrieve_mapdata(mld, fileinfo + ML_LINEDEFS); + retrieve_mapdata(msd, fileinfo + ML_SIDEDEFS); +#undef retrieve_mapdata + Z_Free(wadData); // we're done with this now + } + else // phew it's just a WAD + { + ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE); + mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE); + msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE); + } for (i = 0; i < numsectors; i++, ss++, ms++) { diff --git a/src/p_setup.c b/src/p_setup.c index 9f3ff423..931a5b84 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -348,16 +348,13 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) * \param lump VERTEXES lump number. * \sa ML_VERTEXES */ -static inline void P_LoadVertexes(lumpnum_t lumpnum) + +static inline void P_LoadRawVertexes(UINT8 *data, size_t i) { - UINT8 *data; - size_t i; mapvertex_t *ml; vertex_t *li; - // Determine number of lumps: - // total lump length / vertex record length. - numvertexes = W_LumpLength(lumpnum) / sizeof (mapvertex_t); + numvertexes = i / sizeof (mapvertex_t); if (numvertexes <= 0) I_Error("Level has no vertices"); // instead of crashing @@ -365,9 +362,6 @@ static inline void P_LoadVertexes(lumpnum_t lumpnum) // Allocate zone memory for buffer. vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - // Load data into cache. - data = W_CacheLumpNum(lumpnum, PU_STATIC); - ml = (mapvertex_t *)data; li = vertexes; @@ -377,11 +371,16 @@ static inline void P_LoadVertexes(lumpnum_t lumpnum) li->x = SHORT(ml->x)<y = SHORT(ml->y)<numlights = 0; li->rlights = NULL; } +} +static void P_LoadSegs(lumpnum_t lumpnum) +{ + UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); + P_LoadRawSegs(data, W_LumpLength(lumpnum)); Z_Free(data); } + /** Loads the SSECTORS resource from a level. * * \param lump Lump number of the SSECTORS resource. * \sa ::ML_SSECTORS */ -static inline void P_LoadSubsectors(lumpnum_t lumpnum) +static inline void P_LoadRawSubsectors(void *data, size_t i) { - void *data; - size_t i; mapsubsector_t *ms; subsector_t *ss; - numsubsectors = W_LumpLength(lumpnum) / sizeof (mapsubsector_t); + numsubsectors = i / sizeof (mapsubsector_t); if (numsubsectors <= 0) I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); ss = subsectors = Z_Calloc(numsubsectors * sizeof (*subsectors), PU_LEVEL, NULL); - data = W_CacheLumpNum(lumpnum,PU_STATIC); ms = (mapsubsector_t *)data; @@ -504,7 +503,12 @@ static inline void P_LoadSubsectors(lumpnum_t lumpnum) #endif ss->validcount = 0; } +} +static void P_LoadSubsectors(lumpnum_t lumpnum) +{ + UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); + P_LoadRawSubsectors(data, W_LumpLength(lumpnum)); Z_Free(data); } @@ -638,29 +642,31 @@ INT32 P_CheckLevelFlat(const char *flatname) return (INT32)i; } -static void P_LoadSectors(lumpnum_t lumpnum) +// Sets up the ingame sectors structures. +// Lumpnum is the lumpnum of a SECTORS lump. +static void P_LoadRawSectors(UINT8 *data, size_t i) { - UINT8 *data; - size_t i; mapsector_t *ms; sector_t *ss; levelflat_t *foundflats; - numsectors = W_LumpLength(lumpnum) / sizeof (mapsector_t); + // We count how many sectors we got. + numsectors = i / sizeof (mapsector_t); if (numsectors <= 0) I_Error("Level has no sectors"); + + // Allocate as much memory as we need into the global sectors table. sectors = Z_Calloc(numsectors*sizeof (*sectors), PU_LEVEL, NULL); - data = W_CacheLumpNum(lumpnum,PU_STATIC); - - //Fab : FIXME: allocate for whatever number of flats - // 512 different flats per level should be plenty + // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. + //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats)); if (foundflats == NULL) I_Error("Ran out of memory while loading sectors\n"); numlevelflats = 0; + // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. ms = (mapsector_t *)data; ss = sectors; for (i = 0; i < numsectors; i++, ss++, ms++) @@ -668,9 +674,6 @@ static void P_LoadSectors(lumpnum_t lumpnum) ss->floorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = P_AddLevelFlat(ms->floorpic, foundflats); ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); @@ -735,8 +738,6 @@ static void P_LoadSectors(lumpnum_t lumpnum) #endif // ----- end special tricks ----- } - Z_Free(data); - // set the sky flat num skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats); @@ -748,22 +749,26 @@ static void P_LoadSectors(lumpnum_t lumpnum) P_SetupLevelFlatAnims(); } +static void P_LoadSectors(lumpnum_t lumpnum) +{ + UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); + P_LoadRawSectors(data, W_LumpLength(lumpnum)); + Z_Free(data); +} + // // P_LoadNodes // -static void P_LoadNodes(lumpnum_t lumpnum) +static void P_LoadRawNodes(UINT8 *data, size_t i) { - UINT8 *data; - size_t i; UINT8 j, k; mapnode_t *mn; node_t *no; - numnodes = W_LumpLength(lumpnum) / sizeof (mapnode_t); + numnodes = i / sizeof (mapnode_t); if (numnodes <= 0) I_Error("Level has no nodes"); nodes = Z_Calloc(numnodes * sizeof (*nodes), PU_LEVEL, NULL); - data = W_CacheLumpNum(lumpnum, PU_STATIC); mn = (mapnode_t *)data; no = nodes; @@ -781,7 +786,12 @@ static void P_LoadNodes(lumpnum_t lumpnum) no->bbox[j][k] = SHORT(mn->bbox[j][k])<slopetype = ST_VERTICAL; else if (!ld->dy) ld->slopetype = ST_HORIZONTAL; - else if (FixedDiv(ld->dy, ld->dx) > 0) + else if ((ld->dy > 0) == (ld->dx > 0)) ld->slopetype = ST_POSITIVE; else ld->slopetype = ST_NEGATIVE; @@ -1217,7 +1224,7 @@ static void P_LoadLineDefs(lumpnum_t lumpnum) if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) { ld->sidenum[j] = 0xffff; - CONS_Debug(DBG_SETUP, "P_LoadLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); } } } @@ -1232,14 +1239,14 @@ static void P_LoadLineDefs(lumpnum_t lumpnum) { ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadLineDefs: linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); } if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) { ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadLineDefs: linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); } if (ld->sidenum[0] != 0xffff && ld->special) @@ -1251,7 +1258,12 @@ static void P_LoadLineDefs(lumpnum_t lumpnum) ld->polyobj = NULL; #endif } +} +static void P_LoadLineDefs(lumpnum_t lumpnum) +{ + UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); + P_LoadRawLineDefs(data, W_LumpLength(lumpnum)); Z_Free(data); } @@ -1353,22 +1365,24 @@ static void P_LoadLineDefs2(void) } } -// -// P_LoadSideDefs -// -static inline void P_LoadSideDefs(lumpnum_t lumpnum) + + +static inline void P_LoadRawSideDefs(size_t i) { - numsides = W_LumpLength(lumpnum) / sizeof (mapsidedef_t); + numsides = i / sizeof (mapsidedef_t); if (numsides <= 0) I_Error("Level has no sidedefs"); sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); } -// Delay loading texture names until after loaded linedefs. - -static void P_LoadSideDefs2(lumpnum_t lumpnum) +static inline void P_LoadSideDefs(lumpnum_t lumpnum) +{ + P_LoadRawSideDefs(W_LumpLength(lumpnum)); +} + + +static void P_LoadRawSideDefs2(void *data) { - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); UINT16 i; INT32 num; @@ -1386,7 +1400,7 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) if (sector_num >= numsectors) { - CONS_Debug(DBG_SETUP, "P_LoadSideDefs2: sidedef %u has out-of-range sector num %u\n", i, sector_num); + CONS_Debug(DBG_SETUP, "P_LoadRawSideDefs2: sidedef %u has out-of-range sector num %u\n", i, sector_num); sector_num = 0; } sd->sector = sec = §ors[sector_num]; @@ -1528,6 +1542,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) sd->text[6] = 0; break; } + + case 4: // Speed pad parameters case 414: // Play SFX { sd->toptexture = sd->midtexture = sd->bottomtexture = 0; @@ -1541,6 +1557,9 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) break; } + case 9: // Mace parameters + case 14: // Bustable block parameters + case 15: // Fan particle spawner parameters case 425: // Calls P_SetMobjState on calling mobj case 434: // Custom Power case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors @@ -1595,11 +1614,18 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) break; } } - - Z_Free(data); R_ClearTextureNumCache(true); } +// Delay loading texture names until after loaded linedefs. +static void P_LoadSideDefs2(lumpnum_t lumpnum) +{ + UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); + P_LoadRawSideDefs2(data); + Z_Free(data); +} + + static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1) { fixed_t bbox[4]; @@ -1855,6 +1881,30 @@ static void P_CreateBlockMap(void) } } +// Split from P_LoadBlockMap for convenience +// -- Monster Iestyn 08/01/18 +static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) +{ + size_t i; + blockmaplump = Z_Calloc(sizeof (*blockmaplump) * count, PU_LEVEL, NULL); + + // killough 3/1/98: Expand wad blockmap into larger internal one, + // by treating all offsets except -1 as unsigned and zero-extending + // them. This potentially doubles the size of blockmaps allowed, + // because Doom originally considered the offsets as always signed. + + blockmaplump[0] = SHORT(wadblockmaplump[0]); + blockmaplump[1] = SHORT(wadblockmaplump[1]); + blockmaplump[2] = (INT32)(SHORT(wadblockmaplump[2])) & 0xffff; + blockmaplump[3] = (INT32)(SHORT(wadblockmaplump[3])) & 0xffff; + + for (i = 4; i < count; i++) + { + INT16 t = SHORT(wadblockmaplump[i]); // killough 3/1/98 + blockmaplump[i] = t == -1 ? (INT32)-1 : (INT32) t & 0xffff; + } +} + // // P_LoadBlockMap // @@ -1881,38 +1931,20 @@ static boolean P_LoadBlockMap(lumpnum_t lumpnum) return false; { - size_t i; INT16 *wadblockmaplump = malloc(count); //INT16 *wadblockmaplump = W_CacheLumpNum (lump, PU_LEVEL); - - if (wadblockmaplump) W_ReadLump(lumpnum, wadblockmaplump); - else return false; + if (!wadblockmaplump) + return false; + W_ReadLump(lumpnum, wadblockmaplump); count /= 2; - blockmaplump = Z_Calloc(sizeof (*blockmaplump) * count, PU_LEVEL, 0); - - // killough 3/1/98: Expand wad blockmap into larger internal one, - // by treating all offsets except -1 as unsigned and zero-extending - // them. This potentially doubles the size of blockmaps allowed, - // because Doom originally considered the offsets as always signed. - - blockmaplump[0] = SHORT(wadblockmaplump[0]); - blockmaplump[1] = SHORT(wadblockmaplump[1]); - blockmaplump[2] = (INT32)(SHORT(wadblockmaplump[2])) & 0xffff; - blockmaplump[3] = (INT32)(SHORT(wadblockmaplump[3])) & 0xffff; - - for (i = 4; i < count; i++) - { - INT16 t = SHORT(wadblockmaplump[i]); // killough 3/1/98 - blockmaplump[i] = t == -1 ? (INT32)-1 : (INT32) t & 0xffff; - } - + P_ReadBlockMapLump(wadblockmaplump, count); free(wadblockmaplump); - - bmaporgx = blockmaplump[0]<= 0x20000) + return false; + + CONS_Printf("Reading blockmap lump for pk3...\n"); + + // no need to malloc anything, assume the data is uncompressed for now + count /= 2; + P_ReadBlockMapLump((INT16 *)data, count); + + bmaporgx = blockmaplump[0]<infotableofs); + fileinfo += ML_THINGS; // we only need the THINGS lump + P_PrepareRawThings(wadData + fileinfo->filepos, fileinfo->size); + Z_Free(wadData); // we're done with this now + } + else // phew it's just a WAD + P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); P_LoadThings(); P_SpawnSecretItems(true); @@ -2688,7 +2800,12 @@ boolean P_SetupLevel(boolean skipprecip) } // internal game map - lastloadedmaplumpnum = W_GetNumForName(maplumpname = G_BuildMapName(gamemap)); + maplumpname = G_BuildMapName(gamemap); + //lastloadedmaplumpnum = LUMPERROR; + lastloadedmaplumpnum = W_CheckNumForName(maplumpname); + + if (lastloadedmaplumpnum == INT16_MAX) + I_Error("Map %s not found.\n", maplumpname); R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette); CON_SetupBackColormap(); @@ -2698,38 +2815,93 @@ boolean P_SetupLevel(boolean skipprecip) P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5); - // note: most of this ordering is important - loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP); + // HACK ALERT: Cache the WAD, get the map data into the tables, free memory. + // As it is implemented right now, we're assuming an uncompressed WAD. + // (As in, a normal PWAD, not ZWAD or anything. The lump itself can be compressed.) + // We're not accounting for extra lumps and scrambled lump positions. Any additional data will cause an error. + if (W_IsLumpWad(lastloadedmaplumpnum)) + { + // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. + UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); + //filelump_t *fileinfo = wadData + ((wadinfo_t *)wadData)->infotableofs; + filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); + UINT32 numlumps = ((wadinfo_t *)wadData)->numlumps; - P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES); - P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS); + if (numlumps < ML_REJECT) // at least 9 lumps should be in the wad for a map to be loaded + { + I_Error("Bad WAD file for map %s!\n", maplumpname); + } - P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS); + if (numlumps > ML_BLOCKMAP) // enough room for a BLOCKMAP lump at least + { + loadedbm = P_LoadRawBlockMap( + wadData + (fileinfo + ML_BLOCKMAP)->filepos, + (fileinfo + ML_BLOCKMAP)->size, + (fileinfo + ML_BLOCKMAP)->name); + } + P_LoadRawVertexes(wadData + (fileinfo + ML_VERTEXES)->filepos, (fileinfo + ML_VERTEXES)->size); + P_LoadRawSectors(wadData + (fileinfo + ML_SECTORS)->filepos, (fileinfo + ML_SECTORS)->size); + P_LoadRawSideDefs((fileinfo + ML_SIDEDEFS)->size); + P_LoadRawLineDefs(wadData + (fileinfo + ML_LINEDEFS)->filepos, (fileinfo + ML_LINEDEFS)->size); + P_LoadRawSideDefs2(wadData + (fileinfo + ML_SIDEDEFS)->filepos); + P_LoadRawSubsectors(wadData + (fileinfo + ML_SSECTORS)->filepos, (fileinfo + ML_SSECTORS)->size); + P_LoadRawNodes(wadData + (fileinfo + ML_NODES)->filepos, (fileinfo + ML_NODES)->size); + P_LoadRawSegs(wadData + (fileinfo + ML_SEGS)->filepos, (fileinfo + ML_SEGS)->size); + if (numlumps > ML_REJECT) // enough room for a REJECT lump at least + { + P_LoadRawReject( + wadData + (fileinfo + ML_REJECT)->filepos, + (fileinfo + ML_REJECT)->size, + (fileinfo + ML_REJECT)->name); + } - P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS); - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 - P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); + // Important: take care of the ordering of the next functions. + if (!loadedbm) + P_CreateBlockMap(); // Graue 02-29-2004 + P_LoadLineDefs2(); + P_GroupLines(); + numdmstarts = numredctfstarts = numbluectfstarts = 0; - P_LoadLineDefs2(); - P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); - P_LoadNodes(lastloadedmaplumpnum + ML_NODES); - P_LoadSegs(lastloadedmaplumpnum + ML_SEGS); - P_LoadReject(lastloadedmaplumpnum + ML_REJECT); - P_GroupLines(); + // reset the player starts + for (i = 0; i < MAXPLAYERS; i++) + playerstarts[i] = NULL; + for (i = 0; i < 2; i++) + skyboxmo[i] = NULL; + P_MapStart(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; + P_PrepareRawThings(wadData + (fileinfo + ML_THINGS)->filepos, (fileinfo + ML_THINGS)->size); + Z_Free(wadData); + } + else + { + // Important: take care of the ordering of the next functions. + loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP); + P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES); + P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS); + P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS); + P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS); + P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); + P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); + P_LoadNodes(lastloadedmaplumpnum + ML_NODES); + P_LoadSegs(lastloadedmaplumpnum + ML_SEGS); + P_LoadReject(lastloadedmaplumpnum + ML_REJECT); - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = NULL; + // Important: take care of the ordering of the next functions. + if (!loadedbm) + P_CreateBlockMap(); // Graue 02-29-2004 - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; + P_LoadLineDefs2(); + P_GroupLines(); + numdmstarts = numredctfstarts = numbluectfstarts = 0; - P_MapStart(); - - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); + // reset the player starts + for (i = 0; i < MAXPLAYERS; i++) + playerstarts[i] = NULL; + for (i = 0; i < 2; i++) + skyboxmo[i] = NULL; + P_MapStart(); + P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); + } #ifdef ESLOPE P_ResetDynamicSlopes(); @@ -2977,7 +3149,7 @@ boolean P_RunSOC(const char *socfilename) lumpnum_t lump; if (strstr(socfilename, ".soc") != NULL) - return P_AddWadFile(socfilename, NULL); + return P_AddWadFile(socfilename); lump = W_CheckNumForName(socfilename); if (lump == LUMPERROR) @@ -2993,17 +3165,17 @@ boolean P_RunSOC(const char *socfilename) // Add a wadfile to the active wad files, // replace sounds, musics, patches, textures, sprites and maps // -boolean P_AddWadFile(const char *wadfilename, char **firstmapname) +boolean P_AddWadFile(const char *wadfilename) { size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; UINT16 numlumps, wadnum; - INT16 firstmapreplaced = 0, num; char *name; lumpinfo_t *lumpinfo; boolean texturechange = false; + boolean mapsadded = false; boolean replacedcurrentmap = false; - if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX) + if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX) { CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename); return false; @@ -3059,6 +3231,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) if (!devparm && digmreplaces) CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces)); + // // search for sprite replacements // @@ -3093,10 +3266,10 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) for (i = 0; i < numlumps; i++, lumpinfo++) { name = lumpinfo->name; - num = firstmapreplaced; if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers { + INT16 num; if (name[5]!='\0') continue; num = (INT16)M_MapNumber(name[3], name[4]); @@ -3106,16 +3279,10 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) replacedcurrentmap = true; CONS_Printf("%s\n", name); - } - - if (num && (num < firstmapreplaced || !firstmapreplaced)) - { - firstmapreplaced = num; - if (firstmapname) - *firstmapname = name; + mapsadded = true; } } - if (!firstmapreplaced) + if (!mapsadded) CONS_Printf(M_GetText("No maps added\n")); // reload status bar (warning should have valid player!) diff --git a/src/p_setup.h b/src/p_setup.h index 3bca1104..da25ee26 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -59,7 +59,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); #endif void P_LoadThingsOnly(void); boolean P_SetupLevel(boolean skipprecip); -boolean P_AddWadFile(const char *wadfilename, char **firstmapname); +boolean P_AddWadFile(const char *wadfilename); #ifdef DELFILE boolean P_DelWadFile(void); #endif diff --git a/src/r_data.c b/src/r_data.c index f2c9b146..fb7eb975 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -365,8 +365,8 @@ void R_FlushTextureCache(void) } // Need these prototypes for later; defining them here instead of r_data.h so they're "private" -int R_CountTexturesInTEXTURESLump(UINT16 wadNum); -void R_ParseTEXTURESLump(UINT16 wadNum, INT32 *index); +int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum); +void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); // // R_LoadTextures @@ -404,13 +404,22 @@ void R_LoadTextures(void) // but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures. for (w = 0, numtextures = 0; w < numwadfiles; w++) { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - - if (texturesLumpPos != INT16_MAX) + if (wadfiles[w]->type == RET_PK3) { - numtextures += R_CountTexturesInTEXTURESLump((UINT16)w); + texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); + } + + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + while (texturesLumpPos != INT16_MAX) + { + numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); } // Add all the textures between TX_START and TX_END @@ -447,12 +456,25 @@ void R_LoadTextures(void) for (i = 0, w = 0; w < numwadfiles; w++) { // Get the lump numbers for the markers in the WAD, if they exist. - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - - if (texturesLumpPos != INT16_MAX) - R_ParseTEXTURESLump(w,&i); + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + while (texturesLumpPos != INT16_MAX) + { + R_ParseTEXTURESLump(w, texturesLumpPos, &i); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); + } + } + else + { + texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + if (texturesLumpPos != INT16_MAX) + R_ParseTEXTURESLump(w, texturesLumpPos, &i); + } if (texstart == INT16_MAX || texend == INT16_MAX) continue; @@ -817,7 +839,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) } // Parses the TEXTURES lump... but just to count the number of textures. -int R_CountTexturesInTEXTURESLump(UINT16 wadNum) +int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) { char *texturesLump; size_t texturesLumpLength; @@ -828,11 +850,11 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum) // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll // need to make a space of memory where I can ensure that it will terminate // correctly. Start by loading the relevant data from the WAD. - texturesLump = (char *)W_CacheLumpNumPwad(wadNum,W_CheckNumForNamePwad("TEXTURES", wadNum, 0),PU_STATIC); + texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); // If that didn't exist, we have nothing to do here. if (texturesLump == NULL) return 0; // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. - texturesLumpLength = W_LumpLengthPwad(wadNum,W_CheckNumForNamePwad("TEXTURES",wadNum,0)); + texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum); texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL); // Now move the contents of the lump into this new location. memmove(texturesText,texturesLump,texturesLumpLength); @@ -864,7 +886,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum) } // Parses the TEXTURES lump... for real, this time. -void R_ParseTEXTURESLump(UINT16 wadNum, INT32 *texindex) +void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) { char *texturesLump; size_t texturesLumpLength; @@ -877,11 +899,11 @@ void R_ParseTEXTURESLump(UINT16 wadNum, INT32 *texindex) // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll // need to make a space of memory where I can ensure that it will terminate // correctly. Start by loading the relevant data from the WAD. - texturesLump = (char *)W_CacheLumpNumPwad(wadNum,W_CheckNumForNamePwad("TEXTURES", wadNum, 0),PU_STATIC); + texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); // If that didn't exist, we have nothing to do here. if (texturesLump == NULL) return; // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. - texturesLumpLength = W_LumpLengthPwad(wadNum,W_CheckNumForNamePwad("TEXTURES",wadNum,0)); + texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum); texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL); // Now move the contents of the lump into this new location. memmove(texturesText,texturesLump,texturesLumpLength); @@ -968,12 +990,51 @@ static void R_InitExtraColormaps(void) CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps)); } -// 12/14/14 -- only take flats in F_START/F_END +// Search for flat name. lumpnum_t R_GetFlatNumForName(const char *name) { - lumpnum_t lump = W_CheckNumForNameInBlock(name, "F_START", "F_END"); - if (lump == LUMPERROR) - lump = W_CheckNumForNameInBlock(name, "FF_START", "FF_END"); // deutex, some other old things + INT32 i; + lumpnum_t lump; + lumpnum_t start; + lumpnum_t end; + + // Scan wad files backwards so patched flats take preference. + for (i = numwadfiles - 1; i >= 0; i--) + { + switch (wadfiles[i]->type) + { + case RET_WAD: + if ((start = W_CheckNumForNamePwad("F_START", (UINT16)i, 0)) == INT16_MAX) + { + if ((start = W_CheckNumForNamePwad("FF_START", (UINT16)i, 0)) == INT16_MAX) + continue; + else if ((end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start)) == INT16_MAX) + continue; + } + else + if ((end = W_CheckNumForNamePwad("F_END", (UINT16)i, start)) == INT16_MAX) + continue; + break; + case RET_PK3: + if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX) + continue; + break; + default: + continue; + } + + // Now find lump with specified name in that range. + lump = W_CheckNumForNamePwad(name, (UINT16)i, start); + if (lump < end) + { + lump += (i<<16); // found it, in our constraints + break; + } + lump = LUMPERROR; + } + if (lump == LUMPERROR) { if (strcmp(name, SKYFLATNAME)) diff --git a/src/r_things.c b/src/r_things.c index ee2d8a9b..305d6b82 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -327,21 +327,28 @@ void R_AddSpriteDefs(UINT16 wadnum) UINT16 start, end; char wadname[MAX_WADPATH]; - // find the sprites section in this pwad - // we need at least the S_END - // (not really, but for speedup) + switch (wadfiles[wadnum]->type) + { + case RET_WAD: + start = W_CheckNumForNamePwad("S_START", wadnum, 0); + if (start == INT16_MAX) + start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib. + if (start == INT16_MAX) + start = 0; //let say S_START is lump 0 + else + start++; // just after S_START + end = W_CheckNumForNamePwad("S_END",wadnum,start); + if (end == INT16_MAX) + end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib. + break; + case RET_PK3: + start = W_CheckNumForFolderStartPK3("Sprites/", wadnum, 0); + end = W_CheckNumForFolderEndPK3("Sprites/", wadnum, start); + break; + default: + return; + } - start = W_CheckNumForNamePwad("S_START", wadnum, 0); - if (start == INT16_MAX) - start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib. - if (start == INT16_MAX) - start = 0; //let say S_START is lump 0 - else - start++; // just after S_START - - end = W_CheckNumForNamePwad("S_END",wadnum,start); - if (end == INT16_MAX) - end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib. if (end == INT16_MAX) { CONS_Debug(DBG_SETUP, "no sprites in pwad %d\n", wadnum); diff --git a/src/w_wad.c b/src/w_wad.c index 3789eab5..977b7e6f 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -26,6 +26,8 @@ #include "lzf.h" #endif +#include "zlib.h" + #include "doomdef.h" #include "doomstat.h" #include "doomtype.h" @@ -67,14 +69,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #pragma pack(1) #endif -// a raw entry of the wad directory -typedef struct -{ - UINT32 filepos; // file offset of the resource - UINT32 size; // size of the resource - char name[8]; // name of the resource -} ATTRPACK filelump_t; - #if defined(_MSC_VER) #pragma pack() #endif @@ -116,6 +110,8 @@ void W_Shutdown(void) Z_Free(wadfiles[numwadfiles]->lumpinfo); Z_Free(wadfiles[numwadfiles]->filename); Z_Free(wadfiles[numwadfiles]); + while (wadfiles[numwadfiles]->numlumps--) + Z_Free(wadfiles[numwadfiles]->lumpinfo[wadfiles[numwadfiles]->numlumps].name2); } } @@ -174,6 +170,28 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) return handle; } +// Look for all DEHACKED and Lua scripts inside a PK3 archive. +static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum) +{ + UINT16 posStart, posEnd; + posStart = W_CheckNumForFolderStartPK3("Lua/", wadnum, 0); + if (posStart != INT16_MAX) + { + posStart++; + posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart); + for (; posStart < posEnd; posStart++) + LUA_LoadLump(wadnum, posStart); + } + posStart = W_CheckNumForFolderStartPK3("SOC/", wadnum, 0); + if (posStart != INT16_MAX) + { + posStart++; + posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart); + for(; posStart < posEnd; posStart++) + DEH_LoadDehackedLumpPwad(wadnum, posStart); + } +} + // search for all DEHACKED lump in all wads and load it static inline void W_LoadDehackedLumps(UINT16 wadnum) { @@ -291,12 +309,13 @@ static void W_InvalidateLumpnumCache(void) // // Can now load dehacked files (.soc) // -UINT16 W_LoadWadFile(const char *filename) +UINT16 W_InitFile(const char *filename) { FILE *handle; lumpinfo_t *lumpinfo; wadfile_t *wadfile; - UINT32 numlumps; + enum restype type; + UINT16 numlumps; size_t i; INT32 compressed = 0; size_t packetsize = 0; @@ -339,12 +358,34 @@ UINT16 W_LoadWadFile(const char *filename) return INT16_MAX; } +#ifndef NOMD5 + // + // w-waiiiit! + // Let's not add a wad file if the MD5 matches + // an MD5 of an already added WAD file! + // + W_MakeFileMD5(filename, md5sum); + + for (i = 0; i < numwadfiles; i++) + { + if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); + if (handle) + fclose(handle); + return INT16_MAX; + } + } +#endif + // detect dehacked file with the "soc" extension if (!stricmp(&filename[strlen(filename) - 4], ".soc")) { // This code emulates a wadfile with one lump name "OBJCTCFG" // at position 0 and size of the whole file. // This allows soc files to be like all wads, copied by network and loaded at the console. + type = RET_SOC; + numlumps = 1; lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); lumpinfo->position = 0; @@ -352,6 +393,10 @@ UINT16 W_LoadWadFile(const char *filename) lumpinfo->size = ftell(handle); fseek(handle, 0, SEEK_SET); strcpy(lumpinfo->name, "OBJCTCFG"); + // Allocate the lump's full name. + lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strcpy(lumpinfo->name2, "OBJCTCFG"); + lumpinfo->name2[8] = '\0'; } #ifdef HAVE_BLUA // detect lua script with the "lua" extension @@ -360,6 +405,8 @@ UINT16 W_LoadWadFile(const char *filename) // This code emulates a wadfile with one lump name "LUA_INIT" // at position 0 and size of the whole file. // This allows soc files to be like all wads, copied by network and loaded at the console. + type = RET_LUA; + numlumps = 1; lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); lumpinfo->position = 0; @@ -367,16 +414,206 @@ UINT16 W_LoadWadFile(const char *filename) lumpinfo->size = ftell(handle); fseek(handle, 0, SEEK_SET); strcpy(lumpinfo->name, "LUA_INIT"); + // Allocate the lump's full name. + lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strcpy(lumpinfo->name2, "OBJCTCFG"); + lumpinfo->name2[8] = '\0'; } #endif +else if (!stricmp(&filename[strlen(filename) - 4], ".pk3")) + { + char curHeader[4]; + unsigned long size; + char seekPat[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; + char endPat[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; + char *s; + int c; + UINT32 position; + boolean matched = false; + lumpinfo_t *lump_p; + + type = RET_PK3; + + // Obtain the file's size. + fseek(handle, 0, SEEK_END); + size = ftell(handle); + CONS_Debug(DBG_SETUP, "PK3 size is: %ld\n", size); + + // We must look for the central directory through the file. (Thanks to JTE for this algorithm.) + // All of the central directory entry headers have a signature of 0x50 0x4b 0x01 0x02. + // The first entry found means the beginning of the central directory. + fseek(handle, -min(size, (22 + 65536)), SEEK_CUR); + s = endPat; + while((c = fgetc(handle)) != EOF) + { + if (*s != c && s > endPat) // No match? + s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array. + if (*s == c) + { + s++; + if (*s == 0x00) // The array pointer has reached the key char which marks the end. It means we have matched the signature. + { + matched = true; + CONS_Debug(DBG_SETUP, "Found PK3 central directory at position %ld.\n", ftell(handle)); + break; + } + } + } + + // Error if we couldn't find the central directory at all. It likely means this is not a ZIP/PK3 file. + if (matched == false) + { + CONS_Alert(CONS_ERROR, "No central directory inside PK3! File may be corrupted or incomplete.\n"); + return INT16_MAX; + } + + fseek(handle, 4, SEEK_CUR); + fread(&numlumps, 1, 2, handle); + fseek(handle, 6, SEEK_CUR); + fread(&position, 1, 4, handle); + lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); + fseek(handle, position, SEEK_SET); + + // Since we found the central directory, now we can map our lumpinfo table. + // We will look for file headers inside it, until we reach the central directory end signature. + // We exactly know what data to expect this time, so now we don't need to do a byte-by-byte search. + CONS_Debug(DBG_SETUP, "Now finding central directory file headers...\n"); + for (i = 0; i < numlumps; i++, lump_p++) + { + fread(curHeader, 1, 4, handle); + + // We found a central directory entry signature? + if (!strncmp(curHeader, seekPat, 3)) + { + // Let's fill in the fields that we actually need. + // (Declaring all those vars might not be the optimal way to do this, sorry.) + char *eName; + int namePos; + int nameEnd; + unsigned short int eNameLen = 8; + unsigned short int eXFieldLen = 0; + unsigned short int lNameLen = 0; + unsigned short int lXFieldLen = 0; + unsigned short int eCommentLen = 0; + unsigned short int eCompression = 0; + unsigned int eSize = 0; + unsigned int eCompSize = 0; + unsigned int eLocalHeaderOffset = 0; + unsigned long int rememberPos = 0; + + // We get the compression type indicator value. + fseek(handle, 6, SEEK_CUR); + fread(&eCompression, 1, 2, handle); + // Get the size + fseek(handle, 8, SEEK_CUR); + fread(&eCompSize, 1, 4, handle); + fread(&eSize, 1, 4, handle); + // We get the variable length fields. + fread(&eNameLen, 1, 2, handle); + fread(&eXFieldLen, 1, 2, handle); + fread(&eCommentLen, 1, 2, handle); + fseek(handle, 8, SEEK_CUR); + fread(&eLocalHeaderOffset, 1, 4, handle); // Get the offset. + + eName = malloc(sizeof(char)*(eNameLen + 1)); + fgets(eName, eNameLen + 1, handle); + + // Don't load lump if folder. +// if (*(eName + eNameLen - 1) == '/') +// continue; + + // We must calculate the position for the actual data. + // Why not eLocalHeaderOffset + 30 + eNameLen + eXFieldLen? That's because the extra field and name lengths MAY be different in the local headers. + rememberPos = ftell(handle); + fseek(handle, eLocalHeaderOffset + 26, SEEK_SET); + fread(&lNameLen, 1, 2, handle); + fread(&lXFieldLen, 1, 2, handle); + lump_p->position = ftell(handle) + lNameLen + lXFieldLen; + + fseek(handle, rememberPos, SEEK_SET); // Let's go back to the central dir. + lump_p->disksize = eCompSize; + lump_p->size = eSize; + + // We will trim the file's full name so that only the filename is left. + namePos = eNameLen - 1; + while(namePos--) + if(eName[namePos] == '/') + break; + namePos++; + // We will remove the file extension too. + nameEnd = 0; + while(nameEnd++ < 8) + if(eName[namePos + nameEnd] == '.') + break; + memset(lump_p->name, '\0', 9); + strncpy(lump_p->name, eName + namePos, nameEnd); + + lump_p->name2 = Z_Malloc((eNameLen+1)*sizeof(char), PU_STATIC, NULL); + strncpy(lump_p->name2, eName, eNameLen); + lump_p->name2[eNameLen] = '\0'; + + // We set the compression type from what we're supporting so far. + switch(eCompression) + { + case 0: + lump_p->compression = CM_NOCOMPRESSION; + break; + case 8: + lump_p->compression = CM_DEFLATE; + break; + case 14: + lump_p->compression = CM_LZF; + break; + default: + CONS_Alert(CONS_WARNING, "Lump has an unsupported compression type!\n"); + lump_p->compression = CM_UNSUPPORTED; + break; + } + CONS_Debug(DBG_SETUP, "File %s, data begins at: %ld\n", eName, lump_p->position); + fseek(handle, eXFieldLen + eCommentLen, SEEK_CUR); // We skip to where we expect the next central directory entry or end marker to be. + free(eName); + } + // We found the central directory end signature? + else if (!strncmp(curHeader, endPat, 4)) + { + CONS_Debug(DBG_SETUP, "Central directory end signature found at: %ld\n", ftell(handle)); + + /*// We will create a "virtual" marker lump at the very end of lumpinfo for convenience. + // This marker will be used by the different lump-seeking (eg. textures, sprites, etc.) in PK3-specific cases in an auxiliary way. + lumpinfo = (lumpinfo_t*) Z_Realloc(lumpinfo, (numlumps + 1)*sizeof(*lumpinfo), PU_STATIC, NULL); + strcpy(lumpinfo[numlumps].name, "PK3_ENDM\0"); + lumpinfo[numlumps].name2 = Z_Malloc(14 * sizeof(char), PU_STATIC, NULL); + strcpy(lumpinfo[numlumps].name2, "PK3_ENDMARKER\0"); + lumpinfo[numlumps].position = 0; + lumpinfo[numlumps].size = 0; + lumpinfo[numlumps].disksize = 0; + lumpinfo[numlumps].compression = CM_NOCOMPRESSION; + numlumps++;*/ + break; + } + // ... None of them? We're only expecting either a central directory signature entry or the central directory end signature. + // The file may be broken or incomplete... + else + { + CONS_Alert(CONS_WARNING, "Expected central directory header signature, got something else!"); + return INT16_MAX; + } + } + // If we've reached this far, then it means our dynamically stored lumpinfo has to be ready. + // Now we finally build our... incorrectly called wadfile. + // TODO: Maybe we should give them more generalized names, like resourcefile or resfile or something. + // Mostly for clarity and better understanding when reading the code. + } + // assume wad file else { - // assume wad file wadinfo_t header; lumpinfo_t *lump_p; filelump_t *fileinfo; void *fileinfov; + type = RET_WAD; + // read the header if (fread(&header, 1, sizeof header, handle) < sizeof header) { @@ -437,44 +674,29 @@ UINT16 W_LoadWadFile(const char *filename) if (realsize != 0) { lump_p->size = realsize; - lump_p->compressed = 1; + lump_p->compression = CM_LZF; } else { lump_p->size -= 4; - lump_p->compressed = 0; + lump_p->compression = CM_NOCOMPRESSION; } lump_p->position += 4; lump_p->disksize -= 4; } - else lump_p->compressed = 0; + else + lump_p->compression = CM_NOCOMPRESSION; memset(lump_p->name, 0x00, 9); strncpy(lump_p->name, fileinfo->name, 8); + // Allocate the lump's full name. + lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strncpy(lump_p->name2, fileinfo->name, 8); + lump_p->name2[8] = '\0'; } free(fileinfov); } -#ifndef NOMD5 - // - // w-waiiiit! - // Let's not add a wad file if the MD5 matches - // an MD5 of an already added WAD file! - // - W_MakeFileMD5(filename, md5sum); - - for (i = 0; i < numwadfiles; i++) - { - if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) - { - CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); - if (handle) - fclose(handle); - return INT16_MAX; - } - } -#endif - // // link wad file to search files // @@ -485,6 +707,7 @@ UINT16 W_LoadWadFile(const char *filename) wadfile->lumpinfo = lumpinfo; fseek(handle, 0, SEEK_END); wadfile->filesize = (unsigned)ftell(handle); + wadfile->type = type; // already generated, just copy it over M_Memcpy(&wadfile->md5sum, &md5sum, 16); @@ -505,10 +728,30 @@ UINT16 W_LoadWadFile(const char *filename) CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps); 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 - W_LoadDehackedLumps(numwadfiles-1); + + // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. + switch (wadfile->type) + { + case RET_WAD: + W_LoadDehackedLumps(numwadfiles - 1); + break; + case RET_PK3: + W_LoadDehackedLumpsPK3(numwadfiles - 1); + break; + case RET_SOC: + CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename); + DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0); + break; + case RET_LUA: + LUA_LoadLump(numwadfiles - 1, 0); + break; + default: + break; + } W_InvalidateLumpnumCache(); + CONS_Printf("Ended function.\n"); return wadfile->numlumps; } @@ -566,7 +809,7 @@ INT32 W_InitMultipleFiles(char **filenames) for (; *filenames; filenames++) { //CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); - rc &= (W_LoadWadFile(*filenames) != INT16_MAX) ? 1 : 0; + rc &= (W_InitFile(*filenames) != INT16_MAX) ? 1 : 0; } if (!numwadfiles) @@ -644,6 +887,51 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) return INT16_MAX; } +// Look for the first lump from a folder. +UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump) +{ + INT32 i; + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + { + if (strnicmp(name, lump_p->name2, strlen(name)) == 0) + break; + } + return i; +} + +// In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile. +// Useful for finding folder ends. +// Returns the position of the lumpinfo entry. +UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) +{ + INT32 i; + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + { + if (strnicmp(name, lump_p->name2, strlen(name))) + break; + } + return i; +} + +// In a PK3 type of resource file, it looks for an entry with the specified full name. +// Returns lump position in PK3's lumpinfo, or INT16_MAX if not found. +UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump) +{ + INT32 i; + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + { + if (!strnicmp(name, lump_p->name2, strlen(name))) + { + return i; + } + } + // Not found at all? + return INT16_MAX; +} + // // W_CheckNumForName // Returns LUMPERROR if name not found. @@ -684,6 +972,37 @@ lumpnum_t W_CheckNumForName(const char *name) } } +// Look for valid map data through all added files in descendant order. +// Get a map marker for WADs, and a standalone WAD file lump inside PK3s. +// TODO: Make it search through cache first, maybe...? +lumpnum_t W_CheckNumForMap(const char *name) +{ + UINT16 lumpNum, end; + UINT32 i; + for (i = numwadfiles - 1; i < numwadfiles; i--) + { + if (wadfiles[i]->type == RET_WAD) + { + for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++) + if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8)) + return (i<<16) + lumpNum; + } + else if (wadfiles[i]->type == RET_PK3) + { + lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0); + if (lumpNum != INT16_MAX) + end = W_CheckNumForFolderEndPK3("maps/", i, lumpNum); + else + continue; + // Now look for the specified map. + for (++lumpNum; lumpNum < end; lumpNum++) + if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8)) + return (i<<16) + lumpNum; + } + } + return LUMPERROR; +} + // // W_GetNumForName // @@ -714,15 +1033,19 @@ lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, con // scan wad files backwards so patch lump files take precedence for (i = numwadfiles - 1; i >= 0; i--) { - bsid = W_CheckNumForNamePwad(blockstart,(UINT16)i,0); - if (bsid == INT16_MAX) - continue; // block doesn't exist, keep going - beid = W_CheckNumForNamePwad(blockend,(UINT16)i,0); - // if block end doesn't exist, just search through everything + if (wadfiles[i]->type == RET_WAD) + { + bsid = W_CheckNumForNamePwad(blockstart, (UINT16)i, 0); + if (bsid == INT16_MAX) + continue; // Start block doesn't exist? + beid = W_CheckNumForNamePwad(blockend, (UINT16)i, 0); + if (beid == INT16_MAX) + continue; // End block doesn't exist? - check = W_CheckNumForNamePwad(name,(UINT16)i,bsid); - if (check < beid) - return (i<<16)+check; // found it, in our constraints + check = W_CheckNumForNamePwad(name, (UINT16)i, bsid); + if (check < beid) + return (i<<16)+check; // found it, in our constraints + } } return LUMPERROR; } @@ -759,6 +1082,24 @@ size_t W_LumpLength(lumpnum_t lumpnum) return W_LumpLengthPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); } +// +// W_IsLumpWad +// Is the lump a WAD? (presumably in a PK3) +// +boolean W_IsLumpWad(lumpnum_t lumpnum) +{ + if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3) + { + const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->name2; + + if (strlen(lumpfullName) < 4) + return false; // can't possibly be a WAD can it? + return !strnicmp(lumpfullName + strlen(lumpfullName) - 4, ".wad", 4); + } + + return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned +} + /** Reads bytes from the head of a lump, without doing decompression. * * \param wad Wad number to read from. @@ -785,54 +1126,35 @@ static size_t W_RawReadLumpHeader(UINT16 wad, UINT16 lump, void *dest, size_t si return bytesread; } -// Read a compressed lump; return it in newly Z_Malloc'd memory. -// wad is number of wad file, lump is number of lump in wad. -static void *W_ReadCompressedLump(UINT16 wad, UINT16 lump) +/* report a zlib or i/o error */ +void zerr(int ret) { -#ifdef ZWAD - char *compressed, *data; - const lumpinfo_t *l = &wadfiles[wad]->lumpinfo[lump]; - size_t retval; - - compressed = Z_Malloc(l->disksize, PU_STATIC, NULL); - data = Z_Malloc(l->size, PU_STATIC, NULL); - if (W_RawReadLumpHeader(wad, lump, compressed, l->disksize, 0) - < l->disksize) - { - I_Error("wad %d, lump %d: cannot read compressed data", - wad, lump); - } - - retval = lzf_decompress(compressed, l->disksize, data, l->size); -#ifndef AVOID_ERRNO - if (retval == 0 && errno == E2BIG) - { - I_Error("wad %d, lump %d: compressed data too big " - "(bigger than %s)", wad, lump, sizeu1(l->size)); - } - else if (retval == 0 && errno == EINVAL) - I_Error("wad %d, lump %d: invalid compressed data", wad, lump); - else -#endif - if (retval != l->size) - { - I_Error("wad %d, lump %d: decompressed to wrong number of " - "bytes (expected %s, got %s)", wad, lump, - sizeu1(l->size), sizeu2(retval)); - } - Z_Free(compressed); - return data; -#else - (void)wad; - (void)lump; - //I_Error("ZWAD files not supported on this platform."); - return NULL; -#endif + CONS_Printf("zpipe: "); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + CONS_Printf("error reading stdin\n"); + if (ferror(stdout)) + CONS_Printf("error writing stdout\n"); + break; + case Z_STREAM_ERROR: + CONS_Printf("invalid compression level\n"); + break; + case Z_DATA_ERROR: + CONS_Printf("invalid or incomplete deflate data\n"); + break; + case Z_MEM_ERROR: + CONS_Printf("out of memory\n"); + break; + case Z_VERSION_ERROR: + CONS_Printf("zlib version mismatch!\n"); + } } /** Reads bytes from the head of a lump. * Note: If the lump is compressed, the whole thing has to be read anyway. * + * \param wad Wad number to read from. * \param lump Lump number to read from. * \param dest Buffer in memory to serve as destination. * \param size Number of bytes to read. @@ -843,6 +1165,8 @@ static void *W_ReadCompressedLump(UINT16 wad, UINT16 lump) size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset) { size_t lumpsize; + lumpinfo_t *l; + FILE *handle; if (!TestValidLump(wad,lump)) return 0; @@ -856,17 +1180,112 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si if (!size || size+offset > lumpsize) size = lumpsize - offset; - if (wadfiles[wad]->lumpinfo[lump].compressed) + // Let's get the raw lump data. + // We setup the desired file handle to read the lump data. + l = wadfiles[wad]->lumpinfo + lump; + handle = wadfiles[wad]->handle; + fseek(handle, (long)(l->position + offset), SEEK_SET); + + // But let's not copy it yet. We support different compression formats on lumps, so we need to take that into account. + switch(wadfiles[wad]->lumpinfo[lump].compression) { - UINT8 *data; - data = W_ReadCompressedLump(wad, lump); - if (!data) return 0; - M_Memcpy(dest, data+offset, size); - Z_Free(data); - return size; + case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read. + return fread(dest, 1, size, handle); + case CM_LZF: // Is it LZF compressed? Used by ZWADs. + { +#ifdef ZWAD + char *rawData; // The lump's raw data. + char *decData; // Lump's decompressed real data. + size_t retval; // Helper var, lzf_decompress returns 0 when an error occurs. + + rawData = Z_Malloc(l->disksize, PU_STATIC, NULL); + decData = Z_Malloc(l->size, PU_STATIC, NULL); + + if (fread(rawData, 1, l->disksize, handle) < l->disksize) + I_Error("wad %d, lump %d: cannot read compressed data", wad, lump); + retval = lzf_decompress(rawData, l->disksize, decData, l->size); +#ifndef AVOID_ERRNO + if (retval == 0 && errno == E2BIG) // errno is a global var set by the lzf functions when something goes wrong. + { + I_Error("wad %d, lump %d: compressed data too big (bigger than %s)", wad, lump, sizeu1(l->size)); + } + else if (retval == 0 && errno == EINVAL) + I_Error("wad %d, lump %d: invalid compressed data", wad, lump); + else +#endif + if (retval != l->size) + { + I_Error("wad %d, lump %d: decompressed to wrong number of bytes (expected %s, got %s)", wad, lump, sizeu1(l->size), sizeu2(retval)); + } +#else + (void)wad; + (void)lump; + //I_Error("ZWAD files not supported on this platform."); + return NULL; +#endif + if (!decData) // Did we get no data at all? + return 0; + M_Memcpy(dest, decData + offset, size); + Z_Free(rawData); + Z_Free(decData); + return size; + } + case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support. + { + z_const Bytef *rawData; // The lump's raw data. + Bytef *decData; // Lump's decompressed real data. + + int zErr; // Helper var. + z_stream strm; + unsigned long rawSize = l->disksize; + unsigned long decSize = l->size; + + rawData = Z_Malloc(rawSize, PU_STATIC, NULL); + decData = Z_Malloc(decSize, PU_STATIC, NULL); + + if (fread(rawData, 1, rawSize, handle) < rawSize) + I_Error("wad %d, lump %d: cannot read compressed data", wad, lump); + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + strm.total_in = strm.avail_in = rawSize; + strm.total_out = strm.avail_out = decSize; + + strm.next_in = rawData; + strm.next_out = decData; + + zErr = inflateInit2(&strm, -15); + if (zErr == Z_OK) + { + zErr = inflate(&strm, Z_FINISH); + if (zErr == Z_STREAM_END) + { + M_Memcpy(dest, decData, size); + } + else + { + size = 0; + zerr(zErr); + (void)inflateEnd(&strm); + } + } + else + { + CONS_Printf("whopet\n"); + size = 0; + zerr(zErr); + } + + Z_Free(rawData); + Z_Free(decData); + + return size; + } + default: + I_Error("wad %d, lump %d: unsupported compression type!", wad, lump); } - else - return W_RawReadLumpHeader(wad, lump, dest, size, offset); } size_t W_ReadLumpHeader(lumpnum_t lumpnum, void *dest, size_t size, size_t offset) @@ -1150,12 +1569,12 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, if ((handle = W_OpenWadFile(&filename, false)) == NULL) return -1; - // detect dehacked file with the "soc" extension - if (stricmp(&filename[strlen(filename) - 4], ".soc") != 0 + // detect wad file by the absence of the other supported extensions + if (stricmp(&filename[strlen(filename) - 4], ".soc") #ifdef HAVE_BLUA - && stricmp(&filename[strlen(filename) - 4], ".lua") != 0 + && stricmp(&filename[strlen(filename) - 4], ".lua") #endif - ) + && stricmp(&filename[strlen(filename) - 4], ".pk3")) { // assume wad file wadinfo_t header; diff --git a/src/w_wad.h b/src/w_wad.h index 0e62cc9b..b84a5634 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -22,6 +22,15 @@ #pragma interface #endif +// a raw entry of the wad directory +// NOTE: This sits here and not in w_wad.c because p_setup.c makes use of it to load map WADs inside PK3s. +typedef struct +{ + UINT32 filepos; // file offset of the resource + UINT32 size; // size of the resource + char name[8]; // name of the resource +} ATTRPACK filelump_t; + // ============================================================== // WAD FILE STRUCTURE DEFINITIONS // ============================================================== @@ -34,14 +43,25 @@ typedef struct UINT32 infotableofs; // the 'directory' of resources } wadinfo_t; +// Available compression methods for lumps. +typedef enum +{ + CM_NOCOMPRESSION, + CM_DEFLATE, + CM_LZF, + CM_UNSUPPORTED +} compmethod; + // a memory entry of the wad directory typedef struct { unsigned long position; // filelump_t filepos unsigned long disksize; // filelump_t size char name[9]; // filelump_t name[] + char *name2; // Used by PK3s. Dynamically allocated name. size_t size; // real (uncompressed) size INT32 compressed; // i + compmethod compression; // lump compression method } lumpinfo_t; // ========================================================================= @@ -58,9 +78,19 @@ typedef struct #include "m_aatree.h" #endif +// Resource type of the WAD. Yeah, I know this sounds dumb, but I'll leave it like this until I clean up the code further. +typedef enum restype +{ + RET_WAD, + RET_SOC, + RET_LUA, + RET_PK3 +} restype_t; + typedef struct wadfile_s { char *filename; + enum restype type; lumpinfo_t *lumpinfo; lumpcache_t *lumpcache; #ifdef HWRENDER @@ -85,7 +115,7 @@ void W_Shutdown(void); // Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened FILE *W_OpenWadFile(const char **filename, boolean useerrors); // Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error -UINT16 W_LoadWadFile(const char *filename); +UINT16 W_InitFile(const char *filename); #ifdef DELFILE void W_UnloadWadFile(UINT16 num); #endif @@ -98,6 +128,12 @@ const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump); const char *W_CheckNameForNum(lumpnum_t lumpnum); UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad + +UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump); +UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump); +UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump); + +lumpnum_t W_CheckNumForMap(const char *name); lumpnum_t W_CheckNumForName(const char *name); lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend); @@ -106,6 +142,10 @@ UINT8 W_LumpExists(const char *name); // Lua uses this. size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump); size_t W_LumpLength(lumpnum_t lumpnum); +boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s + +void zerr(int ret); // zlib error checking + size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset); size_t W_ReadLumpHeader(lumpnum_t lump, void *dest, size_t size, size_t offest); // read all or a part of a lump void W_ReadLumpPwad(UINT16 wad, UINT16 lump, void *dest); From 0487558a980365d1fc3adfd859c6a5cee8226ef1 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Fri, 23 Nov 2018 17:58:45 +0100 Subject: [PATCH 74/93] Add missing tweaks Also remove a test printf. Signed-off-by: Nev3r --- src/p_spec.c | 14 +++++++++++++- src/w_wad.c | 31 +++++++++++++++++-------------- src/w_wad.h | 2 +- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index ff6691a9..047cb14d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6243,9 +6243,21 @@ void P_SpawnSpecials(INT32 fromnetsave) case 259: // Make-Your-Own FOF! if (lines[i].sidenum[1] != 0xffff) { - UINT8 *data = W_CacheLumpNum(lastloadedmaplumpnum + ML_SIDEDEFS,PU_STATIC); + UINT8 *data; UINT16 b; + if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 + { // HACK: Open wad file rather quickly so we can get the data from the sidedefs lump + UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); + filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); + fileinfo += ML_SIDEDEFS; // we only need the SIDEDEFS lump + data = Z_Malloc(fileinfo->size, PU_STATIC, NULL); + M_Memcpy(data, wadData + fileinfo->filepos, fileinfo->size); // copy data + Z_Free(wadData); // we're done with this now + } + else // phew it's just a WAD + data = W_CacheLumpNum(lastloadedmaplumpnum + ML_SIDEDEFS,PU_STATIC); + for (b = 0; b < (INT16)numsides; b++) { register mapsidedef_t *msd = (mapsidedef_t *)data + b; diff --git a/src/w_wad.c b/src/w_wad.c index 977b7e6f..28cbe033 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -177,18 +177,28 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum) posStart = W_CheckNumForFolderStartPK3("Lua/", wadnum, 0); if (posStart != INT16_MAX) { - posStart++; posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart); + posStart++; for (; posStart < posEnd; posStart++) LUA_LoadLump(wadnum, posStart); } posStart = W_CheckNumForFolderStartPK3("SOC/", wadnum, 0); if (posStart != INT16_MAX) { - posStart++; posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart); + posStart++; for(; posStart < posEnd; posStart++) + { + lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart]; + size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name + char *name = malloc(length + 1); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2); + name[length] = '\0'; + CONS_Printf(M_GetText("Loading SOC from %s\n"), name); DEH_LoadDehackedLumpPwad(wadnum, posStart); + free(name); + } + } } @@ -212,20 +222,13 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum) for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++) if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump { // shameless copy+paste of code from LUA_LoadLump - size_t len = strlen(wadfiles[wadnum]->filename); - char *name = malloc(len+10); - - strcpy(name, wadfiles[wadnum]->filename); - if (!fasticmp(&name[len - 4], ".soc")) { - // If it's not a .soc file, copy the lump name in too. - name[len] = '|'; - M_Memcpy(name+len+1, lump_p->name, 8); - name[len+9] = '\0'; - } + size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name + char *name = malloc(length + 1); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2); + name[length] = '\0'; CONS_Printf(M_GetText("Loading SOC from %s\n"), name); DEH_LoadDehackedLumpPwad(wadnum, lump); - free(name); } else if (memcmp(lump_p->name,"MAINCFG",8)==0) // Check for MAINCFG @@ -314,7 +317,7 @@ UINT16 W_InitFile(const char *filename) FILE *handle; lumpinfo_t *lumpinfo; wadfile_t *wadfile; - enum restype type; + restype_t type; UINT16 numlumps; size_t i; INT32 compressed = 0; diff --git a/src/w_wad.h b/src/w_wad.h index b84a5634..263b7119 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -90,7 +90,7 @@ typedef enum restype typedef struct wadfile_s { char *filename; - enum restype type; + restype_t type; lumpinfo_t *lumpinfo; lumpcache_t *lumpcache; #ifdef HWRENDER From b60c10dc9bbe595a6fb73c09077137ddce5a6510 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 23 Nov 2018 20:51:57 -0500 Subject: [PATCH 75/93] Change default mouse sensitivity --- src/g_input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index add7c2fc..c5c92f75 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -25,10 +25,10 @@ static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"}, {0, NULL}}; // mouse values are used once -consvar_t cv_mousesens = {"mousesens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mousesens2 = {"mousesens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mouseysens = {"mouseysens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mouseysens2 = {"mouseysens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mousesens = {"mousesens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mousesens2 = {"mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mouseysens = {"mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mouseysens2 = {"mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; INT32 mousex, mousey; From 3b298b7c42442f64e88af46aee406c75e41422c4 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 23 Nov 2018 21:43:50 -0500 Subject: [PATCH 76/93] Adjust mouse scaling calculation for SDL in windowed mode --- src/sdl/i_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 3cc29dbb..e2c38efb 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -864,8 +864,8 @@ void I_GetEvent(void) //SDL_memset(&event, 0, sizeof(event_t)); event.type = ev_mouse; event.data1 = 0; - event.data2 = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth)); - event.data3 = (INT32)lround(mousemovey * ((float)wheight / (float)realheight)); + event.data2 = (INT32)lround(mousemovex * ((float)realwidth / (float)wwidth)); + event.data3 = (INT32)lround(mousemovey * ((float)realheight / (float)wheight)); D_PostEvent(&event); } From cb0c31fa9ad1b48efae6f2fa62da1fe7018e07bd Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 24 Nov 2018 09:26:52 +0100 Subject: [PATCH 77/93] Final touches -Backported multiple per-wad/pk3 ANIMDEFS supported now, just like TEXTURES. -Removed now-unused function. Signed-off-by: Nev3r --- src/p_spec.c | 14 ++++++++++---- src/w_wad.c | 28 ---------------------------- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 047cb14d..e020ceef 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -279,10 +279,16 @@ void P_InitPicAnims(void) Z_Free(animatedLump); } - // Now find ANIMDEFS - animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); - if (animdefsLumpNum != INT16_MAX) - P_ParseANIMDEFSLump(w, animdefsLumpNum); + for (w = numwadfiles-1; w >= 0; w--) + { + // Find ANIMDEFS lump in the WAD + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); + while (animdefsLumpNum != INT16_MAX) + { + P_ParseANIMDEFSLump(w, animdefsLumpNum); + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); + } + } } // Define the last one animdefs[maxanims].istexture = -1; diff --git a/src/w_wad.c b/src/w_wad.c index 28cbe033..57bde14c 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -753,8 +753,6 @@ else if (!stricmp(&filename[strlen(filename) - 4], ".pk3")) } W_InvalidateLumpnumCache(); - - CONS_Printf("Ended function.\n"); return wadfile->numlumps; } @@ -1103,32 +1101,6 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned } -/** Reads bytes from the head of a lump, without doing decompression. - * - * \param wad Wad number to read from. - * \param lump Lump number to read from, within wad. - * \param dest Buffer in memory to serve as destination. - * \param size Number of bytes to read. - * \param offest Number of bytes to offset. - * \return Number of bytes read (should equal size). - * \sa W_ReadLumpHeader - */ -static size_t W_RawReadLumpHeader(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset) -{ - size_t bytesread; - lumpinfo_t *l; - FILE *handle; - - l = wadfiles[wad]->lumpinfo + lump; - - handle = wadfiles[wad]->handle; - - fseek(handle, (long)(l->position + offset), SEEK_SET); - bytesread = fread(dest, 1, size, handle); - - return bytesread; -} - /* report a zlib or i/o error */ void zerr(int ret) { From 17528a6aa934162c222e98fba79079e7996fd77f Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 24 Nov 2018 14:48:56 -0500 Subject: [PATCH 78/93] LFS fixup for PK3 support --- src/w_wad.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/w_wad.c b/src/w_wad.c index 57bde14c..1530a4a0 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -26,6 +26,18 @@ #include "lzf.h" #endif +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + #include "zlib.h" #include "doomdef.h" From f80691eb6ef319993467b7c1ebc515cac42106ed Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 24 Nov 2018 15:36:50 -0500 Subject: [PATCH 79/93] Revert "Adjust mouse scaling calculation for SDL in windowed mode" This reverts commit 3b298b7c42442f64e88af46aee406c75e41422c4. --- src/sdl/i_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index e2c38efb..3cc29dbb 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -864,8 +864,8 @@ void I_GetEvent(void) //SDL_memset(&event, 0, sizeof(event_t)); event.type = ev_mouse; event.data1 = 0; - event.data2 = (INT32)lround(mousemovex * ((float)realwidth / (float)wwidth)); - event.data3 = (INT32)lround(mousemovey * ((float)realheight / (float)wheight)); + event.data2 = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth)); + event.data3 = (INT32)lround(mousemovey * ((float)wheight / (float)realheight)); D_PostEvent(&event); } From a1fb333e9b2b9a36e9e849b06b8a469741ed62cf Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 24 Nov 2018 22:58:35 +0100 Subject: [PATCH 80/93] Revamped the lumpinfo_t array generation code. -The resource type is 'adequately*' detected first. -The type-specific behaviors are now contained in their own functions, which are called accordingly for each. -The PKZip lumpinfo_t generation has been almost entirely rewritten. -If the functions return null pointer, the resource addition is considered invalid and pops an error. --- src/w_wad.c | 643 +++++++++++++++++++++++++++------------------------- src/w_wad.h | 5 +- 2 files changed, 332 insertions(+), 316 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 57bde14c..93722c0b 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -26,7 +26,23 @@ #include "lzf.h" #endif +#ifdef HAVE_ZLIB +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + #include "zlib.h" +#endif // HAVE_ZLIB #include "doomdef.h" #include "doomstat.h" @@ -301,6 +317,299 @@ static void W_InvalidateLumpnumCache(void) memset(lumpnumcache, 0, sizeof (lumpnumcache)); } +/** Detect a file type. + * \todo Actually detect the wad/pkzip headers and whatnot, instead of just checking the extensions. + */ +static restype_t ResourceFileDetect (const char* filename) +{ + if (!stricmp(&filename[strlen(filename) - 4], ".pk3")) + return RET_PK3; + if (!stricmp(&filename[strlen(filename) - 4], ".soc")) + return RET_SOC; + if (!stricmp(&filename[strlen(filename) - 4], ".lua")) + return RET_LUA; + + return RET_WAD; +} + +/** Create a 1-lump lumpinfo_t for standalone files. + */ +static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const char* lumpname) +{ + lumpinfo_t* lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); + lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); + lumpinfo->position = 0; + fseek(handle, 0, SEEK_END); + lumpinfo->size = ftell(handle); + fseek(handle, 0, SEEK_SET); + strcpy(lumpinfo->name, lumpname); + // Allocate the lump's full name. + lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strcpy(lumpinfo->name2, lumpname); + lumpinfo->name2[8] = '\0'; + *numlumps = 1; + return lumpinfo; +} + +/** Create a lumpinfo_t array for a WAD file. + */ +static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filename) +{ + UINT16 numlumps = *nlmp; + lumpinfo_t* lumpinfo; + size_t i; + INT32 compressed = 0; + + wadinfo_t header; + lumpinfo_t *lump_p; + filelump_t *fileinfo; + void *fileinfov; + + // read the header + if (fread(&header, 1, sizeof header, handle) < sizeof header) + { + CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header because %s\n"), strerror(ferror(handle))); + return 0; + } + + if (memcmp(header.identification, "ZWAD", 4) == 0) + compressed = 1; + else if (memcmp(header.identification, "IWAD", 4) != 0 + && memcmp(header.identification, "PWAD", 4) != 0 + && memcmp(header.identification, "SDLL", 4) != 0) + { + CONS_Alert(CONS_ERROR, M_GetText("Invalid WAD header\n")); + return 0; + } + + header.numlumps = LONG(header.numlumps); + header.infotableofs = LONG(header.infotableofs); + + // read wad file directory + i = header.numlumps * sizeof (*fileinfo); + fileinfov = fileinfo = malloc(i); + if (fseek(handle, header.infotableofs, SEEK_SET) == -1 + || fread(fileinfo, 1, i, handle) < i) + { + CONS_Alert(CONS_ERROR, M_GetText("Corrupt wadfile directory (%s)\n"), strerror(ferror(handle))); + free(fileinfov); + return 0; + } + + numlumps = header.numlumps; + + // fill in lumpinfo for this wad + lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); + for (i = 0; i < numlumps; i++, lump_p++, fileinfo++) + { + lump_p->position = LONG(fileinfo->filepos); + lump_p->size = lump_p->disksize = LONG(fileinfo->size); + if (compressed) // wad is compressed, lump might be + { + UINT32 realsize = 0; + if (fseek(handle, lump_p->position, SEEK_SET) + == -1 || fread(&realsize, 1, sizeof realsize, + handle) < sizeof realsize) + { + I_Error("corrupt compressed file: %s; maybe %s", /// \todo Avoid the bailout? + filename, strerror(ferror(handle))); + } + realsize = LONG(realsize); + if (realsize != 0) + { + lump_p->size = realsize; + lump_p->compression = CM_LZF; + } + else + { + lump_p->size -= 4; + lump_p->compression = CM_NOCOMPRESSION; + } + + lump_p->position += 4; + lump_p->disksize -= 4; + } + else + lump_p->compression = CM_NOCOMPRESSION; + memset(lump_p->name, 0x00, 9); + strncpy(lump_p->name, fileinfo->name, 8); + // Allocate the lump's full name. + lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strncpy(lump_p->name2, fileinfo->name, 8); + lump_p->name2[8] = '\0'; + } + free(fileinfov); + *nlmp = numlumps; + return lumpinfo; +} + +/** Optimized pattern search in a file. + */ +static boolean ResFindSignature (FILE* handle, char endPat[], UINT32 startpos) +{ + char *s; + int c; + + fseek(handle, startpos, SEEK_SET); + s = endPat; + while((c = fgetc(handle)) != EOF) + { + if (*s != c && s > endPat) // No match? + s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array. + if (*s == c) + { + s++; + if (*s == 0x00) // The array pointer has reached the key char which marks the end. It means we have matched the signature. + { + return true; + } + } + } + return false; +} + +typedef struct zend_s +{ + char signature[4]; + UINT16 diskpos; + UINT16 cdirdisk; + UINT16 diskentries; + UINT16 entries; + UINT32 cdirsize; + UINT32 cdiroffset; + UINT16 commentlen; +} ATTRPACK zend_t; + +typedef struct zentry_s +{ + char signature[4]; + UINT16 version; + UINT16 versionneeded; + UINT16 flags; + UINT16 compression; + UINT16 modtime; + UINT16 moddate; + UINT32 CRC32; + UINT32 compsize; + UINT32 size; + UINT16 namelen; + UINT16 xtralen; + UINT16 commlen; + UINT16 diskstart; + UINT16 attrint; + UINT32 attrext; + UINT32 offset; +} ATTRPACK zentry_t; + +typedef struct zlentry_s +{ + char signature[4]; + UINT16 versionneeded; + UINT16 flags; + UINT16 compression; + UINT16 modtime; + UINT16 moddate; + UINT32 CRC32; + UINT32 compsize; + UINT32 size; + UINT16 namelen; + UINT16 xtralen; +} ATTRPACK zlentry_t; + +/** Create a lumpinfo_t array for a PKZip file. + */ +static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) +{ + zend_t zend; + zentry_t* zentries; + zentry_t* zentry; + + UINT16 numlumps = *nlmp; + lumpinfo_t* lumpinfo; + lumpinfo_t *lump_p; + size_t i; + + char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; + char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; + + // Look for central directory end signature near end of file. + // Contains entry number (number of lumps), and central directory start offset. + fseek(handle, 0, SEEK_END); + if (!ResFindSignature(handle, pat_end, max(0, ftell(handle) - (22 + 65536)))) + { + CONS_Alert(CONS_ERROR, "Missing central directory\n"); + return 0; + } + + fseek(handle, -4, SEEK_CUR); + fread(&zend, 1, sizeof zend, handle); + numlumps = zend.entries; + + lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); + zentry = zentries = malloc(numlumps * sizeof (*zentries)); + + fseek(handle, zend.cdiroffset, SEEK_SET); + for (i = 0; i < numlumps; i++, zentry++, lump_p++) + { + char* fullname; + char* trimname; + char* dotpos; + + fread(zentry, 1, sizeof(zentry_t), handle); + if (memcmp(zentry->signature, pat_central, 4)) + { + CONS_Alert(CONS_ERROR, "Central directory is corrupt\n"); + Z_Free(lumpinfo); + free(zentry); + return 0; + } + + lump_p->position = zentry->offset + zentry->namelen + zentry->xtralen + sizeof(zlentry_t); + lump_p->disksize = zentry->compsize; + lump_p->size = zentry->size; + + fullname = malloc(zentry->namelen + 1); + fgets(fullname, zentry->namelen + 1, handle); + + // Strip away file address and extension for the 8char name. + if ((trimname = strrchr(fullname, '/')) != 0) + trimname++; + else + trimname = fullname; // Care taken for root files. + + if ((dotpos = strrchr(trimname, '.')) == 0) + dotpos = fullname + strlen(fullname); // Watch for files without extension. + + memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary? + strncpy(lump_p->name, trimname, min(8, dotpos - trimname)); + + lump_p->name2 = Z_Calloc(zentry->namelen + 1, PU_STATIC, NULL); + strncpy(lump_p->name2, fullname, zentry->namelen); + + free(fullname); + + switch(zentry->compression) + { + case 0: + lump_p->compression = CM_NOCOMPRESSION; + break; + case 8: + lump_p->compression = CM_DEFLATE; + break; + case 14: + lump_p->compression = CM_LZF; + break; + default: + CONS_Alert(CONS_WARNING, "%s: Unsupported compression method\n", fullname); + lump_p->compression = CM_UNSUPPORTED; + break; + } + } + + *nlmp = numlumps; + return lumpinfo; +} + // Allocate a wadfile, setup the lumpinfo (directory) and // lumpcache, add the wadfile to the current active wadfiles // @@ -318,9 +627,8 @@ UINT16 W_InitFile(const char *filename) lumpinfo_t *lumpinfo; wadfile_t *wadfile; restype_t type; - UINT16 numlumps; + UINT16 numlumps = 0; size_t i; - INT32 compressed = 0; size_t packetsize = 0; serverinfo_pak *dummycheck = NULL; UINT8 md5sum[16]; @@ -381,323 +689,30 @@ UINT16 W_InitFile(const char *filename) } #endif - // detect dehacked file with the "soc" extension - if (!stricmp(&filename[strlen(filename) - 4], ".soc")) + switch(type = ResourceFileDetect(filename)) { - // This code emulates a wadfile with one lump name "OBJCTCFG" - // at position 0 and size of the whole file. - // This allows soc files to be like all wads, copied by network and loaded at the console. - type = RET_SOC; - - numlumps = 1; - lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); - lumpinfo->position = 0; - fseek(handle, 0, SEEK_END); - lumpinfo->size = ftell(handle); - fseek(handle, 0, SEEK_SET); - strcpy(lumpinfo->name, "OBJCTCFG"); - // Allocate the lump's full name. - lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); - strcpy(lumpinfo->name2, "OBJCTCFG"); - lumpinfo->name2[8] = '\0'; - } + case RET_SOC: + lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "OBJCTCFG"); + break; #ifdef HAVE_BLUA - // detect lua script with the "lua" extension - else if (!stricmp(&filename[strlen(filename) - 4], ".lua")) - { - // This code emulates a wadfile with one lump name "LUA_INIT" - // at position 0 and size of the whole file. - // This allows soc files to be like all wads, copied by network and loaded at the console. - type = RET_LUA; - - numlumps = 1; - lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); - lumpinfo->position = 0; - fseek(handle, 0, SEEK_END); - lumpinfo->size = ftell(handle); - fseek(handle, 0, SEEK_SET); - strcpy(lumpinfo->name, "LUA_INIT"); - // Allocate the lump's full name. - lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); - strcpy(lumpinfo->name2, "OBJCTCFG"); - lumpinfo->name2[8] = '\0'; - } + case RET_LUA: + lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "LUA_INIT"); + break; #endif -else if (!stricmp(&filename[strlen(filename) - 4], ".pk3")) - { - char curHeader[4]; - unsigned long size; - char seekPat[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; - char endPat[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; - char *s; - int c; - UINT32 position; - boolean matched = false; - lumpinfo_t *lump_p; - - type = RET_PK3; - - // Obtain the file's size. - fseek(handle, 0, SEEK_END); - size = ftell(handle); - CONS_Debug(DBG_SETUP, "PK3 size is: %ld\n", size); - - // We must look for the central directory through the file. (Thanks to JTE for this algorithm.) - // All of the central directory entry headers have a signature of 0x50 0x4b 0x01 0x02. - // The first entry found means the beginning of the central directory. - fseek(handle, -min(size, (22 + 65536)), SEEK_CUR); - s = endPat; - while((c = fgetc(handle)) != EOF) - { - if (*s != c && s > endPat) // No match? - s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array. - if (*s == c) - { - s++; - if (*s == 0x00) // The array pointer has reached the key char which marks the end. It means we have matched the signature. - { - matched = true; - CONS_Debug(DBG_SETUP, "Found PK3 central directory at position %ld.\n", ftell(handle)); - break; - } - } - } - - // Error if we couldn't find the central directory at all. It likely means this is not a ZIP/PK3 file. - if (matched == false) - { - CONS_Alert(CONS_ERROR, "No central directory inside PK3! File may be corrupted or incomplete.\n"); - return INT16_MAX; - } - - fseek(handle, 4, SEEK_CUR); - fread(&numlumps, 1, 2, handle); - fseek(handle, 6, SEEK_CUR); - fread(&position, 1, 4, handle); - lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); - fseek(handle, position, SEEK_SET); - - // Since we found the central directory, now we can map our lumpinfo table. - // We will look for file headers inside it, until we reach the central directory end signature. - // We exactly know what data to expect this time, so now we don't need to do a byte-by-byte search. - CONS_Debug(DBG_SETUP, "Now finding central directory file headers...\n"); - for (i = 0; i < numlumps; i++, lump_p++) - { - fread(curHeader, 1, 4, handle); - - // We found a central directory entry signature? - if (!strncmp(curHeader, seekPat, 3)) - { - // Let's fill in the fields that we actually need. - // (Declaring all those vars might not be the optimal way to do this, sorry.) - char *eName; - int namePos; - int nameEnd; - unsigned short int eNameLen = 8; - unsigned short int eXFieldLen = 0; - unsigned short int lNameLen = 0; - unsigned short int lXFieldLen = 0; - unsigned short int eCommentLen = 0; - unsigned short int eCompression = 0; - unsigned int eSize = 0; - unsigned int eCompSize = 0; - unsigned int eLocalHeaderOffset = 0; - unsigned long int rememberPos = 0; - - // We get the compression type indicator value. - fseek(handle, 6, SEEK_CUR); - fread(&eCompression, 1, 2, handle); - // Get the size - fseek(handle, 8, SEEK_CUR); - fread(&eCompSize, 1, 4, handle); - fread(&eSize, 1, 4, handle); - // We get the variable length fields. - fread(&eNameLen, 1, 2, handle); - fread(&eXFieldLen, 1, 2, handle); - fread(&eCommentLen, 1, 2, handle); - fseek(handle, 8, SEEK_CUR); - fread(&eLocalHeaderOffset, 1, 4, handle); // Get the offset. - - eName = malloc(sizeof(char)*(eNameLen + 1)); - fgets(eName, eNameLen + 1, handle); - - // Don't load lump if folder. -// if (*(eName + eNameLen - 1) == '/') -// continue; - - // We must calculate the position for the actual data. - // Why not eLocalHeaderOffset + 30 + eNameLen + eXFieldLen? That's because the extra field and name lengths MAY be different in the local headers. - rememberPos = ftell(handle); - fseek(handle, eLocalHeaderOffset + 26, SEEK_SET); - fread(&lNameLen, 1, 2, handle); - fread(&lXFieldLen, 1, 2, handle); - lump_p->position = ftell(handle) + lNameLen + lXFieldLen; - - fseek(handle, rememberPos, SEEK_SET); // Let's go back to the central dir. - lump_p->disksize = eCompSize; - lump_p->size = eSize; - - // We will trim the file's full name so that only the filename is left. - namePos = eNameLen - 1; - while(namePos--) - if(eName[namePos] == '/') - break; - namePos++; - // We will remove the file extension too. - nameEnd = 0; - while(nameEnd++ < 8) - if(eName[namePos + nameEnd] == '.') - break; - memset(lump_p->name, '\0', 9); - strncpy(lump_p->name, eName + namePos, nameEnd); - - lump_p->name2 = Z_Malloc((eNameLen+1)*sizeof(char), PU_STATIC, NULL); - strncpy(lump_p->name2, eName, eNameLen); - lump_p->name2[eNameLen] = '\0'; - - // We set the compression type from what we're supporting so far. - switch(eCompression) - { - case 0: - lump_p->compression = CM_NOCOMPRESSION; - break; - case 8: - lump_p->compression = CM_DEFLATE; - break; - case 14: - lump_p->compression = CM_LZF; - break; - default: - CONS_Alert(CONS_WARNING, "Lump has an unsupported compression type!\n"); - lump_p->compression = CM_UNSUPPORTED; - break; - } - CONS_Debug(DBG_SETUP, "File %s, data begins at: %ld\n", eName, lump_p->position); - fseek(handle, eXFieldLen + eCommentLen, SEEK_CUR); // We skip to where we expect the next central directory entry or end marker to be. - free(eName); - } - // We found the central directory end signature? - else if (!strncmp(curHeader, endPat, 4)) - { - CONS_Debug(DBG_SETUP, "Central directory end signature found at: %ld\n", ftell(handle)); - - /*// We will create a "virtual" marker lump at the very end of lumpinfo for convenience. - // This marker will be used by the different lump-seeking (eg. textures, sprites, etc.) in PK3-specific cases in an auxiliary way. - lumpinfo = (lumpinfo_t*) Z_Realloc(lumpinfo, (numlumps + 1)*sizeof(*lumpinfo), PU_STATIC, NULL); - strcpy(lumpinfo[numlumps].name, "PK3_ENDM\0"); - lumpinfo[numlumps].name2 = Z_Malloc(14 * sizeof(char), PU_STATIC, NULL); - strcpy(lumpinfo[numlumps].name2, "PK3_ENDMARKER\0"); - lumpinfo[numlumps].position = 0; - lumpinfo[numlumps].size = 0; - lumpinfo[numlumps].disksize = 0; - lumpinfo[numlumps].compression = CM_NOCOMPRESSION; - numlumps++;*/ - break; - } - // ... None of them? We're only expecting either a central directory signature entry or the central directory end signature. - // The file may be broken or incomplete... - else - { - CONS_Alert(CONS_WARNING, "Expected central directory header signature, got something else!"); - return INT16_MAX; - } - } - // If we've reached this far, then it means our dynamically stored lumpinfo has to be ready. - // Now we finally build our... incorrectly called wadfile. - // TODO: Maybe we should give them more generalized names, like resourcefile or resfile or something. - // Mostly for clarity and better understanding when reading the code. + case RET_PK3: + lumpinfo = ResGetLumpsZip(handle, &numlumps); + break; + case RET_WAD: + lumpinfo = ResGetLumpsWad(handle, &numlumps, filename); + break; + default: + CONS_Alert(CONS_ERROR, "Unsupported file format\n"); } - // assume wad file - else + + if (lumpinfo == 0) { - wadinfo_t header; - lumpinfo_t *lump_p; - filelump_t *fileinfo; - void *fileinfov; - - type = RET_WAD; - - // read the header - if (fread(&header, 1, sizeof header, handle) < sizeof header) - { - CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header from %s because %s\n"), filename, strerror(ferror(handle))); - if (handle) - fclose(handle); - return INT16_MAX; - } - - if (memcmp(header.identification, "ZWAD", 4) == 0) - compressed = 1; - else if (memcmp(header.identification, "IWAD", 4) != 0 - && memcmp(header.identification, "PWAD", 4) != 0 - && memcmp(header.identification, "SDLL", 4) != 0) - { - CONS_Alert(CONS_ERROR, M_GetText("%s does not have a valid WAD header\n"), filename); - if (handle) - fclose(handle); - return INT16_MAX; - } - - header.numlumps = LONG(header.numlumps); - header.infotableofs = LONG(header.infotableofs); - - // read wad file directory - i = header.numlumps * sizeof (*fileinfo); - fileinfov = fileinfo = malloc(i); - if (fseek(handle, header.infotableofs, SEEK_SET) == -1 - || fread(fileinfo, 1, i, handle) < i) - { - CONS_Alert(CONS_ERROR, M_GetText("Wadfile directory in %s is corrupted (%s)\n"), filename, strerror(ferror(handle))); - free(fileinfov); - if (handle) - fclose(handle); - return INT16_MAX; - } - - numlumps = header.numlumps; - - // fill in lumpinfo for this wad - lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); - for (i = 0; i < numlumps; i++, lump_p++, fileinfo++) - { - lump_p->position = LONG(fileinfo->filepos); - lump_p->size = lump_p->disksize = LONG(fileinfo->size); - if (compressed) // wad is compressed, lump might be - { - UINT32 realsize = 0; - - if (fseek(handle, lump_p->position, SEEK_SET) - == -1 || fread(&realsize, 1, sizeof realsize, - handle) < sizeof realsize) - { - I_Error("corrupt compressed file: %s; maybe %s", - filename, strerror(ferror(handle))); - } - realsize = LONG(realsize); - if (realsize != 0) - { - lump_p->size = realsize; - lump_p->compression = CM_LZF; - } - else - { - lump_p->size -= 4; - lump_p->compression = CM_NOCOMPRESSION; - } - - lump_p->position += 4; - lump_p->disksize -= 4; - } - else - lump_p->compression = CM_NOCOMPRESSION; - memset(lump_p->name, 0x00, 9); - strncpy(lump_p->name, fileinfo->name, 8); - // Allocate the lump's full name. - lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); - strncpy(lump_p->name2, fileinfo->name, 8); - lump_p->name2[8] = '\0'; - } - free(fileinfov); + fclose(handle); + return INT16_MAX; } // diff --git a/src/w_wad.h b/src/w_wad.h index 263b7119..287a9dfa 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -60,7 +60,6 @@ typedef struct char name[9]; // filelump_t name[] char *name2; // Used by PK3s. Dynamically allocated name. size_t size; // real (uncompressed) size - INT32 compressed; // i compmethod compression; // lump compression method } lumpinfo_t; @@ -84,9 +83,11 @@ typedef enum restype RET_WAD, RET_SOC, RET_LUA, - RET_PK3 + RET_PK3, + RET_UNKNOWN, } restype_t; + typedef struct wadfile_s { char *filename; From 1bcfe16933d34f78672ae0e46a70e5620f6c76c3 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 24 Nov 2018 17:30:49 -0500 Subject: [PATCH 81/93] Do not remove newlines from the end of files --- src/m_argv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_argv.c b/src/m_argv.c index 5c5dc37c..e8bfdd3d 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -214,4 +214,4 @@ void M_FindResponseFile(void) break; } -} \ No newline at end of file +} From ec67c4cbd6b61273c0a6aafa2c0c7a0b491b49b7 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 24 Nov 2018 23:39:31 +0100 Subject: [PATCH 82/93] Fix uninitialized pointer. Signed-off-by: Nev3r --- src/w_wad.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 93722c0b..958195aa 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -369,7 +369,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen if (fread(&header, 1, sizeof header, handle) < sizeof header) { CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header because %s\n"), strerror(ferror(handle))); - return 0; + return NULL; } if (memcmp(header.identification, "ZWAD", 4) == 0) @@ -379,7 +379,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen && memcmp(header.identification, "SDLL", 4) != 0) { CONS_Alert(CONS_ERROR, M_GetText("Invalid WAD header\n")); - return 0; + return NULL; } header.numlumps = LONG(header.numlumps); @@ -393,7 +393,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen { CONS_Alert(CONS_ERROR, M_GetText("Corrupt wadfile directory (%s)\n"), strerror(ferror(handle))); free(fileinfov); - return 0; + return NULL; } numlumps = header.numlumps; @@ -538,7 +538,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) if (!ResFindSignature(handle, pat_end, max(0, ftell(handle) - (22 + 65536)))) { CONS_Alert(CONS_ERROR, "Missing central directory\n"); - return 0; + return NULL; } fseek(handle, -4, SEEK_CUR); @@ -561,7 +561,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) CONS_Alert(CONS_ERROR, "Central directory is corrupt\n"); Z_Free(lumpinfo); free(zentry); - return 0; + return NULL; } lump_p->position = zentry->offset + zentry->namelen + zentry->xtralen + sizeof(zlentry_t); @@ -624,7 +624,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) UINT16 W_InitFile(const char *filename) { FILE *handle; - lumpinfo_t *lumpinfo; + lumpinfo_t *lumpinfo = NULL; wadfile_t *wadfile; restype_t type; UINT16 numlumps = 0; @@ -709,7 +709,7 @@ UINT16 W_InitFile(const char *filename) CONS_Alert(CONS_ERROR, "Unsupported file format\n"); } - if (lumpinfo == 0) + if (lumpinfo == NULL) { fclose(handle); return INT16_MAX; From 7c44054aa3b5ab8d32d21229db881ce7b75a90c8 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 25 Nov 2018 09:48:52 +0100 Subject: [PATCH 83/93] Take out the ifdef? Signed-off-by: Nev3r --- src/w_wad.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 958195aa..ed79f220 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -26,7 +26,6 @@ #include "lzf.h" #endif -#ifdef HAVE_ZLIB #ifndef _MSC_VER #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE @@ -42,7 +41,6 @@ #endif #include "zlib.h" -#endif // HAVE_ZLIB #include "doomdef.h" #include "doomstat.h" From 32a9e40baa75f7f4fcce981bd2b9bebc6099c95a Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 25 Nov 2018 11:11:50 +0100 Subject: [PATCH 84/93] Progress? Get all IO outputs used for possible errors. Attempt to fix errors from travis-ci. Signed-off-by: Nev3r --- src/w_wad.c | 29 ++++++++++++++++++++++++++--- src/w_wad.h | 2 ++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index ed79f220..f1ae8b83 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -540,7 +540,11 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) } fseek(handle, -4, SEEK_CUR); - fread(&zend, 1, sizeof zend, handle); + if (fread(&zend, 1, sizeof zend, handle) < sizeof zend) + { + CONS_Alert(CONS_ERROR, "Corrupt central directory (%s)\n", strerror(ferror(handle))); + return NULL; + } numlumps = zend.entries; lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); @@ -553,7 +557,13 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) char* trimname; char* dotpos; - fread(zentry, 1, sizeof(zentry_t), handle); + if (fread(zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t)) + { + CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", strerror(ferror(handle))); + Z_Free(lumpinfo); + free(zentry); + return NULL; + } if (memcmp(zentry->signature, pat_central, 4)) { CONS_Alert(CONS_ERROR, "Central directory is corrupt\n"); @@ -567,7 +577,14 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) lump_p->size = zentry->size; fullname = malloc(zentry->namelen + 1); - fgets(fullname, zentry->namelen + 1, handle); + if (fgets(fullname, zentry->namelen + 1, handle) != fullname) + { + CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", strerror(ferror(handle))); + Z_Free(lumpinfo); + free(zentry); + free(fullname); + return NULL; + } // Strip away file address and extension for the 8char name. if ((trimname = strrchr(fullname, '/')) != 0) @@ -591,9 +608,11 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) case 0: lump_p->compression = CM_NOCOMPRESSION; break; +#ifdef HAVE_ZLIB case 8: lump_p->compression = CM_DEFLATE; break; +#endif case 14: lump_p->compression = CM_LZF; break; @@ -1114,6 +1133,7 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned } +#ifdef HAVE_ZLIB /* report a zlib or i/o error */ void zerr(int ret) { @@ -1138,6 +1158,7 @@ void zerr(int ret) CONS_Printf("zlib version mismatch!\n"); } } +#endif /** Reads bytes from the head of a lump. * Note: If the lump is compressed, the whole thing has to be read anyway. @@ -1218,6 +1239,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si Z_Free(decData); return size; } +#ifdef HAVE_ZLIB case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support. { z_const Bytef *rawData; // The lump's raw data. @@ -1271,6 +1293,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si return size; } +#endif default: I_Error("wad %d, lump %d: unsupported compression type!", wad, lump); } diff --git a/src/w_wad.h b/src/w_wad.h index 287a9dfa..e77301dc 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -47,7 +47,9 @@ typedef struct typedef enum { CM_NOCOMPRESSION, +#ifdef HAVE_ZLIB CM_DEFLATE, +#endif CM_LZF, CM_UNSUPPORTED } compmethod; From d7b3cf93148e5cd7b466aafa8fabdb84114f3a0d Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 25 Nov 2018 11:35:19 +0100 Subject: [PATCH 85/93] Forgot the alignment for compact structs. Signed-off-by: Nev3r --- src/w_wad.c | 13 ++++++------- src/w_wad.h | 7 +++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index f1ae8b83..d0af5ede 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -79,13 +79,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #define O_BINARY 0 #endif -#if defined(_MSC_VER) -#pragma pack(1) -#endif - -#if defined(_MSC_VER) -#pragma pack() -#endif typedef struct { @@ -466,6 +459,9 @@ static boolean ResFindSignature (FILE* handle, char endPat[], UINT32 startpos) return false; } +#if defined(_MSC_VER) +#pragma pack(1) +#endif typedef struct zend_s { char signature[4]; @@ -513,6 +509,9 @@ typedef struct zlentry_s UINT16 namelen; UINT16 xtralen; } ATTRPACK zlentry_t; +#if defined(_MSC_VER) +#pragma pack() +#endif /** Create a lumpinfo_t array for a PKZip file. */ diff --git a/src/w_wad.h b/src/w_wad.h index e77301dc..6c33988c 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -24,12 +24,19 @@ // a raw entry of the wad directory // NOTE: This sits here and not in w_wad.c because p_setup.c makes use of it to load map WADs inside PK3s. +#if defined(_MSC_VER) +#pragma pack(1) +#endif typedef struct { UINT32 filepos; // file offset of the resource UINT32 size; // size of the resource char name[8]; // name of the resource } ATTRPACK filelump_t; +#if defined(_MSC_VER) +#pragma pack() +#endif + // ============================================================== // WAD FILE STRUCTURE DEFINITIONS From fd891aa21d577d5ef2e15b398958cddce563a7e0 Mon Sep 17 00:00:00 2001 From: Digiku Date: Mon, 26 Nov 2018 15:48:08 -0500 Subject: [PATCH 86/93] "Turn Left/Right" control naming instead of "Look Left/Right" due to analog mode keymapping quirk --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index a24447e2..5eb254ed 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1039,8 +1039,8 @@ static menuitem_t OP_MoveControlsMenu[] = {IT_HEADER, NULL, " Camera", NULL, 0}, {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup }, {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown }, - {IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, gc_turnleft }, - {IT_CALL | IT_STRING2, NULL, "Look Right", M_ChangeControl, gc_turnright }, + {IT_CALL | IT_STRING2, NULL, "Turn Left", M_ChangeControl, gc_turnleft }, + {IT_CALL | IT_STRING2, NULL, "Turn Right", M_ChangeControl, gc_turnright }, {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview }, {IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming }, {IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle}, From 4e332b38483774ac089ad130a132ae914e190098 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 26 Nov 2018 18:27:07 -0500 Subject: [PATCH 87/93] Fix MSVC build --- src/w_wad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/w_wad.c b/src/w_wad.c index 1d34095a..d001979a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1296,6 +1296,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si default: I_Error("wad %d, lump %d: unsupported compression type!", wad, lump); } + return -1; } size_t W_ReadLumpHeader(lumpnum_t lumpnum, void *dest, size_t size, size_t offset) From b7f7c2ecf785f5b5d3f9610fcc86072bfdc2993b Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 26 Nov 2018 20:08:26 -0500 Subject: [PATCH 88/93] PK3: fixup support for newer version of zlib --- src/w_wad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/w_wad.c b/src/w_wad.c index d001979a..9c97c72f 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1241,7 +1241,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si #ifdef HAVE_ZLIB case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support. { - z_const Bytef *rawData; // The lump's raw data. + void *rawData; // The lump's raw data. Bytef *decData; // Lump's decompressed real data. int zErr; // Helper var. From 1889c36dea2865b10fe5fcbc11d784e1c9255d23 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 27 Nov 2018 13:57:32 +0000 Subject: [PATCH 89/93] add HAVE_ZLIB around the rest of the zlib stuff in w_wad.c/h, move zlib.h inclusion down below doomdef.h etc includes in case that does anything for compiling (?) --- src/w_wad.c | 34 ++++++++++++++++++---------------- src/w_wad.h | 2 ++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 9c97c72f..8693dd40 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -26,22 +26,6 @@ #include "lzf.h" #endif -#ifndef _MSC_VER -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#include "zlib.h" - #include "doomdef.h" #include "doomstat.h" #include "doomtype.h" @@ -79,6 +63,24 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #define O_BINARY 0 #endif +#ifdef HAVE_ZLIB +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include "zlib.h" +#endif + typedef struct { diff --git a/src/w_wad.h b/src/w_wad.h index 4a15b23b..8baf061a 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -154,7 +154,9 @@ size_t W_LumpLength(lumpnum_t lumpnum); boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s +#ifdef HAVE_ZLIB void zerr(int ret); // zlib error checking +#endif size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset); size_t W_ReadLumpHeader(lumpnum_t lump, void *dest, size_t size, size_t offest); // read all or a part of a lump From 3e6388c1832c087cdeee404d3c8910a932990fd6 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 27 Nov 2018 15:49:41 +0000 Subject: [PATCH 90/93] use UINT8 * instead of void or Bytef * --- src/w_wad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 8693dd40..92c2aeab 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1243,8 +1243,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si #ifdef HAVE_ZLIB case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support. { - void *rawData; // The lump's raw data. - Bytef *decData; // Lump's decompressed real data. + UINT8 *rawData; // The lump's raw data. + UINT8 *decData; // Lump's decompressed real data. int zErr; // Helper var. z_stream strm; From cb53bc8afe6f03a78afc35dfc7aad77d3eb476b9 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 27 Nov 2018 23:05:33 +0000 Subject: [PATCH 91/93] remove redundant wadfile loop within wadfile loop for ANIMDEFS code --- src/p_spec.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 54407dd9..50b8aec9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -279,15 +279,12 @@ void P_InitPicAnims(void) Z_Free(animatedLump); } - for (w = numwadfiles-1; w >= 0; w--) + // Find ANIMDEFS lump in the WAD + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); + while (animdefsLumpNum != INT16_MAX) { - // Find ANIMDEFS lump in the WAD - animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); - while (animdefsLumpNum != INT16_MAX) - { - P_ParseANIMDEFSLump(w, animdefsLumpNum); - animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); - } + P_ParseANIMDEFSLump(w, animdefsLumpNum); + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); } } // Define the last one From e158206e5505ba4933384cc4767d56de2dff84bd Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 27 Nov 2018 23:06:31 +0000 Subject: [PATCH 92/93] backport string len tweaks I made to LUA_LoadLump in internal --- src/lua_script.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index 3fb1960d..a079f57f 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -186,27 +186,30 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump) { MYFILE f; char *name; + size_t len; f.wad = wad; f.size = W_LumpLengthPwad(wad, lump); f.data = Z_Malloc(f.size, PU_LUA, NULL); W_ReadLumpPwad(wad, lump, f.data); f.curpos = f.data; + len = strlen(wadfiles[wad]->filename); // length of file name + if (wadfiles[wad]->type == RET_LUA) { - name = malloc(strlen(wadfiles[wad]->filename)+1); + name = malloc(len+1); strcpy(name, wadfiles[wad]->filename); } else // If it's not a .lua file, copy the lump name in too. { lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump]; - size_t length = strlen(wadfiles[wad]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name - name = malloc(length + 1); + len += 1 + strlen(lump_p->name2); // length of file name, '|', and lump name + name = malloc(len+1); sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->name2); - name[length] = '\0'; + name[len] = '\0'; } - LUA_LoadFile(&f, name); + LUA_LoadFile(&f, name); // actually load file! free(name); Z_Free(f.data); From 305ad4f73eef9dcdbbbeab104a97b9581cf045a0 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 29 Nov 2018 14:16:02 +0000 Subject: [PATCH 93/93] backport some cleanup that I clearly missed wasn't there already to do with ZWAD lump loading --- src/w_wad.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 92c2aeab..ddf789ec 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1215,30 +1215,31 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si I_Error("wad %d, lump %d: cannot read compressed data", wad, lump); retval = lzf_decompress(rawData, l->disksize, decData, l->size); #ifndef AVOID_ERRNO - if (retval == 0 && errno == E2BIG) // errno is a global var set by the lzf functions when something goes wrong. + if (retval == 0) // If this was returned, check if errno was set { - I_Error("wad %d, lump %d: compressed data too big (bigger than %s)", wad, lump, sizeu1(l->size)); + // errno is a global var set by the lzf functions when something goes wrong. + if (errno == E2BIG) + I_Error("wad %d, lump %d: compressed data too big (bigger than %s)", wad, lump, sizeu1(l->size)); + else if (errno == EINVAL) + I_Error("wad %d, lump %d: invalid compressed data", wad, lump); } - else if (retval == 0 && errno == EINVAL) - I_Error("wad %d, lump %d: invalid compressed data", wad, lump); - else + // Otherwise, fall back on below error (if zero was actually the correct size then ???) #endif if (retval != l->size) { I_Error("wad %d, lump %d: decompressed to wrong number of bytes (expected %s, got %s)", wad, lump, sizeu1(l->size), sizeu2(retval)); } -#else - (void)wad; - (void)lump; - //I_Error("ZWAD files not supported on this platform."); - return NULL; -#endif + if (!decData) // Did we get no data at all? return 0; M_Memcpy(dest, decData + offset, size); Z_Free(rawData); Z_Free(decData); return size; +#else + //I_Error("ZWAD files not supported on this platform."); + return 0; +#endif } #ifdef HAVE_ZLIB case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support.