diff --git a/src/m_misc.c b/src/m_misc.c index 22effdddf..6899059b6 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1787,17 +1787,6 @@ UINT8 M_CountBits(UINT32 num, UINT8 size) return sum; } - -/** Get the most significant bit in a number. - * (integer log2) - */ -UINT8 M_HighestBit(UINT32 num) -{ - UINT8 i = 0; - while (num >>= 1) ++i; - return i; -} - const char *GetRevisionString(void) { static char rev[9] = {0}; diff --git a/src/m_misc.h b/src/m_misc.h index f681bfcb3..5fc4fa63b 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -95,7 +95,6 @@ void M_SetupMemcpy(void); // counting bits, for weapon ammo code, usually FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); -FUNCMATH UINT8 M_HighestBit(UINT32 num); // Flags for AA trees. #define AATREE_ZUSER 1 // Treat values as z_zone-allocated blocks and set their user fields diff --git a/src/r_segs.c b/src/r_segs.c index 24c01f167..ca24df586 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -288,6 +288,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) line_t *ldef; sector_t *front, *back; INT32 times, repeats; + INT64 overflow_test; #ifdef ESLOPE INT32 range; #endif @@ -485,7 +486,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; } - #ifndef ESLOPE if (curline->linedef->flags & ML_DONTPEGBOTTOM) { @@ -523,6 +523,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // calculate lighting if (maskedtexturecol[dc_x] != INT16_MAX) { + // Check for overflows first + overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) + { + // Eh, no, go away, don't waste our time + spryscale += rw_scalestep; + continue; + } + if (dc_numlights) { lighttable_t **xwalllights; @@ -947,16 +957,38 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Set heights according to plane, or slope, whichever { fixed_t left_top, right_top, left_bottom, right_bottom; + INT64 overflow_test; - left_top = *pfloor->t_slope ? P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) : *pfloor->topheight; - right_top = *pfloor->t_slope ? P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) : *pfloor->topheight; - left_bottom = *pfloor->b_slope ? P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) : *pfloor->bottomheight; - right_bottom = *pfloor->b_slope ? P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) : *pfloor->bottomheight; + if (*pfloor->t_slope) + { + left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz; + } + else + left_top = right_top = *pfloor->topheight - viewz; - left_top -= viewz; - right_top -= viewz; - left_bottom -= viewz; - right_bottom -= viewz; + if (*pfloor->b_slope) + { + left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz; + } + else + left_bottom = right_bottom = *pfloor->bottomheight - viewz; + + // overflow tests + // if any of these fail, abandon. likely we're too high up to see anything anyway + overflow_test = (INT64)centeryfrac - (((INT64)left_top*ds->scale1)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; + overflow_test = (INT64)centeryfrac - (((INT64)left_bottom*ds->scale1)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; + overflow_test = (INT64)centeryfrac - (((INT64)right_top*ds->scale2)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; + overflow_test = (INT64)centeryfrac - (((INT64)right_bottom*ds->scale2)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; top_frac = centeryfrac - FixedMul(left_top, ds->scale1); bottom_frac = centeryfrac - FixedMul(left_bottom, ds->scale1); @@ -1133,19 +1165,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - //Handle over/underflows before they happen. This fixes the textures part of the FOF rendering bug. - //...for the most part, anyway. - if (((signed)dc_texturemid > 0 && (spryscale>>FRACBITS > INT32_MAX / (signed)dc_texturemid)) - || ((signed)dc_texturemid < 0 && (spryscale) && (signed)(dc_texturemid)>>FRACBITS < (INT32_MIN / spryscale))) - { - spryscale += rw_scalestep; -#ifdef ESLOPE - top_frac += top_step; - bottom_frac += bottom_step; -#endif - continue; - } - #ifdef ESLOPE sprtopscreen = windowtop = top_frac; sprbotscreen = windowbottom = bottom_frac; diff --git a/src/r_things.c b/src/r_things.c index 2ec2f6ead..c53f8914c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -744,10 +744,16 @@ static void R_DrawVisSprite(vissprite_t *vis) patch_t *patch = W_CacheLumpNum(vis->patch, PU_CACHE); fixed_t this_scale = vis->mobj->scale; INT32 x1, x2; + INT64 overflow_test; if (!patch) return; + // Check for overflow + overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow + colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" @@ -1239,15 +1245,6 @@ static void R_ProjectSprite(mobj_t *thing) return; } - // quick check for possible overflows - // if either of these triggers then there's a possibility that drawing is unsafe - if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47 // 31 bits + 16 from the division by FRACUNIT - || M_HighestBit(abs(gz - viewz)) + M_HighestBit(abs(yscale)) > 47) - { - CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectSprite (sprite %s), ignoring\n", sprnames[thing->sprite]); - return; - } - // store information in a vissprite vis = R_NewVisSprite(); vis->heightsec = heightsec; //SoM: 3/17/2000 @@ -1458,14 +1455,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; } - // quick check for possible overflows - // if either of these triggers then there's a possibility that drawing is unsafe - if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47) // 31 bits + 16 from the division by FRACUNIT - { - CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectPrecipitationSprite (sprite %s), ignoring\n", sprnames[thing->sprite]); - return; - } - // store information in a vissprite vis = R_NewVisSprite(); vis->scale = yscale; //<