Merge branch 'the_elder_skyscroll' into 'next'

Rewrite F_SkyScroll to fix overflows

Closes #1008

See merge request STJr/SRB2!1985
This commit is contained in:
sphere 2023-06-12 23:36:37 +00:00
commit 0dea372336
5 changed files with 40 additions and 51 deletions

View file

@ -2487,7 +2487,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
if (!snake)
{
F_MenuPresTicker(true); // title sky
F_MenuPresTicker(); // title sky
F_TitleScreenTicker(true);
F_TitleScreenDrawer();
}

View file

@ -63,7 +63,6 @@ static tic_t stoptimer;
static boolean keypressed = false;
// (no longer) De-Demo'd Title Screen
static INT32 menuanimtimer; // Title screen: background animation timing
mobj_t *titlemapcameraref = NULL;
// menu presentation state
@ -75,6 +74,8 @@ INT32 curbgyspeed;
boolean curbghide;
boolean hidetitlemap; // WARNING: set to false by M_SetupNextMenu and M_ClearMenus
static fixed_t curbgx = 0;
static fixed_t curbgy = 0;
static UINT8 curDemo = 0;
static UINT32 demoDelayLeft;
static UINT32 demoIdleLeft;
@ -2242,7 +2243,8 @@ void F_GameEndTicker(void)
void F_InitMenuPresValues(void)
{
menuanimtimer = 0;
curbgx = 0;
curbgy = 0;
prevMenuId = 0;
activeMenuId = MainDef.menuid;
@ -2275,17 +2277,11 @@ void F_InitMenuPresValues(void)
//
// F_SkyScroll
//
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
void F_SkyScroll(const char *patchname)
{
INT32 xscrolled, x, xneg = (scrollxspeed > 0) - (scrollxspeed < 0), tilex;
INT32 yscrolled, y, yneg = (scrollyspeed > 0) - (scrollyspeed < 0), tiley;
boolean xispos = (scrollxspeed >= 0), yispos = (scrollyspeed >= 0);
INT32 x, basey = 0;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
INT16 patwidth, patheight;
INT32 pw, ph; // scaled by dupz
patch_t *pat;
INT32 i, j;
fixed_t fracmenuanimtimer, xscrolltimer, yscrolltimer;
if (rendermode == render_none)
return;
@ -2296,43 +2292,34 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
return;
}
if (!scrollxspeed && !scrollyspeed)
pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY);
if (!curbgxspeed && !curbgyspeed)
{
V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY));
V_DrawPatchFill(pat);
W_UnlockCachedPatch(pat);
return;
}
pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY);
// Modulo the background scrolling to prevent jumps from integer overflows
// We already load the background patch here, so we can modulo it here
// to avoid also having to load the patch in F_MenuPresTicker
curbgx %= pat->width * 16;
curbgy %= pat->height * 16;
patwidth = pat->width;
patheight = pat->height;
pw = patwidth * dupz;
ph = patheight * dupz;
// Ooh, fancy frame interpolation
x = ((curbgx*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*dupz)) / 16;
basey = ((curbgy*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*dupz)) / 16;
tilex = max(FixedCeil(FixedDiv(vid.width, pw)) >> FRACBITS, 1)+2; // one tile on both sides of center
tiley = max(FixedCeil(FixedDiv(vid.height, ph)) >> FRACBITS, 1)+2;
if (x > 0) // Make sure that we don't leave the left or top sides empty
x -= pat->width * dupz;
if (basey > 0)
basey -= pat->height * dupz;
fracmenuanimtimer = (menuanimtimer * FRACUNIT) - (FRACUNIT - rendertimefrac);
xscrolltimer = ((fracmenuanimtimer*scrollxspeed)/16 + patwidth*xneg*FRACUNIT) % (patwidth * FRACUNIT);
yscrolltimer = ((fracmenuanimtimer*scrollyspeed)/16 + patheight*yneg*FRACUNIT) % (patheight * FRACUNIT);
// coordinate offsets
xscrolled = FixedInt(xscrolltimer * dupz);
yscrolled = FixedInt(yscrolltimer * dupz);
for (x = (xispos) ? -pw*(tilex-1)+pw : 0, i = 0;
i < tilex;
x += pw, i++)
for (; x < vid.width; x += pat->width * dupz)
{
for (y = (yispos) ? -ph*(tiley-1)+ph : 0, j = 0;
j < tiley;
y += ph, j++)
{
V_DrawScaledPatch(
(xispos) ? xscrolled - x : x + xscrolled,
(yispos) ? yscrolled - y : y + yscrolled,
V_NOSCALESTART, pat);
}
for (INT32 y = basey; y < vid.height; y += pat->height * dupz)
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
}
W_UnlockCachedPatch(pat);
@ -2655,7 +2642,7 @@ void F_TitleScreenDrawer(void)
if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS)
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
F_SkyScroll(curbgname);
// Don't draw outside of the title screen, or if the patch isn't there.
if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)
@ -3410,10 +3397,10 @@ luahook:
// separate animation timer for backgrounds, since we also count
// during GS_TIMEATTACK
void F_MenuPresTicker(boolean run)
void F_MenuPresTicker(void)
{
if (run)
menuanimtimer++;
curbgx += curbgxspeed;
curbgy += curbgyspeed;
}
// (no longer) De-Demo'd Title Screen

View file

@ -40,7 +40,7 @@ void F_TextPromptTicker(void);
void F_GameEndDrawer(void);
void F_IntroDrawer(void);
void F_TitleScreenDrawer(void);
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname);
void F_SkyScroll(const char *patchname);
void F_GameEvaluationDrawer(void);
void F_StartGameEvaluation(void);
@ -131,7 +131,7 @@ extern UINT16 curtttics;
#define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0])
void F_InitMenuPresValues(void);
void F_MenuPresTicker(boolean run);
void F_MenuPresTicker(void);
//
// WIPE

View file

@ -2391,7 +2391,8 @@ void G_Ticker(boolean run)
break;
case GS_TIMEATTACK:
F_MenuPresTicker(run);
if (run)
F_MenuPresTicker();
break;
case GS_INTRO:
@ -2439,7 +2440,8 @@ void G_Ticker(boolean run)
// then intentionally fall through
/* FALLTHRU */
case GS_WAITINGPLAYERS:
F_MenuPresTicker(run);
if (run)
F_MenuPresTicker();
F_TitleScreenTicker(run);
break;

View file

@ -5981,7 +5981,7 @@ static void M_DrawLevelPlatterMenu(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
else if (!curbghide || !titlemapinaction)
{
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
F_SkyScroll(curbgname);
// Draw and animate foreground
if (!strncmp("RECATKBG", curbgname, 8))
M_DrawRecordAttackForeground();
@ -6243,7 +6243,7 @@ static void M_DrawMessageMenu(void)
}
else
{
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
F_SkyScroll(curbgname);
if (!strncmp("RECATKBG", curbgname, 8))
M_DrawRecordAttackForeground();
}
@ -9938,7 +9938,7 @@ void M_DrawTimeAttackMenu(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
else if (!curbghide || !titlemapinaction)
{
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
F_SkyScroll(curbgname);
// Draw and animate foreground
if (!strncmp("RECATKBG", curbgname, 8))
M_DrawRecordAttackForeground();