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).
This commit is contained in:
OBattler
2018-08-24 13:37:10 +02:00
parent 1895b31d27
commit e4c60e1ff6
2 changed files with 81 additions and 26 deletions

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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;

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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);