diff --git a/src/acpi.c b/src/acpi.c index 87bc58924..43529701c 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -216,7 +216,7 @@ acpi_reg_read_intel(int size, uint16_t addr, void *p) static uint32_t -acpi_reg_read_via(int size, uint16_t addr, void *p) +acpi_reg_read_via_common(int size, uint16_t addr, void *p) { acpi_t *dev = (acpi_t *) p; uint32_t ret = 0x00000000; @@ -279,6 +279,27 @@ acpi_reg_read_via(int size, uint16_t addr, void *p) /* GP Timer Reload Enable */ ret = (dev->regs.gptren >> shift32) & 0xff; break; + default: + ret = acpi_reg_read_common_regs(size, addr, p); + break; + } + + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + return ret; +} + + +static uint32_t +acpi_reg_read_via(int size, uint16_t addr, void *p) +{ + acpi_t *dev = (acpi_t *) p; + uint32_t ret = 0x00000000; + int shift16; + + addr &= 0xff; + shift16 = (addr & 1) << 3; + + switch (addr) { case 0x40: /* GPIO Direction Control */ if (size == 1) @@ -303,7 +324,41 @@ acpi_reg_read_via(int size, uint16_t addr, void *p) ret = (dev->regs.gpi_val >> shift16) & 0xff; break; default: - ret = acpi_reg_read_common_regs(size, addr, p); + ret = acpi_reg_read_via_common(size, addr, p); + break; + } + + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + return ret; +} + + +static uint32_t +acpi_reg_read_via_596b(int size, uint16_t addr, void *p) +{ + acpi_t *dev = (acpi_t *) p; + uint32_t ret = 0x00000000; + int shift16, shift32; + + addr &= 0x7f; + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x44: case 0x45: + /* External SMI Input Value */ + ret = (dev->regs.extsmi_val >> shift16) & 0xff; + break; + case 0x48: case 0x49: case 0x4a: case 0x4b: + /* GPI Port Input Value */ + ret = (dev->regs.gpi_val >> shift32) & 0xff; + break; + case 0x4c: case 0x4d: case 0x4e: case 0x4f: + /* GPO Port Output Value */ + ret = (dev->regs.gpi_val >> shift32) & 0xff; + break; + default: + ret = acpi_reg_read_via_common(size, addr, p); break; } @@ -492,7 +547,7 @@ acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p) static void -acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p) { acpi_t *dev = (acpi_t *) p; int shift16, shift32; @@ -569,6 +624,32 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) /* GP Timer Reload Enable */ dev->regs.gptren = ((dev->regs.gptren & ~(0xff << shift32)) | (val << shift32)) & 0x000000d9; break; + default: + acpi_reg_write_common_regs(size, addr, val, p); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.glbctl &= ~0x0002; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.glbsts |= 0x20; + if (dev->regs.glben & 0x20) + acpi_raise_smi(dev); + } + break; + } +} + + +static void +acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + int shift16; + + addr &= 0xff; + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); + shift16 = (addr & 1) << 3; + + switch (addr) { case 0x40: /* GPIO Direction Control */ if (size == 1) @@ -584,15 +665,29 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift16)) | (val << shift16)) & 0xffff; break; default: - acpi_reg_write_common_regs(size, addr, val, p); - /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ - if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) - dev->regs.glbctl &= ~0x0002; - else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { - dev->regs.glbsts |= 0x20; - if (dev->regs.glben & 0x20) - acpi_raise_smi(dev); - } + acpi_reg_write_via_common(size, addr, val, p); + break; + } +} + + +static void +acpi_reg_write_via_596b(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + int shift32; + + addr &= 0x7f; + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x4c: case 0x4d: case 0x4e: case 0x4f: + /* GPO Port Output Value */ + dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift32)) | (val << shift32)) & 0x7fffffff; + break; + default: + acpi_reg_write_via_common(size, addr, val, p); break; } } @@ -672,6 +767,8 @@ acpi_reg_read_common(int size, uint16_t addr, void *p) if (dev->vendor == VEN_VIA) ret = acpi_reg_read_via(size, addr, p); + else if (dev->vendor == VEN_VIA_596B) + ret = acpi_reg_read_via_596b(size, addr, p); else if (dev->vendor == VEN_INTEL) ret = acpi_reg_read_intel(size, addr, p); else if (dev->vendor == VEN_SMC) @@ -688,6 +785,8 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) if (dev->vendor == VEN_VIA) acpi_reg_write_via(size, addr, val, p); + else if (dev->vendor == VEN_VIA_596B) + acpi_reg_write_via_596b(size, addr, val, p); else if (dev->vendor == VEN_INTEL) acpi_reg_write_intel(size, addr, val, p); else if (dev->vendor == VEN_SMC) @@ -853,7 +952,23 @@ acpi_aux_reg_write(uint16_t addr, uint8_t val, void *p) void acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) { - int size = (dev->vendor == VEN_SMC) ? 0x10 : 0x40; + int size; + + switch (dev->vendor) { + case VEN_INTEL: + default: + size = 0x040; + break; + case VEN_SMC: + size = 0x010; + break; + case VEN_VIA: + size = 0x100; + break; + case VEN_VIA_596B: + size = 0x080; + break; + } if (dev->io_base != 0x0000) { io_removehandler(dev->io_base, size, @@ -1022,6 +1137,8 @@ acpi_reset(void *priv) dev->regs.gpireg[0] = dev->regs.gpireg[1] = dev->regs.gpireg[2] = 0xff; for (i = 0; i < 4; i++) dev->regs.gporeg[i] = dev->gporeg_default[i]; + if (dev->vendor == VEN_VIA_596B) + dev->regs.gpo_val = 0x7fffffff; } @@ -1067,7 +1184,7 @@ acpi_init(const device_t *info) timer_add(&dev->timer, acpi_timer_count, dev, 0); timer_set_delay_u64(&dev->timer, ACPICONST); - dev->regs.gpireg[0] = dev->regs.gpireg[1] = dev->regs.gpireg[2] = 0xff; + acpi_reset(dev); return dev; } @@ -1103,6 +1220,21 @@ const device_t acpi_via_device = }; +const device_t acpi_via_596b_device = +{ + "VIA ACPI (VT82C596B)", + DEVICE_PCI, + VEN_VIA_596B, + acpi_init, + acpi_close, + acpi_reset, + NULL, + acpi_speed_changed, + NULL, + NULL +}; + + const device_t acpi_smc_device = { "SMC FDC73C931APM ACPI", diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index 3f9ea76e3..affc34264 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -42,30 +42,32 @@ extern "C" { #define ACPI_ENABLE 0xf1 #define ACPI_DISABLE 0xf0 -#define VEN_INTEL 0x8086 -#define VEN_SMC 0x1055 -#define VEN_VIA 0x1106 +#define VEN_INTEL 0x08086 +#define VEN_SMC 0x01055 +#define VEN_VIA 0x01106 +#define VEN_VIA_596B 0x11106 typedef struct { uint8_t plvl2, plvl3, smicmd, gpio_dir, - gpio_val, extsmi_val, + gpio_val, pad, timer32, gpireg[3], gporeg[4]; uint16_t pmsts, pmen, pmcntrl, gpsts, gpen, gpscien, gpsmien, pscntrl, - gpo_val, gpi_val, gpscists; int smi_lock, smi_active; uint32_t pcntrl, glbsts, devsts, glben, glbctl, devctl, padsts, paden, - gptren, timer_val; + gptren, timer_val, + gpo_val, gpi_val, + extsmi_val, pad0; uint64_t tmr_overflow_time; } acpi_regs_t; @@ -88,6 +90,7 @@ typedef struct extern const device_t acpi_intel_device; extern const device_t acpi_smc_device; extern const device_t acpi_via_device; +extern const device_t acpi_via_596b_device; /* Functions. */ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 98b734b0e..805960295 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -374,6 +374,7 @@ extern int machine_at_i430vx_init(const machine_t *); extern int machine_at_brio80xx_init(const machine_t *); extern int machine_at_8500tvxa_init(const machine_t *); extern int machine_at_presario4500_init(const machine_t *); +extern int machine_at_gw2kte_init(const machine_t *); extern int machine_at_pb680_init(const machine_t *); extern int machine_at_nupro592_init(const machine_t *); @@ -387,6 +388,7 @@ extern int machine_at_ficva502_init(const machine_t *); extern int machine_at_ficpa2012_init(const machine_t *); #ifdef EMU_DEVICE_H +extern const device_t *at_thor_get_device(void); extern const device_t *at_pb640_get_device(void); #endif @@ -460,6 +462,9 @@ extern const device_t europc_device; /* m_oivetti_m24.c */ extern int machine_olim24_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern const device_t *m24_get_device(void); +#endif /* m_pcjr.c */ extern int machine_pcjr_init(const machine_t *); @@ -504,6 +509,7 @@ extern int machine_tandy1000sl2_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *tandy1k_get_device(void); extern const device_t *tandy1k_hx_get_device(void); +extern const device_t *tandy1k_sl_get_device(void); #endif /* m_xt.c */ @@ -529,7 +535,8 @@ extern int machine_xt_hed919_init(const machine_t *); #endif /* m_xt_compaq.c */ -extern int machine_xt_compaq_init(const machine_t *); +extern int machine_xt_compaq_deskpro_init(const machine_t *); +extern int machine_xt_compaq_portable_init(const machine_t *); /* m_xt_laserxt.c */ #if defined(DEV_BRANCH) && defined(USE_LASERXT) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 597fcc5ea..9499823a6 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -312,6 +312,8 @@ extern const device_t s3_phoenix_trio32_pci_device; extern const device_t s3_phoenix_trio64_vlb_device; extern const device_t s3_phoenix_trio64_onboard_pci_device; extern const device_t s3_phoenix_trio64_pci_device; +extern const device_t s3_phoenix_trio64vplus_vlb_device; +extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_vision864_pci_device; extern const device_t s3_phoenix_vision864_vlb_device; extern const device_t s3_diamond_stealth64_pci_device; @@ -329,7 +331,9 @@ extern const device_t s3_virge_375_vlb_device; extern const device_t s3_virge_375_pci_device; extern const device_t s3_virge_375_4_vlb_device; extern const device_t s3_virge_375_4_pci_device; +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) extern const device_t s3_trio3d_2x_pci_device; +#endif /* Sigma Color 400 */ extern const device_t sigma_device; @@ -345,6 +349,7 @@ extern const device_t ibm_ps1_2121_device; /* Trident TVGA 8900 */ extern const device_t tvga8900b_device; extern const device_t tvga8900d_device; +extern const device_t tvga9000b_device; /* IBM VGA */ extern const device_t vga_device; diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c index 3ab2d8649..16144bc75 100644 --- a/src/machine/m_at_socket7_s7.c +++ b/src/machine/m_at_socket7_s7.c @@ -753,6 +753,40 @@ machine_at_pb680_init(const machine_t *model) } +int +machine_at_gw2kte_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined2(L"roms/machines/gw2kte/1008CY1T.BIO", + L"roms/machines/gw2kte/1008CY1T.BI1", + L"roms/machines/gw2kte/1008CY1T.BI2", + L"roms/machines/gw2kte/1008CY1T.BI3", + L"roms/machines/gw2kte/1008CY1T.RCV", + 0x3a000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + int machine_at_nupro592_init(const machine_t *model) { diff --git a/src/machine/m_olivetti_m24.c b/src/machine/m_olivetti_m24.c index 8d8c94229..c01363167 100644 --- a/src/machine/m_olivetti_m24.c +++ b/src/machine/m_olivetti_m24.c @@ -818,6 +818,12 @@ const device_t m24_device = { NULL }; +const device_t * +m24_get_device(void) +{ + return &m24_device; +} + static void kbd_reset(void *priv) diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 26777dc77..44fc7f533 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1192,6 +1192,12 @@ tandy1k_hx_get_device(void) return &vid_device_hx; } +const device_t * +tandy1k_sl_get_device(void) +{ + return &vid_device_sl; +} + static void eep_write(uint16_t addr, uint8_t val, void *priv) diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index 1b84a10de..da41a4a41 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -37,9 +37,37 @@ #include <86box/lpt.h> #include <86box/machine.h> +int +machine_xt_compaq_deskpro_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/deskpro/Compaq - BIOS - Revision J - 106265-002.bin", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + machine_common_init(model); + + pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + + device_add(&keyboard_xt_compaq_device); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + nmi_init(); + if (joystick_type != JOYSTICK_TYPE_NONE) + device_add(&gameport_device); + + lpt1_remove(); + lpt1_init(0x03bc); + + return ret; +} + int -machine_xt_compaq_init(const machine_t *model) +machine_xt_compaq_portable_init(const machine_t *model) { int ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 4b79b23a2..5ea37c5f3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -97,7 +97,7 @@ const machine_t machines[] = { { "[8088] AMI XT clone", "amixt", MACHINE_TYPE_8088, {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, { "[8088] Tandy 1000", "tandy", MACHINE_TYPE_8088, {{"Intel", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_tandy_init, tandy1k_get_device }, { "[8088] Tandy 1000 HX", "tandy1000hx", MACHINE_TYPE_8088, {{"Intel", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 256, 640, 128, 0, machine_tandy1000hx_init, tandy1k_hx_get_device }, - { "[8088] Compaq Portable", "portable", MACHINE_TYPE_8088, {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL }, + { "[8088] Compaq Portable", "portable", MACHINE_TYPE_8088, {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 128, 640, 128, 0, machine_xt_compaq_portable_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_genxt_init, NULL }, { "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, @@ -118,9 +118,10 @@ const machine_t machines[] = { { "[8086] Amstrad PC3086", "pc3086", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 640, 640, 0, 63, machine_pc3086_init, pc3086_get_device }, { "[8086] Amstrad PC20(0)", "pc200", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_pc200_init, pc200_get_device }, { "[8086] Amstrad PPC512/640", "ppc512", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_ppc512_init, ppc512_get_device }, - { "[8086] Olivetti M24", "olivetti_m24", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL }, + { "[8086] Compaq Deskpro", "deskpro", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 128, 640, 128, 0, machine_xt_compaq_deskpro_init, NULL }, + { "[8086] Olivetti M24", "olivetti_m24", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, m24_get_device }, { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, - { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, NULL }, + { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, { "[8086] Toshiba T1200", "t1200", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) { "[8086] VTech Laser XT3", "lxt3", MACHINE_TYPE_8086, {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 256, 640, 256, 0, machine_xt_lxt3_init, NULL }, @@ -284,8 +285,8 @@ const machine_t machines[] = { /* 430FX */ { "[i430FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, { "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", "mr586", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_PS2, 8, 128, 8, 127, machine_at_mr586_init, NULL }, - { "[i430FX] Gateway 2000 P5-xxx", "gw2katx", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_gw2katx_init, NULL }, - { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, + { "[i430FX] Gateway 2000 Thor", "gw2katx", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_gw2katx_init, NULL }, + { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_thor_init, NULL }, { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL }, { "[i430FX] Intel Advanced/EV", "endeavor", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, { "[i430FX] Packard Bell PB640", "pb640", MACHINE_TYPE_SOCKET7_3V, MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, at_pb640_get_device }, @@ -312,6 +313,7 @@ const machine_t machines[] = { { "[i430VX] HP Brio 80xx", "brio80xx", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_brio80xx_init, NULL }, { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_8500tvxa_init, NULL }, { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_presario4500_init, NULL }, + { "[i430VX] Gateway 2000 Tigereye", "gw2kte", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_gw2kte_init, NULL }, { "[i430VX] Packard Bell PB680", "pb680", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_pb680_init, NULL }, /* 430TX */ diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 74222d5c8..780d1559d 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -537,7 +537,12 @@ ega_poll(void *p) ega->vc++; ega->vc &= 1023; if (ega->vc == ega->split) { - ega->ma = ega->maback = 0; + if (ega->interlace && ega->oddeven) + ega->ma = ega->maback = ega->ma_latch + (ega->rowoffset << 1); + else + ega->ma = ega->maback = ega->ma_latch; + ega->ma <<= 2; + ega->maback <<= 2; ega->sc = 0; if (ega->attrregs[0x10] & 0x20) { ega->scrollcache = 0; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 1bdbeff18..f328361fb 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -47,6 +47,7 @@ #define ROM_PHOENIX_TRIO64 L"roms/video/s3/86c764x1.bin" #define ROM_DIAMOND_STEALTH64_764 L"roms/video/s3/stealt64.bin" #define ROM_TRIO64V2_DX_VBE20 L"roms/video/s3/86c775_2.bin" +#define ROM_PHOENIX_TRIO64VPLUS L"roms/video/s3/octekmirage64.vbi" enum { @@ -64,6 +65,7 @@ enum S3_METHEUS_86C928, S3_AMI_86C924, S3_TRIO64V2_DX, + S3_PHOENIX_TRIO64VPLUS }; @@ -78,6 +80,7 @@ enum S3_VISION864, S3_TRIO32 = 0x18, S3_TRIO64, + S3_TRIO64V, S3_TRIO64V2 }; @@ -403,6 +406,7 @@ s3_data_len(s3_t *s3) static uint16_t s3_accel_pix_trans_w(s3_t *s3, uint16_t port, uint16_t val) { + svga_t *svga = &s3->svga; int i, word = 0; int s3dl, bswap; @@ -456,6 +460,8 @@ s3_accel_pix_trans_w(s3_t *s3, uint16_t port, uint16_t val) /* Normal dword mode, do 1 dword blit if (port & 2). */ if (port & 2) s3_accel_start(32, 1, s3->accel.pix_trans.dw, 0, s3); + else if (svga->crtc[0x53] & 0x08) + s3_accel_start(32, 1, val | (val << 16), 0, s3); break; } } else { @@ -472,6 +478,8 @@ s3_accel_pix_trans_w(s3_t *s3, uint16_t port, uint16_t val) /* Normal dword mode, do 1 dword blit if (port & 2). */ if (port & 2) s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans.dw, s3); + else if (svga->crtc[0x53] & 0x08) + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); break; } } @@ -998,6 +1006,8 @@ s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { + svga_t *svga = &s3->svga; + if (s3->packed_mmio) { int addr_lo = addr & 1; switch (addr & 0xfffe) { @@ -1082,8 +1092,15 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) addr |= addr_lo; } - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { + if ((addr & 0xffff) < 0x8000) { + if (s3_cpu_src(s3)) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } + } else { switch (addr & 0xffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: @@ -1106,7 +1123,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x8505: s3->subsys_cntl = val; s3_update_irqs(s3); - break; + break; case 0x850c: s3->accel.advfunc_cntl = val; s3_updatemapping(s3); @@ -1115,26 +1132,47 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); break; } - } else - s3_accel_out_fifo(s3, addr & 0xffff, val); - } else { - if (s3_cpu_src(s3)) { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } + } else { + if (addr & 0x8000) { + s3_accel_out_fifo(s3, addr & 0xffff, val); + } else { + if (s3_cpu_src(s3)) { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } + } } } static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) -{ - if (addr & 0x8000) { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } else if (s3_cpu_src(s3)) - (void) s3_accel_pix_trans_w(s3, addr & 0xfffe, val); +{ + svga_t *svga = &s3->svga; + + if (svga->crtc[0x53] & 0x08) { + if ((addr & 0xfffe) < 0x8000) { + if (s3_cpu_src(s3)) { + (void) s3_accel_pix_trans_w(s3, addr & 0xfffe, val); + } + } else { + switch (addr & 0xfffe) { + case 0x83d4: + default: + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + break; + } + } + } else { + if (addr & 0x8000) { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } else if (s3_cpu_src(s3)) + (void) s3_accel_pix_trans_w(s3, addr & 0xfffe, val); + } } @@ -1143,8 +1181,12 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { svga_t *svga = &s3->svga; - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { + if ((addr & 0xfffc) < 0x8000) { + if (s3_cpu_src(s3)) { + (void) s3_accel_pix_trans_l(s3, addr & 0xfffc, val); + } + } else { switch (addr & 0xfffc) { case 0x8180: s3->streams.pri_ctrl = val; @@ -1261,21 +1303,34 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) svga->fullchange = changeframecount; break; + case 0x8504: + s3->subsys_stat &= ~(val & 0xff); + s3->subsys_cntl = (val >> 8); + s3_update_irqs(s3); + break; + + case 0x850c: + s3->accel.advfunc_cntl = val & 0xff; + s3_updatemapping(s3); + break; + default: s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); s3_accel_write_fifo(s3, addr + 2, val >> 16); s3_accel_write_fifo(s3, addr + 3, val >> 24); break; - } - } else { + } + } + } else { + if (addr & 0x8000) { s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); s3_accel_write_fifo(s3, addr + 2, val >> 16); s3_accel_write_fifo(s3, addr + 3, val >> 24); - } - } else if (s3_cpu_src(s3)) - (void) s3_accel_pix_trans_l(s3, addr & 0xfffc, val); + } else if (s3_cpu_src(s3)) + (void) s3_accel_pix_trans_l(s3, addr & 0xfffc, val); + } } static void @@ -1798,7 +1853,7 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V2) + if (s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V) { io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1844,7 +1899,7 @@ s3_io_set(s3_t *s3) io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V2) + if (s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V) { io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1903,15 +1958,24 @@ s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) + if (s3->chip >= S3_TRIO64V) { + if (svga->seqaddr >= 0x10) { - case 0x12: case 0x13: + svga->seqregs[svga->seqaddr & 0x1f]=val; svga_recalctimings(svga); return; } + } else { + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) + { + case 0x12: case 0x13: + svga_recalctimings(svga); + return; + } + } } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ { @@ -2170,8 +2234,17 @@ s3_in(uint16_t addr, void *p) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; + if (s3->chip >= S3_TRIO64V) { + if (svga->seqaddr >= 8) + return svga->seqregs[svga->seqaddr & 0x1f]; + else if (svga->seqaddr <= 4) + return svga_in(addr, svga); + else + return 0xff; + } else { + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + return svga->seqregs[svga->seqaddr]; + } break; case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: @@ -2196,7 +2269,7 @@ s3_in(uint16_t addr, void *p) { case 0x2d: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; /*Extended chip ID*/ case 0x2e: return s3->id_ext; /*New chip ID*/ - case 0x2f: return 0; /*Revision level*/ + case 0x2f: return (s3->chip == S3_TRIO64V) ? 0x40 : 0; /*Revision level*/ case 0x30: return s3->id; /*Chip ID*/ case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); @@ -2213,8 +2286,8 @@ s3_in(uint16_t addr, void *p) case 0x6a: return s3->bank; /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ - case 0x6b: return svga->crtc[0x59]; - case 0x6c: return svga->crtc[0x5a] & 0x80; + case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; + case 0x6c: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); } return svga->crtc[svga->crtcreg]; } @@ -2319,6 +2392,14 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->interlace = svga->crtc[0x42] & 0x20; svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock(clk_sel, svga->clock_gen); + + if (s3->chip == S3_TRIO64V) { + switch (svga->crtc[0x67] >> 4) { + case 3: case 5: case 7: + svga->clock /= 2; + break; + } + } if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { @@ -2349,7 +2430,8 @@ static void s3_trio64v_recalctimings(svga_t *svga) break; } } - svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : s3->vram_mask; + if (s3->chip == S3_TRIO64V2) + svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : s3->vram_mask; } else /*Streams mode*/ { @@ -2395,7 +2477,9 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; break; } - svga->vram_display_mask = s3->vram_mask; + + if (s3->chip == S3_TRIO64V2) + svga->vram_display_mask = s3->vram_mask; } } @@ -2453,8 +2537,7 @@ s3_updatemapping(s3_t *s3) if ((svga->crtc[0x58] & 0x10) || (s3->accel.advfunc_cntl & 0x10)) { /*Linear framebuffer*/ - if (s3->chip != S3_TRIO64V2) - mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&svga->mapping); switch (svga->crtc[0x58] & 3) { @@ -2470,6 +2553,7 @@ s3_updatemapping(s3_t *s3) case 3: /*8mb*/ switch (s3->chip) { /* Not on video cards that don't support 4MB*/ case S3_TRIO64: + case S3_TRIO64V: case S3_TRIO64V2: case S3_86C928: s3->linear_size = 0x400000; @@ -2484,12 +2568,10 @@ s3_updatemapping(s3_t *s3) s3->linear_base &= ~(s3->linear_size - 1); if (s3->linear_base == 0xa0000) { mem_mapping_disable(&s3->linear_mapping); - if (!(svga->crtc[0x53] & 0x10) && (s3->chip != S3_TRIO64V2)) + if (!(svga->crtc[0x53] & 0x10)) { mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; - } else if (s3->chip == S3_TRIO64V2) { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); } } else { mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); @@ -2500,23 +2582,20 @@ s3_updatemapping(s3_t *s3) /* Memory mapped I/O. */ if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { - if (s3->chip != S3_TRIO64V2) { - mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&svga->mapping); + if (svga->crtc[0x53] & 0x20) + mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); + else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); - } else { - if (svga->crtc[0x53] & 0x20) - mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); - else - mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); - } } else { mem_mapping_disable(&s3->mmio_mapping); } /* New MMIO. */ - if (svga->crtc[0x53] & 0x08) + if (svga->crtc[0x53] & 0x08) { + mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); - else + } else mem_mapping_disable(&s3->new_mmio_mapping); } } @@ -2543,7 +2622,8 @@ s3_enable_fifo(s3_t *s3) { svga_t *svga = &s3->svga; - if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V2) || + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || + (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964)) return 1; /* FIFO always enabled on these chips. */ @@ -2681,7 +2761,7 @@ s3_accel_in(uint16_t port, void *p) temp = 0; /* FIFO empty */ if (!s3->blitter_busy) wake_fifo_thread(s3); - if (FIFO_FULL && (s3->chip >= S3_VISION864)) + if (FIFO_FULL && (s3->chip >= S3_VISION964)) temp = 0xff; /*FIFO full*/ return temp; /*FIFO empty*/ case 0x9949: case 0x9ae9: @@ -2698,7 +2778,7 @@ s3_accel_in(uint16_t port, void *p) temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } - if (FIFO_FULL && s3->chip >= S3_VISION864) + if (FIFO_FULL && s3->chip >= S3_VISION964) temp |= 0xf8; /*FIFO full*/ } else { if (s3->busy || s3->force_busy) { @@ -2966,49 +3046,47 @@ static uint8_t s3_accel_read(uint32_t addr, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint8_t temp = 0x00; if (!s3->enable_8514) return 0xff; - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { - switch (addr & 0xffff) { - case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: - case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: - case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: - case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: - case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: - case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: - case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: - case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: - case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: - case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: - case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: - case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - temp = s3_in(addr & 0x3ff, s3); - break; - case 0x8504: - temp = s3->subsys_stat; - break; - case 0x8505: - temp = s3->subsys_cntl; - break; - default: - temp = s3_accel_in(addr & 0xffff, s3); - break; - } - } else { - temp = s3_accel_in(addr & 0xffff, s3); + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0xffff) { + case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: + case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: + case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: + case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf: + case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3: + case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7: + case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb: + case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf: + case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3: + case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: + case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: + case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: + return s3_in(addr & 0x3ff, s3); + case 0x8504: + return s3->subsys_stat; + case 0x8505: + return s3->subsys_cntl;; + default: + return s3_accel_in(addr & 0xffff, s3); } - } else if (s3_cpu_dest(s3)) { - temp = s3->accel.pix_trans.b[addr & 3]; + return 0xff; + } else { + if (addr & 0x8000) { + temp = s3_accel_in(addr & 0xffff, s3); + } else if (s3_cpu_dest(s3)) { + temp = s3->accel.pix_trans.b[addr & 3]; - if (s3->accel.cmd & 0x100) { + if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - s3_accel_start(8, 1, 0xffffffff, 0, s3); + s3_accel_start(8, 1, 0xffffffff, 0, s3); else - s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + s3_accel_start(1, 1, 0xffffffff, 0xffffffff, s3); + } } } @@ -3019,16 +3097,26 @@ static uint16_t s3_accel_read_w(uint32_t addr, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint16_t temp = 0x0000; if (!s3->enable_8514) return 0xffff; - - if (addr & 0x8000) { - temp = s3_accel_read((addr & 0xfffe), p); - temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; - } else if (s3_cpu_dest(s3)) - temp = s3_accel_pix_trans_w(s3, (addr & 0xfffe), 0xffff); + + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0xfffe) { + default: + return s3_accel_read(addr, p) | + s3_accel_read(addr + 1, p) << 8; + } + return 0xffff; + } else { + if (addr & 0x8000) { + temp = s3_accel_read((addr & 0xfffe), p); + temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; + } else if (s3_cpu_dest(s3)) + temp = s3_accel_pix_trans_w(s3, (addr & 0xfffe), 0xffff); + } return temp; } @@ -3038,96 +3126,94 @@ static uint32_t s3_accel_read_l(uint32_t addr, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; if (!s3->enable_8514) return 0xffffffff; - if (addr & 0x8000) { - if (s3->chip == S3_TRIO64V2) { - switch (addr & 0xfffc) { - case 0x8180: - temp = s3->streams.pri_ctrl; - break; - case 0x8184: - temp = s3->streams.chroma_ctrl; - break; - case 0x8190: - temp = s3->streams.sec_ctrl; - break; - case 0x8194: - temp = s3->streams.chroma_upper_bound; - break; - case 0x8198: - temp = s3->streams.sec_filter; - break; - case 0x81a0: - temp = s3->streams.blend_ctrl; - break; - case 0x81c0: - temp = s3->streams.pri_fb0; - break; - case 0x81c4: - temp = s3->streams.pri_fb1; - break; - case 0x81c8: - temp = s3->streams.pri_stride; - break; - case 0x81cc: - temp = s3->streams.buffer_ctrl; - break; - case 0x81d0: - temp = s3->streams.sec_fb0; - break; - case 0x81d4: - temp = s3->streams.sec_fb1; - break; - case 0x81d8: - temp = s3->streams.sec_stride; - break; - case 0x81dc: - temp = s3->streams.overlay_ctrl; - break; - case 0x81e0: - temp = s3->streams.k1_vert_scale; - break; - case 0x81e4: - temp = s3->streams.k2_vert_scale; - break; - case 0x81e8: - temp = s3->streams.dda_vert_accumulator; - break; - case 0x81ec: - temp = s3->streams.fifo_ctrl; - break; - case 0x81f0: - temp = s3->streams.pri_start; - break; - case 0x81f4: - temp = s3->streams.pri_size; - break; - case 0x81f8: - temp = s3->streams.sec_start; - break; - case 0x81fc: - temp = s3->streams.sec_size; - break; - - default: - temp = s3_accel_read((addr & 0xfffc), p); - temp |= s3_accel_read((addr & 0xfffc) + 1, p) << 8; - temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16; - temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24; - break; - } - } else { - temp = s3_accel_read((addr & 0xfffc), p); - temp |= s3_accel_read((addr & 0xfffc) + 1, p) << 8; - temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16; - temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24; + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0xfffc) { + case 0x8180: + temp = s3->streams.pri_ctrl; + break; + case 0x8184: + temp = s3->streams.chroma_ctrl; + break; + case 0x8190: + temp = s3->streams.sec_ctrl; + break; + case 0x8194: + temp = s3->streams.chroma_upper_bound; + break; + case 0x8198: + temp = s3->streams.sec_filter; + break; + case 0x81a0: + temp = s3->streams.blend_ctrl; + break; + case 0x81c0: + temp = s3->streams.pri_fb0; + break; + case 0x81c4: + temp = s3->streams.pri_fb1; + break; + case 0x81c8: + temp = s3->streams.pri_stride; + break; + case 0x81cc: + temp = s3->streams.buffer_ctrl; + break; + case 0x81d0: + temp = s3->streams.sec_fb0; + break; + case 0x81d4: + temp = s3->streams.sec_fb1; + break; + case 0x81d8: + temp = s3->streams.sec_stride; + break; + case 0x81dc: + temp = s3->streams.overlay_ctrl; + break; + case 0x81e0: + temp = s3->streams.k1_vert_scale; + break; + case 0x81e4: + temp = s3->streams.k2_vert_scale; + break; + case 0x81e8: + temp = s3->streams.dda_vert_accumulator; + break; + case 0x81ec: + temp = s3->streams.fifo_ctrl; + break; + case 0x81f0: + temp = s3->streams.pri_start; + break; + case 0x81f4: + temp = s3->streams.pri_size; + break; + case 0x81f8: + temp = s3->streams.sec_start; + break; + case 0x81fc: + temp = s3->streams.sec_size; + break; + + default: + temp = s3_accel_read_w(addr, p) | (s3_accel_read_w(addr + 2, p) << 16); + break; } - } else if (s3_cpu_dest(s3)) - temp = s3_accel_pix_trans_l(s3, (addr & 0xfffc), 0xffffffff); + } else { + if (addr & 0x8000) { + temp = s3_accel_read((addr & 0xfffc), p); + temp |= s3_accel_read((addr & 0xfffc) + 1, p) << 8; + temp |= s3_accel_read((addr & 0xfffc) + 2, p) << 16; + temp |= s3_accel_read((addr & 0xfffc) + 3, p) << 24; + } else if (s3_cpu_dest(s3)) + temp = s3_accel_pix_trans_l(s3, (addr & 0xfffc), 0xffffffff); + } return temp; } @@ -3245,12 +3331,33 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ uint32_t rd_mask = s3->accel.rd_mask; int cmd = s3->accel.cmd >> 13; int read = 0, byte_cnt = 0, i; + uint32_t srcbase, dstbase; - if ((s3->chip == S3_TRIO64 || s3->chip == S3_TRIO64V2) && (s3->accel.cmd & (1 << 11))) + if ((s3->chip >= S3_TRIO64) && (s3->accel.cmd & (1 << 11))) cmd |= 8; + // SRC-BASE/DST-BASE + if ((s3->accel.multifunc[0xd] >> 4) & 7) { + srcbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 4) & 3); + } else { + srcbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 2) & 3); + } + if ((s3->accel.multifunc[0xd] >> 0) & 7) { + dstbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 0) & 3); + } else { + dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3); + } + if (s3->bpp == 1) { + srcbase >>= 1; + dstbase >>= 1; + } else if (s3->bpp == 3) { + srcbase >>= 2; + dstbase >>= 2; + } + + if ((s3_cpu_src(s3) || s3_cpu_dest(s3))) { - if (s3->accel.pixtrans_failed) { + if (s3->accel.pixtrans_failed) { /*Some hack for some 911/924 driver*/ if (s3->busy) s3->busy = 0; if (cpu_input) @@ -3324,8 +3431,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { while (count-- && s3->accel.sy >= 0) { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -3374,7 +3481,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } else /*Bresenham*/ { - if (s3->accel.sy < 0 && cpu_input) { + if (s3->accel.sy < 0 && cpu_input && !(svga->crtc[0x53] & 0x08)) { s3->busy = 0; s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -3383,8 +3490,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ while (count-- && s3->accel.sy >= 0) { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -3466,7 +3573,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.cur_y; if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - s3->accel.dest = s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.cy * s3->width; if (s3_cpu_src(s3)) { return; /*Wait for data from CPU*/ @@ -3476,14 +3583,14 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + s3->accel.pix_trans.b[0] = 0xff; s3->accel.pix_trans.b[1] = 0xff; s3->accel.pix_trans.b[2] = 0xff; s3->accel.pix_trans.b[3] = 0xff; - - if ((s3->accel.sy < 0 && cpu_input)) { + + if ((s3->accel.sy < 0 && cpu_input) && !(svga->crtc[0x53] & 0x08)) { s3->busy = 0; s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -3494,8 +3601,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ while (count-- && s3->accel.sy >= 0) { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) mix_dat = mix_mask; /* Mix data = forced to foreground register. */ @@ -3570,7 +3677,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.cmd & 0x80) s3->accel.cy++; else s3->accel.cy--; - s3->accel.dest = s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.cy * s3->width; s3->accel.sy--; if (s3->accel.sy < 0) { @@ -3613,8 +3720,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.cur_y & 0xfff; if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; + s3->accel.src = srcbase + s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; } if ((s3->accel.cmd & 0x100) && !cpu_input) { @@ -3626,12 +3733,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7) - { while (1) { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && + (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { READ(s3->accel.src + s3->accel.cx, src_dat); READ(s3->accel.dest + s3->accel.dx, dest_dat); @@ -3653,8 +3759,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy++; s3->accel.dy++; - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; + s3->accel.src = srcbase + s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; s3->accel.sy--; @@ -3669,8 +3775,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { while (count-- && s3->accel.sy >= 0) { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && + (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { if (vram_mask) { @@ -3742,8 +3848,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dy--; } - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; + s3->accel.src = srcbase + s3->accel.cy * s3->width; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; s3->accel.sy--; @@ -3779,12 +3885,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ /*Align source with destination*/ s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; - s3->accel.dest = s3->accel.dy * s3->width; + s3->accel.dest = dstbase + s3->accel.dy * s3->width; s3->accel.cx = s3->accel.dx & 7; s3->accel.cy = s3->accel.dy & 7; - s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); + s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); } if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ @@ -3794,8 +3900,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ while (count-- && s3->accel.sy >= 0) { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && + (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { if (vram_mask) { @@ -3867,8 +3973,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dy--; } - s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); - s3->accel.dest = s3->accel.dy * s3->width; + s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); + s3->accel.dest = dstbase + s3->accel.dy * s3->width; s3->accel.sy--; @@ -3886,7 +3992,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64 && s3->chip != S3_TRIO64V2) + if (s3->chip != S3_TRIO64) break; polygon_setup(s3); @@ -3903,12 +4009,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ int y = s3->accel.poly_cy; int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; - s3->accel.dest = y * s3->width; + s3->accel.dest = dstbase + y * s3->width; while (x_count-- && count--) { - if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && - s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && + (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) { switch (frgd_mix) { @@ -3961,7 +4067,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64 && s3->chip != S3_TRIO64V2) + if (s3->chip != S3_TRIO64) break; polygon_setup(s3); @@ -3979,15 +4085,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ int y = s3->accel.poly_cy; int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; - s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width); - s3->accel.dest = y * s3->width; + s3->accel.src = srcbase + s3->accel.pattern + ((y & 7) * s3->width); + s3->accel.dest = dstbase + y * s3->width; while (x_count-- && count--) { int pat_x = s3->accel.poly_x & 7; - if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && - s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && + (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) { if (vram_mask) { READ(s3->accel.src + pat_x, mix_dat); @@ -4059,7 +4165,7 @@ s3_pci_read(int func, int addr, void *p) case 0x01: return 0x53; case 0x02: return s3->id_ext_pci; - case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; + case 0x03: return 0x88; case PCI_REG_COMMAND: return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ @@ -4086,7 +4192,7 @@ s3_pci_read(int func, int addr, void *p) case 0x11: return 0x00; case 0x12: return svga->crtc[0x5a] & 0x80; case 0x13: return svga->crtc[0x59]; - + case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ case 0x31: return 0x00; case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00; @@ -4118,6 +4224,7 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); s3_updatemapping(s3); break; + case 0x13: svga->crtc[0x59] = val; s3_updatemapping(s3); @@ -4144,6 +4251,103 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) } } +static uint8_t s3_trio64v_pci_read(int func, int addr, void *p) +{ + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + uint8_t ret = 0; + + switch (addr) { + case 0x00: ret = 0x33; break; /*'S3'*/ + case 0x01: ret = 0x53; break; + + case 0x02: ret = s3->id_ext_pci; break; + case 0x03: ret = s3->chip == S3_TRIO64V ? 0x88 : 0x89; break; + + case PCI_REG_COMMAND: ret = s3->pci_regs[PCI_REG_COMMAND] & 0x27; break; + + case 0x07: ret = s3->pci_regs[0x07] & 0x36; break; + + case 0x08: ret = (s3->chip == S3_TRIO64V) ? 0x40 : 0; break; /*Revision ID*/ + case 0x09: ret = 0; break; /*Programming interface*/ + + case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ + case 0x0b: ret = 0x03; break; + + case 0x0d: ret = s3->pci_regs[0x0d] & 0xf8; break; + + case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ + case 0x11: ret = 0x00; break; + case 0x12: ret = 0x00; break; + case 0x13: ret = svga->crtc[0x59] & 0xfc; break; + + case 0x30: ret = s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; break; /*BIOS ROM address*/ + case 0x31: ret = 0x00; break; + case 0x32: ret = s3->has_bios ? s3->pci_regs[0x32] : 0x00; break; + case 0x33: ret = s3->has_bios ? s3->pci_regs[0x33] : 0x00; break; + + case 0x3c: ret = s3->int_line; break; + + case 0x3d: ret = PCI_INTA; break; /*INTA*/ + + case 0x3e: ret = 0x04; break; + case 0x3f: ret = 0xff; break; + + } + return ret; +} + +static void s3_trio64v_pci_write(int func, int addr, uint8_t val, void *p) +{ + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + switch (addr) + { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x3d: case 0x3e: case 0x3f: + return; + + case PCI_REG_COMMAND: + if (val & PCI_COMMAND_IO) + s3_io_set(s3); + else + s3_io_remove(s3); + s3->pci_regs[PCI_REG_COMMAND] = val & 0x27; + s3_updatemapping(s3); + return; + case 0x07: + s3->pci_regs[0x07] = val & 0x3e; + return; + case 0x0d: + s3->pci_regs[0x0d] = val & 0xf8; + return; + + case 0x13: + svga->crtc[0x59] = val & 0xfc; + s3_updatemapping(s3); + return; + + case 0x30: case 0x32: case 0x33: + if (!s3->has_bios) + return; + s3->pci_regs[addr] = val; + if (s3->pci_regs[0x30] & 0x01) + { + uint32_t biosaddr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); + mem_mapping_set_addr(&s3->bios_rom.mapping, biosaddr, 0x8000); + } + else + { + mem_mapping_disable(&s3->bios_rom.mapping); + } + return; + case 0x3c: + s3->int_line = val; + return; + } +} + static int vram_sizes[] = { 7, /*512 kB*/ @@ -4243,6 +4447,14 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); break; + case S3_PHOENIX_TRIO64VPLUS: + bios_fn = ROM_PHOENIX_TRIO64VPLUS; + chip = S3_TRIO64V; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; case S3_DIAMOND_STEALTH64_764: bios_fn = ROM_DIAMOND_STEALTH64_764; chip = S3_TRIO64; @@ -4292,7 +4504,7 @@ static void *s3_init(const device_t *info) mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, - NULL, 0, &s3->svga); + NULL, MEM_MAPPING_EXTERNAL, &s3->svga); mem_mapping_add(&s3->mmio_mapping, 0, 0, s3_accel_read, s3_accel_read_w, s3_accel_read_l, s3_accel_write, s3_accel_write_w, s3_accel_write_l, @@ -4310,7 +4522,7 @@ static void *s3_init(const device_t *info) NULL, NULL); else { - if (chip == S3_TRIO64V2) { + if (chip == S3_TRIO64V2 || chip == S3_TRIO64V) { svga_init(info, &s3->svga, s3, vram_size, s3_trio64v_recalctimings, s3_in, s3_out, @@ -4377,10 +4589,22 @@ static void *s3_init(const device_t *info) s3_io_set(s3); - if (s3->pci) - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); - - s3->pci_regs[0x04] = 7; + if (s3->pci) { + if (chip >= S3_TRIO64V) + s3->card = pci_add_card(PCI_ADD_VIDEO, s3_trio64v_pci_read, s3_trio64v_pci_write, s3); + else + s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); + } + if (chip >= S3_TRIO64V) { + s3->pci_regs[PCI_REG_COMMAND] = 3; + s3->pci_regs[0x05] = 0; + s3->pci_regs[0x06] = 0; + s3->pci_regs[0x3d] = 1; + s3->pci_regs[0x3e] = 4; + s3->pci_regs[0x3f] = 0xff; + } else { + s3->pci_regs[PCI_REG_COMMAND] = 7; + } s3->pci_regs[0x30] = 0x00; s3->pci_regs[0x32] = 0x0c; @@ -4483,7 +4707,7 @@ static void *s3_init(const device_t *info) case S3_DIAMOND_STEALTH64_964: svga->decode_mask = (8 << 20) - 1; - stepping = 0xd0; /*Vision964P*/ + stepping = 0xd0; /*Vision964*/ s3->id = stepping; s3->id_ext = s3->id_ext_pci = stepping; s3->packed_mmio = 1; @@ -4507,6 +4731,7 @@ static void *s3_init(const device_t *info) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: + case S3_PHOENIX_TRIO64VPLUS: case S3_DIAMOND_STEALTH64_764: if (device_get_config_int("memory") == 1) s3->svga.vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ @@ -4595,6 +4820,11 @@ static int s3_phoenix_trio64_available(void) return rom_present(ROM_PHOENIX_TRIO64); } +static int s3_phoenix_trio64vplus_available(void) +{ + return rom_present(ROM_PHOENIX_TRIO64VPLUS); +} + static int s3_diamond_stealth64_764_available(void) { return rom_present(ROM_DIAMOND_STEALTH64_764); @@ -4999,6 +5229,34 @@ const device_t s3_phoenix_trio64_pci_device = s3_config }; +const device_t s3_phoenix_trio64vplus_vlb_device = +{ + "Phoenix S3 Trio64V+ VLB", + DEVICE_VLB, + S3_PHOENIX_TRIO64VPLUS, + s3_init, + s3_close, + NULL, + s3_phoenix_trio64vplus_available, + s3_speed_changed, + s3_force_redraw, + s3_config +}; + +const device_t s3_phoenix_trio64vplus_pci_device = +{ + "Phoenix S3 Trio64V+ PCI", + DEVICE_PCI, + S3_PHOENIX_TRIO64VPLUS, + s3_init, + s3_close, + NULL, + s3_phoenix_trio64vplus_available, + s3_speed_changed, + s3_force_redraw, + s3_config +}; + const device_t s3_phoenix_vision864_vlb_device = { "Phoenix S3 Vision864 VLB", diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index e9a7f0945..b01d2e710 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -68,23 +68,29 @@ static int dither[4][4] = #define ROM_DIAMOND_STEALTH3D_3000 L"roms/video/s3virge/diamondstealth3000.vbi" #define ROM_VIRGE_DX L"roms/video/s3virge/86c375_1.bin" #define ROM_VIRGE_DX_VBE20 L"roms/video/s3virge/86c375_4.bin" +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) #define ROM_TRIO3D_2X L"roms/video/s3virge/TRIO3D2X_8mbsdr.VBI" +#endif enum { S3_DIAMOND_STEALTH3D_2000, S3_DIAMOND_STEALTH3D_3000, S3_VIRGE_DX, - S3_VIRGE_DX_VBE20, - S3_TRIO3D_2X + S3_VIRGE_DX_VBE20 +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + , S3_TRIO3D_2X +#endif }; enum { S3_VIRGE, S3_VIRGEVX, - S3_VIRGEDX, - S3_TRIO3D2X + S3_VIRGEDX +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + , S3_TRIO3D2X +#endif }; enum @@ -154,6 +160,7 @@ typedef struct virge_t uint8_t bank; uint8_t ma_ext; + uint8_t reg6b, lfb_bios; uint8_t virge_id, virge_id_high, virge_id_low, virge_rev; @@ -396,16 +403,12 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) - { - case 0x12: case 0x13: - svga_recalctimings(svga); - return; - } - } + if (svga->seqaddr >= 0x10) + { + svga->seqregs[svga->seqaddr & 0x1f]=val; + svga_recalctimings(svga); + return; + } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ { if (val & 8) @@ -422,7 +425,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); + val = (svga->crtc[7] & ~0x10) | (val & 0x10); if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) && (svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) && (svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48)) @@ -552,52 +555,63 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) { virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; + uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { - case 0x3c1: - if (svga->attraddr > 0x14) - return 0xff; - break; + case 0x3c1: + if (svga->attraddr > 0x14) + ret = 0xff; + else + ret = svga_in(addr, svga); + break; - case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; - break; + case 0x3c5: + if (svga->seqaddr >= 8) + ret = svga->seqregs[svga->seqaddr & 0x1f]; + else if (svga->seqaddr <= 4) + ret = svga_in(addr, svga); + else + ret = 0xff; + break; case 0x3D4: - return svga->crtcreg; + ret = svga->crtcreg; + break; case 0x3D5: switch (svga->crtcreg) { - case 0x2d: return virge->virge_id_high; /*Extended chip ID*/ - case 0x2e: return virge->virge_id_low; /*New chip ID*/ - case 0x2f: return virge->virge_rev; - case 0x30: return virge->virge_id; /*Chip ID*/ - case 0x31: return (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); - case 0x35: return (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); - case 0x45: virge->hwc_col_stack_pos = 0; break; - case 0x51: return (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); - case 0x69: return virge->ma_ext; - case 0x6a: return virge->bank; - case 0x6b: return svga->crtc[0x59] & 0xfc; - case 0x6c: return 0; + case 0x2d: ret = virge->virge_id_high; break; /*Extended chip ID*/ + case 0x2e: ret = virge->virge_id_low; break; /*New chip ID*/ + case 0x2f: ret = virge->virge_rev; break; + case 0x30: ret = virge->virge_id; break; /*Chip ID*/ + case 0x31: ret = (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); break; + case 0x35: ret = (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); break; + case 0x45: virge->hwc_col_stack_pos = 0; ret = svga->crtc[0x45]; break; + case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); break; + case 0x69: ret = virge->ma_ext; break; + case 0x6a: ret = virge->bank; break; + default: ret = svga->crtc[svga->crtcreg]; break; } - return svga->crtc[svga->crtcreg]; + break; + + default: + ret = svga_in(addr, svga); + break; } - return svga_in(addr, svga);; + return ret; } static void s3_virge_recalctimings(svga_t *svga) { virge_t *virge = (virge_t *)svga->p; - + svga->hdisp = svga->hdisp_old; - if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; + if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time += 0x100; svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); @@ -615,8 +629,10 @@ static void s3_virge_recalctimings(svga_t *svga) if (virge->chip == S3_VIRGEVX || virge->chip == S3_VIRGEDX) r &= 7; +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) else if (virge->chip == S3_TRIO3D2X) r &= 10; +#endif else r &= 3; @@ -641,21 +657,35 @@ static void s3_virge_recalctimings(svga_t *svga) break; case 15: svga->render = svga_render_15bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip != S3_TRIO3D2X) { +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + if (virge->chip != S3_VIRGEVX && virge->chip != S3_TRIO3D2X) +#else + if (virge->chip != S3_VIRGEVX) +#endif + { svga->htotal >>= 1; svga->hdisp >>= 1; } break; case 16: svga->render = svga_render_16bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip != S3_TRIO3D2X) { +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + if (virge->chip != S3_VIRGEVX && virge->chip != S3_TRIO3D2X) +#else + if (virge->chip != S3_VIRGEVX) +#endif + { svga->htotal >>= 1; svga->hdisp >>= 1; } break; - case 24: + case 24: svga->render = svga_render_24bpp_highres; +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) if (virge->chip != S3_VIRGEVX && virge->chip != S3_TRIO3D2X) +#else + if (virge->chip != S3_VIRGEVX) +#endif svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ break; case 32: @@ -728,8 +758,7 @@ static void s3_virge_updatemapping(virge_t *virge) s3_virge_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); /*Banked framebuffer*/ - switch (svga->gdcreg[6] & 0xc) /*VGA mapping*/ - { + switch (svga->gdcreg[6] & 0xc) { /*VGA mapping*/ case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; @@ -748,11 +777,10 @@ static void s3_virge_updatemapping(virge_t *virge) break; } - virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - s3_virge_log("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); - if ((svga->crtc[0x58] & 0x10) || (virge->advfunc_cntl & 0x10)) /*Linear framebuffer*/ - { + s3_virge_log("Linear framebuffer %02X, linear base = %08x\n", svga->crtc[0x58] & 0x10, virge->linear_base); + if ((svga->crtc[0x58] & 0x10) || (virge->advfunc_cntl & 0x10)) { /*Linear framebuffer*/ switch (svga->crtc[0x58] & 3) { case 0: /*64k*/ virge->linear_size = 0x10000; @@ -764,7 +792,11 @@ static void s3_virge_updatemapping(virge_t *virge) virge->linear_size = 0x200000; break; case 3: /*4mb*/ - if (virge->chip == S3_TRIO3D2X) +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + if (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) +#else + if (virge->chip == S3_VIRGEVX) +#endif virge->linear_size = 0x800000; else virge->linear_size = 0x400000; @@ -773,25 +805,19 @@ static void s3_virge_updatemapping(virge_t *virge) virge->linear_base &= ~(virge->linear_size - 1); s3_virge_log("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); if (virge->linear_base == 0xa0000) { + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); mem_mapping_disable(&virge->linear_mapping); - if (!(svga->crtc[0x53] & 0x10)) { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - } } else mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); svga->fb_only = 1; - } - else - { + } else { mem_mapping_disable(&virge->linear_mapping); svga->fb_only = 0; } - s3_virge_log("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); + s3_virge_log("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x28); /* Memory mapped I/O. */ - /* Old MMIO. */ if ((svga->crtc[0x53] & 0x10) || (virge->advfunc_cntl & 0x20)) { if (svga->crtc[0x53] & 0x20) @@ -829,23 +855,18 @@ static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) { virge_t *virge = (virge_t *)p; - uint8_t ret = 0x00; + uint8_t ret; switch (addr & 0xffff) { - case 0x8504: - ret = virge->subsys_cntl; - break; - case 0x8505: if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) ret = 0x10; else - ret = 0x30; - ret |= virge->subsys_stat; + ret = 0x10 | (1 << 5); if (!virge->virge_busy) wake_fifo_thread(virge); - break; + return ret; case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: @@ -859,177 +880,269 @@ s3_virge_mmio_read(uint32_t addr, void *p) case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7: case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: - ret = s3_virge_in(addr & 0x3ff, virge); - break; + return s3_virge_in(addr & 0x3ff, virge); } - return ret; + return 0xff; } static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p) { virge_t *virge = (virge_t *)p; - uint16_t ret = 0x0000; - - if (addr & 0x8000) - ret = s3_virge_mmio_read(addr & 0xfffe, virge) | - (s3_virge_mmio_read((addr & 0xfffe) + 1, virge) << 8); - return ret; + switch (addr & 0xfffe) { + default: + return s3_virge_mmio_read(addr, virge) | + (s3_virge_mmio_read(addr + 1, virge) << 8); + } + + return 0xffff; } + static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) { virge_t *virge = (virge_t *)p; - uint32_t ret = 0x00000000; - - if (addr & 0x8000) { - switch (addr & 0xfffc) { - case 0x8180: - ret = virge->streams.pri_ctrl; - break; - case 0x8184: - ret = virge->streams.chroma_ctrl; - break; - case 0x8190: - ret = virge->streams.sec_ctrl; - break; - case 0x8194: - ret = virge->streams.chroma_upper_bound; - break; - case 0x8198: - ret = virge->streams.sec_filter; - break; - case 0x81a0: - ret = virge->streams.blend_ctrl; - break; - case 0x81c0: - ret = virge->streams.pri_fb0; - break; - case 0x81c4: - ret = virge->streams.pri_fb1; - break; - case 0x81c8: - ret = virge->streams.pri_stride; - break; - case 0x81cc: - ret = virge->streams.buffer_ctrl; - break; - case 0x81d0: - ret = virge->streams.sec_fb0; - break; - case 0x81d4: - ret = virge->streams.sec_fb1; - break; - case 0x81d8: - ret = virge->streams.sec_stride; - break; - case 0x81dc: - ret = virge->streams.overlay_ctrl; - break; - case 0x81e0: - ret = virge->streams.k1_vert_scale; - break; - case 0x81e4: - ret = virge->streams.k2_vert_scale; - break; - case 0x81e8: - ret = virge->streams.dda_vert_accumulator; - break; - case 0x81ec: - ret = virge->streams.fifo_ctrl; - break; - case 0x81f0: - ret = virge->streams.pri_start; - break; - case 0x81f4: - ret = virge->streams.pri_size; - break; - case 0x81f8: - ret = virge->streams.sec_start; - break; - case 0x81fc: - ret = virge->streams.sec_size; - break; - - default: - ret = s3_virge_mmio_read(addr & 0xfffc, virge) | - (s3_virge_mmio_read((addr & 0xfffc) + 1, virge) << 8) | - (s3_virge_mmio_read((addr & 0xfffc) + 2, virge) << 16) | - (s3_virge_mmio_read((addr & 0xfffc) + 3, virge) << 24); - break; - } - } else if ((addr & 0xfffc) >= 0xa000) { - switch (addr & 0xfffc) { - case 0xa4d4: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.src_base; - break; - case 0xa4d8: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.dest_base; - break; - case 0xa4dc: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; - break; - case 0xa4e0: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; - break; - case 0xa4e4: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; - break; - case 0xa4e8: case 0xace8: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.mono_pat_0; - break; - case 0xa4ec: case 0xacec: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.mono_pat_1; - break; - case 0xa4f0: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.pat_bg_clr; - break; - case 0xa4f4: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.pat_fg_clr; - break; - case 0xa4f8: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.src_bg_clr; - break; - case 0xa4fc: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.src_fg_clr; - break; - case 0xa500: - s3_virge_wait_fifo_idle(virge); - ret = virge->s3d.cmd_set; - break; - case 0xa504: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; - break; - case 0xa508: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; - break; - case 0xa50c: - s3_virge_wait_fifo_idle(virge); - ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; - break; - } + uint32_t ret = 0xffffffff; + + switch (addr & 0xfffc) { + case 0x8180: + ret = virge->streams.pri_ctrl; + break; + case 0x8184: + ret = virge->streams.chroma_ctrl; + break; + case 0x8190: + ret = virge->streams.sec_ctrl; + break; + case 0x8194: + ret = virge->streams.chroma_upper_bound; + break; + case 0x8198: + ret = virge->streams.sec_filter; + break; + case 0x81a0: + ret = virge->streams.blend_ctrl; + break; + case 0x81c0: + ret = virge->streams.pri_fb0; + break; + case 0x81c4: + ret = virge->streams.pri_fb1; + break; + case 0x81c8: + ret = virge->streams.pri_stride; + break; + case 0x81cc: + ret = virge->streams.buffer_ctrl; + break; + case 0x81d0: + ret = virge->streams.sec_fb0; + break; + case 0x81d4: + ret = virge->streams.sec_fb1; + break; + case 0x81d8: + ret = virge->streams.sec_stride; + break; + case 0x81dc: + ret = virge->streams.overlay_ctrl; + break; + case 0x81e0: + ret = virge->streams.k1_vert_scale; + break; + case 0x81e4: + ret = virge->streams.k2_vert_scale; + break; + case 0x81e8: + ret = virge->streams.dda_vert_accumulator; + break; + case 0x81ec: + ret = virge->streams.fifo_ctrl; + break; + case 0x81f0: + ret = virge->streams.pri_start; + break; + case 0x81f4: + ret = virge->streams.pri_size; + break; + case 0x81f8: + ret = virge->streams.sec_start; + break; + case 0x81fc: + ret = virge->streams.sec_size; + break; + + case 0x8504: + if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) + ret = (0x10 << 8); + else + ret = (0x10 << 8) | (1 << 13); + ret |= virge->subsys_stat; + if (!virge->virge_busy) + wake_fifo_thread(virge); + break; + + case 0xa4d4: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.src_base; + break; + case 0xa4d8: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.dest_base; + break; + case 0xa4dc: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; + break; + case 0xa4e0: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; + break; + case 0xa4e4: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; + break; + case 0xa4e8: case 0xace8: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.mono_pat_0; + break; + case 0xa4ec: case 0xacec: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.mono_pat_1; + break; + case 0xa4f0: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.pat_bg_clr; + break; + case 0xa4f4: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.pat_fg_clr; + break; + case 0xa4f8: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.src_bg_clr; + break; + case 0xa4fc: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.src_fg_clr; + break; + case 0xa500: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.cmd_set; + break; + case 0xa504: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; + break; + case 0xa508: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; + break; + case 0xa50c: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; + break; + + default: + ret = s3_virge_mmio_read_w(addr, virge) | + (s3_virge_mmio_read_w(addr + 2, virge) << 16); + break; } + + s3_virge_log("MMIO ReadL addr = %04x, val = %08x\n", addr & 0xfffc, ret); return ret; } -static void -s3_virge_write_fifo(virge_t *virge, uint32_t addr, uint8_t val) + +static void fifo_thread(void *param) { - if ((addr & 0xffff) < 0x8000) { - s3_virge_bitblt(virge, 8, val); + virge_t *virge = (virge_t *)param; + + while (1) + { + thread_set_event(virge->fifo_not_full_event); + thread_wait_event(virge->wake_fifo_thread, -1); + thread_reset_event(virge->wake_fifo_thread); + virge->virge_busy = 1; + while (!FIFO_EMPTY) + { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + uint32_t addr, val; + fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK]; + addr = fifo->addr_type & FIFO_ADDR; + val = fifo->val; + + switch (fifo->addr_type & FIFO_TYPE) + { + case FIFO_WRITE_BYTE: + if ((addr & 0xfffc) < 0x8000) + s3_virge_bitblt(virge, 8, val); + break; + case FIFO_WRITE_WORD: + if ((addr & 0xfffc) < 0x8000) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); + else + s3_virge_bitblt(virge, 16, val); + } + break; + case FIFO_WRITE_DWORD: + if ((addr & 0xfffc) < 0x8000) + { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); + } + break; + } + + virge->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; + + if (FIFO_ENTRIES > 0xe000) + thread_set_event(virge->fifo_not_full_event); + + end_time = plat_timer_read(); + virge_time += end_time - start_time; + } + virge->virge_busy = 0; + virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP; + s3_virge_update_irqs(virge); + } +} + +static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) +{ + fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; + + if (FIFO_FULL) + { + thread_reset_event(virge->fifo_not_full_event); + if (FIFO_FULL) + { + thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } + + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; + + virge->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(virge); +} + +static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) +{ + virge_t *virge = (virge_t *)p; + s3_virge_log("MMIO WriteB addr = %04x, val = %02x\n", addr & 0xffff, val); + + if ((addr & 0xfffc) < 0x8000) { + s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE); } else { switch (addr & 0xffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: @@ -1046,44 +1159,43 @@ s3_virge_write_fifo(virge_t *virge, uint32_t addr, uint8_t val) case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: s3_virge_out(addr & 0x3ff, val, virge); break; - case 0x8504: - virge->subsys_stat &= ~val; - s3_virge_update_irqs(virge); - break; - case 0x8505: - virge->subsys_cntl = val; - s3_virge_update_irqs(virge); - break; - case 0x850c: - virge->advfunc_cntl = val; - s3_virge_updatemapping(virge); - break; } } } static void -s3_virge_write_fifo_w(virge_t *virge, uint32_t addr, uint16_t val) +s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) { - if ((addr & 0xfffe) < 0x8000) { - if (virge->s3d.cmd_set & CMD_SET_MS) { - s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); - } else { - s3_virge_bitblt(virge, 16, val); - } + virge_t *virge = (virge_t *)p; + s3_virge_log("MMIO WriteW addr = %04x, val = %04x\n", addr & 0xfffe, val); + if ((addr & 0xfffc) < 0x8000) { + s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD); } else { - s3_virge_mmio_write(addr & 0xfffe, val, virge); - s3_virge_mmio_write((addr & 0xfffe) + 1, val >> 8, virge); + if ((addr & 0xfffe) == 0x83d4) { + s3_virge_mmio_write(addr, val, virge); + s3_virge_mmio_write(addr + 1, val >> 8, virge); + } } } static void -s3_virge_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) +s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) { + virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; - if ((addr & 0xfffc) >= 0x8000 && (addr & 0xfffc) < 0xa000) { - switch (addr & 0xfffc) { + s3_virge_log("MMIO WriteL addr = %04x, val = %08x\n", addr & 0xfffc, val); + if ((addr & 0xfffc) < 0x8000) { + if ((addr & 0xe000) == 0) { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); + } else { + s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); + } + } else { + switch (addr & 0xfffc) { case 0x8180: virge->streams.pri_ctrl = val; svga_recalctimings(svga); @@ -1199,22 +1311,17 @@ s3_virge_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) svga->fullchange = changeframecount; break; - default: - s3_virge_mmio_write(addr & 0xfffc, val, virge); - s3_virge_mmio_write((addr & 0xfffc) + 1, val >> 8, virge); - s3_virge_mmio_write((addr & 0xfffc) + 2, val >> 16, virge); - s3_virge_mmio_write((addr & 0xfffc) + 3, val >> 24, virge); + case 0x8504: + virge->subsys_stat &= ~(val & 0xff); + virge->subsys_cntl = (val >> 8); + s3_virge_update_irqs(virge); break; - } - } else if ((addr & 0xfffc) < 0x8000) { - if (virge->s3d.cmd_set & CMD_SET_MS) { - s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); - } else { - s3_virge_bitblt(virge, 32, val); - } - } else if ((addr & 0xfffc) >= 0xa000) { - switch (addr & 0xfffc) - { + + case 0x850c: + virge->advfunc_cntl = val & 0xff; + s3_virge_updatemapping(virge); + break; + case 0xa000: case 0xa004: case 0xa008: case 0xa00c: case 0xa010: case 0xa014: case 0xa018: case 0xa01c: case 0xa020: case 0xa024: case 0xa028: case 0xa02c: @@ -1517,94 +1624,10 @@ s3_virge_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) if (virge->s3d_tri.cmd_set & CMD_SET_AE) queue_triangle(virge); break; - } + } } } -static void fifo_thread(void *param) -{ - virge_t *virge = (virge_t *)param; - - while (1) - { - thread_set_event(virge->fifo_not_full_event); - thread_wait_event(virge->wake_fifo_thread, -1); - thread_reset_event(virge->wake_fifo_thread); - virge->virge_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - s3_virge_write_fifo(virge, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - s3_virge_write_fifo_w(virge, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - s3_virge_write_fifo_l(virge, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - virge->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(virge->fifo_not_full_event); - - end_time = plat_timer_read(); - virge_time += end_time - start_time; - } - virge->virge_busy = 0; - virge->subsys_stat |= INT_FIFO_EMP; - s3_virge_update_irqs(virge); - } -} - -static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) -{ - fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; - - if (FIFO_FULL) - { - thread_reset_event(virge->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } - - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; - - virge->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(virge); -} - -static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - s3_virge_queue(virge, addr & 0xffff, val, FIFO_WRITE_BYTE); -} -static void -s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - s3_virge_queue(virge, addr & 0xffff, val, FIFO_WRITE_WORD); -} -static void -s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) -{ - virge_t *virge = (virge_t *)p; - s3_virge_queue(virge, addr & 0xffff, val, FIFO_WRITE_DWORD); -} - #define READ(addr, val) \ { \ switch (bpp) \ @@ -1698,14 +1721,14 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) svga_t *svga = &virge->svga; uint8_t *vram = virge->svga.vram; uint32_t mono_pattern[64]; - int count_mask = -1; + int count_mask; int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; - int bpp = -1; - int x_mul = -1; - int cpu_dat_shift = 0; - uint32_t *pattern_data = NULL; - uint32_t src_fg_clr = 0, src_bg_clr = 0; + int bpp; + int x_mul; + int cpu_dat_shift; + uint32_t *pattern_data; + uint32_t src_fg_clr, src_bg_clr; uint32_t src_addr; uint32_t dest_addr; uint32_t source = 0, dest = 0, pattern; @@ -1731,6 +1754,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) src_bg_clr = virge->s3d.src_bg_clr & 0xffff; break; case CMD_SET_FORMAT_24: + default: bpp = 2; x_mul = 3; cpu_dat_shift = 24; @@ -1751,6 +1775,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) count_mask = ~0xf; break; case CMD_SET_ITA_DWORD: + default: count_mask = ~0x1f; break; } @@ -1762,13 +1787,13 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) for (x = 0; x < 8; x++) { if (virge->s3d.mono_pat_0 & (1 << (x + y*8))) - mono_pattern[y*8 + x] = virge->s3d.pat_fg_clr; + mono_pattern[y*8 + (7 - x)] = virge->s3d.pat_fg_clr; else - mono_pattern[y*8 + x] = virge->s3d.pat_bg_clr; + mono_pattern[y*8 + (7 - x)] = virge->s3d.pat_bg_clr; if (virge->s3d.mono_pat_1 & (1 << (x + y*8))) - mono_pattern[(y+4)*8 + x] = virge->s3d.pat_fg_clr; + mono_pattern[(y+4)*8 + (7 - x)] = virge->s3d.pat_fg_clr; else - mono_pattern[(y+4)*8 + x] = virge->s3d.pat_bg_clr; + mono_pattern[(y+4)*8 + (7 - x)] = virge->s3d.pat_bg_clr; } } } @@ -1816,7 +1841,6 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) READ(src_addr, source); if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr) update = 0; - count--; break; case CMD_SET_IDS: if (virge->s3d.data_left_count) @@ -1880,9 +1904,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.w = virge->s3d.r_width; virge->s3d.src_y += y_inc; - virge->s3d.src_y &= 0x7ff; virge->s3d.dest_y += y_inc; - virge->s3d.dest_y &= 0x7ff; virge->s3d.h--; switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) @@ -1929,7 +1951,8 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) while (count && virge->s3d.h) { - dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + source = virge->s3d.pat_fg_clr; + dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); pattern = virge->s3d.pat_fg_clr; out = 0; update = 1; @@ -3050,25 +3073,41 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal; break; case (0 | 8): case (1 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#else + if (virge->chip == S3_VIRGEDX) +#endif tex_sample = tex_sample_persp_mipmap_375; else tex_sample = tex_sample_persp_mipmap; break; case (2 | 8): case (3 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#else + if (virge->chip == S3_VIRGEDX) +#endif tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; else tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; break; case (4 | 8): case (5 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#else + if (virge->chip == S3_VIRGEDX) +#endif tex_sample = tex_sample_persp_normal_375; else tex_sample = tex_sample_persp_normal; break; case (6 | 8): case (7 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) + if (virge->chip == S3_VIRGEDX || virge->chip == S3_TRIO3D2X) +#else + if (virge->chip == S3_VIRGEDX) +#endif tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; else tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; @@ -3496,45 +3535,46 @@ static uint8_t s3_virge_pci_read(int func, int addr, void *p) { virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; - switch (addr) - { - case 0x00: return 0x33; /*'S3'*/ - case 0x01: return 0x53; - - case 0x02: return virge->virge_id_low; - case 0x03: return virge->virge_id_high; + uint8_t ret = 0; - case PCI_REG_COMMAND: - return virge->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + switch (addr) { + case 0x00: ret = 0x33; break; /*'S3'*/ + case 0x01: ret = 0x53; break; - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ + case 0x02: ret = virge->virge_id_low; break; + case 0x03: ret = virge->virge_id_high; break; + + case PCI_REG_COMMAND: ret = virge->pci_regs[PCI_REG_COMMAND] & 0x27; break; + + case 0x07: ret = virge->pci_regs[0x07] & 0x36; break; - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ + case 0x08: ret = 0; break; /*Revision ID*/ + case 0x09: ret = 0; break; /*Programming interface*/ - case 0x0a: return 0x00; /*Supports VGA interface*/ - case 0x0b: return 0x03; + case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ + case 0x0b: ret = 0x03; break; - case 0x0d: return virge->pci_regs[0x0d] & 0xf8; + case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break; - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return 0x00; - case 0x13: return svga->crtc[0x59] & 0xfc; + case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ + case 0x11: ret = 0x00; break; + case 0x12: ret = 0x00; break; + case 0x13: ret = svga->crtc[0x59] & 0xfc; break; - case 0x30: return virge->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return virge->pci_regs[0x32]; - case 0x33: return virge->pci_regs[0x33]; + case 0x30: ret = virge->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ + case 0x31: ret = 0x00; break; + case 0x32: ret = virge->pci_regs[0x32]; break; + case 0x33: ret = virge->pci_regs[0x33]; break; - case 0x3c: return virge->int_line; - case 0x3d: return PCI_INTA; + case 0x3c: ret = virge->pci_regs[0x3c]; break; + + case 0x3d: ret = PCI_INTA; break; /*INTA*/ - case 0x3e: return 0x04; - case 0x3f: return 0xff; + case 0x3e: ret = 0x04; break; + case 0x3f: ret = 0xff; break; } - return 0; + return ret; } static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) @@ -3543,8 +3583,12 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) svga_t *svga = &virge->svga; switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x3d: case 0x3e: case 0x3f: + return; + case PCI_REG_COMMAND: - virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; if (val & PCI_COMMAND_IO) { io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); @@ -3552,19 +3596,20 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) } else io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - s3_virge_updatemapping(virge); - break; + virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; + s3_virge_updatemapping(virge); + return; case 0x07: virge->pci_regs[0x07] = val & 0x3e; - break; - case 0x0d: + return; + case 0x0d: virge->pci_regs[0x0d] = val & 0xf8; - break; + return; - case 0x13: - svga->crtc[0x59] = val & 0xfc; - s3_virge_updatemapping(virge); - break; + case 0x13: + svga->crtc[0x59] = val & 0xfc; + s3_virge_updatemapping(virge); + return; case 0x30: case 0x32: case 0x33: virge->pci_regs[addr] = val; @@ -3579,7 +3624,7 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) } return; case 0x3c: - virge->int_line = val; + virge->pci_regs[0x3c] = val; return; } } @@ -3608,9 +3653,11 @@ static void *s3_virge_init(const device_t *info) case S3_VIRGE_DX_VBE20: bios_fn = ROM_VIRGE_DX_VBE20; break; +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) case S3_TRIO3D_2X: bios_fn = ROM_TRIO3D_2X; break; +#endif default: free(virge); return NULL; @@ -3621,7 +3668,6 @@ static void *s3_virge_init(const device_t *info) s3_virge_in, s3_virge_out, s3_virge_hwcursor_draw, s3_virge_overlay_draw); - virge->svga.vblank_start = s3_virge_vblank_start; virge->pci = !!(info->flags & DEVICE_PCI); @@ -3659,49 +3705,56 @@ static void *s3_virge_init(const device_t *info) io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - virge->pci_regs[0x04] = 7; + virge->pci_regs[PCI_REG_COMMAND] = 3; virge->pci_regs[0x05] = 0; virge->pci_regs[0x06] = 0; virge->pci_regs[0x07] = 2; - virge->pci_regs[0x30] = 0x00; virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x33] = 0x00; virge->pci_regs[0x3d] = 1; virge->pci_regs[0x3e] = 4; virge->pci_regs[0x3f] = 0xff; virge->virge_rev = 0; virge->virge_id = 0xe1; - - virge->int_line = 0; switch (virge->memory_size) { case 2: + virge->svga.vram_mask = (2 << 20) - 1; + virge->svga.vram_max = 2 << 20; if (virge->pci) virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); else virge->svga.crtc[0x36] = 1 | (0 << 2) | (1 << 4) | (4 << 5); break; + case 8: + virge->svga.vram_mask = (8 << 20) - 1; + virge->svga.vram_max = 8 << 20; + if (virge->pci) + virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (3 << 5); + else + virge->svga.crtc[0x36] = 1 | (0 << 2) | (1 << 4) | (3 << 5); + break; case 4: default: + virge->svga.vram_mask = (4 << 20) - 1; + virge->svga.vram_max = 4 << 20; if (virge->pci) virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); else virge->svga.crtc[0x36] = 1 | (0 << 2) | (1 << 4) | (0 << 5); break; - case 8: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (3 << 5); - break; } - virge->svga.crtc[0x37] = 1 | (7 << 5); - virge->svga.crtc[0x59] = virge->pci ? 0x70 : 0x0a; + virge->svga.crtc[0x37] = 1; + virge->svga.crtc[0x53] = 8; switch(info->local) { case S3_DIAMOND_STEALTH3D_2000: + virge->svga.decode_mask = (4 << 20) - 1; virge->virge_id_high = 0x56; virge->virge_id_low = 0x31; + virge->svga.crtc[0x59] = virge->pci ? 0x70 : 0x0a; virge->chip = S3_VIRGE; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_2000_pci); @@ -3709,23 +3762,36 @@ static void *s3_virge_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_2000_vlb); break; case S3_DIAMOND_STEALTH3D_3000: + virge->svga.decode_mask = (8 << 20) - 1; virge->virge_id_high = 0x88; virge->virge_id_low = 0x3d; + virge->svga.crtc[0x59] = virge->pci ? 0x70 : 0x0a; virge->chip = S3_VIRGEVX; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_3000_pci); else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_3000_vlb); break; +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) case S3_TRIO3D_2X: + virge->svga.decode_mask = (8 << 20) - 1; virge->virge_id_high = 0x8a; virge->virge_id_low = 0x13; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = 0x70; + virge->svga.vblank_start = s3_virge_vblank_start; virge->chip = S3_TRIO3D2X; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_virge_dx_pci); break; +#endif + default: + virge->svga.decode_mask = (4 << 20) - 1; virge->virge_id_high = 0x8a; virge->virge_id_low = 0x01; + virge->svga.crtc[0x6c] = 1; + virge->svga.crtc[0x59] = virge->pci ? 0x70 : 0x0a; + virge->svga.vblank_start = s3_virge_vblank_start; virge->chip = S3_VIRGEDX; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_virge_dx_pci); @@ -3787,10 +3853,12 @@ static int s3_virge_375_4_available(void) return rom_present(ROM_VIRGE_DX_VBE20); } +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) static int s3_trio3d_2x_available(void) { return rom_present(ROM_TRIO3D_2X); } +#endif static void s3_virge_speed_changed(void *p) { @@ -3833,6 +3901,7 @@ static const device_config_t s3_virge_config[] = } }; +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) static const device_config_t s3_trio3d_2x_config[] = { { @@ -3859,6 +3928,7 @@ static const device_config_t s3_trio3d_2x_config[] = "", "", -1 } }; +#endif const device_t s3_virge_vlb_device = { @@ -3972,6 +4042,7 @@ const device_t s3_virge_375_4_pci_device = s3_virge_config }; +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) const device_t s3_trio3d_2x_pci_device = { "S3 Trio3D/2X PCI", @@ -3985,3 +4056,4 @@ const device_t s3_trio3d_2x_pci_device = s3_virge_force_redraw, s3_trio3d_2x_config }; +#endif diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 3bec9dd24..915328c81 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -741,7 +741,12 @@ svga_poll(void *p) ret = svga->line_compare(svga); if (ret) { - svga->ma = svga->maback = 0; + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + else + svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); + svga->ma = (svga->ma << 2); + svga->maback = (svga->maback << 2); svga->sc = 0; if (svga->attrregs[0x10] & 0x20) { svga->scrollcache = 0; @@ -805,7 +810,7 @@ svga_poll(void *p) changeframecount = svga->interlace ? 3 : 2; svga->vslines = 0; - if (svga->interlace && svga->oddeven) + if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); else svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); diff --git a/src/video/vid_table.c b/src/video/vid_table.c index ef3c5942e..a95720077 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -88,10 +88,11 @@ video_cards[] = { { "[ISA] Hercules Plus", "hercules_plus", &herculesplus_device }, { "[ISA] Hercules InColor", "incolor", &incolor_device }, { "[ISA] Image Manager 1024", "im1024", &im1024_device }, - { "[ISA] Schetmash Iskra EGA (Cyrillic ROM)", "iskra_ega", &iskra_ega_device }, + { "[ISA] Schetmash Iskra EGA (Cyrillic ROM)", "iskra_ega", &iskra_ega_device }, { "[ISA] Kasan Hangulmadang-16 VGA (ET4000AX)", "kasan16vga", &et4000_kasan_isa_device }, { "[ISA] MDA", "mda", &mda_device }, { "[ISA] MDSI Genius", "genius", &genius_device }, + { "[ISA] Metheus Premier 928 (S3 86c928)", "metheus928_isa", &s3_metheus_86c928_isa_device }, { "[ISA] OAK OTI-037C", "oti037c", &oti037c_device }, { "[ISA] OAK OTI-067", "oti067", &oti067_device }, { "[ISA] OAK OTI-077", "oti077", &oti077_device }, @@ -105,6 +106,7 @@ video_cards[] = { { "[ISA] SPEA V7 Mirage (S3 86c801)", "px_s3_v7_801_isa", &s3_v7mirage_86c801_isa_device }, { "[ISA] Trident TVGA8900B", "tvga8900b", &tvga8900b_device }, { "[ISA] Trident TVGA8900D", "tvga8900d", &tvga8900d_device }, + { "[ISA] Trident TVGA9000B", "tvga9000b", &tvga9000b_device }, { "[ISA] Trigem Korean VGA (ET4000AX)", "tgkorvga", &et4000k_isa_device }, { "[ISA] Tseng ET4000AX", "et4000ax", &et4000_isa_device }, { "[ISA] VGA", "vga", &vga_device }, @@ -135,8 +137,11 @@ video_cards[] = { { "[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device }, { "[PCI] Phoenix S3 Trio32", "px_trio32_pci", &s3_phoenix_trio32_pci_device }, { "[PCI] Phoenix S3 Trio64", "px_trio64_pci", &s3_phoenix_trio64_pci_device }, + { "[PCI] Phoenix S3 Trio64V+", "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, +#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X) { "[PCI] S3 Trio3D/2X", "trio3d2x", &s3_trio3d_2x_pci_device }, - { "[PCI] S3 Trio64V2/DX", "trio64v2dx_pci", &s3_trio64v2_dx_pci_device }, +#endif + { "[PCI] S3 Trio64V2/DX", "trio64v2dx_pci", &s3_trio64v2_dx_pci_device }, { "[PCI] S3 ViRGE/DX", "virge375_pci", &s3_virge_375_pci_device }, { "[PCI] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_pci", &s3_virge_375_4_pci_device }, { "[PCI] STB Nitro 64V (CL-GD 5446)", "cl_gd5446_stb_pci", &gd5446_stb_pci_device }, @@ -156,12 +161,14 @@ video_cards[] = { { "[VLB] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, { "[VLB] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_vlb", &s3_diamond_stealth64_vlb_device }, { "[VLB] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, + { "[VLB] Metheus Premier 928 (S3 86c928)", "metheus928_vlb", &s3_metheus_86c928_vlb_device }, { "[VLB] Number Nine 9FX (S3 Trio64)", "n9_9fx_vlb", &s3_9fx_vlb_device }, { "[VLB] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_vlb", &s3_bahamas64_vlb_device }, { "[VLB] Phoenix S3 86c805", "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, { "[VLB] Phoenix S3 Vision864", "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, { "[VLB] Phoenix S3 Trio32", "px_trio32_vlb", &s3_phoenix_trio32_vlb_device }, { "[VLB] Phoenix S3 Trio64", "px_trio64_vlb", &s3_phoenix_trio64_vlb_device }, + { "[VLB] Phoenix S3 Trio64V+", "px_trio64vplus_vlb", &s3_phoenix_trio64vplus_vlb_device }, { "[VLB] S3 ViRGE/DX", "virge375_vlb", &s3_virge_375_vlb_device }, { "[VLB] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device }, { "[VLB] Trident TGUI9400CXi", "tgui9400cxi_vlb", &tgui9400cxi_device }, diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index 3c149a145..2bcab6696 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -32,10 +32,12 @@ #include <86box/vid_svga_render.h> #define TVGA8900B_ID 0x03 +#define TVGA9000B_ID 0x23 #define TVGA8900CLD_ID 0x33 #define ROM_TVGA_8900B L"roms/video/tvga/tvga8900B.VBI" #define ROM_TVGA_8900CLD L"roms/video/tvga/trident.bin" +#define ROM_TVGA_9000B L"roms/video/tvga/tvga9000b.bin" typedef struct tvga_t { @@ -56,7 +58,8 @@ typedef struct tvga_t uint32_t vram_mask; } tvga_t; -video_timings_t timing_tvga = {VIDEO_ISA, 3, 3, 6, 8, 8, 12}; +video_timings_t timing_tvga8900 = {VIDEO_ISA, 3, 3, 6, 8, 8, 12}; +video_timings_t timing_tvga9000 = {VIDEO_ISA, 7, 7, 12, 7, 7, 12}; static uint8_t crtc_mask[0x40] = { @@ -115,8 +118,11 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - tkd8001_ramdac_out(addr, val, svga->ramdac, svga); - return; + if (tvga->card_id != TVGA9000B_ID) { + tkd8001_ramdac_out(addr, val, svga->ramdac, svga); + return; + } + break; case 0x3CF: switch (svga->gdcaddr & 15) @@ -143,35 +149,39 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) old = svga->crtc[svga->crtcreg]; val &= crtc_mask[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; - if (old != val) - { - if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) - { + if (old != val) { + if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) { svga->fullchange = changeframecount; svga_recalctimings(svga); } } - switch (svga->crtcreg) - { + switch (svga->crtcreg) { case 0x1e: svga->vram_display_mask = (val & 0x80) ? tvga->vram_mask : 0x3ffff; break; } return; case 0x3D8: - if (svga->gdcreg[0xf] & 4) - { + if (svga->gdcreg[0xf] & 4) { tvga->tvga_3d8 = val; tvga_recalcbanking(tvga); } return; case 0x3D9: - if (svga->gdcreg[0xf] & 4) - { + if (svga->gdcreg[0xf] & 4) { tvga->tvga_3d9 = val; tvga_recalcbanking(tvga); } return; + case 0x3DB: + if (tvga->card_id != TVGA9000B_ID) { + /*3db appears to be a 4 bit clock select register on 8900D*/ + svga->miscout = (svga->miscout & ~0x0c) | ((val & 3) << 2); + tvga->newctrl2 = (tvga->newctrl2 & ~0x01) | ((val & 4) >> 2); + tvga->oldctrl1 = (tvga->oldctrl1 & ~0x10) | ((val & 8) << 1); + svga_recalctimings(svga); + } + break; } svga_out(addr, val, svga); } @@ -203,7 +213,10 @@ uint8_t tvga_in(uint16_t addr, void *p) } break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return tkd8001_ramdac_in(addr, svga->ramdac, svga); + if (tvga->card_id != TVGA9000B_ID) { + return tkd8001_ramdac_in(addr, svga->ramdac, svga); + } + break; case 0x3D4: return svga->crtcreg; case 0x3D5: @@ -233,6 +246,9 @@ static void tvga_recalcbanking(tvga_t *tvga) void tvga_recalctimings(svga_t *svga) { tvga_t *tvga = (tvga_t *)svga->p; + int clksel; + int high_res_256 = 0; + if (!svga->rowoffset) svga->rowoffset = 0x100; /*This is the only sensible way I can see this being handled, given that TVGA8900D has no overflow bits. Some sort of overflow is required for 320x200x24 and 1024x768x16*/ @@ -264,18 +280,43 @@ void tvga_recalctimings(svga_t *svga) if (svga->interlace) svga->rowoffset >>= 1; - switch (((svga->miscout >> 2) & 3) | ((tvga->newctrl2 << 2) & 4)) - { - case 2: svga->clock = (cpuclock * (double)(1ull << 32))/44900000.0; break; - case 3: svga->clock = (cpuclock * (double)(1ull << 32))/36000000.0; break; - case 4: svga->clock = (cpuclock * (double)(1ull << 32))/57272000.0; break; - case 5: svga->clock = (cpuclock * (double)(1ull << 32))/65000000.0; break; - case 6: svga->clock = (cpuclock * (double)(1ull << 32))/50350000.0; break; - case 7: svga->clock = (cpuclock * (double)(1ull << 32))/40000000.0; break; + if (tvga->card_id == TVGA8900CLD_ID) + clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->oldctrl1 & 0x10) >> 1); + else + clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->newctrl2 & 0x40) >> 3); + + switch (clksel) { + case 0x2: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break; + case 0x3: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break; + case 0x4: svga->clock = (cpuclock * (double)(1ull << 32)) / 57272000.0; break; + case 0x5: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break; + case 0x6: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break; + case 0x7: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break; + case 0x8: svga->clock = (cpuclock * (double)(1ull << 32)) / 88000000.0; break; + case 0x9: svga->clock = (cpuclock * (double)(1ull << 32)) / 98000000.0; break; + case 0xa: svga->clock = (cpuclock * (double)(1ull << 32)) / 118800000.0; break; + case 0xb: svga->clock = (cpuclock * (double)(1ull << 32)) / 108000000.0; break; + case 0xc: svga->clock = (cpuclock * (double)(1ull << 32)) / 72000000.0; break; + case 0xd: svga->clock = (cpuclock * (double)(1ull << 32)) / 77000000.0; break; + case 0xe: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; + case 0xf: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break; } - if (tvga->oldctrl2 & 0x10) + if (tvga->card_id != TVGA8900CLD_ID) { + /*TVGA9000 doesn't seem to have support for a 'high res' 256 colour mode + (without the VGA pixel doubling). Instead it implements these modes by + doubling the horizontal pixel count and pixel clock. Hence we use a + basic heuristic to detect this*/ + if (svga->interlace) + high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4); + else + high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2); + } + + if ((tvga->oldctrl2 & 0x10) || high_res_256) { + if (high_res_256) + svga->hdisp /= 2; switch (svga->bpp) { case 8: @@ -304,11 +345,16 @@ static void *tvga_init(const device_t *info) const wchar_t *bios_fn; tvga_t *tvga = malloc(sizeof(tvga_t)); memset(tvga, 0, sizeof(tvga_t)); - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga); - tvga->vram_size = device_get_config_int("memory") << 10; - tvga->vram_mask = tvga->vram_size - 1; + if (info->local == TVGA9000B_ID) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga9000); + tvga->vram_size = 512 << 10; + } else { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900); + tvga->vram_size = device_get_config_int("memory") << 10; + } + + tvga->vram_mask = tvga->vram_size - 1; tvga->card_id = info->local; @@ -320,6 +366,9 @@ static void *tvga_init(const device_t *info) case TVGA8900CLD_ID: bios_fn = ROM_TVGA_8900CLD; break; + case TVGA9000B_ID: + bios_fn = ROM_TVGA_9000B; + break; default: free(tvga); return NULL; @@ -333,7 +382,8 @@ static void *tvga_init(const device_t *info) NULL, NULL); - tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); + if (info->local != TVGA9000B_ID) + tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga); @@ -350,6 +400,11 @@ static int tvga8900d_available(void) return rom_present(ROM_TVGA_8900CLD); } +static int tvga9000b_available(void) +{ + return rom_present(ROM_TVGA_9000B); +} + void tvga_close(void *p) { tvga_t *tvga = (tvga_t *)p; @@ -425,3 +480,17 @@ const device_t tvga8900d_device = tvga_force_redraw, tvga_config }; + +const device_t tvga9000b_device = +{ + "Trident TVGA 9000B", + DEVICE_ISA, + TVGA9000B_ID, + tvga_init, + tvga_close, + NULL, + tvga9000b_available, + tvga_speed_changed, + tvga_force_redraw, + NULL +}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 544d85d5d..0e2fd0cbe 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -72,6 +72,9 @@ ifeq ($(DEV_BUILD), y) ifndef VECTRA54 VECTRA54 := y endif + ifndef S3TRIO3D2X + S3TRIO3D2X := y + endif ifndef SIEMENS SIEMENS := y endif @@ -151,6 +154,9 @@ else ifndef VECTRA54 VECTRA54 := n endif + ifndef S3TRIO3D2X + S3TRIO3D2X := n + endif ifndef SIEMENS SIEMENS := n endif @@ -550,6 +556,10 @@ ifeq ($(VECTRA54), y) OPTS += -DUSE_VECTRA54 endif +ifeq ($(S3TRIO3D2X), y) +OPTS += -DUSE_S3TRIO3D2X +endif + ifeq ($(SIEMENS), y) OPTS += -DUSE_SIEMENS endif