diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 0c506e281..0c42fd201 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1134,10 +1134,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) if (!(color & V_NOSCALESTART)) { - float dupx = (float)vid.dupx, dupy = (float)vid.dupy; - INT32 intx, inty; - - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + if (x == 0 && y == 0 && w == BASEVIDWIDTH*FRACUNIT && h == BASEVIDHEIGHT*FRACUNIT) { RGBA_t rgbaColour = V_GetColor(color); FRGBAFloat clearColour; @@ -1148,39 +1145,8 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) HWD.pfnClearBuffer(true, false, &clearColour); return; } - - fx *= dupx; - fy *= dupy; - fw *= dupx; - fh *= dupy; - - intx = (INT32)fx; - inty = (INT32)fy; - V_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); - fx = (float)intx; - fy = (float)inty; } - if (fx >= vid.width || fy >= vid.height) - return; - if (fx < 0) - { - fw += fx; - fx = 0; - } - if (fy < 0) - { - fh += fy; - fy = 0; - } - - if (fw <= 0 || fh <= 0) - return; - if (fx + fw > vid.width) - fw = (float)vid.width - fx; - if (fy + fh > vid.height) - fh = (float)vid.height - fy; - fx = -1 + fx / (vid.width / 2); fy = 1 - fy / (vid.height / 2); fw = fw / (vid.width / 2); diff --git a/src/k_hud.c b/src/k_hud.c index a3a78452e..b683106dc 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3047,45 +3047,12 @@ static void K_DrawNameTagForPlayer(fixed_t x, fixed_t y, player_t *p) const INT32 namelen = V_ThinStringWidth(player_names[p - players], V_6WIDTHSPACE|V_ALLOWLOWERCASE); UINT8 *colormap = V_GetStringColormap(clr); - INT32 barx = 0, bary = 0, barw = 0; - - UINT8 cnum = R_GetViewNumber(); - - // Since there's no "V_DrawFixedFill", and I don't feel like making it, - // fuck it, we're gonna just V_NOSCALESTART hack it - if (cnum & 1) - { - x += (BASEVIDWIDTH/2) * FRACUNIT; - } - - if ((r_splitscreen == 1 && cnum == 1) - || (r_splitscreen > 1 && cnum > 1)) - { - y += (BASEVIDHEIGHT/2) * FRACUNIT; - } - - barw = (namelen * vid.dupx); - - barx = (x * vid.dupx) / FRACUNIT; - bary = (y * vid.dupy) / FRACUNIT; - - barx += (6 * vid.dupx); - bary -= (16 * vid.dupx); - - // Center it if necessary - if (vid.width != BASEVIDWIDTH * vid.dupx) - { - barx += (vid.width - (BASEVIDWIDTH * vid.dupx)) / 2; - } - - if (vid.height != BASEVIDHEIGHT * vid.dupy) - { - bary += (vid.height - (BASEVIDHEIGHT * vid.dupy)) / 2; - } + INT32 barx = x + 6*FRACUNIT, bary = y - 16*FRACUNIT, barw = namelen*FRACUNIT; + UINT8 backcolor = colormap ? colormap[31] : 31, frontcolor = colormap ? colormap[0] : 0; + INT32 vflags = V_SPLITSCREEN; // Lat: 10/06/2020: colormap can be NULL on the frame you join a game, just arbitrarily use palette indexes 31 and 0 instead of whatever the colormap would give us instead to avoid crashes. - // Draw the stem { fixed_t stemx; @@ -3098,38 +3065,25 @@ static void K_DrawNameTagForPlayer(fixed_t x, fixed_t y, player_t *p) flipped = (p->mo->eflags & MFE_VERTICALFLIP) != (stplyr->mo->eflags & MFE_VERTICALFLIP); else flipped = p->mo->eflags & MFE_VERTICALFLIP;*/ - stemx = (x * vid.dupx) / FRACUNIT; - stemy = (y * vid.dupy) / FRACUNIT; - - // Center it if necessary - if (vid.width != BASEVIDWIDTH * vid.dupx) - { - stemx += (vid.width - (BASEVIDWIDTH * vid.dupx)) / 2; - } - - if (vid.height != BASEVIDHEIGHT * vid.dupy) - { - stemy += (vid.height - (BASEVIDHEIGHT * vid.dupy)) / 2; - } + stemx = x; + stemy = y; for (j = 0; j < 4; j++) { - stemy -= vid.dupy*4; - V_DrawFill(stemx, stemy, vid.dupy*3, vid.dupy*4, (colormap ? colormap[31] : 31)|V_NOSCALESTART); - V_DrawFill(stemx+vid.dupx, stemy + vid.dupy, vid.dupy, vid.dupy*4, (colormap ? colormap[0] : 0)|V_NOSCALESTART); - stemx += vid.dupx; + fixed_t last = j == 3 ? FRACUNIT : 0; + stemy -= FRACUNIT*4; + V_DrawFixedFill(stemx, stemy, 3*FRACUNIT, 4*FRACUNIT, vflags|backcolor); + V_DrawFixedFill(stemx + FRACUNIT, stemy + last, FRACUNIT, 4*FRACUNIT - last, vflags|frontcolor); + stemx += FRACUNIT; } - V_DrawFill(barx, bary, barw, (3 * vid.dupy), (colormap ? colormap[31] : 31)|V_NOSCALESTART); - V_DrawFill(barx, bary + vid.dupy, barw, vid.dupy, (colormap ? colormap[0] : 0)|V_NOSCALESTART); - V_DrawFill(stemx+vid.dupx, stemy+vid.dupy, barw - vid.dupx*3, vid.dupy, (colormap ? colormap[0] : 0)|V_NOSCALESTART); + V_DrawFixedFill(barx, bary, barw, 3*FRACUNIT, vflags|backcolor); + V_DrawFixedFill(barx - FRACUNIT, bary + FRACUNIT, barw, FRACUNIT, vflags|frontcolor); } // END DRAWFILL DUMBNESS - - // Draw the name itself - V_DrawThinStringAtFixed(x + (5*FRACUNIT), y - (26*FRACUNIT), V_6WIDTHSPACE|V_ALLOWLOWERCASE|clr, player_names[p - players]); + V_DrawThinStringAtFixed(x + (5*FRACUNIT), y - (26*FRACUNIT), vflags|V_6WIDTHSPACE|V_ALLOWLOWERCASE|clr, player_names[p - players]); } typedef struct weakspotdraw_t @@ -3190,29 +3144,7 @@ static void K_drawKartNameTags(void) } // Crop within splitscreen bounds - switch (r_splitscreen) - { - case 1: - V_SetClipRect( - 0, - cnum == 1 ? (BASEVIDHEIGHT / 2) * FRACUNIT : 0, - BASEVIDWIDTH * FRACUNIT, - (BASEVIDHEIGHT / 2) * FRACUNIT, - 0 - ); - break; - - case 2: - case 3: - V_SetClipRect( - cnum & 1 ? (BASEVIDWIDTH / 2) * FRACUNIT : 0, - cnum > 1 ? (BASEVIDHEIGHT / 2) * FRACUNIT : 0, - (BASEVIDWIDTH / 2) * FRACUNIT, - (BASEVIDHEIGHT / 2) * FRACUNIT, - 0 - ); - break; - } + V_SetClipRectForPlayer(cnum); c.x = viewx; c.y = viewy; @@ -3560,10 +3492,10 @@ static void K_drawKartMinimapNametag(fixed_t objx, fixed_t objy, INT32 hudx, INT V_DrawCenteredSmallStringAtFixed(amxpos + (4*FRACUNIT), amypos - (3*FRACUNIT), V_ALLOWLOWERCASE|flags|chatcolor, player_name); } -static inline void K_drawKartMinimapDot(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, UINT8 color, UINT8 size) +static inline void K_drawKartMinimapDot(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, UINT8 color, UINT8 intsize) { fixed_t amnumxpos, amnumypos; - INT32 amxpos, amypos; + fixed_t size = intsize * FRACUNIT; amnumxpos = (FixedMul(objx, minimapinfo.zoom) - minimapinfo.offs_x); amnumypos = -(FixedMul(objy, minimapinfo.zoom) - minimapinfo.offs_y); @@ -3571,16 +3503,10 @@ static inline void K_drawKartMinimapDot(fixed_t objx, fixed_t objy, INT32 hudx, if (encoremode) amnumxpos = -amnumxpos; - amxpos = (amnumxpos / FRACUNIT) + (minimapinfo.minimap_pic->width / 2); - amypos = (amnumypos / FRACUNIT) + (minimapinfo.minimap_pic->height / 2); + amnumxpos += minimapinfo.minimap_pic->width*FRACUNIT/2; + amnumypos += minimapinfo.minimap_pic->height*FRACUNIT/2; - if (flags & V_NOSCALESTART) - { - amxpos *= vid.dupx; - amypos *= vid.dupy; - } - - V_DrawFill((amxpos + hudx) - (size / 2), (amypos + hudy) - (size / 2), size, size, flags | color); + V_DrawFixedFill((amnumxpos + hudx*FRACUNIT) - (size / 2), (amnumypos + hudy*FRACUNIT) - (size / 2), size, size, flags | color); } static void K_drawKartMinimapWaypoint(waypoint_t *wp, INT32 hudx, INT32 hudy, INT32 flags) @@ -3606,13 +3532,7 @@ static void K_drawKartMinimapWaypoint(waypoint_t *wp, INT32 hudx, INT32 hudy, IN pal = 0x40; // yellow } - if (!(flags & V_NOSCALESTART)) - { - hudx *= vid.dupx; - hudy *= vid.dupy; - } - - K_drawKartMinimapDot(wp->mobj->x, wp->mobj->y, hudx, hudy, flags | V_NOSCALESTART, pal, size); + K_drawKartMinimapDot(wp->mobj->x, wp->mobj->y, hudx, hudy, flags, pal, size); } static void K_drawKartMinimapCluster(INT32 hudx, INT32 hudy, INT32 flags) @@ -3620,13 +3540,7 @@ static void K_drawKartMinimapCluster(INT32 hudx, INT32 hudy, INT32 flags) UINT8 pal = 180; // Strong pink color. UINT8 size = 6; - if (!(flags & V_NOSCALESTART)) - { - hudx *= vid.dupx; - hudy *= vid.dupy; - } - - K_drawKartMinimapDot(clusterpoint.x, clusterpoint.y, hudx, hudy, flags | V_NOSCALESTART, pal, size); + K_drawKartMinimapDot(clusterpoint.x, clusterpoint.y, hudx, hudy, flags, pal, size); } #define ICON_DOT_RADIUS (cv_minihead.value && !cv_showminimapnames.value) ? 8 : 10 @@ -3735,6 +3649,13 @@ static void K_drawKartMinimap(void) else V_DrawScaledPatch(x, y, splitflags|minimaptrans, minimapinfo.minimap_pic); + // let offsets transfer to the heads, too! + if (encoremode) + x += SHORT(minimapinfo.minimap_pic->leftoffset); + else + x -= SHORT(minimapinfo.minimap_pic->leftoffset); + y -= SHORT(minimapinfo.minimap_pic->topoffset); + // initialize for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) localplayers[i] = -1; diff --git a/src/v_video.c b/src/v_video.c index bc8c4fe76..0b1145b95 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -647,6 +647,24 @@ const cliprect_t *V_GetClipRect(void) return &cliprect; } +static inline void V_GetClipBounds(INT32 *left, INT32 *right, INT32 *top, INT32 *bottom) +{ + if (cliprect.enabled) + { + *left = cliprect.left; + *right = cliprect.right; + *top = cliprect.top; + *bottom = cliprect.bottom; + } + else + { + *left = 0; + *right = vid.width; + *top = 0; + *bottom = vid.height; + } +} + void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags) { // Adjust position. @@ -700,17 +718,15 @@ void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags) y = 0; } - if (x > vid.width) - { - x = vid.width; - w = 0; - } + if (x + w > vid.width) + w = vid.width - x; + if (y + h > vid.height) + h = vid.height - y; - if (y > vid.height) - { - y = vid.height; - h = 0; - } + x = min(x, vid.width); + y = min(y, vid.height); + w = max(w, 0); + h = max(h, 0); cliprect.left = x; cliprect.top = y; @@ -725,6 +741,18 @@ void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags) */ } +// sets up a cliprect for a splitscreen player (and actually accounts for non-green res) +void V_SetClipRectForPlayer(UINT8 pnum) +{ + INT32 w = vid.width, h = vid.height; + if (r_splitscreen == 0) + V_ClearClipRect(); // no need to + else if (r_splitscreen == 1) + V_SetClipRect(0, pnum ? h/2 : 0, w, h/2, V_NOSCALESTART); + else + V_SetClipRect(pnum & 1 ? w/2 : 0, pnum & 2 ? h/2 : 0, w/2, h/2, V_NOSCALESTART); +} + void V_ClearClipRect(void) { cliprect.enabled = false; @@ -1272,7 +1300,7 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const // // Fills a box of pixels with a single color, NOTE: scaled to screen size // -void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) +void V_DrawFixedFill(fixed_t x, fixed_t y, INT32 w, INT32 h, INT32 c) { UINT8 *dest; const UINT8 *deststop; @@ -1300,56 +1328,70 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) v_translevel = R_GetBlendTable(blendmode+1, alphalevel); } + if (!(c & V_NOSCALESTART)) + { + INT32 dupx = vid.dupx, dupy = vid.dupy; + + if (x == 0 && y == 0 && w == BASEVIDWIDTH*FRACUNIT && h == BASEVIDHEIGHT*FRACUNIT) + { // Clear the entire screen, from dest to deststop. Yes, this really works. +#ifdef HWRENDER + if (rendermode == render_opengl) + goto fillscreen; +#endif + memset(screens[0], (c&255), vid.width * vid.height * vid.bpp); + return; + } + + x = (x * dupx) >> FRACBITS; + y = (y * dupy) >> FRACBITS; + w = (w * dupx) >> FRACBITS; + h = (h * dupy) >> FRACBITS; + + // Center it if necessary + V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); + } + else + { + x >>= FRACBITS; + y >>= FRACBITS; + w >>= FRACBITS; + h >>= FRACBITS; + } + + INT32 left, right, top, bottom; + V_GetClipBounds(&left, &right, &top, &bottom); + + if (x >= right || y >= bottom) + return; // off the screen + + if (x < left) + { + w += x - left; + x = left; + } + if (y < top) + { + h += y - top; + y = top; + } + + if (w <= 0 || h <= 0) + return; // zero width/height wouldn't draw anything + if (x + w > right) + w = right - x; + if (y + h > bottom) + h = bottom - y; #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Not this again if (rendermode == render_opengl) { +fillscreen: HWR_DrawFill(x, y, w, h, c); return; } #endif - if (!(c & V_NOSCALESTART)) - { - INT32 dupx = vid.dupx, dupy = vid.dupy; - - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) - { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (c&255), vid.width * vid.height * vid.bpp); - return; - } - - x *= dupx; - y *= dupy; - w *= dupx; - h *= dupy; - - // Center it if necessary - V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); - } - - if (x >= vid.width || y >= vid.height) - return; // off the screen - - if (x < 0) - { - w += x; - x = 0; - } - if (y < 0) - { - h += y; - y = 0; - } - - if (w <= 0 || h <= 0) - return; // zero width/height wouldn't draw anything - if (x + w > vid.width) - w = vid.width - x; - if (y + h > vid.height) - h = vid.height - y; - dest = screens[0] + y*vid.width + x; deststop = screens[0] + vid.rowbytes * vid.height; diff --git a/src/v_video.h b/src/v_video.h index 8a7468ff9..fd3930732 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -184,6 +184,7 @@ struct cliprect_t const cliprect_t *V_GetClipRect(void); void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags); +void V_SetClipRectForPlayer(UINT8 pnum); void V_ClearClipRect(void); // defines for old functions @@ -211,7 +212,8 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 ski void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const UINT8 *src); // fill a box with a single color -void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c); +#define V_DrawFill(x,y,w,h,c) V_DrawFixedFill((x)<