From 996530a94e7deae0e0254b5165a786cb0d5f54fe Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Jan 2024 03:54:56 +0100 Subject: [PATCH] Horizontal blanking calculation now takes into account horizontal timings multiplications and divisions, fixes a lot of S3 (and ViRGE) modes. --- src/video/vid_ati28800.c | 12 +- src/video/vid_ati_mach64.c | 5 +- src/video/vid_ati_mach8.c | 9 +- src/video/vid_cl54xx.c | 63 +++++----- src/video/vid_mga.c | 7 +- src/video/vid_s3.c | 215 +++++++++++++++++++++++++++------ src/video/vid_s3_virge.c | 41 +++++-- src/video/vid_voodoo_banshee.c | 12 +- 8 files changed, 271 insertions(+), 93 deletions(-) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 8ac7e0292..b3f138dc7 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -407,6 +407,9 @@ ati28800_recalctimings(svga_t *svga) ati28800_t *ati28800 = (ati28800_t *) svga->priv; int clock_sel; + if (ati28800->regs[0xad] & 0x08) + svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; + clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1); @@ -426,6 +429,8 @@ ati28800_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -441,6 +446,8 @@ ati28800_recalctimings(svga_t *svga) if ((ati28800->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; @@ -487,6 +494,8 @@ ati28800_recalctimings(svga_t *svga) else { svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->rowoffset <<= 1; svga->ma_latch <<= 1; } @@ -501,9 +510,6 @@ ati28800_recalctimings(svga_t *svga) } } } - - if (ati28800->regs[0xad] & 0x08) - svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; } static void diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 9704a432c..cdd906067 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -511,7 +511,6 @@ mach64_recalctimings(svga_t *svga) const mach64_t *mach64 = (mach64_t *) svga->priv; if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) { - svga->hoverride = 1; svga->vtotal = (mach64->crtc_v_total_disp & 2047) + 1; svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1; svga->htotal = (mach64->crtc_h_total_disp & 255) + 1; @@ -571,10 +570,8 @@ mach64_recalctimings(svga_t *svga) } svga->vram_display_mask = mach64->vram_mask; - } else { - svga->hoverride = 0; + } else svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; - } } void diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index f24ca9c4c..34cd8b11b 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2594,6 +2594,8 @@ mach_recalctimings(svga_t *svga) ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int clock_sel; + if (mach->regs[0xad] & 0x08) + svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); if ((dev->local & 0xff) >= 0x02) { @@ -2613,6 +2615,8 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->rowoffset <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -2630,6 +2634,8 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; @@ -2841,9 +2847,6 @@ mach_recalctimings(svga_t *svga) } } } - - if (mach->regs[0xad] & 0x08) - svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; } static void diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index f87e8b87e..c1d622ac5 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1751,6 +1751,35 @@ gd54xx_recalctimings(svga_t *svga) uint8_t rdmask; uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + svga->hblankstart = svga->crtc[2] + 1; + + if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { + /* Special blanking mode: the blank start and end become components of the window generator, + and the actual blanking comes from the display enable signal. */ + /* This means blanking during overscan, we already calculate it that way, so just use the + same calculation and force otvercan to 0. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | + (((svga->crtc[0x1a] >> 4) & 3) << 6); + + if (svga->crtc[0x1b] & 0x20) { + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } + } + svga->rowoffset = (svga->crtc[0x13]) | (((int) (uint32_t) (svga->crtc[0x1b] & 0x10)) << 4); svga->interlace = (svga->crtc[0x1a] & 0x01); @@ -1765,8 +1794,11 @@ gd54xx_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_lowres; else { svga->render = svga_render_8bpp_highres; - if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) + if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) { svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } } } else if (svga->gdcreg[5] & 0x40) svga->render = svga_render_8bpp_lowres; @@ -1945,35 +1977,6 @@ gd54xx_recalctimings(svga_t *svga) if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); - svga->hblankstart = svga->crtc[2] + 1; - - if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { - /* Special blanking mode: the blank start and end become components of the window generator, - and the actual blanking comes from the display enable signal. */ - /* This means blanking during overscan, we already calculate it that way, so just use the - same calculation and force otvercan to 0. */ - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | - (((svga->crtc[0x1a] >> 4) & 3) << 6); - - if (svga->crtc[0x1b] & 0x20) { - svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; - svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); - - /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ - if (!svga->scrblank && svga->attr_palette_enable) - svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - - /* No overscan in this mode. */ - svga->hblank_overscan = 0; - - svga->monitor->mon_overscan_y = 0; - svga->monitor->mon_overscan_x = 0; - - /* Also make sure vertical blanking starts on display end. */ - svga->vblankstart = svga->dispend; - } - } - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { svga->render = svga_render_text_40; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index c101b272c..f84464bc1 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -945,8 +945,6 @@ mystique_recalctimings(svga_t *svga) svga->htotal |= 0x100; svga->hblankstart = (((mystique->crtcext_regs[1] & 0x02) >> 2) << 8) + svga->crtc[2] + 1; - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) svga->vtotal |= 0x400; @@ -978,8 +976,9 @@ mystique_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - svga->hblank_end_val = (mystique->crtcext_regs[1] & 0x40) | (svga->crtc[3] & 0x1f) | - ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); + svga->dots_per_clock = 8; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); svga->hblank_overscan = 0; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 5242652e8..6a6b949f8 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3248,6 +3248,44 @@ s3_recalctimings(svga_t *svga) break; } + if (svga->crtc[0x33] & 0x20) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } else if (s3->chip >= S3_86C801) { + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + + if (svga->crtc[0x5d] & 0x04) + svga->hblankstart += 0x100; + if (s3->chip >= S3_VISION964) { + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + } + } + #ifdef OLD_CODE_REFERENCE if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { if (!(svga->crtc[0x5e] & 0x04)) @@ -3292,14 +3330,20 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 1280: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; case 2048: /*Account for the 1280x1024 resolution*/ switch (svga->hdisp) { case 320: svga->hdisp <<= 2; + svga->hblankstart = ((svga->hblankstart - 1) << 2) + 1; + svga->hblank_end_val <<= 2; break; case 640: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3320,6 +3364,8 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3334,6 +3380,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_ELSAWIN2KPROX_964: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: @@ -3347,12 +3395,16 @@ s3_recalctimings(svga_t *svga) case S3_ELSAWIN2KPROX: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; case S3_MIROVIDEO40SV_ERGO_968: switch (s3->width) { case 1152: case 1280: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3385,6 +3437,7 @@ s3_recalctimings(svga_t *svga) } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { if (s3->width == 1280 || s3->width == 1600) svga->hdisp <<= 1; + } } else if (s3->card_type == S3_NUMBER9_9FX_771) svga->hdisp <<= 1; } @@ -3402,6 +3455,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3415,6 +3470,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_SPEA_MIRAGE_86C805: @@ -3422,8 +3479,12 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 800: case 1024: - if (svga->hdisp == 400) /*SPEA specific drivers + its VBE RAM BIOS...*/ + if (svga->hdisp == 400) { + /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } break; default: break; @@ -3437,8 +3498,11 @@ s3_recalctimings(svga_t *svga) case S3_86C928: switch (s3->card_type) { case S3_METHEUS_86C928: - if (!s3->color_16bit) + if (!s3->color_16bit) { svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } switch (svga->hdisp) { /*This might be a driver issue*/ case 800: s3->width = 1024; @@ -3461,6 +3525,8 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3475,6 +3541,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL20SD_864: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3488,6 +3556,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3503,6 +3573,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3514,6 +3586,9 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; break; @@ -3523,6 +3598,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3536,6 +3613,8 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3571,12 +3650,16 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_86C801: switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3590,6 +3673,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case S3_SPEA_MIRAGE_86C805: @@ -3597,8 +3682,12 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 800: case 1024: - if (svga->hdisp == 400) /*SPEA specific drivers + its VBE RAM BIOS...*/ + if (svga->hdisp == 400) { + /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + } break; default: break; @@ -3613,6 +3702,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_METHEUS_86C928: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; switch (svga->hdisp) { /*This might be a driver issue*/ case 800: s3->width = 1024; @@ -3635,7 +3726,9 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - break; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; + break; default: break; } @@ -3649,6 +3742,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL20SD_864: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3660,6 +3755,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3673,6 +3770,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3688,6 +3787,9 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; break; @@ -3697,6 +3799,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3710,6 +3814,8 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: @@ -3752,6 +3858,9 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_AMI_86C924: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + /* TODO: Is this still needed? */ if (svga->hdisp == 645) svga->hdisp -= 5; break; @@ -3764,6 +3873,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C801: case S3_SPEA_MIRAGE_86C801: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3777,6 +3888,8 @@ s3_recalctimings(svga_t *svga) case S3_SPEA_MIRAGE_86C805: case S3_86C805_ONBOARD: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3786,6 +3899,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_SPEA_MERCURY_LITE_PCI: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3795,6 +3910,8 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_MIROCRYSTAL20SD_864: svga->hdisp = (svga->hdisp << 1) / 3; + svga->hblankstart = (((svga->hblankstart - 1) << 1) / 3) + 1; + svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; break; default: break; @@ -3805,8 +3922,9 @@ s3_recalctimings(svga_t *svga) case S3_MIROVIDEO40SV_ERGO_968: switch (s3->width) { case 1280: - svga->hdisp = (svga->hdisp << 1) / 3; - svga->hdisp <<= 1; + svga->hdisp = ((svga->hdisp << 1) / 3) << 1; + svga->hblankstart = ((((svga->hblankstart - 1) << 1) / 3) << 1) + 1; + svga->hblank_end_val = ((svga->hblank_end_val << 1) / 3) << 1; break; default: break; @@ -3821,6 +3939,8 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp /= 3; + svga->hblankstart = ((svga->hblankstart - 1) / 3) + 1; + svga->hblank_end_val /= 3; break; default: @@ -3862,6 +3982,8 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3874,6 +3996,8 @@ s3_recalctimings(svga_t *svga) case 800: case 1024: svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; default: break; @@ -3884,6 +4008,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3898,6 +4024,9 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; + /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; break; @@ -3907,6 +4036,8 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; + svga->hblankstart = ((svga->hblankstart - 1) << 1) + 1; + svga->hblank_end_val <<= 1; break; default: break; @@ -3981,28 +4112,6 @@ s3_recalctimings(svga_t *svga) } } } - - if (s3->chip >= S3_86C801) { - if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { - /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); - } - - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - - if (svga->crtc[0x5d] & 0x04) - svga->hblankstart += 0x100; - if (s3->chip >= S3_VISION964) { - /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? - The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, - and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, - and Vision968. */ - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); - } - } - - svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void @@ -4061,6 +4170,35 @@ s3_trio64v_recalctimings(svga_t *svga) break; } + if ((svga->crtc[0x33] & 0x20) ||((svga->crtc[0x67] & 0xc) == 0xc)) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } else { + svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + } + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { svga->ma_latch |= (s3->ma_ext << 16); @@ -4082,14 +4220,20 @@ s3_trio64v_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case 16: svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; break; case 24: svga->render = svga_render_24bpp_highres; svga->hdisp /= 3; + svga->hblankstart = ((svga->hblankstart - 1) / 3) + 1; + svga->hblank_end_val /= 3; break; case 32: svga->render = svga_render_32bpp_highres; @@ -4132,10 +4276,14 @@ s3_trio64v_recalctimings(svga_t *svga) break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -4149,17 +4297,6 @@ s3_trio64v_recalctimings(svga_t *svga) break; } } - - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - - /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? - The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, - and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, - and Vision968. */ - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); - - svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index fdac95bac..8f05552c3 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -818,6 +818,31 @@ s3_virge_recalctimings(svga_t *svga) svga->clock = (cpuclock * (float) (1ULL << 32)) / freq; } + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + /* No overscan in this mode. */ + svga->hblank_overscan = 0; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } else { + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2] + 1; + + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + } + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { svga->ma_latch |= (virge->ma_ext << 16); @@ -839,6 +864,9 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; + svga->hoverride = 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; } break; case 16: @@ -846,6 +874,8 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; } break; case 24: @@ -893,10 +923,14 @@ s3_virge_recalctimings(svga_t *svga) break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -911,13 +945,6 @@ s3_virge_recalctimings(svga_t *svga) } svga->vram_display_mask = virge->vram_mask; } - - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); - - svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 03db89d2e..d013ec2e5 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -560,11 +560,18 @@ banshee_recalctimings(svga_t *svga) (((svga->crtc[0x1a] & 0x04) >> 2) << 8) + 1; svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + /* No overscan in this mode. */ svga->hblank_overscan = 0; svga->monitor->mon_overscan_y = 0; svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; } else { svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | @@ -591,9 +598,6 @@ banshee_recalctimings(svga_t *svga) banshee_log("svga->hdisp=%i\n", svga->hdisp); #endif - if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) - svga->dots_per_clock *= 2; - svga->interlace = 0; if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT) { @@ -637,6 +641,8 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; svga->htotal *= 2; + svga->hblankstart = ((svga->hblankstart - 1) * 2) + 1; + svga->hblank_end_val *= 2; } svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE);