From 95b1250f4d1ca08b309d7dcfe33816572d6a5d2a Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 11 Jul 2025 03:43:04 +0200 Subject: [PATCH] Paradise WD90C11: First batch of fixes - fixes the fast 1024x768x4bpp mode. --- src/video/vid_paradise.c | 205 +++++++++++++++++++++++++++++++++------ 1 file changed, 177 insertions(+), 28 deletions(-) diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index a9b0c65a5..7748afdf6 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -212,6 +212,20 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) else svga->gdcreg[0x0b] |= 0x40; + if (svga->crtc[0x2f] & 0x02) + svga->decode_mask = 0x3ffff; + else switch (svga->gdcreg[0x0b] & 0xc0) { + case 0x00: case 0x40: + svga->decode_mask = 0x3ffff; + break; + case 0x80: + svga->decode_mask = 0x7ffff; + break; + case 0xc0: + svga->decode_mask = 0xfffff; + break; + } + paradise_remap(paradise); return; case 0x0e: @@ -243,6 +257,21 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) if (old != val) { if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { + if (svga->crtcreg == 0x2f) { + if (svga->crtc[0x2f] & 0x02) + svga->decode_mask = 0x3ffff; + else switch (svga->gdcreg[0x0b] & 0xc0) { + case 0x00: case 0x40: + svga->decode_mask = 0x3ffff; + break; + case 0x80: + svga->decode_mask = 0x7ffff; + break; + case 0xc0: + svga->decode_mask = 0xfffff; + break; + } + } if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); @@ -267,30 +296,92 @@ paradise_remap(paradise_t *paradise) svga_t *svga = ¶dise->svga; if (svga->seqregs[0x11] & 0x80) { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[0x0a] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } else if (svga->gdcreg[0x0b] & 0x08) { - if (svga->gdcreg[6] & 0x0c) { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } else { - paradise->read_bank[0] = paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; - paradise->read_bank[1] = paradise->write_bank[1] = (svga->gdcreg[0xa] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->read_bank[2] = paradise->write_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[3] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } - } else { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[9] << 12; - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } + paradise->read_bank[0] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[0] + 0x8000; - /*There are separate drivers for 1M and 512K/256K versions of the PVGA chips.*/ + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[0] + 0x8000; + + if ((svga->gdcreg[6] & 0x0c) == 0x00) { + paradise->read_bank[2] = paradise->read_bank[1] + 0x8000; + paradise->read_bank[3] = paradise->read_bank[2] + 0x8000; + + paradise->write_bank[2] = paradise->write_bank[1] + 0x8000; + paradise->write_bank[3] = paradise->write_bank[2] + 0x8000; + } else { + if (svga->gdcreg[6] & 0x08) { + paradise->read_bank[1] = paradise->read_bank[0]; + + paradise->write_bank[1] = paradise->write_bank[0]; + } + + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[1]; + + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[1]; + } + } else if (svga->gdcreg[0x0b] & 0x08) { + if ((svga->gdcreg[6] & 0x0c) == 0x00) { + paradise->read_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->read_bank[0] + 0x8000; + paradise->read_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[3] = paradise->read_bank[2] + 0x8000; + + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[0] + 0x8000; + paradise->write_bank[2] = svga->gdcreg[9] << 12; + paradise->write_bank[3] = paradise->write_bank[2] + 0x8000; + } else if ((svga->gdcreg[6] & 0x0c) == 0x04) { + paradise->read_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = svga->gdcreg[9] << 12; + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[1]; + + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = svga->gdcreg[9] << 12; + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[1]; + } else { + paradise->read_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->read_bank[0]; + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[0]; + + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[0]; + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[0]; + } + } else { + paradise->read_bank[0] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[0] + 0x8000; + + paradise->write_bank[0] = svga->gdcreg[9] << 12; + paradise->write_bank[1] = paradise->write_bank[0] + 0x8000; + + if ((svga->gdcreg[6] & 0x0c) == 0x00) { + paradise->read_bank[2] = paradise->read_bank[1] + 0x8000; + paradise->read_bank[3] = paradise->read_bank[2] + 0x8000; + + paradise->write_bank[2] = paradise->write_bank[1] + 0x8000; + paradise->write_bank[3] = paradise->write_bank[2] + 0x8000; + } else { + if (svga->gdcreg[6] & 0x08) { + paradise->read_bank[1] = paradise->read_bank[0]; + + paradise->write_bank[1] = paradise->write_bank[0]; + } + + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[1]; + + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[1]; + } + } + + /* There are separate drivers for 1M and 512K/256K versions of the PVGA chips. */ if ((svga->gdcreg[0x0b] & 0xc0) < 0xc0) { paradise->read_bank[1] &= 0x7ffff; paradise->write_bank[1] &= 0x7ffff; @@ -326,9 +417,21 @@ paradise_recalctimings(svga_t *svga) if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if ((svga->bpp >= 8) && !svga->lowres) { svga->render = svga_render_8bpp_highres; - svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; + if (paradise->type != WD90C11) + svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; } } + if (paradise->type == WD90C11) switch (svga->crtc[0x2f] & 0x60) { + case 0x60: case 0x40: + svga->vram_display_mask = 0x3ffff; + break; + case 0x20: + svga->vram_display_mask = 0x7ffff; + break; + case 0x00: + svga->vram_display_mask = 0xfffff; + break; + } } else { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if ((svga->bpp >= 8) && !svga->lowres) { @@ -354,6 +457,44 @@ paradise_recalctimings(svga_t *svga) } } +uint32_t +paradise_decode_addr(paradise_t *paradise, uint32_t addr, int write) +{ + svga_t *svga = ¶dise->svga; + int memory_map_mode = (svga->gdcreg[6] >> 2) & 3; + + addr &= 0x1ffff; + + switch (memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return 0xffffffff; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return 0xffffffff; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return 0xffffffff; + break; + } + + if (memory_map_mode <= 1) { + if (write) + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + else + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + } + + return addr; +} + static void paradise_write(uint32_t addr, uint8_t val, void *priv) { @@ -362,7 +503,9 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { @@ -395,7 +538,9 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { @@ -428,7 +573,9 @@ paradise_read(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return 0xff; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { @@ -461,7 +608,9 @@ paradise_readw(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return 0xffff; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) {