From 11e29d5afa52f2bad94e0bfe4a28b97558ba2094 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Thu, 26 Jun 2025 11:13:32 -0400 Subject: [PATCH] Port Saturn's VoteBG scaling code Thanks to Alug and Indev as per usual --- src/d_netcmd.c | 1 + src/p_setup.c | 44 ++++++++++++++++++ src/p_setup.h | 5 ++ src/screen.c | 3 ++ src/screen.h | 2 +- src/v_video.c | 45 ++++++++++++++++++ src/v_video.h | 4 ++ src/y_inter.c | 124 ++++++++++++++++++++++++++++--------------------- 8 files changed, 173 insertions(+), 55 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f3585db99..d22cea64b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1172,6 +1172,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_renderview); CV_RegisterVar(&cv_vhseffect); CV_RegisterVar(&cv_shittyscreen); + CV_RegisterVar(&cv_votebgscaling); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); diff --git a/src/p_setup.c b/src/p_setup.c index 061c50939..c82da3227 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -9246,6 +9246,12 @@ boolean P_AddWadFile(const char *wadfilename, wadcompat_t compat) return true; } +// check for replacement votescreen backgrounds +boolean wideracereplaced = false; +boolean racereplaced = false; +boolean widebattlereplaced = false; +boolean battlereplaced = false; + // // Add a WAD file and do the per-WAD setup stages. // Call P_MultiSetupWadFiles as soon as possible after any number of these. @@ -9411,6 +9417,44 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, wadcompat_t compat) // R_LoadSpriteInfoLumps(wadnum, numlumps); + // + // check for votescreen replacements + // + if (!wideracereplaced && !racereplaced && !widebattlereplaced && !battlereplaced) + { + lumpinfo = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + + // widescreen patch Race + if (!wideracereplaced && !strncmp(name, "INTERSCW", 8)) + { + wideracereplaced = true; + continue; + } + + if (!racereplaced && !strncmp(name, "INTERSCR", 8)) + { + racereplaced = true; + continue; + } + + // widescreen patch Battle + if (!widebattlereplaced && !strncmp(name, "BATTLSCW", 8)) + { + widebattlereplaced = true; + continue; + } + + if (!battlereplaced && !strncmp(name, "BATTLSCR", 8)) + { + battlereplaced = true; + continue; + } + } + } + refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_ flags to disappear the next frame, but this one's a bit too dangerous for that... partadd_stage = 0; return wadnum; diff --git a/src/p_setup.h b/src/p_setup.h index c7c438d3d..b207709f2 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -87,6 +87,11 @@ void HWR_LoadLevel(void); #endif boolean P_AddWadFile(const char *wadfilename, wadcompat_t compat); +extern boolean wideracereplaced; +extern boolean racereplaced; +extern boolean widebattlereplaced; +extern boolean battlereplaced; + #define MAPRET_ADDED (1) #define MAPRET_CURRENTREPLACED (1<<1) UINT8 P_InitMapData(boolean existingmapheaders); diff --git a/src/screen.c b/src/screen.c index ac7c0d391..4ee60f956 100644 --- a/src/screen.c +++ b/src/screen.c @@ -65,6 +65,9 @@ consvar_t cv_vhseffect = CVAR_INIT ("vhspause", "On", CV_SAVE, CV_OnOff, NULL); static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}}; consvar_t cv_shittyscreen = CVAR_INIT ("televisionsignal", "Okay", 0, shittyscreen_cons_t, NULL); +static CV_PossibleValue_t votescale_cons_t[] = {{0, "Vanilla"}, {1, "Adaptive"}, {2, "VerticalFill"}, {3, "HorizontalFill"}, {0, NULL}}; +consvar_t cv_votebgscaling = CVAR_INIT ("votebgscaling", "Adaptive", 0, votescale_cons_t, NULL); + CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER diff --git a/src/screen.h b/src/screen.h index ca3d91fac..de51d7101 100644 --- a/src/screen.h +++ b/src/screen.h @@ -133,7 +133,7 @@ extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_renderhitbox, cv_fullscreen; -extern consvar_t cv_vhseffect, cv_shittyscreen; +extern consvar_t cv_vhseffect, cv_shittyscreen, cv_votebgscaling; extern consvar_t cv_parallelsoftware; // wait for page flipping to end or not diff --git a/src/v_video.c b/src/v_video.c index e4d39cd40..fe57b7af4 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1539,6 +1539,51 @@ void V_DrawPatchFill(patch_t *pat) } } +// Draws a patch and tries to always fill the screen with the patch +void V_DrawAdaptiveScaledFullScreenPatch(patch_t *patch) +{ + fixed_t x = 0, y = 0; + fixed_t scale = ((vid.width * FRACUNIT) / patch->width); // fit the screen horizontally + fixed_t scaled_height = FixedMul(patch->height << FRACBITS, scale); + + // however, if this means the patch doesent fill out the screen vertically then + if (scaled_height < (vid.height << FRACBITS)) + { + scale = ((vid.height * FRACUNIT) / patch->height); // scale it to fit the screen vertically + x = ((vid.width << FRACBITS) - FixedMul(patch->width << FRACBITS, scale)) / 2; + } + else + y = (vid.height << FRACBITS) - scaled_height; + + V_DrawFixedPatch(x, y, scale, V_NOSCALEPATCH, patch, NULL); +} + +// Draws a patch and scales it to fill out the screen vertically while remaining centered +void V_DrawVerticallyScaledFullScreenPatch(patch_t *patch) +{ + fixed_t scale = ((vid.height * FRACUNIT) / patch->height); + fixed_t x = ((vid.width << FRACBITS) - FixedMul(patch->width << FRACBITS, scale)) / 2; // i fucking hate maths + + V_DrawFixedPatch(x, 0, scale, V_NOSCALEPATCH, patch, NULL); +} + +// Draws a patch and scales it to fill out the screen horizontally +// centers the patch when its too small to fit the screen vertically +void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch) +{ + fixed_t scale = ((vid.width * FRACUNIT) / patch->width); + fixed_t scaled_height = FixedMul(patch->height << FRACBITS, scale); + fixed_t y = (vid.height << FRACBITS) - scaled_height; + + // center it if it does not fit the screen vertically + if (scaled_height < (vid.height << FRACBITS)) + { + y /= 2; + } + + V_DrawFixedPatch(0, y, scale, V_NOSCALEPATCH, patch, NULL); +} + void V_DrawVhsEffect(boolean rewind) { static fixed_t upbary = 100*FRACUNIT, downbary = 150*FRACUNIT; diff --git a/src/v_video.h b/src/v_video.h index 1a17cd84c..9e518bdb6 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -341,6 +341,10 @@ void V_DoPostProcessor(INT32 view, INT32 param); void V_DrawPatchFill(patch_t *pat); +void V_DrawAdaptiveScaledFullScreenPatch(patch_t *patch); +void V_DrawVerticallyScaledFullScreenPatch(patch_t *patch); +void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch); + void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes, size_t destrowbytes); diff --git a/src/y_inter.c b/src/y_inter.c index ff5eb5dfc..0310b0fbe 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -367,27 +367,22 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) static void Y_AnimatedVoteScreenCheck(void) { char tmpPrefix[] = "INTS"; - boolean stopSearching = false; if (luaVoteScreen) strncpy(tmpPrefix, luaVoteScreen, 4); - else - { - if(gametype == GT_BATTLE) - strcpy(tmpPrefix, "BTLS"); - } + else if(gametype == GT_BATTLE) + strcpy(tmpPrefix, "BTLS"); strncpy(animPrefix, tmpPrefix, 4); animPrefix[4] = 'C'; strncpy(animWidePrefix, tmpPrefix, 4); animWidePrefix[4] = 'W'; - foundAnimVoteFrames = 0; - foundAnimVoteWideFrames = 0; + foundAnimVoteFrames = foundAnimVoteWideFrames = 0; currentAnimFrame = 0; INT32 i = 1; - while(!stopSearching) + for (;;) { boolean normalLumpExists = W_LumpExists(va("%sC%d", tmpPrefix, i)); boolean wideLumpExists = W_LumpExists(va("%sW%d", tmpPrefix, i)); @@ -401,7 +396,7 @@ static void Y_AnimatedVoteScreenCheck(void) foundAnimVoteWideFrames++; } else // If we don't find at least frame 1 (e.g VEXTRN1), let's just stop looking - stopSearching = true; + break; i++; } @@ -1132,35 +1127,53 @@ static void Y_UnloadData(void) // SRB2Kart: Voting! +static void Y_DrawVoteBackground(patch_t *patch) +{ + switch (cv_votebgscaling.value) + { + case 1: // adaptive + V_DrawAdaptiveScaledFullScreenPatch(patch); + break; + case 2: // vertical-fill + V_DrawVerticallyScaledFullScreenPatch(patch); + break; + case 3: // horizontal-fill + V_DrawHorizontallyScaledFullScreenPatch(patch); + break; + case 0: // vanilla + default: + V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (patch->width/2), + (vid.height / vid.dupy) - patch->height, + V_SNAPTOTOP|V_SNAPTOLEFT, patch); + break; + } +} + // Y_DrawAnimatedVoteScreenPatch // // Draw animated patch based on frame counter on vote screen // -static inline void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) +static void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) { + INT32 nextframe = 0; + patch_t *votebg = NULL; char tempAnimPrefix[7]; - (widePatch) ? strcpy(tempAnimPrefix, animWidePrefix) : strcpy(tempAnimPrefix, animPrefix); - INT32 tempFoundAnimVoteFrames = (widePatch) ? foundAnimVoteWideFrames : foundAnimVoteFrames; + const INT32 tempFoundAnimVoteFrames = ((widePatch ? foundAnimVoteWideFrames : foundAnimVoteFrames) - 1); + + strcpy(tempAnimPrefix, (widePatch ? animWidePrefix : animPrefix)); // Just in case someone provides LESS widescreen frames than normal frames or vice versa, reset the frame counter to 0 - if (widePatch) - { - if (currentAnimFrame > foundAnimVoteWideFrames-1) - currentAnimFrame = 0; - } - else - { - if (currentAnimFrame > foundAnimVoteFrames-1) - currentAnimFrame = 0; - } + if (currentAnimFrame > tempFoundAnimVoteFrames) + currentAnimFrame = 0; - patch_t *background = W_CachePatchName(va("%s%d", tempAnimPrefix, currentAnimFrame + 1), PU_CACHE); - V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(background->width)/2), // Keep the width/height adjustments, for screens that are less wide than 320(?) - (vid.height / vid.dupy) - SHORT(background->height), - V_SNAPTOTOP|V_SNAPTOLEFT, background); + nextframe = (currentAnimFrame + 1); - if (renderisnewtic && votetic % 2 == 0 && !paused) - currentAnimFrame = (currentAnimFrame + 1 > tempFoundAnimVoteFrames - 1) ? 0 : currentAnimFrame + 1; + votebg = W_CachePatchName(va("%s%d", (widePatch ? animWidePrefix : animPrefix), nextframe), PU_PATCH); + + Y_DrawVoteBackground(votebg); + + if (renderisnewtic && (votetic % 2 == 0) && !paused) + currentAnimFrame = (nextframe > tempFoundAnimVoteFrames) ? 0 : nextframe; } static fixed_t Y_CalculatePicScale(fixed_t picscale, INT32 hypoti) @@ -1179,6 +1192,32 @@ static fixed_t Y_CalculatePicScale(fixed_t picscale, INT32 hypoti) return picscale; } +static void Y_DrawVoteScreenPatch(void) +{ + patch_t *votebg = NULL; + const boolean widescreen = (vid.width / vid.dupx > 320); + + if (foundAnimVoteWideFrames || foundAnimVoteFrames) + { + Y_DrawAnimatedVoteScreenPatch((foundAnimVoteWideFrames && widescreen)); + return; + } + + votebg = bgpatch; // non widescreen patch + + UINT8 prefgametype = (votelevels[0][1] & ~0x80); + const boolean widebgreplaced = (prefgametype == GT_BATTLE) ? widebattlereplaced : wideracereplaced; + const boolean bgreplaced = (prefgametype == GT_BATTLE) ? battlereplaced : racereplaced; + + if ((widescreen && (widebgreplaced || !bgreplaced)) + || (!widescreen && (widebgreplaced && !bgreplaced))) + { + votebg = widebgpatch; + } + + Y_DrawVoteBackground(votebg); +} + // // Y_VoteDrawer // @@ -1236,31 +1275,8 @@ void Y_VoteDrawer(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - if (widebgpatch && vid.width / vid.dupx > 320) { - - if(foundAnimVoteWideFrames == 0){ - V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(widebgpatch->width)/2), - (vid.height / vid.dupy) - SHORT(widebgpatch->height), - V_SNAPTOTOP|V_SNAPTOLEFT, widebgpatch); - } else { - // patch_t *currPatch = W_CachePatchName(va("%s%d", animPrefix, currentAnimFrame+1), PU_CACHE); - // V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(currPatch->width)/2), // Keep the width/height adjustments, for screens that are less wide than 320(?) - // (vid.height / vid.dupy) - SHORT(currPatch->height), - // V_SNAPTOTOP|V_SNAPTOLEFT, currPatch); - // if(votetic % 4 == 0 && !paused){ - // currentAnimFrame = (currentAnimFrame+1 > foundAnimVoteFrames-1) ? 0 : currentAnimFrame + 1; - // } - Y_DrawAnimatedVoteScreenPatch(true); - } - } else { - if(foundAnimVoteFrames == 0) { - V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(bgpatch->width)/2), // Keep the width/height adjustments, for screens that are less wide than 320(?) - (vid.height / vid.dupy) - SHORT(bgpatch->height), - V_SNAPTOTOP|V_SNAPTOLEFT, bgpatch); - } else { - Y_DrawAnimatedVoteScreenPatch(false); - } - } + // decides which votebg to draw and draws it + Y_DrawVoteScreenPatch(); rowval = (votemax*3)+((votemax > 1) ? (votemax - 1) : 0); for (i = 0; i < (rowval+1); i++) // First, we need to figure out the height of this thing...