SVGA video card fixes of the day.

Vendor banking should be 0 when plain IBM VGA modes are set, fixes corrupt text modes (Cirrus and Paradise at the moment).
This commit is contained in:
TC1995
2024-02-06 21:26:23 +01:00
parent 9a272105e7
commit 9926e1ff6a
2 changed files with 65 additions and 63 deletions

View File

@@ -817,6 +817,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)
svga->set_reset_disabled = svga->seqregs[7] & 1; svga->set_reset_disabled = svga->seqregs[7] & 1;
gd54xx_set_svga_fast(gd54xx); gd54xx_set_svga_fast(gd54xx);
gd54xx_recalc_banking(gd54xx);
svga_recalctimings(svga); svga_recalctimings(svga);
break; break;
case 0x17: case 0x17:
@@ -1642,7 +1643,7 @@ gd54xx_recalc_banking(gd54xx_t *gd54xx)
svga->extra_banks[1] = svga->extra_banks[0] + 0x8000; svga->extra_banks[1] = svga->extra_banks[0] + 0x8000;
} }
svga->write_bank = svga->read_bank = svga->extra_banks[0]; svga->write_bank = svga->read_bank = svga->packed_chain4 ? svga->extra_banks[0] : 0;
} }
static void static void

View File

@@ -51,7 +51,7 @@ typedef struct paradise_t {
uint32_t read_bank[4], write_bank[4]; uint32_t read_bank[4], write_bank[4];
int interlace; int interlace;
int check, check2; int check;
struct { struct {
uint8_t reg_block_ptr; uint8_t reg_block_ptr;
@@ -79,6 +79,7 @@ paradise_in(uint16_t addr, void *priv)
{ {
paradise_t *paradise = (paradise_t *) priv; paradise_t *paradise = (paradise_t *) priv;
svga_t *svga = &paradise->svga; svga_t *svga = &paradise->svga;
uint8_t temp = 0;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60; addr ^= 0x60;
@@ -109,13 +110,14 @@ paradise_in(uint16_t addr, void *priv)
} }
switch (svga->gdcaddr) { switch (svga->gdcaddr) {
case 0x0b: case 0x0b:
temp = svga->gdcreg[0x0b];
if (paradise->type == WD90C30) { if (paradise->type == WD90C30) {
if (paradise->vram_mask == ((512 << 10) - 1)) { if (paradise->vram_mask == ((512 << 10) - 1)) {
svga->gdcreg[0x0b] |= 0xc0; temp &= ~0x40;
svga->gdcreg[0x0b] &= ~0x40; temp |= 0xc0;
} }
} }
return svga->gdcreg[0x0b]; return temp;
case 0x0f: case 0x0f:
return (svga->gdcreg[0x0f] & 0x17) | 0x80; return (svga->gdcreg[0x0f] & 0x17) | 0x80;
@@ -184,9 +186,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv)
return; return;
} }
old = svga->gdcreg[svga->gdcaddr];
switch (svga->gdcaddr) { switch (svga->gdcaddr) {
case 6: case 6:
if ((svga->gdcreg[6] & 0x0c) != (val & 0x0c)) { if (old ^ (val & 0x0c)) {
switch (val & 0x0c) { switch (val & 0x0c) {
case 0x00: /*128k at A0000*/ case 0x00: /*128k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
@@ -208,9 +211,9 @@ paradise_out(uint16_t addr, uint8_t val, void *priv)
default: default:
break; break;
} }
}
svga->gdcreg[6] = val; svga->gdcreg[6] = val;
paradise_remap(paradise); paradise_remap(paradise);
}
return; return;
case 9: case 9:
@@ -222,6 +225,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv)
svga->gdcreg[0x0b] = val; svga->gdcreg[0x0b] = val;
paradise_remap(paradise); paradise_remap(paradise);
return; return;
case 0x0e:
svga->gdcreg[0x0e] = val;
svga_recalctimings(svga);
return;
default: default:
break; break;
@@ -258,15 +265,6 @@ paradise_out(uint16_t addr, uint8_t val, void *priv)
} }
break; break;
case 0x46e8:
io_removehandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
mem_mapping_disable(&paradise->svga.mapping);
if (val & 8) {
io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
mem_mapping_enable(&paradise->svga.mapping);
}
break;
default: default:
break; break;
} }
@@ -277,7 +275,7 @@ paradise_out(uint16_t addr, uint8_t val, void *priv)
void void
paradise_remap(paradise_t *paradise) paradise_remap(paradise_t *paradise)
{ {
const svga_t *svga = &paradise->svga; svga_t *svga = &paradise->svga;
paradise->check = 0; paradise->check = 0;
@@ -319,8 +317,6 @@ paradise_recalctimings(svga_t *svga)
{ {
const paradise_t *paradise = (paradise_t *) svga->priv; const paradise_t *paradise = (paradise_t *) svga->priv;
svga->lowres = !(svga->gdcreg[0x0e] & 0x01);
if (paradise->type == WD90C30) { if (paradise->type == WD90C30) {
if (svga->crtc[0x3e] & 0x01) if (svga->crtc[0x3e] & 0x01)
svga->vtotal |= 0x400; svga->vtotal |= 0x400;
@@ -335,22 +331,21 @@ paradise_recalctimings(svga_t *svga)
svga->interlace = !!(svga->crtc[0x2d] & 0x20); svga->interlace = !!(svga->crtc[0x2d] & 0x20);
if (!svga->interlace && svga->lowres && (svga->hdisp >= 1024) && ((svga->gdcreg[5] & 0x60) == 0) && (svga->miscout >= 0x27) && (svga->miscout <= 0x2f) && ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { /*Horrible tweak to re-enable the interlace after returning to if (!svga->interlace && !(svga->gdcreg[0x0e] & 0x01) && (svga->hdisp >= 1024) && ((svga->gdcreg[5] & 0x60) == 0) && (svga->miscout >= 0x27) && (svga->miscout <= 0x2f) && ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { /*Horrible tweak to re-enable the interlace after returning to
a windowed DOS box in Win3.x*/ a windowed DOS box in Win3.x*/
svga->interlace = 1; svga->interlace = 1;
} }
} }
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
svga->interlace = 0;
}
if (paradise->type < WD90C30) { if (paradise->type < WD90C30) {
if ((svga->bpp >= 8) && !svga->lowres) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) {
svga->render = svga_render_8bpp_highres; svga->render = svga_render_8bpp_highres;
} }
}
} else { } else {
if ((svga->bpp >= 8) && !svga->lowres) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) {
if (svga->bpp == 16) { if (svga->bpp == 16) {
svga->render = svga_render_16bpp_highres; svga->render = svga_render_16bpp_highres;
svga->hdisp >>= 1; svga->hdisp >>= 1;
@@ -370,15 +365,8 @@ paradise_recalctimings(svga_t *svga)
} }
} }
} }
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
if (svga->hdisp == 360)
svga->hdisp <<= 1;
if (svga->seqregs[1] & 8) {
svga->render = svga_render_text_40;
} else
svga->render = svga_render_text_80;
} }
svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask;
} }
static void static void
@@ -389,10 +377,15 @@ paradise_write(uint32_t addr, uint8_t val, void *priv)
uint32_t prev_addr; uint32_t prev_addr;
uint32_t prev_addr2; uint32_t prev_addr2;
if (!(svga->gdcreg[5] & 0x40)) {
svga_write(addr, val, svga);
return;
}
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/ /*Could be done in a better way but it works.*/
if (!svga->lowres) { if (svga->gdcreg[0x0e] & 0x01) {
if (paradise->check) { if (paradise->check) {
prev_addr = addr & 3; prev_addr = addr & 3;
prev_addr2 = addr & 0xfffc; prev_addr2 = addr & 0xfffc;
@@ -427,7 +420,6 @@ paradise_write(uint32_t addr, uint8_t val, void *priv)
} }
} }
} }
svga_write_linear(addr, val, svga); svga_write_linear(addr, val, svga);
} }
static void static void
@@ -438,10 +430,15 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv)
uint32_t prev_addr; uint32_t prev_addr;
uint32_t prev_addr2; uint32_t prev_addr2;
if (!(svga->gdcreg[5] & 0x40)) {
svga_writew(addr, val, svga);
return;
}
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/ /*Could be done in a better way but it works.*/
if (!svga->lowres) { if (svga->gdcreg[0x0e] & 0x01) {
if (paradise->check) { if (paradise->check) {
prev_addr = addr & 3; prev_addr = addr & 3;
prev_addr2 = addr & 0xfffc; prev_addr2 = addr & 0xfffc;
@@ -476,7 +473,6 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv)
} }
} }
} }
svga_writew_linear(addr, val, svga); svga_writew_linear(addr, val, svga);
} }
@@ -488,10 +484,14 @@ paradise_read(uint32_t addr, void *priv)
uint32_t prev_addr; uint32_t prev_addr;
uint32_t prev_addr2; uint32_t prev_addr2;
if (!(svga->gdcreg[5] & 0x40)) {
return svga_read(addr, svga);
}
addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/ /*Could be done in a better way but it works.*/
if (!svga->lowres) { if (svga->gdcreg[0x0e] & 0x01) {
if (paradise->check) { if (paradise->check) {
prev_addr = addr & 3; prev_addr = addr & 3;
prev_addr2 = addr & 0xfffc; prev_addr2 = addr & 0xfffc;
@@ -526,7 +526,6 @@ paradise_read(uint32_t addr, void *priv)
} }
} }
} }
return svga_read_linear(addr, svga); return svga_read_linear(addr, svga);
} }
static uint16_t static uint16_t
@@ -537,10 +536,14 @@ paradise_readw(uint32_t addr, void *priv)
uint32_t prev_addr; uint32_t prev_addr;
uint32_t prev_addr2; uint32_t prev_addr2;
if (!(svga->gdcreg[5] & 0x40)) {
return svga_readw(addr, svga);
}
addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/ /*Could be done in a better way but it works.*/
if (!svga->lowres) { if (svga->gdcreg[0x0e] & 0x01) {
if (paradise->check) { if (paradise->check) {
prev_addr = addr & 3; prev_addr = addr & 3;
prev_addr2 = addr & 0xfffc; prev_addr2 = addr & 0xfffc;
@@ -575,7 +578,6 @@ paradise_readw(uint32_t addr, void *priv)
} }
} }
} }
return svga_readw_linear(addr, svga); return svga_readw_linear(addr, svga);
} }
@@ -641,7 +643,6 @@ paradise_init(const device_t *info, uint32_t memsize)
case WD90C11: case WD90C11:
svga->crtc[0x36] = '1'; svga->crtc[0x36] = '1';
svga->crtc[0x37] = '1'; svga->crtc[0x37] = '1';
io_sethandler(0x46e8, 0x0001, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise);
break; break;
case WD90C30: case WD90C30:
svga->crtc[0x36] = '3'; svga->crtc[0x36] = '3';