Video: more changes and fixes of the day (June 26th, 2025)

1. Convert the ramdac types into an enumerator.
2. Make sure the 8514/A compatible ramdacs are, if in VGA mode, using VGA compatible ports and/or, in 8514/A mode, the 8514/A ports when needed, fixes color issues in 1280x1024 resolutions on NT 3.1 and various stuff using the Mach32.
3. Add pitch initialization on reset, fixes 8514/A display drivers on various stuff on Mach8/Mach32 cards.
This commit is contained in:
TC1995
2025-06-26 13:11:42 +02:00
parent 08e281cfd5
commit 07af9f12d7
7 changed files with 74 additions and 52 deletions

View File

@@ -18,6 +18,12 @@
#ifndef VIDEO_ATI_MACH8_H
#define VIDEO_ATI_MACH8_H
typedef enum {
ATI_68875 = 0,
ATI_68860,
RAMDAC_MAX
} mach_ramdac_type;
typedef struct mach_t {
ati_eeprom_t eeprom;
svga_t svga;
@@ -39,7 +45,7 @@ typedef struct mach_t {
uint8_t irq_state;
int index;
int ramdac_type;
mach_ramdac_type ramdac_type;
int old_mode;
uint16_t config1;

View File

@@ -136,6 +136,7 @@ typedef struct svga_t {
int packed_4bpp;
int ps_bit_bug;
int ati_4color;
int vblankend;
/*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
0MB-1MB - VRAM
@@ -404,15 +405,15 @@ uint32_t svga_lookup_lut_ram(svga_t* svga, uint32_t val);
/* We need a way to add a device with a pointer to a parent device so it can attach itself to it, and
possibly also a second ATi 68860 RAM DAC type that auto-sets SVGA render on RAM DAC render change. */
extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
extern uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, int is_8514, void *priv, svga_t *svga);
extern uint8_t ati68860_ramdac_in(uint16_t addr, int is_8514, void *priv, svga_t *svga);
extern void ati68860_set_ramdac_type(void *priv, int type);
extern void ati68860_ramdac_set_render(void *priv, svga_t *svga);
extern void ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col);
extern void ati68860_hwcursor_draw(svga_t *svga, int displine);
extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga);
extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga);
extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, int is_8514, void *priv, svga_t *svga);
extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, int is_8514, void *priv, svga_t *svga);
extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);

View File

@@ -67,22 +67,22 @@ typedef struct ati68860_ramdac_t {
} ati68860_ramdac_t;
void
ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga)
ati68860_ramdac_out(uint16_t addr, uint8_t val, int is_8514, void *priv, svga_t *svga)
{
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
switch (addr) {
case 0:
svga_out(0x3c8, val, svga);
svga_out(is_8514 ? 0x2ec : 0x3c8, val, svga);
break;
case 1:
svga_out(0x3c9, val, svga);
svga_out(is_8514 ? 0x2ed : 0x3c9, val, svga);
break;
case 2:
svga_out(0x3c6, val, svga);
svga_out(is_8514 ? 0x2ea : 0x3c6, val, svga);
break;
case 3:
svga_out(0x3c7, val, svga);
svga_out(is_8514 ? 0x2eb : 0x3c7, val, svga);
break;
default:
ramdac->regs[addr & 0xf] = val;
@@ -172,23 +172,23 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga)
}
uint8_t
ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga)
ati68860_ramdac_in(uint16_t addr, int is_8514, void *priv, svga_t *svga)
{
const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
uint8_t temp = 0;
switch (addr) {
case 0:
temp = svga_in(0x3c8, svga);
temp = svga_in(is_8514 ? 0x2ec : 0x3c8, svga);
break;
case 1:
temp = svga_in(0x3c9, svga);
temp = svga_in(is_8514 ? 0x2ed : 0x3c9, svga);
break;
case 2:
temp = svga_in(0x3c6, svga);
temp = svga_in(is_8514 ? 0x2ea : 0x3c6, svga);
break;
case 3:
temp = svga_in(0x3c7, svga);
temp = svga_in(is_8514 ? 0x2eb : 0x3c7, svga);
break;
case 4:
case 8:

View File

@@ -38,7 +38,7 @@ typedef struct ati68875_ramdac_t {
} ati68875_ramdac_t;
void
ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga)
ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, int is_8514, void *priv, svga_t *svga)
{
ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv;
uint8_t rs = (addr & 0x03);
@@ -48,10 +48,16 @@ ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, sv
switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */
svga_out(is_8514 ? 0x2ec : 0x3c8, val, svga);
break;
case 0x01: /* Palette Data Register (RS value = 0001) */
svga_out(is_8514 ? 0x2ed : 0x3c9, val, svga);
break;
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
case 0x03:
svga_out(addr, val, svga);
svga_out(is_8514 ? 0x2ea : 0x3c6, val, svga);
break;
case 0x03: /* Palette Read Index Register (RS value = 0011) */
svga_out(is_8514 ? 0x2eb : 0x3c7, val, svga);
break;
case 0x08: /* General Control Register (RS value = 1000) */
ramdac->gen_cntl = val;
@@ -83,7 +89,7 @@ ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, sv
}
uint8_t
ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, int is_8514, void *priv, svga_t *svga)
{
const ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv;
uint8_t rs = (addr & 0x03);
@@ -94,10 +100,16 @@ ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */
temp = svga_in(is_8514 ? 0x2ec : 0x3c8, svga);
break;
case 0x01: /* Palette Data Register (RS value = 0001) */
temp = svga_in(is_8514 ? 0x2ed : 0x3c9, svga);
break;
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
case 0x03:
temp = svga_in(addr, svga);
temp = svga_in(is_8514 ? 0x2ea : 0x3c6, svga);
break;
case 0x03: /* Palette Read Index Register (RS value = 0011) */
temp = svga_in(is_8514 ? 0x2eb : 0x3c7, svga);
break;
case 0x08: /* General Control Register (RS value = 1000) */
temp = ramdac->gen_cntl;

View File

@@ -425,7 +425,7 @@ mach64_out(uint16_t addr, uint8_t val, void *priv)
case 0x3C8:
case 0x3C9:
if (mach64->type == MACH64_GX)
ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga);
ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, 0, svga->ramdac, svga);
else
svga_out(addr, val, svga);
return;
@@ -492,7 +492,7 @@ mach64_in(uint16_t addr, void *priv)
case 0x3C8:
case 0x3C9:
if (mach64->type == MACH64_GX)
return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), svga->ramdac, svga);
return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), 0, svga->ramdac, svga);
return svga_in(addr, svga);
case 0x3D4:
@@ -2530,7 +2530,7 @@ mach64_ext_readb(uint32_t addr, void *priv)
case 0xc2:
case 0xc3:
if (mach64->type == MACH64_GX)
ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga);
ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), 0, mach64->svga.ramdac, &mach64->svga);
else {
switch (addr & 3) {
case 0:
@@ -3313,7 +3313,7 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
case 0xc2:
case 0xc3:
if (mach64->type == MACH64_GX)
ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga);
ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, 0, svga->ramdac, svga);
else {
switch (addr & 3) {
case 0:
@@ -3574,7 +3574,7 @@ mach64_ext_inb(uint16_t port, void *priv)
case 0x5eee:
case 0x5eef:
if (mach64->type == MACH64_GX)
ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga);
ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), 0, mach64->svga.ramdac, &mach64->svga);
else {
switch (port & 3) {
case 0:
@@ -3820,7 +3820,7 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv)
case 0x5eee:
case 0x5eef:
if (mach64->type == MACH64_GX)
ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga);
ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, 0, svga->ramdac, svga);
else {
switch (port & 3) {
case 0:
@@ -4801,6 +4801,7 @@ mach64vt2_init(const device_t *info)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci);
mach64->pci = 1;
mach64->vlb = 0;
mach64->pci_id = 0x5654;
mach64->config_chip_id = 0x40005654;
mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/

View File

@@ -2422,11 +2422,11 @@ mach_out(uint16_t addr, uint8_t val, void *priv)
rs2 = !!(mach->accel.ext_ge_config & 0x1000);
rs3 = !!(mach->accel.ext_ge_config & 0x2000);
mach_log("8514/A Extended mode=%02x.\n", mach->regs[0xb0] & 0x20);
if (ATI_MACH32 && !dev->on) {
if (mach->pci_bus && !mach->ramdac_type)
ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga);
if (ATI_MACH32) {
if (mach->pci_bus && (mach->ramdac_type == ATI_68860))
ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, 1, svga->ramdac, svga);
else
ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga);
ati68875_ramdac_out(addr, rs2, rs3, val, 1, svga->ramdac, svga);
} else
svga_out(addr, val, svga);
return;
@@ -2438,11 +2438,11 @@ mach_out(uint16_t addr, uint8_t val, void *priv)
rs2 = !!(mach->regs[0xa0] & 0x20);
rs3 = !!(mach->regs[0xa0] & 0x40);
mach_log("VGA Extended mode=%02x.\n", mach->regs[0xb0] & 0x20);
if (ATI_MACH32 && !dev->on) {
if (mach->pci_bus && !mach->ramdac_type)
ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga);
if (ATI_MACH32) {
if (mach->pci_bus && (mach->ramdac_type == ATI_68860))
ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, 0, svga->ramdac, svga);
else
ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga);
ati68875_ramdac_out(addr, rs2, rs3, val, 0, svga->ramdac, svga);
} else
svga_out(addr, val, svga);
return;
@@ -2563,11 +2563,11 @@ mach_in(uint16_t addr, void *priv)
case 0x2ed:
rs2 = !!(mach->accel.ext_ge_config & 0x1000);
rs3 = !!(mach->accel.ext_ge_config & 0x2000);
if (ATI_MACH32 && !dev->on) {
if (mach->pci_bus && !mach->ramdac_type)
temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga);
if (ATI_MACH32) {
if (mach->pci_bus && (mach->ramdac_type == ATI_68860))
temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), 1, svga->ramdac, svga);
else
temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga);
temp = ati68875_ramdac_in(addr, rs2, rs3, 1, svga->ramdac, svga);
} else
temp = svga_in(addr, svga);
break;
@@ -3007,6 +3007,7 @@ mach_recalctimings(svga_t *svga)
mach_log("cntl=%d, clksel=%x, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d, vgahdisp=%d.\n",
dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0x01, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset,
mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace, svga->hdisp);
mach_log("EXTGECONFIG bits 11-15=%04x.\n", mach->accel.ext_ge_config & 0x8800);
if ((mach->accel.ext_ge_config & 0x800) || (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800))) {
mach_log("hv=%d,%d, pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d, shadow=%x, vgahdisp=%d.\n",
dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0,
@@ -4759,7 +4760,6 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev)
}
} else {
switch (mach->accel.cmd_type) {
case 1:
case 2:
case 5:
if ((dev->subsys_cntl & INT_GE_BSY) &&
@@ -4770,6 +4770,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev)
(dev->accel.dy <= clip_b))
temp |= INT_GE_BSY;
break;
case 1:
case 3:
case 4:
if ((dev->subsys_cntl & INT_GE_BSY) &&
@@ -7068,7 +7069,7 @@ mach8_init(const device_t *info)
dev->type = info->flags;
dev->local = info->local & 0xff;
mach->has_bios = !(info->local & 0xff00);
mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : 1;
mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : ATI_68875;
dev->vram_amount = device_get_config_int("memory");
dev->vram_512k_8514 = dev->vram_amount == 512;
@@ -7119,7 +7120,7 @@ mach8_init(const device_t *info)
dev->vram_mask = dev->vram_size - 1;
dev->hwcursor.cur_ysize = 64;
mach->config1 = 0x20;
if (mach->pci_bus && !mach->ramdac_type)
if (mach->pci_bus && (mach->ramdac_type == ATI_68860))
svga->ramdac = device_add(&ati68860_ramdac_device);
else
svga->ramdac = device_add(&ati68875_ramdac_device);
@@ -7142,7 +7143,7 @@ mach8_init(const device_t *info)
} else if (mach->pci_bus) {
video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_pci);
mach->config1 |= 0x0e;
if (mach->ramdac_type)
if (mach->ramdac_type == ATI_68860)
mach->config1 |= 0x0400;
else
mach->config1 |= 0x0a00;
@@ -7180,6 +7181,7 @@ mach8_init(const device_t *info)
dev->on = 0;
dev->pitch = 1024;
dev->ext_pitch = 1024;
dev->ext_crt_pitch = 0x80;
dev->accel_bpp = 8;
svga->force_old_addr = 1;
@@ -7242,6 +7244,7 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514)
/*Init as 1024x768 87hz interlaced first, per 8514/A.*/
dev->on = 0;
dev->pitch = 1024;
dev->ext_pitch = 1024;
dev->ext_crt_pitch = 0x80;
dev->accel_bpp = 8;
dev->rowoffset = 0x80;
@@ -7390,12 +7393,12 @@ static const device_config_t mach32_pci_config[] = {
.description = "RAMDAC type",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 0,
.default_int = ATI_68860,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "ATI 68860", .value = 0 },
{ .description = "ATI 68875", .value = 1 },
{ .description = "ATI 68860", .value = ATI_68860 },
{ .description = "ATI 68875", .value = ATI_68875 },
{ .description = "" }
},
.bios = { { 0 } }

View File

@@ -693,7 +693,6 @@ svga_recalctimings(svga_t *svga)
double _dispontime_xga = 0.0;
double _dispofftime_xga = 0.0;
double disptime_xga = 0.0;
int vblankend;
#ifdef ENABLE_SVGA_LOG
int vsyncend;
int hdispend;
@@ -913,9 +912,9 @@ svga_recalctimings(svga_t *svga)
if (xga_active && (svga->xga != NULL))
xga_recalctimings(svga);
vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f);
if (vblankend <= svga->vblankstart)
vblankend += 0x00000080;
svga->vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f);
if (svga->vblankend <= svga->vblankstart)
svga->vblankend += 0x00000080;
if (svga->hoverride || svga->override) {
if (svga->hdisp >= 2048)
@@ -969,7 +968,7 @@ svga_recalctimings(svga_t *svga)
}
/* - 1 because + 1 but also - 2 to compensate for the + 2 added to vtotal above. */
svga->y_add = svga->vtotal - vblankend - 1;
svga->y_add = svga->vtotal - svga->vblankend - 1;
svga->monitor->mon_overscan_y = svga->y_add + abs(svga->vblankstart - svga->dispend);
if ((svga->dispend >= 2048) || (svga->y_add < 0)) {
@@ -1050,7 +1049,7 @@ svga_recalctimings(svga_t *svga)
"\n"
"\n",
svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend,
svga->vblankstart, vblankend,
svga->vblankstart, svga->vblankend,
svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend,
svga->hblankstart, svga->hblankend);