SVGA hskew

This commit is contained in:
Jasmine Iwanek
2023-08-06 20:29:39 -04:00
parent cb24ee27cb
commit 01ffb60df8
7 changed files with 306 additions and 32 deletions

View File

@@ -55,17 +55,19 @@
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#define ET4000_TYPE_TC6058AF 0 /* ISA ET4000AX (TC6058AF) */
#define ET4000_TYPE_ISA 1 /* ISA ET4000AX */
#define ET4000_TYPE_MCA 2 /* MCA ET4000AX */
#define ET4000_TYPE_KOREAN 3 /* Korean ET4000 */
#define ET4000_TYPE_TRIGEM 4 /* Trigem 286M ET4000 */
#define ET4000_TYPE_KASAN 5 /* Kasan ET4000 */
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin"
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
typedef struct {
const char *name;
@@ -115,6 +117,7 @@ et4000_in(uint16_t addr, void *priv)
{
et4000_t *dev = (et4000_t *) priv;
svga_t *svga = &dev->svga;
uint8_t ret;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
@@ -138,7 +141,8 @@ et4000_in(uint16_t addr, void *priv)
case 0x3c7:
case 0x3c8:
case 0x3c9:
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
if (dev->type >= ET4000_TYPE_ISA)
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
case 0x3cd: /*Banking*/
return dev->banking;
@@ -149,6 +153,26 @@ et4000_in(uint16_t addr, void *priv)
case 0x3d5:
return svga->crtc[svga->crtcreg];
case 0x3da:
svga->attrff = 0;
if (svga->cgastat & 0x01)
svga->cgastat &= ~0x30;
else
svga->cgastat ^= 0x30;
ret = svga->cgastat;
if ((svga->fcr & 0x08) && svga->dispon)
ret |= 0x08;
if (ret & 0x08)
ret &= 0x7f;
else
ret |= 0x80;
return ret;
default:
break;
}
@@ -225,12 +249,33 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
addr ^= 0x60;
switch (addr) {
case 0x3c5:
if (svga->seqaddr == 4) {
svga->seqregs[4] = val;
svga->chain2_write = !(val & 4);
svga->chain4 = (svga->chain4 & ~8) | (val & 8);
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8);
return;
} else if (svga->seqaddr == 0x0e) {
svga->seqregs[0x0e] = val;
svga->chain4 &= ~0x02;
if (svga->gdcreg[5] & 0x40)
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
svga_recalctimings(svga);
return;
}
break;
case 0x3c6:
case 0x3c7:
case 0x3c8:
case 0x3c9:
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
return;
if (dev->type >= ET4000_TYPE_ISA) {
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
return;
}
break;
case 0x3cd: /*Banking*/
if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) {
@@ -241,7 +286,11 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
return;
case 0x3cf:
if ((svga->gdcaddr & 15) == 6) {
if ((svga->gdcaddr & 15) == 5) {
svga->chain4 &= ~0x02;
if (val & 0x40)
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
} else if ((svga->gdcaddr & 15) == 6) {
if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) {
svga->write_bank = (dev->banking & 0x0f) * 0x10000;
svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000;
@@ -418,7 +467,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
break;
case 1:
case 2:
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
if ((et4000->kasan_cfg_index - 0xF0) <= 16)
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1];
io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
@@ -465,7 +515,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
case 4:
case 5:
if (et4000->kasan_cfg_regs[0] & 1) {
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4)
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
}
break;
case 6:
@@ -607,6 +658,19 @@ et4000_recalctimings(svga_t *svga)
}
}
}
if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) {
svga->ma_latch <<= (1 << 0);
svga->rowoffset <<= (1 << 0);
svga->render = svga_render_8bpp_highres;
}
if (dev->type == ET4000_TYPE_TC6058AF) {
if (svga->render == svga_render_8bpp_lowres)
svga->render = svga_render_8bpp_tseng_lowres;
else if (svga->render == svga_render_8bpp_highres)
svga->render = svga_render_8bpp_tseng_highres;
}
}
static void
@@ -666,6 +730,7 @@ et4000_init(const device_t *info)
fn = BIOS_ROM_PATH;
switch (dev->type) {
case ET4000_TYPE_TC6058AF: /* ISA ET4000AX (TC6058AF) */
case ET4000_TYPE_ISA: /* ISA ET4000AX */
dev->vram_size = device_get_config_int("memory") << 10;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa);
@@ -674,6 +739,8 @@ et4000_init(const device_t *info)
NULL, NULL);
io_sethandler(0x03c0, 32,
et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev);
if (dev->type == ET4000_TYPE_TC6058AF)
fn = TC6058AF_BIOS_ROM_PATH;
break;
case ET4000_TYPE_MCA: /* MCA ET4000AX */
@@ -750,7 +817,8 @@ et4000_init(const device_t *info)
break;
}
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
if (dev->type >= ET4000_TYPE_ISA)
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
dev->vram_mask = dev->vram_size - 1;
@@ -790,6 +858,12 @@ et4000_force_redraw(void *priv)
dev->svga.fullchange = changeframecount;
}
static int
et4000_tc6058af_available(void)
{
return rom_present(TC6058AF_BIOS_ROM_PATH);
}
static int
et4000_available(void)
{
@@ -808,6 +882,33 @@ et4000_kasan_available(void)
return rom_present(KASAN_BIOS_ROM_PATH) && rom_present(KASAN_FONT_ROM_PATH);
}
static const device_config_t et4000_tc6058af_config[] = {
// clang-format off
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_int = 512,
.selection = {
{
.description = "256 KB",
.value = 256
},
{
.description = "512 KB",
.value = 512
},
{
.description = ""
}
}
},
{
.type = CONFIG_END
}
// clang-format on
};
static const device_config_t et4000_config[] = {
// clang-format off
{
@@ -839,6 +940,20 @@ static const device_config_t et4000_config[] = {
// clang-format on
};
const device_t et4000_tc6058af_isa_device = {
.name = "Tseng Labs ET4000AX (TC6058AF) (ISA)",
.internal_name = "et4000ax_tc6058af",
.flags = DEVICE_ISA,
.local = 0,
.init = et4000_init,
.close = et4000_close,
.reset = NULL,
{ .available = et4000_tc6058af_available },
.speed_changed = et4000_speed_changed,
.force_redraw = et4000_force_redraw,
.config = et4000_tc6058af_config
};
const device_t et4000_isa_device = {
.name = "Tseng Labs ET4000AX (ISA)",
.internal_name = "et4000ax",