From 9926e1ff6aff3b85aa759d0b64df6bc8b9a87855 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 6 Feb 2024 21:26:23 +0100 Subject: [PATCH] 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). --- src/video/vid_cl54xx.c | 3 +- src/video/vid_paradise.c | 125 ++++++++++++++++++++------------------- 2 files changed, 65 insertions(+), 63 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 469de649b..b8f749568 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -817,6 +817,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) svga->set_reset_disabled = svga->seqregs[7] & 1; gd54xx_set_svga_fast(gd54xx); + gd54xx_recalc_banking(gd54xx); svga_recalctimings(svga); break; case 0x17: @@ -1642,7 +1643,7 @@ gd54xx_recalc_banking(gd54xx_t *gd54xx) 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 diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index ad197f302..30666e82c 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -51,7 +51,7 @@ typedef struct paradise_t { uint32_t read_bank[4], write_bank[4]; int interlace; - int check, check2; + int check; struct { uint8_t reg_block_ptr; @@ -79,6 +79,7 @@ paradise_in(uint16_t addr, void *priv) { paradise_t *paradise = (paradise_t *) priv; svga_t *svga = ¶dise->svga; + uint8_t temp = 0; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -109,13 +110,14 @@ paradise_in(uint16_t addr, void *priv) } switch (svga->gdcaddr) { case 0x0b: + temp = svga->gdcreg[0x0b]; if (paradise->type == WD90C30) { if (paradise->vram_mask == ((512 << 10) - 1)) { - svga->gdcreg[0x0b] |= 0xc0; - svga->gdcreg[0x0b] &= ~0x40; + temp &= ~0x40; + temp |= 0xc0; } } - return svga->gdcreg[0x0b]; + return temp; case 0x0f: return (svga->gdcreg[0x0f] & 0x17) | 0x80; @@ -184,9 +186,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) return; } + old = svga->gdcreg[svga->gdcaddr]; switch (svga->gdcaddr) { case 6: - if ((svga->gdcreg[6] & 0x0c) != (val & 0x0c)) { + if (old ^ (val & 0x0c)) { switch (val & 0x0c) { case 0x00: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); @@ -208,9 +211,9 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) default: break; } + svga->gdcreg[6] = val; + paradise_remap(paradise); } - svga->gdcreg[6] = val; - paradise_remap(paradise); return; case 9: @@ -222,6 +225,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) svga->gdcreg[0x0b] = val; paradise_remap(paradise); return; + case 0x0e: + svga->gdcreg[0x0e] = val; + svga_recalctimings(svga); + return; default: break; @@ -258,15 +265,6 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) } break; - case 0x46e8: - io_removehandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); - mem_mapping_disable(¶dise->svga.mapping); - if (val & 8) { - io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); - mem_mapping_enable(¶dise->svga.mapping); - } - break; - default: break; } @@ -277,7 +275,7 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) void paradise_remap(paradise_t *paradise) { - const svga_t *svga = ¶dise->svga; + svga_t *svga = ¶dise->svga; paradise->check = 0; @@ -319,8 +317,6 @@ paradise_recalctimings(svga_t *svga) { const paradise_t *paradise = (paradise_t *) svga->priv; - svga->lowres = !(svga->gdcreg[0x0e] & 0x01); - if (paradise->type == WD90C30) { if (svga->crtc[0x3e] & 0x01) svga->vtotal |= 0x400; @@ -335,50 +331,42 @@ paradise_recalctimings(svga_t *svga) 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*/ svga->interlace = 1; } } - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - svga->interlace = 0; - } - if (paradise->type < WD90C30) { - if ((svga->bpp >= 8) && !svga->lowres) { - svga->render = svga_render_8bpp_highres; - } - } else { - if ((svga->bpp >= 8) && !svga->lowres) { - if (svga->bpp == 16) { - svga->render = svga_render_16bpp_highres; - svga->hdisp >>= 1; - if (svga->hdisp == 788) - svga->hdisp += 12; - if (svga->hdisp == 800) - svga->ma_latch -= 3; - } else if (svga->bpp == 15) { - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - if (svga->hdisp == 788) - svga->hdisp += 12; - if (svga->hdisp == 800) - svga->ma_latch -= 3; - } else { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { svga->render = svga_render_8bpp_highres; } } + } else { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { + if (svga->bpp == 16) { + svga->render = svga_render_16bpp_highres; + svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; + } else if (svga->bpp == 15) { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; + } else { + svga->render = svga_render_8bpp_highres; + } + } + } } - - 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 @@ -389,10 +377,15 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + svga_write(addr, val, svga); + return; + } + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -427,7 +420,6 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) } } } - svga_write_linear(addr, val, svga); } static void @@ -438,10 +430,15 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + svga_writew(addr, val, svga); + return; + } + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -476,7 +473,6 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) } } } - svga_writew_linear(addr, val, svga); } @@ -488,10 +484,14 @@ paradise_read(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + return svga_read(addr, svga); + } + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -526,7 +526,6 @@ paradise_read(uint32_t addr, void *priv) } } } - return svga_read_linear(addr, svga); } static uint16_t @@ -537,10 +536,14 @@ paradise_readw(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + return svga_readw(addr, svga); + } + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -575,7 +578,6 @@ paradise_readw(uint32_t addr, void *priv) } } } - return svga_readw_linear(addr, svga); } @@ -641,7 +643,6 @@ paradise_init(const device_t *info, uint32_t memsize) case WD90C11: svga->crtc[0x36] = '1'; svga->crtc[0x37] = '1'; - io_sethandler(0x46e8, 0x0001, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); break; case WD90C30: svga->crtc[0x36] = '3';