From a1a94076298f52b24be35268bec8e62c4cce97de Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 6 Jun 2025 20:05:04 +0200 Subject: [PATCH] (S)VGA: Fix overscan. --- src/include/86box/vid_svga.h | 1 + src/video/vid_svga.c | 45 ++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 6de73f9f9..6b817f0ee 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -116,6 +116,7 @@ typedef struct svga_t { int lastline_draw; int displine; int fullchange; + int left_overscan; int x_add; int y_add; int pan; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index b4ae192da..8f5907c3f 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -692,9 +692,9 @@ svga_recalctimings(svga_t *svga) double _dispofftime_xga = 0.0; double disptime_xga = 0.0; int vblankend; - int hdispend; #ifdef ENABLE_SVGA_LOG int vsyncend; + int hdispend; int hdispstart; int hsyncstart; int hsyncend; @@ -915,14 +915,12 @@ svga_recalctimings(svga_t *svga) if (vblankend <= svga->vblankstart) vblankend += 0x00000080; - hdispend = svga->crtc[1] + 1; - if (svga->hoverride) { if (svga->hdisp >= 2048) svga->monitor->mon_overscan_x = 0; svga->y_add = (svga->monitor->mon_overscan_y >> 1); - svga->x_add = (svga->monitor->mon_overscan_x >> 1); + svga->left_overscan = svga->x_add = (svga->monitor->mon_overscan_x >> 1); } else { uint32_t dot = svga->hblankstart; uint32_t adj_dot = svga->hblankstart; @@ -931,7 +929,9 @@ svga_recalctimings(svga_t *svga) uint32_t eff_mask = (svga->hblank_end_val & ~0x0000003f) ? svga->hblank_end_mask : 0x0000003f; svga->hblank_sub = 0; - svga_log("HDISP=%d, CRTC1+1=%d, Blank: %04i-%04i, Total: %04i, Mask: %02X, ADJ_DOT=%04i.\n", svga->hdisp, svga->crtc[1] + 1, svga->hblankstart, svga->hblank_end_val, + svga_log("HDISP=%d, CRTC1+1=%d, Blank: %04i-%04i, Total: %04i, " + "Mask: %02X, ADJ_DOT=%04i.\n", svga->hdisp, svga->crtc[1] + 1, + svga->hblankstart, svga->hblank_end_val, svga->htotal, eff_mask, adj_dot); while (adj_dot < (svga->htotal << 1)) { @@ -941,7 +941,10 @@ svga_recalctimings(svga_t *svga) if (adj_dot >= svga->htotal) svga->hblank_sub++; - svga_log("Loop: adjdot=%d, htotal=%d, dotmask=%02x, hblankendvalmask=%02x, blankendval=%02x.\n", adj_dot, svga->htotal, dot & eff_mask, svga->hblank_end_val & eff_mask, svga->hblank_end_val); + svga_log("Loop: adjdot=%d, htotal=%d, dotmask=%02x, " + "hblankendvalmask=%02x, blankendval=%02x.\n", adj_dot, + svga->htotal, dot & eff_mask, svga->hblank_end_val & eff_mask, + svga->hblank_end_val); if ((dot & eff_mask) == (svga->hblank_end_val & eff_mask)) break; @@ -949,17 +952,23 @@ svga_recalctimings(svga_t *svga) adj_dot++; } + uint32_t hd = svga->hdisp; svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); - svga->y_add = svga->vtotal + vblankend + 1; - svga->monitor->mon_overscan_y = svga->y_add + svga->vblankstart - svga->dispend; + svga->left_overscan = svga->x_add = (svga->htotal - adj_dot - 1) * svga->dots_per_clock; + svga->monitor->mon_overscan_x = svga->x_add + (svga->hblankstart * svga->dots_per_clock) - hd; - if (svga->hdisp >= 2048) { - svga->x_add = 0; + if ((svga->hdisp >= 2048) || (svga->left_overscan < 0)) { + svga->left_overscan = svga->x_add = 0; svga->monitor->mon_overscan_x = 0; - } else { - svga->x_add = (svga->htotal + svga->hblank_end_val - 1) * svga->dots_per_clock; - svga->monitor->mon_overscan_x = svga->x_add + ((svga->hblankstart - hdispend) * svga->dots_per_clock); + } + + svga->y_add = svga->vtotal - vblankend + 1; + svga->monitor->mon_overscan_y = svga->y_add + abs(svga->vblankstart - svga->dispend); + + if ((svga->dispend >= 2048) || (svga->y_add < 0)) { + svga->y_add = 0; + svga->monitor->mon_overscan_y = 0; } } @@ -1010,6 +1019,7 @@ svga_recalctimings(svga_t *svga) if (vsyncend <= svga->vsyncstart) vsyncend += 0x00000010; + hdispend = svga->crtc[1] + 1; hdispstart = ((svga->crtc[3] >> 5) & 3); hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1; hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f); @@ -1191,10 +1201,10 @@ svga_do_render(svga_t *svga) if (!svga->override) { svga->render(svga); - svga->x_add = (svga->monitor->mon_overscan_x >> 1); + svga->x_add = svga->left_overscan; svga_render_overscan_left(svga); svga_render_overscan_right(svga); - svga->x_add = (svga->monitor->mon_overscan_x >> 1) - svga->scrollcache; + svga->x_add = svga->left_overscan - svga->scrollcache; } if (svga->overlay_on) { @@ -1373,7 +1383,7 @@ svga_poll(void *priv) svga->sc = 0; if (svga->attrregs[0x10] & 0x20) { svga->scrollcache = 0; - svga->x_add = (svga->monitor->mon_overscan_x >> 1); + svga->x_add = svga->left_overscan; } } } @@ -1479,7 +1489,7 @@ svga_poll(void *priv) if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres)) svga->scrollcache <<= 1; - svga->x_add = (svga->monitor->mon_overscan_x >> 1) - svga->scrollcache; + svga->x_add = svga->left_overscan - svga->scrollcache; svga->linecountff = 0; @@ -1529,6 +1539,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->attrregs[0x11] = 0; svga->overscan_color = 0x000000; + svga->left_overscan = 8; svga->monitor->mon_overscan_x = 16; svga->monitor->mon_overscan_y = 32; svga->x_add = 8;