From d5b28577c113d413e00dce5904a92a717bd827a6 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 25 Aug 2023 13:59:53 +0300 Subject: [PATCH 1/8] Attempt to fix demo buffer overflow crash. Also don't record demos at all when netdemo_record is set to Disabled --- src/g_game.c | 72 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 93c502d06..a2130aed0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5699,6 +5699,9 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim) void G_WriteAllGhostTics(void) { + UINT8 *save_demo_p = demo_p; +#define CHECKSPACE(num) if (demo_p+(num) > demoend) { demo_p = save_demo_p; G_CheckDemoStatus(); return; } + INT32 i, counter = leveltime; for (i = 0; i < MAXPLAYERS; i++) { @@ -5713,10 +5716,16 @@ void G_WriteAllGhostTics(void) if (counter % cv_netdemosyncquality.value != 0) // Only write 1 in this many ghost datas per tic to cut down on multiplayer replay size. continue; + CHECKSPACE(1); + WRITEUINT8(demo_p, i); G_WriteGhostTic(players[i].mo, i); } + + CHECKSPACE(1); WRITEUINT8(demo_p, 0xFF); + +#undef CHECKSPACE } void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) @@ -5727,6 +5736,9 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) UINT8 sprite; UINT8 frame; + UINT8 *save_demo_p = demo_p; +#define CHECKSPACE(num) if (demo_p+(num) > demoend) { demo_p = save_demo_p; G_CheckDemoStatus(); return; } + if (!demo_p) return; if (!(demoflags & DF_GHOST)) @@ -5753,6 +5765,8 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) oldghost[playernum].y = ghost->y; oldghost[playernum].z = ghost->z; ziptic |= GZT_XYZ; + + CHECKSPACE(sizeof(fixed_t)*3); WRITEFIXED(demo_p,oldghost[playernum].x); WRITEFIXED(demo_p,oldghost[playernum].y); WRITEFIXED(demo_p,oldghost[playernum].z); @@ -5769,6 +5783,9 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) oldghost[playernum].momx = momx; oldghost[playernum].momy = momy; ziptic |= GZT_MOMXY; + + CHECKSPACE(4); + WRITEINT16(demo_p,momx); WRITEINT16(demo_p,momy); } @@ -5777,6 +5794,9 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) { oldghost[playernum].momz = momx; ziptic |= GZT_MOMZ; + + CHECKSPACE(2); + WRITEINT16(demo_p,momx); } @@ -5797,6 +5817,9 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) { oldghost[playernum].angle = ghost->angle>>24; ziptic |= GZT_ANGLE; + + CHECKSPACE(1); + WRITEUINT8(demo_p,oldghost[playernum].angle); } @@ -5806,6 +5829,9 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) { oldghost[playernum].frame = frame; ziptic |= GZT_SPRITE; + + CHECKSPACE(1); + WRITEUINT8(demo_p,oldghost[playernum].frame); } @@ -5845,20 +5871,26 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) if (ghostext[playernum].flags & EZT_COLOR) { + CHECKSPACE(1); WRITEUINT8(demo_p,ghostext[playernum].color); ghostext[playernum].lastcolor = ghostext[playernum].color; } if (ghostext[playernum].flags & EZT_SCALE) { + CHECKSPACE(sizeof(fixed_t)); WRITEFIXED(demo_p,ghostext[playernum].scale); ghostext[playernum].lastscale = ghostext[playernum].scale; } if (ghostext[playernum].flags & EZT_HIT) { + CHECKSPACE(2); WRITEUINT16(demo_p,ghostext[playernum].hits); for (i = 0; i < ghostext[playernum].hits; i++) { mobj_t *mo = ghostext[playernum].hitlist[i]; + + CHECKSPACE(4+4+2+sizeof(fixed_t)*3+sizeof(angle_t)); + WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.) WRITEUINT32(demo_p,mo->type); WRITEUINT16(demo_p,(UINT16)mo->health); @@ -5872,9 +5904,14 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) ghostext[playernum].hitlist = NULL; } if (ghostext[playernum].flags & EZT_SPRITE) + { + CHECKSPACE(1); WRITEUINT8(demo_p,sprite); + } if (ghostext[playernum].flags & EZT_KART) { + CHECKSPACE(12); + WRITEINT32(demo_p, ghostext[playernum].kartitem); WRITEINT32(demo_p, ghostext[playernum].kartamount); WRITEINT32(demo_p, ghostext[playernum].kartbumpers); @@ -5891,6 +5928,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) G_CheckDemoStatus(); // no more space return; } +#undef CHECKSPACE } void G_ConsAllGhostTics(void) @@ -6743,22 +6781,30 @@ void G_RecordDemo(const char *name) { INT32 maxsize; - CONS_Printf("Recording demo %s.lmp\n", name); - - strcpy(demoname, name); - strcat(demoname, ".lmp"); - maxsize = cv_maxdemosize.value*1024*1024; - if (demobuffer) - free(demobuffer); demo_p = NULL; demo.recording = false; - demobuffer = malloc(maxsize); - demoend = demobuffer + maxsize; - if (demobuffer) - demo.recording = true; - else - CONS_Alert(CONS_ERROR, "Failed to allocate demo buffer\n"); + free(demobuffer); + demobuffer = NULL; + demoend = NULL; + + if (cv_recordmultiplayerdemos.value) + { + CONS_Printf("Recording demo %s.lmp\n", name); + + strcpy(demoname, name); + strcat(demoname, ".lmp"); + + maxsize = cv_maxdemosize.value*1024*1024; + + demobuffer = malloc(maxsize); + demoend = demobuffer + maxsize; + + if (demobuffer) + demo.recording = true; + else + CONS_Alert(CONS_ERROR, "Failed to allocate demo buffer\n"); + } } void G_RecordMetal(void) -- 2.54.0 From ab6f33929d5cf88c173cb1fbffa96fa5c820533c Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 29 Aug 2023 06:49:10 +0200 Subject: [PATCH 2/8] don't check flippedness in HWR_RotateSpritePolyToAim if the mobj is actually a precipmobj! precipmobj_t does not have eflags, so P_MobjFlip checking it would actually be accessing memory addresses beyond the end of the struct perhaps this fixes a rare crash in P_MobjFlip on maps with snow and rain See: https://git.do.srb2.org/STJr/SRB2/-/commit/197da95a232da92e61f88ee27c754e8671a6624f --- src/hardware/hw_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 13b6b7911..ad63cbc08 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3755,7 +3755,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t } // This is expecting a pointer to an array containing 4 wallVerts for a sprite -static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) +static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts, const boolean precip) { if (cv_grspritebillboarding.value && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) && wallVerts) { @@ -3787,7 +3787,7 @@ static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts } } - if (P_MobjFlip(spr->mobj) == -1) + if (!precip && P_MobjFlip(spr->mobj) == -1) // precip doesn't have eflags so they can't flip { basey = FIXED_TO_FLOAT(interp.z + spr->mobj->height); } @@ -3907,7 +3907,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) } // Let dispoffset work first since this adjust each vertex - HWR_RotateSpritePolyToAim(spr, baseWallVerts); + HWR_RotateSpritePolyToAim(spr, baseWallVerts, false); // push it toward the camera to mitigate floor-clipping sprites { @@ -4254,7 +4254,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // Let dispoffset work first since this adjust each vertex // ...nah - HWR_RotateSpritePolyToAim(spr, wallVerts); + HWR_RotateSpritePolyToAim(spr, wallVerts, false); // push it toward the camera to mitigate floor-clipping sprites { @@ -4348,7 +4348,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) wallVerts[1].z = wallVerts[2].z = spr->z2; // Let dispoffset work first since this adjust each vertex - HWR_RotateSpritePolyToAim(spr, wallVerts); + HWR_RotateSpritePolyToAim(spr, wallVerts, true); wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = gpatch->max_s; -- 2.54.0 From e91c90329dd06dfd5deb31e3826f8a50ea675fdb Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 29 Aug 2023 06:57:52 +0200 Subject: [PATCH 3/8] Fix precip interpolation See: https://git.do.srb2.org/STJr/SRB2/-/commit/6c54af377481a42f639da2db6cefe33d02918bce --- src/p_mobj.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f29a63f43..264a25db7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3792,12 +3792,11 @@ void P_NullPrecipThinker(precipmobj_t *mobj) { //(void)mobj; mobj->precipflags &= ~PCF_THUNK; + R_ResetPrecipitationMobjInterpolationState(mobj); } void P_SnowThinker(precipmobj_t *mobj) { - R_ResetPrecipitationMobjInterpolationState(mobj); - P_CycleStateAnimation((mobj_t *)mobj); // adjust height @@ -3810,8 +3809,6 @@ void P_SnowThinker(precipmobj_t *mobj) void P_RainThinker(precipmobj_t *mobj) { - R_ResetPrecipitationMobjInterpolationState(mobj); - P_CycleStateAnimation((mobj_t *)mobj); if (mobj->state != &states[S_RAIN1]) -- 2.54.0 From 52b4f6558255a0dc8f64fe1247cbf5468795a519 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 29 Aug 2023 07:19:31 +0200 Subject: [PATCH 4/8] Improve rain/weather. * Better thinker with more return optimisation. * Better placement of thinking in rendering, to avoid ceiling-mounted sprite glitches. See: https://git.do.srb2.org/STJr/SRB2/-/commit/6371de806b932d1026904937b19e13feb10fa322 --- src/hardware/hw_main.c | 42 +++++++++++++++++++++++++++++------------- src/p_mobj.c | 19 ++++++++++--------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ad63cbc08..7008e87c7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3787,7 +3787,7 @@ static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts } } - if (!precip && P_MobjFlip(spr->mobj) == -1) // precip doesn't have eflags so they can't flip + if (P_MobjFlip(spr->mobj) == -1) { basey = FIXED_TO_FLOAT(interp.z + spr->mobj->height); } @@ -3797,6 +3797,7 @@ static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts } lowy = wallVerts[0].y; + // Rotate sprites to fully billboard with the camera // X, Y, AND Z need to be manipulated for the polys to rotate around the // origin, because of how the origin setting works I believe that should @@ -5255,6 +5256,7 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // uncapped/interpolation interpmobjstate_t interp = {0}; + float basey, lowy; if (!thing) return; @@ -5262,11 +5264,25 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // do interpolation if (R_UsingFrameInterpolation() && !paused) { - R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp); + if (precip) + { + R_InterpolatePrecipMobjState(spr->mobj, rendertimefrac, &interp); + } + else + { + R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp); + } } else { - R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp); + if (precip) + { + R_InterpolatePrecipMobjState(spr->mobj, FRACUNIT, &interp); + } + else + { + R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp); + } } // transform the origin point @@ -5326,16 +5342,6 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) x1 = tr_x + x1 * rightcos; x2 = tr_x - x2 * rightcos; - // okay, we can't return now... this is a hack, but weather isn't networked, so it should be ok - if (!(thing->precipflags & PCF_THUNK)) - { - if (thing->precipflags & PCF_RAIN) - P_RainThinker(thing); - else - P_SnowThinker(thing); - thing->precipflags |= PCF_THUNK; - } - // // store information in a vissprite // @@ -5364,6 +5370,16 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height); vis->precip = true; + + // okay... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + if (thing->precipflags & PCF_RAIN) + P_RainThinker(thing); + else + P_SnowThinker(thing); + thing->precipflags |= PCF_THUNK; + } } static boolean drewsky = false; diff --git a/src/p_mobj.c b/src/p_mobj.c index 264a25db7..bcf08951b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3835,17 +3835,18 @@ void P_RainThinker(precipmobj_t *mobj) } // adjust height - if ((mobj->z += mobj->momz) <= mobj->floorz) + if ((mobj->z += mobj->momz) > mobj->floorz) + return; + + // no splashes on sky or bottomless pits + if (mobj->precipflags & PCF_PIT) { - // no splashes on sky or bottomless pits - if (mobj->precipflags & PCF_PIT) - mobj->z = mobj->ceilingz; - else - { - mobj->z = mobj->floorz; - P_SetPrecipMobjState(mobj, S_SPLASH1); - } + mobj->z = mobj->ceilingz; + return; } + + mobj->z = mobj->floorz; + P_SetPrecipMobjState(mobj, S_SPLASH1); } static void P_RingThinker(mobj_t *mobj) -- 2.54.0 From b5269ebbb58381ff4b39638a288f38a028145df1 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 29 Aug 2023 07:25:55 +0200 Subject: [PATCH 5/8] oops --- src/hardware/hw_main.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7008e87c7..c0e703ab5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3797,7 +3797,6 @@ static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts } lowy = wallVerts[0].y; - // Rotate sprites to fully billboard with the camera // X, Y, AND Z need to be manipulated for the polys to rotate around the // origin, because of how the origin setting works I believe that should @@ -5254,35 +5253,20 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) unsigned rot = 0; UINT8 flip; - // uncapped/interpolation - interpmobjstate_t interp = {0}; - float basey, lowy; - if (!thing) return; + + // uncapped/interpolation + interpmobjstate_t interp = {0}; // do interpolation if (R_UsingFrameInterpolation() && !paused) { - if (precip) - { - R_InterpolatePrecipMobjState(spr->mobj, rendertimefrac, &interp); - } - else - { - R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp); - } + R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp); } else { - if (precip) - { - R_InterpolatePrecipMobjState(spr->mobj, FRACUNIT, &interp); - } - else - { - R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp); - } + R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp); } // transform the origin point -- 2.54.0 From 664e8c363bd001c5aec84c61dcc1513b1851ba82 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 29 Aug 2023 07:57:35 +0200 Subject: [PATCH 6/8] raise max precip distance a bit basically twice as far, cant go higher or else we hit sprite limit and stuff starts disappearing --- src/r_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/r_main.c b/src/r_main.c index cd4c99b69..dc914e79a 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -160,6 +160,7 @@ static CV_PossibleValue_t drawdist_cons_t[] = { static CV_PossibleValue_t drawdist_precip_cons_t[] = { {256, "256"}, {512, "512"}, {768, "768"}, {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, + {3072, "3072"}, {4096, "4096"}, {0, "None"}, {0, NULL}}; static CV_PossibleValue_t fov_cons_t[] = {{5*FRACUNIT, "MIN"}, {178*FRACUNIT, "MAX"}, {0, NULL}}; -- 2.54.0 From c4746962bd48c0587049f371e3b07548ad311c62 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 29 Aug 2023 08:18:59 +0200 Subject: [PATCH 7/8] do the thing for software renderer too i forgor --- src/r_things.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index a33f908dc..26dad2f0b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1796,17 +1796,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; } - // okay, we can't return now except for vertical clipping... this is a hack, but weather isn't networked, so it should be ok - if (!(thing->precipflags & PCF_THUNK)) - { - if (thing->precipflags & PCF_RAIN) - P_RainThinker(thing); - else - P_SnowThinker(thing); - thing->precipflags |= PCF_THUNK; - } - - //SoM: 3/17/2000: Disregard sprites that are out of view.. gzt = interp.z + spritecachedinfo[lump].topoffset; gz = gzt - spritecachedinfo[lump].height; @@ -1814,7 +1803,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) if (thing->subsector->sector->cullheight) { if (R_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) - return; + goto weatherthink; } // store information in a vissprite @@ -1878,6 +1867,18 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->precip = true; vis->vflip = false; vis->isScaled = false; + +weatherthink: + // okay... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + if (thing->precipflags & PCF_RAIN) + P_RainThinker(thing); + else + P_SnowThinker(thing); + thing->precipflags |= PCF_THUNK; + } + } // R_AddSprites -- 2.54.0 From d577944143a976111efc2815d431f9cfa22c4262 Mon Sep 17 00:00:00 2001 From: Indev Date: Tue, 29 Aug 2023 10:07:26 +0300 Subject: [PATCH 8/8] Don't show music credit when music is disabled --- src/s_sound.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/s_sound.c b/src/s_sound.c index 2afc56596..7658ec6a7 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1551,6 +1551,8 @@ void S_ShowSpecifiedMusicCredit(const char *musname) { musicdef_t *def; + if (digital_disabled) return; + if (!cv_songcredits.value || demo.rewinding) return; -- 2.54.0