ATI VGA mode fixes:

1. Fixed 4-bit packed modes.
2. Preparation of fixing the 2-bit modes.
3. Extra: fixed the accelerator mode switches again (Mach8/32 only).
This commit is contained in:
TC1995
2023-12-27 16:07:03 +01:00
parent c240db50ba
commit 1798b2e51c
4 changed files with 82 additions and 75 deletions

View File

@@ -128,6 +128,8 @@ typedef struct svga_t {
int hblank_sub;
int hblank_end_val;
int hblank_end_len;
int packed_4bpp;
int ati_4color;
/*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
0MB-1MB - VRAM

View File

@@ -186,8 +186,22 @@ ati18800_recalctimings(svga_t *svga)
svga->gdcreg[5] &= ~0x40;
}
if (ati18800->regs[0xb0] & 6)
if (ati18800->regs[0xb0] & 6) {
svga->gdcreg[5] |= 0x40;
if ((ati18800->regs[0xb6] & 0x18) >= 0x10)
svga->packed_4bpp = 1;
else
svga->packed_4bpp = 0;
} else
svga->packed_4bpp = 0;
if ((ati18800->regs[0xb6] & 0x18) == 8) {
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->ati_4color = 1;
} else
svga->ati_4color = 0;
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
@@ -215,8 +229,10 @@ ati18800_recalctimings(svga_t *svga)
svga->render = svga_render_8bpp_lowres;
else {
svga->render = svga_render_8bpp_highres;
svga->ma_latch <<= 1;
svga->rowoffset <<= 1;
if (!svga->packed_4bpp) {
svga->ma_latch <<= 1;
svga->rowoffset <<= 1;
}
}
break;
}

View File

@@ -400,7 +400,10 @@ ati28800k_in(uint16_t addr, void *priv)
static void
ati28800_recalctimings(svga_t *svga)
{
const ati28800_t *ati28800 = (ati28800_t *) svga->priv;
ati28800_t *ati28800 = (ati28800_t *) svga->priv;
int clock_sel;
clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1);
if (ati28800->regs[0xa3] & 0x10)
svga->ma_latch |= 0x10000;
@@ -408,66 +411,13 @@ ati28800_recalctimings(svga_t *svga)
if (ati28800->regs[0xb0] & 0x40)
svga->ma_latch |= 0x20000;
switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1) | ((svga->miscout & 0x0C) >> 2)) {
case 0x00:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 42954000.0;
break;
case 0x01:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 48771000.0;
break;
case 0x02:
ati28800_log("clock 2\n");
break;
case 0x03:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0;
break;
case 0x04:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 50350000.0;
break;
case 0x05:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 56640000.0;
break;
case 0x06:
ati28800_log("clock 2\n");
break;
case 0x07:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0;
break;
case 0x08:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 30240000.0;
break;
case 0x09:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 32000000.0;
break;
case 0x0A:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 37500000.0;
break;
case 0x0B:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 39000000.0;
break;
case 0x0C:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 50350000.0;
break;
case 0x0D:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 56644000.0;
break;
case 0x0E:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 75000000.0;
break;
case 0x0F:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 65000000.0;
break;
default:
break;
}
if (ati28800->regs[0xb8] & 0x40)
svga->clock *= 2;
if (ati28800->regs[0xa7] & 0x80)
svga->clock *= 3;
if (ati28800->regs[0xb6] & 0x10) {
if ((ati28800->regs[0xb6] & 0x18) >= 0x10) {
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->rowoffset <<= 1;
@@ -476,10 +426,24 @@ ati28800_recalctimings(svga_t *svga)
if (ati28800->regs[0xb0] & 0x20) {
svga->gdcreg[5] |= 0x40;
}
if ((ati28800->regs[0xb6] & 0x18) >= 0x10)
svga->packed_4bpp = 1;
else
svga->packed_4bpp = 0;
} else
svga->packed_4bpp = 0;
if (!svga->scrblank && svga->attr_palette_enable) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
if ((ati28800->regs[0xb6] & 0x18) == 8) {
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->ati_4color = 1;
} else
svga->ati_4color = 0;
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen);
ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n", svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60, ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40, ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80);
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
@@ -502,8 +466,10 @@ ati28800_recalctimings(svga_t *svga)
svga->render = svga_render_8bpp_lowres;
else {
svga->render = svga_render_8bpp_highres;
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
if (!svga->packed_4bpp) {
svga->ma_latch <<= 1;
svga->rowoffset <<= 1;
}
}
break;
case 15:
@@ -516,7 +482,6 @@ ati28800_recalctimings(svga_t *svga)
svga->ma_latch <<= 1;
}
break;
default:
break;
}
@@ -586,6 +551,8 @@ ati28800k_init(const device_t *info)
ati28800k_in, ati28800k_out,
NULL,
NULL);
ati28800->svga.clock_gen = device_add(&ati18810_device);
ati28800->svga.getclock = ics2494_getclock;
io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
@@ -652,6 +619,8 @@ ati28800_init(const device_t *info)
ati28800_in, ati28800_out,
NULL,
NULL);
ati28800->svga.clock_gen = device_add(&ati18810_device);
ati28800->svga.getclock = ics2494_getclock;
io_sethandler(0x01ce, 2,
ati28800_in, NULL, NULL,

View File

@@ -2579,15 +2579,30 @@ mach_recalctimings(svga_t *svga)
if (mach->regs[0xb0] & 0x40)
svga->ma_latch |= 0x20000;
if (mach->regs[0xb6] & 0x10) {
if ((mach->regs[0xb6] & 0x18) >= 0x10) {
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->rowoffset <<= 1;
svga->gdcreg[5] &= ~0x40;
}
if (mach->regs[0xb0] & 0x20)
if (mach->regs[0xb0] & 0x20) {
svga->gdcreg[5] |= 0x40;
if ((mach->regs[0xb6] & 0x18) >= 0x10)
svga->packed_4bpp = 1;
else
svga->packed_4bpp = 0;
} else
svga->packed_4bpp = 0;
if ((dev->local & 0xff) < 0x02) {
if ((mach->regs[0xb6] & 0x18) == 8) {
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->ati_4color = 1;
} else
svga->ati_4color = 0;
}
mach_log("ON[0]=%d, ON[1]=%d, exton[0]=%d, exton[1]=%d, vendormode0=%d, vendormode1=%d.\n", dev->on[0], dev->on[1], mach->ext_on[0], mach->ext_on[1], dev->vendor_mode[0], dev->vendor_mode[1]);
if (dev->on[0] || dev->on[1]) {
@@ -2606,9 +2621,6 @@ mach_recalctimings(svga_t *svga)
if (dev->dispend == 598)
dev->dispend += 2;
if (dev->h_disp == 1024)
dev->accel.advfunc_cntl |= 4; /*Bit 2 means high resolution e.g.: 1024x768*/
if (dev->accel.advfunc_cntl & 4) {
if (mach->shadow_set & 2) {
if (dev->h_disp == 8) {
@@ -2784,8 +2796,10 @@ mach_recalctimings(svga_t *svga)
svga->render = svga_render_8bpp_lowres;
else {
svga->render = svga_render_8bpp_highres;
svga->ma_latch <<= 1;
svga->rowoffset <<= 1;
if (!svga->packed_4bpp) {
svga->ma_latch <<= 1;
svga->rowoffset <<= 1;
}
}
break;
}
@@ -3628,7 +3642,9 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach)
case 0x6e8:
case 0x6e9:
if (!(port & 1)) {
if (!dev->on[0] || !dev->on[1])
if ((dev->vendor_mode[0] || dev->vendor_mode[1]) && ((mach->shadow_set & 3) == 0))
dev->hdisp = val;
else if (!dev->on[0] || !dev->on[1])
dev->hdisp = val;
mach_log("ATI 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1);
@@ -3655,10 +3671,13 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach)
case 0x16e8:
case 0x16e9:
if (!dev->on[0] || !dev->on[1]) {
if ((dev->vendor_mode[0] || dev->vendor_mode[1]) && ((mach->shadow_set & 3) == 0)) {
WRITE8(port, dev->vdisp, val);
} else if (!dev->on[0] || !dev->on[1]) {
WRITE8(port, dev->vdisp, val);
dev->vdisp &= 0x1fff;
}
dev->vdisp &= 0x1fff;
mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", (dev->vdisp >> 1) + 1);
svga_recalctimings(svga);
break;
@@ -3848,7 +3867,8 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach)
case 0x5aef:
WRITE8(port, mach->shadow_set, val);
mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val);
svga_recalctimings(svga);
if (mach->shadow_set & 3)
svga_recalctimings(svga);
break;
case 0x5eee: