More and more video changes and fixes (8514/A and compatibles):

1. Made the 8514/A mode switch to VGA and viceversa (including ATI mode) actually usable and eliminating the last bugs related to them. Fixes 8514/A mode in OS/2 1.x/2.x (both IBM and Microsoft).
2. More sanity checks to the 8514/A and XGA pointers. Should fix emulator crashes on hard resets.
This commit is contained in:
TC1995
2023-11-08 23:47:16 +01:00
parent 726aa688c4
commit 6c356df9e7
4 changed files with 63 additions and 76 deletions

View File

@@ -41,7 +41,7 @@ typedef struct ibm8514_t {
int type;
int local;
int bpp;
int on;
int on[2];
int accel_bpp;
uint32_t vram_size;
@@ -64,7 +64,7 @@ typedef struct ibm8514_t {
struct {
uint16_t subsys_cntl;
uint16_t setup_md;
uint8_t advfunc_cntl;
uint16_t advfunc_cntl;
uint8_t ext_advfunc_cntl;
uint16_t cur_y;
uint16_t cur_y_bitres;

View File

@@ -964,8 +964,8 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len)
if (!val)
break;
dev->accel.advfunc_cntl = val & 0x0f;
dev->on = val & 0x01;
vga_on = !dev->on;
dev->on[0] = val & 0x01;
vga_on = !dev->on[0];
ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val);
svga_recalctimings(svga);
break;
@@ -1200,17 +1200,16 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
if (cpu_input) {
if ((dev->accel.cmd & 2) || (pixcntl == 2)) {
if ((frgd_mix == 2) || (bkgd_mix == 2)) {
if ((frgd_mix == 2) || (bkgd_mix == 2))
count >>= 3;
} else if (pixcntl == 2) {
if (dev->accel.cmd & 2) {
else if (pixcntl == 2) {
if (dev->accel.cmd & 2)
count >>= 1;
} else
else
count >>= 3;
}
} else {
} else
count >>= 3;
}
if (dev->bpp) {
if ((dev->accel.cmd & 0x200) && (count == 2))
@@ -1299,7 +1298,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
/*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled.
When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on
the NOP command)*/
ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frgdmix = %02x, bkgdmix = %02x, polygon=%x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_mix, bkgd_mix, dev->accel.multifunc[0x0a] & 6);
if (dev->accel.cmd == 0x53b1 && !cpu_dat)
ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frgdmix = %02x, bkgdmix = %02x, polygon=%x, cpu=%08x, frgdmix=%02x, bkgdmix=%02x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_mix, bkgd_mix, dev->accel.multifunc[0x0a] & 6, cpu_dat, dev->accel.frgd_mix, dev->accel.bkgd_mix);
switch (cmd) {
case 0: /*NOP (Short Stroke Vectors)*/
@@ -4243,7 +4243,7 @@ ibm8514_recalctimings(svga_t *svga)
{
ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
if (dev->on) {
if (dev->on[0]) {
dev->h_disp = (dev->hdisp + 1) << 3;
dev->pitch = (dev->accel.advfunc_cntl & 4) ? 1024 : 640;
dev->h_total = (dev->htotal + 1);

View File

@@ -100,8 +100,8 @@ typedef struct mach_t {
uint8_t bank_w;
uint8_t bank_r;
uint16_t shadow_set;
int ext_on;
int ati_mode;
int ext_on[2];
int ati_mode[2];
struct {
uint8_t line_idx;
@@ -1140,9 +1140,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
mix = 1;
break;
case 1:
if (mach->accel.mono_pattern_enable) {
if (mach->accel.mono_pattern_enable)
mix = mach->accel.mono_pattern[dev->accel.dy & 7][dev->accel.dx & 7];
} else {
else {
if ((dev->accel_bpp == 24) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000))
mix = 1;
else {
@@ -1205,18 +1205,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
src_dat = cpu_dat;
else {
READ(dev->accel.src + (dev->accel.cx), src_dat);
if (mono_src == 3) {
if (mono_src == 3)
src_dat = (src_dat & rd_mask) == rd_mask;
}
}
break;
case 5:
if (mix) {
if (dev->bpp) {
if (dev->bpp)
src_dat = mach->accel.color_pattern_word[mach->accel.color_pattern_idx];
} else {
else
src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx];
}
} else
src_dat = 0;
break;
@@ -1318,9 +1316,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
mach->accel.color_pattern_idx++;
if (mach->accel.color_pattern_idx == 3)
mach->accel.color_pattern_idx = 0;
} else {
} else
mach->accel.color_pattern_idx = (mach->accel.color_pattern_idx + mach->accel.stepx) & mach->accel.patt_len;
}
} else if ((dev->accel_bpp == 24) && (mach->accel.patt_len_reg & 0x4000) && (frgd_sel == 5)) {
mach->accel.color_pattern_idx++;
if (mach->accel.color_pattern_idx == 3)
@@ -1346,9 +1344,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
if (dev->bpp)
dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch));
else {
else
dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * (dev->pitch));
}
if ((mono_src == 1) && (dev->accel_bpp == 24) && (frgd_sel == 5))
mach->accel.color_pattern_idx = 0;
else
@@ -2347,7 +2345,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv)
mach->bank_r |= ((mach->regs[0xae] & 0x0c) << 2);
mach->bank_w |= ((mach->regs[0xae] & 3) << 4);
}
if (dev->on)
if (dev->on[0] || dev->on[1])
mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]);
} else { /* Single bank mode */
mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1);
@@ -2355,7 +2353,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv)
mach->bank_w |= ((mach->regs[0xae] & 3) << 4);
}
mach->bank_r = mach->bank_w;
if (dev->on)
if (dev->on[0] || dev->on[1])
mach_log("Single B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]);
}
svga->read_bank = mach->bank_r << 16;
@@ -2590,7 +2588,7 @@ mach_recalctimings(svga_t *svga)
if (mach->regs[0xb0] & 0x20)
svga->gdcreg[5] |= 0x40;
if (dev->on) {
if (dev->on[0] || dev->on[1]) {
mach_log("8514/A ON.\n");
if (dev->local >= 2) {
dev->h_disp = (dev->hdisp + 1) << 3;
@@ -3686,19 +3684,16 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach)
case 0x4ae8:
case 0x4ae9:
if (!(port & 1)) {
if (dev->local < 2)
dev->ext_crt_pitch = 128;
if (dev->local < 2)
dev->ext_crt_pitch = 128;
dev->accel.advfunc_cntl = val & 0x0f;
} else {
dev->on = (dev->accel.advfunc_cntl & 0x01);
vga_on = !dev->on;
mach->ext_on = dev->on;
mach_log("ATI 8514/A: (0x4ae9) val = %04x, ext = %d.\n", dev->accel.advfunc_cntl & 0x01, mach->ext_on);
mach32_updatemapping(mach);
}
mach->ati_mode = 0;
WRITE8(port, dev->accel.advfunc_cntl, val);
dev->on[port & 1] = (dev->accel.advfunc_cntl & 0x01);
mach_log("%04x: ON=%d.\n", port, dev->on[port & 1]);
vga_on = !dev->on[port & 1];
mach->ext_on[port & 1] = dev->on[port & 1];
mach32_updatemapping(mach);
mach->ati_mode[port & 1] = 0;
svga_recalctimings(svga);
break;
@@ -3806,29 +3801,22 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach)
break;
case 0x42ee:
mach->accel.test2[0] = val;
break;
case 0x42ef:
mach->accel.test2[1] = val;
mach->accel.test2[port & 1] = val;
break;
case 0x46ee:
mach->accel.test3[0] = val;
break;
case 0x46ef:
mach->accel.test3[1] = val;
mach->accel.test3[port & 1] = val;
break;
case 0x4aee:
case 0x4aef:
WRITE8(port, mach->accel.clock_sel, val);
if (port & 1) {
dev->on = mach->accel.clock_sel & 0x01;
mach->ext_on = dev->on;
vga_on = !dev->on;
mach_log("ATI 8514/A: (0x4aef) val = %04x, ext = %d.\n", mach->accel.clock_sel & 0x01, mach->ext_on);
}
mach->ati_mode = 1;
dev->on[port & 1] = mach->accel.clock_sel & 0x01;
mach->ext_on[port & 1] = dev->on[port & 1];
vga_on = !dev->on[port & 1];
mach->ati_mode[port & 1] = 1;
svga_recalctimings(svga);
break;
@@ -3836,16 +3824,14 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach)
case 0x52ef:
mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val);
WRITE8(port, mach->accel.scratch0, val);
if (port & 1)
mach->ext_on = 1;
mach->ext_on[port & 1] = 1;
break;
case 0x56ee:
case 0x56ef:
mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val);
WRITE8(port, mach->accel.scratch1, val);
if (port & 1)
mach->ext_on = 1;
mach->ext_on[port & 1] = 1;
break;
case 0x5aee:
@@ -3926,11 +3912,8 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach)
break;
}
svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000));
if (port & 1) {
mach->ati_mode = 1;
mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val);
mach32_updatemapping(mach);
}
mach->ati_mode[port & 1] = 1;
mach32_updatemapping(mach);
}
svga_recalctimings(svga);
break;
@@ -5115,10 +5098,12 @@ mach32_updatemapping(mach_t *mach)
mach->ap_size = 4;
mem_mapping_disable(&mach->mmio_linear_mapping);
}
if (mach->ext_on && (dev->local >= 2) && mach->ati_mode) {
if ((mach->ext_on[0] || mach->ext_on[1]) && (dev->local >= 2) && (mach->ati_mode[0] || mach->ati_mode[1])) {
mach_log("ExtON.\n");
mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel);
mem_mapping_set_p(&svga->mapping, mach);
} else {
mach_log("ExtOFF.\n");
mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
mem_mapping_set_p(&svga->mapping, svga);
}
@@ -5456,7 +5441,8 @@ mach_mca_reset(void *priv)
mem_mapping_disable(&mach->bios_rom.mapping);
mem_mapping_disable(&mach->bios_rom2.mapping);
mach_log("MCA reset.\n");
dev->on = 0;
dev->on[0] = 0;
dev->on[1] = 0;
vga_on = 1;
mach_mca_write(0x102, 0, mach);
}
@@ -5564,12 +5550,10 @@ mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
case 0x12:
mach->linear_base = (mach->linear_base & 0xff000000) | ((val & 0xc0) << 16);
mach->ati_mode = 1;
mach32_updatemapping(mach);
break;
case 0x13:
mach->linear_base = (mach->linear_base & 0xc00000) | (val << 24);
mach->ati_mode = 1;
mach32_updatemapping(mach);
break;
@@ -5722,7 +5706,8 @@ mach8_init(const device_t *info)
dev->bpp = 0;
svga->getclock = ics2494_getclock;
dev->on = 0;
dev->on[0] = 0;
dev->on[1] = 0;
dev->ext_pitch = 1024;
dev->ext_crt_pitch = 0x80;
dev->accel_bpp = 8;

