From 50ca61dfd45b301d1e98003c76ea832154752fda Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 20 Apr 2024 23:43:27 +0200 Subject: [PATCH] ATI/IBM mode changes in the Mach8/32. Reworked the way the mode changes work in said chips (and way less hacky than before). --- src/video/vid_ati_mach8.c | 138 ++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 71 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 2613de767..522df00a6 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -2599,12 +2599,25 @@ mach_recalctimings(svga_t *svga) dev->h_total = dev->htotal + 1; dev->h_blankstart = dev->hblankstart; dev->h_blank_end_val = dev->hblank_end_val; - dev->v_total = dev->vtotal; - dev->v_syncstart = dev->vsyncstart; + dev->v_total = dev->v_total_reg + 1; + dev->v_syncstart = dev->v_sync_start + 1; dev->rowcount = !!(dev->disp_cntl & 0x08); - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; + mach_log("VDISP=%d.\n", dev->vdisp); + if ((dev->hdisp == 800) || (dev->hdisp == 1280)) { + /*For VESA modes in ATI 8514/A mode.*/ + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + } else { + /*Default modes for 8514/A mode*/ + if (dev->accel.advfunc_cntl & 0x04) { + dev->h_disp = 1024; + dev->dispend = 768; + } else { + dev->h_disp = 640; + dev->dispend = 480; + } + } if (dev->dispend == 766) dev->dispend += 2; @@ -2709,13 +2722,6 @@ mach_recalctimings(svga_t *svga) svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); else svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - - if (((mach->shadow_set & 0x03) != 0x02) || !(dev->accel.advfunc_cntl & 0x04)) { /*Shadow set of 2 and bit 2 of port 0x4ae8 mean 1024x768+*/ - if (!(mach->accel.clock_sel & 0x01)) { - dev->h_disp = 640; - dev->dispend = 480; - } - } } if (dev->interlace) { @@ -3620,84 +3626,63 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x2e8: case 0x2e9: WRITE8(port, dev->htotal, val); + dev->htotal &= 0x1ff; break; case 0x6e8: - case 0x6e9: - if (!(port & 1)) { - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { - dev->hdisped = val; - dev->hdisp = (dev->hdisped + 1) << 3; - if ((dev->hdisp == 640) && ((mach->shadow_set & 0x03) == 0x02) && (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) - svga_recalctimings(svga); - else if ((dev->hdisp == 1024) && !(mach->accel.clock_sel & 0x01) && ((dev->disp_cntl & 0x60) == 0x40)) { - if (dev->accel.advfunc_cntl & 0x04) { - dev->hdisp = 1024; - dev->vdisp = 768; - } else { - dev->hdisp = 640; - dev->vdisp = 480; - } - svga_recalctimings(svga); - } - } - } + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) + dev->hdisped = val; + mach_log("[%04X:%08X]: ATI 8514/A: H_DISP write 06E8 = %d, actual val=%d, set lock=%x, shadow set=%x, advfunc bit 2=%x, dispcntl=%02x, clocksel bit 0=%x.\n", CS, cpu_state.pc, dev->hdisp, ((val + 1) << 3), mach->shadow_cntl, mach->shadow_set, dev->accel.advfunc_cntl & 0x04, dev->disp_cntl & 0x60, mach->accel.clock_sel & 0x01); + mach_log("ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", port, val); + break; + case 0x6e9: + dev->hdisped = (dev->hdisp >> 3) - 1; + dev->v_disp = (dev->vdisp - 1) << 1; + mach_log("ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", port, val); break; case 0xae8: - case 0xae9: - if (!(port & 1)) { - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { - dev->hsync_start = val; - dev->hblankstart = (dev->hsync_start & 0x07); - } - } + dev->hsync_start = val; + dev->hblankstart = (dev->hsync_start & 0x07); mach_log("ATI 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); break; case 0xee8: - case 0xee9: - if (!(port & 1)) { - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { - dev->hsync_width = val; - dev->hblank_end_val = (dev->hblankstart + (dev->hsync_width & 0x1f) - 1) & 0x3f; - } - } + dev->hsync_width = val; + dev->hblank_end_val = (dev->hblankstart + (dev->hsync_width & 0x1f) - 1) & 0x3f; mach_log("ATI 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); break; case 0x12e8: case 0x12e9: - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { WRITE8(port, dev->v_total_reg, val); dev->v_total_reg &= 0x1fff; - dev->vtotal = dev->v_total_reg; - dev->vtotal++; } break; case 0x16e8: case 0x16e9: - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { WRITE8(port, dev->v_disp, val); dev->v_disp &= 0x1fff; - dev->vdisp = dev->v_disp; - dev->vdisp >>= 1; - dev->vdisp++; } dev->modechange = dev->accel.advfunc_cntl & 0x04; mach->compat_mode = mach->shadow_set & 0x03; - mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); + mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); + mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); break; case 0x1ae8: case 0x1ae9: - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { WRITE8(port, dev->v_sync_start, val); dev->v_sync_start &= 0x1fff; - dev->vsyncstart = dev->v_sync_start; - dev->vsyncstart++; } break; @@ -3709,7 +3694,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x22e8: dev->disp_cntl = val; dev->interlace = !!(val & 0x10); - mach_log("ATI 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace); + mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); break; case 0x42e8: @@ -3747,7 +3732,10 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach->ext_on[port & 1] = dev->on[port & 1]; mach32_updatemapping(mach, svga); dev->vendor_mode[port & 1] = 0; - mach_log("ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4, dev->hdisp); + dev->hdisp = (dev->hdisped + 1) << 3; + dev->vdisp = (dev->v_disp >> 1) + 1; + mach_log("ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + mach_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); svga_recalctimings(svga); break; @@ -3825,7 +3813,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 else dev->ext_crt_pitch <<= 1; } - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); svga_recalctimings(svga); break; @@ -3864,39 +3852,46 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x46ee: case 0x46ef: - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->shadow_cntl, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); break; case 0x4aee: case 0x4aef: WRITE8(port, mach->accel.clock_sel, val); dev->on[port & 1] = mach->accel.clock_sel & 0x01; - mach_log("ATI 8514/A: (0x%04x): ON=%d.\n", port, dev->on[port & 1]); + mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d.\n", port, dev->on[port & 1], val, dev->hdisp, dev->vdisp); + mach_log("ATI mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); mach->ext_on[port & 1] = dev->on[port & 1]; vga_on = !dev->on[port & 1]; dev->vendor_mode[port & 1] = 1; + dev->hdisp = (dev->hdisped + 1) << 3; + dev->vdisp = (dev->v_disp >> 1) + 1; svga_recalctimings(svga); break; case 0x52ee: case 0x52ef: - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); WRITE8(port, mach->accel.scratch0, val); break; case 0x56ee: case 0x56ef: - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); WRITE8(port, mach->accel.scratch1, val); break; case 0x5aee: case 0x5aef: - if (!(mach->shadow_cntl & 0x3f)) { - WRITE8(port, mach->shadow_set, val); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - } + WRITE8(port, mach->shadow_set, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); + if ((mach->shadow_set & 0x03) == 0x00) + mach_log("Primary CRT register set.\n"); + else if ((mach->shadow_set & 0x03) == 0x01) + mach_log("Shadow Set 1: 640x480.\n"); + else if ((mach->shadow_set & 0x03) == 0x02) + mach_log("Shadow Set 2: 1024x768.\n"); break; case 0x5eee: @@ -3938,7 +3933,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x76ef: WRITE8(port, mach->accel.ge_pitch, val); dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); - mach_log("ATI 8514/A: (0x%04x) val = %04x, extpitch = %d.\n", port, val, dev->ext_pitch); + mach_log("ATI 8514/A: (0x%04x) val=%04x, extpitch=%d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); break; @@ -3971,7 +3966,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); dev->vendor_mode[port & 1] = 1; mach32_updatemapping(mach, svga); - mach_log("ATI 8514/A: (0x%04x) val = %02x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); svga_recalctimings(svga); } else { if (mach->accel.ext_ge_config & 0x8080) @@ -4285,6 +4280,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in temp = dev->hdisped & 0xff; temp |= (dev->htotal << 8); } + mach_log("B2EE read=%02x.\n", temp & 0xff); break; case 0xb2ef: if (len == 1) @@ -4301,15 +4297,15 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xc2ee: if (len == 1) - temp = dev->vtotal & 0xff; + temp = dev->v_total_reg & 0xff; else { - temp = dev->vtotal; + temp = dev->v_total_reg; mach_log("VTOTAL read=%d.\n", temp); } break; case 0xc2ef: if (len == 1) - temp = dev->vtotal >> 8; + temp = dev->v_total_reg >> 8; break; case 0xc6ee: