From e4c60e1ff6b62284257d3755416bafe216e13874 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 24 Aug 2018 13:37:10 +0200 Subject: [PATCH] Removed incorrect 256k wraparound implementation from both Tseng cards (turns out these cards do not have such a wraparound); Fixed the segment address handling on both Tseng cards and also implemented register key protection for both - the real fix for the TSX scrolling problem (it appears TSX spuriously writes to port 3CD, probably to probe something, and that was messing up the banking segments). --- src/video/vid_et4000.c | 52 +++++++++++++++++++++++++++--------- src/video/vid_et4000w32.c | 55 +++++++++++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 794feba7b..c836b9ec0 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -8,7 +8,7 @@ * * Emulation of the Tseng Labs ET4000. * - * Version: @(#)vid_et4000.c 1.0.11 2018/08/23 + * Version: @(#)vid_et4000.c 1.0.12 2018/08/24 * * Authors: Sarah Walker, * Miran Grca, @@ -57,7 +57,8 @@ typedef struct et4000_t int get_korean_font_enabled; int get_korean_font_index; uint16_t get_korean_font_base; - uint32_t vram_mask; + uint32_t vram_mask, key; + uint8_t hcr, mcr; } et4000_t; static uint8_t crtc_mask[0x40] = @@ -72,6 +73,8 @@ static uint8_t crtc_mask[0x40] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +uint8_t et4000_in(uint16_t addr, void *p); + void et4000_out(uint16_t addr, uint8_t val, void *p) { et4000_t *et4000 = (et4000_t *)p; @@ -84,15 +87,25 @@ void et4000_out(uint16_t addr, uint8_t val, void *p) switch (addr) { + case 0x3BF: case 0x3DF: + et4000->hcr = val; + return; + + case 0x3c2: + if (val & 1) + io_sethandler(0x03bf, 0x0001, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); + else + io_removehandler(0x03bf, 0x0001, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); + break; + case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: sc1502x_ramdac_out(addr, val, &et4000->ramdac, svga); return; case 0x3CD: /*Banking*/ - if (!(svga->crtc[0x36] & 0x10)) { - svga->write_bank = ((val & 0xf) * 0x10000) & svga->vram_display_mask; - svga->read_bank = (((val >> 4) & 0xf) * 0x10000) & svga->vram_display_mask; - pclog("write bank: %08X, read bank: %08X\n", svga->write_bank, svga->read_bank); + if (et4000->key && !(svga->crtc[0x36] & 0x10)) { + svga->write_bank = (val & 0xf) * 0x10000; + svga->read_bank = ((val >> 4) & 0xf) * 0x10000; } et4000->banking = val; return; @@ -102,6 +115,10 @@ void et4000_out(uint16_t addr, uint8_t val, void *p) case 0x3D5: if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; + if ((svga->crtcreg == 0x35) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg > 0x18) && (svga->crtcreg != 0x33) && (svga->crtcreg != 0x35) && !et4000->key) + return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); old = svga->crtc[svga->crtcreg]; @@ -109,12 +126,10 @@ void et4000_out(uint16_t addr, uint8_t val, void *p) svga->crtc[svga->crtcreg] = val; if (svga->crtcreg == 0x36) { - svga->vram_display_mask = (val & 0x20) ? et4000->vram_mask : 0x3ffff; if (!(val & 0x10)) { - svga->write_bank = ((et4000->banking & 0xf) * 0x10000) & svga->vram_display_mask; - svga->read_bank = (((et4000->banking >> 4) & 0xf) * 0x10000) & svga->vram_display_mask; - } else - svga->write_bank = svga->read_bank = 0; + svga->write_bank = (et4000->banking & 0xf) * 0x10000; + svga->read_bank = ((et4000->banking >> 4) & 0xf) * 0x10000; + } } if (old != val) @@ -170,6 +185,16 @@ void et4000_out(uint16_t addr, uint8_t val, void *p) } } break; + case 0x3D8: + et4000->mcr = val; + if (et4000->hcr == 0x03) { + if ((et4000->mcr & 0xa0) == 0xa0) + et4000->key = 1; + } else { + if ((et4000->mcr & 0xa0) != 0xa0) + et4000->key = 0; + } + break; } svga_out(addr, val, svga); } @@ -202,7 +227,7 @@ uint8_t et4000_in(uint16_t addr, void *p) return sc1502x_ramdac_in(addr, &et4000->ramdac, svga); case 0x3CD: /*Banking*/ - return et4000->banking; + return et4000->banking; case 0x3D4: return svga->crtcreg; case 0x3D5: @@ -384,6 +409,7 @@ void *et4000_isa_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + io_sethandler(0x03bf, 0x0001, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); svga_init(&et4000->svga, et4000, device_get_config_int("memory") << 10, /*1mb default*/ @@ -404,6 +430,7 @@ void *et4000k_isa_init(const device_t *info) rom_init(&et4000->bios_rom, KOREAN_BIOS_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); loadfont(KOREAN_FONT_ROM_PATH, 6); + io_sethandler(0x03bf, 0x0001, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); io_sethandler(0x22cb, 0x0001, et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, et4000); @@ -465,6 +492,7 @@ void *et4000_mca_init(const device_t *info) NULL); et4000->vram_mask = (1 << 20) - 1; + io_sethandler(0x03bf, 0x0001, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); return et4000; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index bcc723d66..4f2670cbe 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -10,7 +10,7 @@ * * Known bugs: Accelerator doesn't work in planar modes * - * Version: @(#)vid_et4000w32.c 1.0.12 2018/08/23 + * Version: @(#)vid_et4000w32.c 1.0.13 2018/08/24 * * Authors: Sarah Walker, * Miran Grca, @@ -148,6 +148,8 @@ typedef struct et4000w32p_t uint64_t blitter_time; uint64_t status_time; int type; + uint8_t hcr, mcr; + uint32_t key; } et4000w32p_t; void et4000w32p_recalcmapping(et4000w32p_t *et4000); @@ -179,6 +181,8 @@ et4000w32_log(const char *format, ...) } +uint8_t et4000w32p_in(uint16_t addr, void *p); + void et4000w32p_out(uint16_t addr, uint8_t val, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -190,28 +194,36 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) switch (addr) { -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) + case 0x3BF: case 0x3DF: + et4000->hcr = val; + return; + case 0x3c2: + if (val & 1) + io_sethandler(0x03bf, 0x0001, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); + else + io_removehandler(0x03bf, 0x0001, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); +#if defined(DEV_BRANCH) && defined(USE_STEALTH32) if (et4000->type == ET4000W32_DIAMOND) icd2061_write(&et4000->icd2061, (val >> 2) & 3); - break; #endif + break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: stg_ramdac_out(addr, val, &et4000->ramdac, svga); return; case 0x3CB: /*Banking extension*/ - if (!(svga->crtc[0x36] & 0x10)) { - svga->write_bank = ((svga->write_bank & 0xfffff) | ((val & 1) << 20)) & svga->vram_display_mask; - svga->read_bank = ((svga->read_bank & 0xfffff) | ((val & 0x10) << 16)) & svga->vram_display_mask; + if (et4000->key && !(svga->crtc[0x36] & 0x10)) { + svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20); + svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x10) << 16); } et4000->banking2 = val; return; case 0x3CD: /*Banking*/ - if (!(svga->crtc[0x36] & 0x10)) { - svga->write_bank = ((svga->write_bank & 0x100000) | ((val & 0xf) * 65536)) & svga->vram_display_mask; - svga->read_bank = ((svga->read_bank & 0x100000) | (((val >> 4) & 0xf) * 65536)) & svga->vram_display_mask; + if (et4000->key && !(svga->crtc[0x36] & 0x10)) { + svga->write_bank = (svga->write_bank & 0x100000) | ((val & 0xf) * 65536); + svga->read_bank = (svga->read_bank & 0x100000) | (((val >> 4) & 0xf) * 65536); } et4000->banking = val; return; @@ -230,17 +242,19 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) case 0x3D5: if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; + if ((svga->crtcreg == 0x35) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg > 0x18) && (svga->crtcreg != 0x33) && (svga->crtcreg != 0x35) && !et4000->key) + return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; if (svga->crtcreg == 0x36) { - svga->vram_display_mask = (val & 0x28) ? et4000->vram_mask : 0x3ffff; /* Both bits 5 and 3 must be off for 256k wraparound. */ if (!(val & 0x10)) { - svga->write_bank = (((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536)) & svga->vram_display_mask; - svga->read_bank = (((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536)) & svga->vram_display_mask; - } else - svga->write_bank = svga->read_bank = 0; + svga->write_bank = ((et4000->banking2 & 1) << 20) | ((et4000->banking & 0xf) * 65536); + svga->read_bank = ((et4000->banking2 & 0x10) << 16) | (((et4000->banking >> 4) & 0xf) * 65536); + } } if (old != val) { @@ -266,6 +280,16 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36) et4000w32p_recalcmapping(et4000); break; + case 0x3D8: + et4000->mcr = val; + if (et4000->hcr == 0x03) { + if ((et4000->mcr & 0xa0) == 0xa0) + et4000->key = 1; + } else { + if ((et4000->mcr & 0xa0) != 0xa0) + et4000->key = 0; + } + break; case 0x210A: case 0x211A: case 0x212A: case 0x213A: case 0x214A: case 0x215A: case 0x216A: case 0x217A: @@ -1118,6 +1142,7 @@ void et4000w32p_hwcursor_draw(svga_t *svga, int displine) static void et4000w32p_io_remove(et4000w32p_t *et4000) { + io_removehandler(0x03bf, 0x0001, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); io_removehandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); io_removehandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); @@ -1134,6 +1159,8 @@ static void et4000w32p_io_set(et4000w32p_t *et4000) { et4000w32p_io_remove(et4000); + if (et4000->svga.miscout & 1) + io_sethandler(0x03bf, 0x0001, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); io_sethandler(0x03c0, 0x0020, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000);