View File

@@ -212,10 +212,12 @@ svga_out(uint16_t addr, uint8_t val, void *priv)
svga_recalctimings(svga);
break;
case 0x3c3:
if (xga_active)
if (xga_active && xga)
xga->on = (val & 0x01) ? 0 : 1;
if (ibm8514_active)
dev->on = (val & 0x01) ? 0 : 1;
if (ibm8514_active && dev) {
dev->on[0] = (val & 0x01) ? 0 : 1;
dev->on[1] = dev->on[0];
}
svga_log("3C3: XGA ON = %d.\n", xga->on);
vga_on = val & 0x01;
@@ -527,7 +529,7 @@ svga_set_ramdac_type(svga_t *svga, int type)
svga->ramdac_type = type;
for (int c = 0; c < 256; c++) {
if (ibm8514_active) {
if (ibm8514_active && dev) {
if (svga->ramdac_type == RAMDAC_8BIT)
dev->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b);
else
@@ -535,7 +537,7 @@ svga_set_ramdac_type(svga_t *svga, int type)
(svga->vgapal[c].g & 0x3f) * 4,
(svga->vgapal[c].b & 0x3f) * 4);
}
if (xga_active) {
if (xga_active && xga) {
if (svga->ramdac_type == RAMDAC_8BIT)
xga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b);
else
@@ -834,11 +836,11 @@ svga_poll(void *priv)
int old_ma;
if (!svga->override) {
if (ibm8514_active && dev->on) {
if (ibm8514_active && dev && (dev->on[0] || dev->on[1])) {
ibm8514_poll(dev, svga);
return;
}
if (xga_active && xga->on) {
if (xga_active && xga && xga->on) {
if ((xga->disp_cntl_2 & 7) >= 2) {
xga_poll(xga, svga);
return;
@@ -1253,7 +1255,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv)
cycles -= svga->monitor->mon_video_timing_write_b;
if (!linear) {
if (xga_active) {
if (xga_active && xga) {
if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) {
if (val == 0xa5) { /*Memory size test of XGA*/
xga->test = val;
@@ -1474,7 +1476,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *priv)
cycles -= svga->monitor->mon_video_timing_read_b;
if (!linear) {
if (xga_active) {
if (xga_active && xga) {
if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) {
if (xga->test == 0xa5) { /*Memory size test of XGA*/
if (addr == 0xa0001) {