diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index f644c2b63..32bfbfd2f 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -118,16 +118,16 @@ typedef struct svga_t { int vram_display_mask; int vidclock; int dots_per_clock; - int hblank_ext; int hwcursor_on; int dac_hwcursor_on; int overlay_on; int set_override; int hblankstart; int hblankend; - int hblank_sub; int hblank_end_val; int hblank_end_len; + int hblank_end_mask; + int hblank_sub; int packed_4bpp; int ati_4color; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 1f2b69e25..be9654aca 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -429,8 +429,7 @@ ati28800_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -446,8 +445,7 @@ ati28800_recalctimings(svga_t *svga) if ((ati28800->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index de40dc24e..ff6024677 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2485,6 +2485,9 @@ ati8514_recalctimings(svga_t *svga) { const mach_t *mach = (mach_t *) svga->ext8514; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint32_t dot; + uint32_t adj_dot; + uint32_t eff_mask; mach_log("ON0=%d, ON1=%d, vgahdisp=%d.\n", dev->on[0], dev->on[1], svga->hdisp); if (dev->on[0] || dev->on[1]) { @@ -2528,19 +2531,26 @@ ati8514_recalctimings(svga_t *svga) svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; - dev->hblankend = (dev->h_blankstart & ~0x3f) | dev->h_blank_end_val; - if (dev->hblankend <= dev->h_blankstart) - dev->hblankend += 0x40; - - dev->hblankend += dev->hblank_ext; - + dot = svga->hblankstart; + adj_dot = svga->hblankstart; + eff_mask = 0x0000003f; dev->hblank_sub = 0; - if (dev->hblankend > dev->h_total) { - dev->hblankend &= 0x3f; - dev->hblank_sub = dev->hblankend + 1; - dev->h_disp -= dev->hblank_sub; + while (1) { + if (dot == dev->h_total) + dot = 0; + + if (adj_dot >= dev->h_total) + dev->hblank_sub++; + + if ((dot & 0x0000003f) == (svga->hblank_end_val & 0x0000003f)) + break; + + dot++; + adj_dot++; } + + dev->h_disp -= dev->hblank_sub); } else { if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { /*40 column*/ @@ -2582,8 +2592,7 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->rowoffset <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -2601,8 +2610,7 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index aaa208a23..7ae985e95 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1766,6 +1766,8 @@ gd54xx_recalctimings(svga_t *svga) svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | (((svga->crtc[0x1a] >> 4) & 3) << 6); + svga->hblank_end_mask = 0x0000007f; + 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); @@ -1774,9 +1776,6 @@ gd54xx_recalctimings(svga_t *svga) 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; @@ -1801,8 +1800,7 @@ gd54xx_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_highres; if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) { svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } } } else if (svga->gdcreg[5] & 0x40) diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index f5f9ad813..6d52fc91b 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -668,8 +668,7 @@ et4000_recalctimings(svga_t *svga) svga->htotal += 256; if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index f3cac960b..259fefffb 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -450,8 +450,7 @@ et4000w32p_recalctimings(svga_t *svga) svga->htotal += 256; if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); @@ -502,8 +501,7 @@ et4000w32p_recalctimings(svga_t *svga) case 16: if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; } if (et4000->type <= ET4000W32P_REVC) { if (et4000->type == ET4000W32P_REVC) { @@ -515,8 +513,7 @@ et4000w32p_recalctimings(svga_t *svga) break; case 24: svga->hdisp /= 3; - svga->hblankstart /= 3; - svga->hblank_end_val /= 3; + svga->dots_per_clock /= 3; if (et4000->type <= ET4000W32P_REVC) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index bc335fc9c..088085355 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -976,11 +976,10 @@ 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->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; + 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_end_mask = 0x0000007f; if (mystique->type != MGA_2164W && mystique->type != MGA_2064W) svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index ad7e77aa7..d8691ad77 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3153,6 +3153,17 @@ s3_recalctimings(svga_t *svga) int clk_sel = (svga->miscout >> 2) & 3; uint8_t mask = 0xc0; + if (svga->crtc[0x33] & 0x20) { + /* 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; + } else { + 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->hdisp = svga->hdisp_old; svga->ma_latch |= (s3->ma_ext << 16); @@ -3255,24 +3266,15 @@ s3_recalctimings(svga_t *svga) ((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); - } + if (s3->chip >= S3_VISION964) + svga->hblank_end_mask = 0x7f; + } else if (s3->chip >= S3_86C801) { svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2] + 1; if (s3->chip >= S3_VISION964) { @@ -3280,8 +3282,9 @@ s3_recalctimings(svga_t *svga) 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_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; } } @@ -3329,20 +3332,17 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 1280: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; case 2048: /*Account for the 1280x1024 resolution*/ switch (svga->hdisp) { case 320: svga->hdisp <<= 2; - svga->hblankstart <<= 2; - svga->hblank_end_val <<= 2; + svga->dots_per_clock <<= 2; break; case 640: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3363,8 +3363,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3382,8 +3381,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; default: break; } @@ -3398,29 +3396,16 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION968: case S3_NUMBER9_9FX_771: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; + if (svga->hdisp == 832) + svga->hdisp -= 32; break; - case S3_SPEA_MERCURY_P64V: case S3_ELSAWIN2KPROX: switch (s3->width) { case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; - default: - break; - } - break; - case S3_MIROVIDEO40SV_ERGO_968: - switch (s3->width) { - case 1152: - case 1280: - svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; - break; + svga->dots_per_clock <<= 1; default: break; } @@ -3464,16 +3449,14 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_86C801: switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3487,22 +3470,19 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_SPEA_MIRAGE_86C805: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; switch (s3->width) { case 800: case 1024: if (svga->hdisp == 400) { /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } break; default: @@ -3519,8 +3499,7 @@ s3_recalctimings(svga_t *svga) case S3_METHEUS_86C928: if (!s3->color_16bit) { svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } switch (svga->hdisp) { /*This might be a driver issue*/ case 800: @@ -3544,8 +3523,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3558,8 +3536,7 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_VISION964: switch (s3->card_type) { @@ -3568,8 +3545,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3585,8 +3561,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3598,8 +3573,7 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -3610,8 +3584,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3625,8 +3598,7 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3662,16 +3634,14 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_86C801: switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3685,8 +3655,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_SPEA_MIRAGE_86C805: @@ -3697,8 +3666,7 @@ s3_recalctimings(svga_t *svga) if (svga->hdisp == 400) { /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } break; default: @@ -3714,8 +3682,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_METHEUS_86C928: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; switch (svga->hdisp) { /*This might be a driver issue*/ case 800: s3->width = 1024; @@ -3738,8 +3705,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3752,16 +3718,14 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_VISION868: switch (s3->card_type) { case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3775,8 +3739,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3792,8 +3755,7 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -3804,8 +3766,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3819,8 +3780,7 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3863,8 +3823,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_AMI_86C924: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; /* TODO: Is this still needed? */ if (svga->hdisp == 645) svga->hdisp -= 5; @@ -3878,8 +3837,7 @@ 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) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; default: break; @@ -3893,8 +3851,7 @@ 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) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; default: break; @@ -3904,8 +3861,7 @@ 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) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; default: break; @@ -3913,34 +3869,13 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; - break; - case S3_VISION968: - switch (s3->card_type) { - case S3_MIROVIDEO40SV_ERGO_968: - case S3_SPEA_MERCURY_P64V: - switch (s3->width) { - case 1280: - svga->hdisp = ((svga->hdisp << 1) / 3) << 1; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = ((svga->hblank_end_val << 1) / 3) << 1; - break; - default: - break; - } - break; - - default: - break; - } + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; case S3_TRIO64: case S3_TRIO32: svga->hdisp /= 3; - svga->hblankstart /= 3; - svga->hblank_end_val /= 3; + svga->dots_per_clock /= 3; break; default: @@ -3969,7 +3904,8 @@ s3_recalctimings(svga_t *svga) svga->hdisp = 640; } } else { - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) + if ((s3->card_type == S3_MIROVIDEO40SV_ERGO_968) || + (s3->card_type == S3_PHOENIX_VISION968) || (s3->card_type == S3_SPEA_MERCURY_P64V)) svga->hdisp = s3->width; } #endif @@ -3982,8 +3918,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3996,8 +3931,7 @@ s3_recalctimings(svga_t *svga) case 800: case 1024: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -4008,8 +3942,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -4024,8 +3957,7 @@ s3_recalctimings(svga_t *svga) case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -4036,8 +3968,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -4105,7 +4036,8 @@ s3_recalctimings(svga_t *svga) if (svga->crtc[0x31] & 0x08) { svga->vram_display_mask = s3->vram_mask; if (svga->bpp == 8) { - svga->render = svga_render_8bpp_highres; /*Enhanced 4bpp mode, just like the 8bpp mode per spec.*/ + /*Enhanced 4bpp mode, just like the 8bpp mode per the spec. */ + svga->render = svga_render_8bpp_highres; svga->rowoffset <<= 1; } } @@ -4125,6 +4057,12 @@ s3_trio64v_recalctimings(svga_t *svga) svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } + if ((svga->crtc[0x33] & 0x20) ||((svga->crtc[0x67] & 0xc) == 0xc)) { + /* 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; + } + svga->hdisp = svga->hdisp_old; if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; @@ -4176,13 +4114,6 @@ s3_trio64v_recalctimings(svga_t *svga) ((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; @@ -4197,6 +4128,7 @@ s3_trio64v_recalctimings(svga_t *svga) and Vision968. */ svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; } if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ @@ -4220,20 +4152,17 @@ s3_trio64v_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case 16: svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case 24: svga->render = svga_render_24bpp_highres; svga->hdisp /= 3; - svga->hblankstart >>= 1; - svga->hblank_end_val /= 3; + svga->dots_per_clock /= 3; break; case 32: svga->render = svga_render_32bpp_highres; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index a0bf98815..3184a1ccd 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -783,6 +783,12 @@ s3_virge_recalctimings(svga_t *svga) svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { + /* 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; + } + if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; if (svga->crtc[0x5d] & 0x02) { @@ -824,13 +830,6 @@ s3_virge_recalctimings(svga_t *svga) ((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; @@ -839,8 +838,9 @@ s3_virge_recalctimings(svga_t *svga) } 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); + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; } if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 692bfef27..a1ab605ea 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -641,10 +641,17 @@ svga_recalctimings(svga_t *svga) svga->render = svga_render_blank; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - if (svga->seqregs[1] & 8) - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { + if (svga->seqregs[1] & 8) + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + } else { + if (svga->seqregs[1] & 8) + svga->hdisp *= 16; + else + svga->hdisp *= 8; + } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { /*40 column*/ @@ -740,19 +747,24 @@ svga_recalctimings(svga_t *svga) svga->hblankstart = svga->crtc[2] + 1; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); + svga->hblank_end_mask = 0x0000003f; svga_log("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", svga->htotal, svga->hblankstart, svga->hblank_end_val); - svga->hblank_end_len = 0x00000040; - svga->hblank_overscan = 1; - if (!svga->scrblank && svga->attr_palette_enable) { /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - if (svga->seqregs[1] & 8) - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); - else - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { + if (svga->seqregs[1] & 8) + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + else + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + } else { + if (svga->seqregs[1] & 8) + svga->dots_per_clock = 16; + else + svga->dots_per_clock = 8; + } } else svga->dots_per_clock = 1; @@ -768,18 +780,31 @@ svga_recalctimings(svga_t *svga) xga_recalctimings(svga); if (!svga->hoverride) { - svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; - if (svga->hblankend <= svga->hblankstart) - svga->hblankend += svga->hblank_end_len; - svga->hblankend += svga->hblank_ext; - + uint32_t dot = svga->hblankstart; + uint32_t adj_dot = svga->hblankstart; + /* Verified with both the Voodoo 3 and the S3 cards: compare 7 bits if bit 7 is set, + otherwise compare 6 bits. */ + uint32_t eff_mask = (svga->hblank_end_val & ~0x0000003f) ? svga->hblank_end_mask : 0x0000003f; svga->hblank_sub = 0; - if (svga->hblankend > svga->htotal) { - svga->hblankend &= (svga->hblank_end_len - 1); - svga->hblank_sub = svga->hblankend + svga->hblank_overscan; - svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + svga_log("Blank: %04i-%04i, Total: %04i, Mask: %02X\n", svga->hblankstart, svga->hblank_end_val, + svga->htotal, eff_mask); + + while (1) { + if (dot == svga->htotal) + dot = 0; + + if (adj_dot >= svga->htotal) + svga->hblank_sub++; + + if ((dot & eff_mask) == (svga->hblank_end_val & eff_mask)) + break; + + dot++; + adj_dot++; } + + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); } if (svga->hdisp >= 2048) @@ -1278,7 +1303,6 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->ramdac_type = RAMDAC_6BIT; svga->map8 = svga->pallook; - svga->hblank_overscan = 1; /* Do at least 1 character of overscan after horizontal blanking. */ return 0; } diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index cf8cc154c..9fec8c073 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -556,17 +556,20 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE) { /* Video processing mode - assume timings akin to Cirrus' special blanking mode, that is, no overscan and relying on display end to blank. */ - svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + - (((svga->crtc[0x1a] & 0x04) >> 2) << 8) + 1; + if (banshee->vgaInit0 & 0x40) { + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + + (((svga->crtc[0x1a] & 0x04) >> 2) << 8) + 1; + svga->hblank_end_mask = 0x0000007f; + } else { + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_mask = 0x0000003f; + } 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; @@ -575,9 +578,16 @@ banshee_recalctimings(svga_t *svga) svga->linedbl = 0; } 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) | - (((svga->crtc[0x1a] & 0x20) >> 5) << 6); + if (banshee->vgaInit0 & 0x40) { + 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) | + (((svga->crtc[0x1a] & 0x20) >> 5) << 6); + svga->hblank_end_mask = 0x0000007f; + } else { + svga->hblankstart = svga->crtc[2] + 1; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5); + svga->hblank_end_mask = 0x0000003f; + } } /*6 R/W Vertical Retrace Start bit 10 0x10 @@ -642,9 +652,10 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; - svga->htotal *= 2; - svga->hblankstart *= 2; - svga->hblank_end_val *= 2; + // svga->htotal *= 2; + // svga->hblankstart *= 2; + // svga->hblank_end_val *= 2; + svga->dots_per_clock *= 2; } svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE);