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:
@@ -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;
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user