diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 94ef408f6..7d17b9983 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -72,6 +72,7 @@ add_library(chipset OBJECT sis_5572_usb.c sis_5595_pmu.c sis_55xx.c + sl82c461.c via_vt82c49x.c via_vt82c505.c gc100.c diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index f9d6af150..84bd872f8 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1656,7 +1656,12 @@ i4x0_init(const device_t *info) regs[0x57] = 0x31; regs[0x59] = 0x0f; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; - dev->max_drb = 3; + /* At the very least the 420ZX seems to read to 0x64, per the SB486PV. */ + if (dev->type == INTEL_420ZX) { + regs[0x64] = 0x02; + dev->max_drb = 4; + } else + dev->max_drb = 3; dev->drb_unit = 1; dev->drb_default = 0x02; break; diff --git a/src/chipset/sl82c461.c b/src/chipset/sl82c461.c new file mode 100644 index 000000000..f94aa2e99 --- /dev/null +++ b/src/chipset/sl82c461.c @@ -0,0 +1,362 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Symphony SL82C461 (Haydn II) chipset. + * + * Symphony SL82C461 Configuration Registers (WARNING: May be inaccurate!): + * + * - Register 00h: + * - Bit 6: External cache present (if clear, AMI BIOS'es will not + * allow enabling external cache). + * + * - Register 01h: + * - Bit 0: Fast Gate A20 Enable (Handler mostly). + * Is it? Enabling/disabling fast gate A20 doesn't appear + * to do much to any register at all. + * + * - Register 02h: + * - Bit 0: Optional Chipset Turbo Pin; + * - Bits 4-2: + * - 000 = CLK2/3; + * - 001 = CLK2/4; + * - 010 = CLK2/5; + * - 011 = 7.159 MHz (ATCLK2); + * - 100 = CLK2/6; + * - 110 = CLK2/2.5; + * - 111 = CLK2/2. + * + * - Register 06h: + * - Bit 2: Decoupled Refresh Option. + * + * - Register 08h: + * - Bits 3, 2: I/O Recovery Time (SYSCLK): + * - 0, 0 = 0; + * - 1, 1 = 12. + * - Bit 1: Extended ALE. + * + * - Register 25h: + * Bit 7 here causes AMI 111192 CMOS Setup to return 7168 KB RAM + * instead of 6912 KB. This is 256 KB off. Relocation? + * Also, returning bit 5 clear instead of set, causes the AMI BIOS + * to set bits 0,1 of register 45h to 1,0 instead of 0,1. + * + * - Register 2Dh: + * - Bit 7: Enable 256KB Memory Relocation; + * - Bit 6: Enable 384KB Memory Relocation, bit 7 must also be set. + * + * - Register 2Eh: + * - Bit 7: CC000-CFFFF Shadow Read Enable; + * - Bit 6: CC000-CFFFF Shadow Write Enable; + * - Bit 5: C8000-CBFFF Shadow Read Enable; + * - Bit 4: C8000-CBFFF Shadow Write Enable; + * - Bit 3: C4000-C7FFF Shadow Read Enable; + * - Bit 2: C4000-C7FFF Shadow Write Enable; + * - Bit 1: C0000-C3FFF Shadow Read Enable; + * - Bit 0: C0000-C3FFF Shadow Write Enable. + * + * - Register 2Fh: + * - Bit 7: DC000-DFFFF Shadow Read Enable; + * - Bit 6: DC000-DFFFF Shadow Write Enable; + * - Bit 5: D8000-DBFFF Shadow Read Enable; + * - Bit 4: D8000-DBFFF Shadow Write Enable; + * - Bit 3: D4000-D7FFF Shadow Read Enable; + * - Bit 2: D4000-D7FFF Shadow Write Enable; + * - Bit 1: D0000-D3FFF Shadow Read Enable; + * - Bit 0: D0000-D3FFF Shadow Write Enable. + * + * - Register 30h: + * - Bit 7: E0000-EFFFF Shadow Read Enable; + * - Bit 6: E0000-EFFFF Shadow Write Enable. + * + * - Register 31h: + * - Bit 7: F0000-FFFFF Shadow Read Enable; + * - Bit 6: F0000-FFFFF Shadow Write Enable. + * + * - Register 33h (NOTE: Waitstates also affect register 32h): + * - Bits 3, 0: + * - 0,0 = 0 W/S; + * - 1,0 = 1 W/S; + * - 1,1 = 2 W/S. + * + * - Register 40h: + * - Bit 3: External Cache Enabled (0 = yes, 1 = no); + * I also see bits 5, 4, 3 of register 44h affected: + * - 38h (so all 3 set) when cache is disabled; + * - 00h (all 3 clear) when it's enabled. + * + * - Register 45h: + * - Bit 3: Video Shadow RAM Cacheable; + * - Bit 4: Adapter Shadow RAM Cacheable; + * - Bit 5: BIOS Shadow RAM Cacheable. + * + * Authors: Miran Grca, + * Tiseno100, + * + * Copyright 2025 Miran Grca. + * Copyright 2021-2025 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/chipset.h> + +typedef struct { + uint8_t index; + uint8_t regs[256]; + uint8_t shadow[4]; +} sl82c461_t; + +#ifdef ENABLE_SL82C461_LOG +int sl82c461_do_log = ENABLE_SL82C461_LOG; + +static void +sl82c461_log(const char *fmt, ...) +{ + va_list ap; + + if (sl82c461_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define sl82c461_log(fmt, ...) +#endif + +static void +sl82c461_recalcmapping(sl82c461_t *dev) +{ + int do_shadow = 0; + + for (uint32_t i = 0; i < 8; i += 2) { + if ((dev->regs[0x2e] ^ dev->shadow[0x00]) & (3 << i)) { + uint32_t base = 0x000c0000 + ((i >> 1) << 14); + uint32_t read = ((dev->regs[0x2e] >> i) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x2e] >> i) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00004000, read | write); + + do_shadow++; + } + + if ((dev->regs[0x2f] ^ dev->shadow[0x01]) & (3 << i)) { + uint32_t base = 0x000d0000 + ((i >> 1) << 14); + uint32_t read = ((dev->regs[0x2f] >> i) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x2f] >> i) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00004000, read | write); + + do_shadow++; + } + } + + if ((dev->regs[0x30] ^ dev->shadow[0x02]) & 0xc0) { + uint32_t base = 0x000e0000; + uint32_t read = ((dev->regs[0x30] >> 6) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x30] >> 6) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00010000, read | write); + + do_shadow++; + } + + if ((dev->regs[0x31] ^ dev->shadow[0x03]) & 0xc0) { + uint32_t base = 0x000f0000; + uint32_t read = ((dev->regs[0x31] >> 6) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x31] >> 6) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + shadowbios = !!((dev->regs[0x31] >> 6) & 0x02); + shadowbios_write = !!((dev->regs[0x31] >> 6) & 0x01); + + mem_set_mem_state_both(base, 0x00010000, read | write); + + do_shadow++; + } + + if (do_shadow) { + memcpy(dev->shadow, &(dev->regs[0x2e]), 4 * sizeof(uint8_t)); + flushmmucache_nopc(); + } +} + +static void +sl82c461_write(uint16_t addr, uint8_t val, void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + + sl82c461_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + + if (addr & 0x0001) { + dev->regs[dev->index] = val; + + switch (dev->index) { + case 0x01: + /* NOTE: This is to be verified. */ + mem_a20_alt = val & 1; + mem_a20_recalc(); + break; + case 0x02: { + double bus_clk; + switch (val & 0x1c) { + case 0x00: + bus_clk = cpu_busspeed / 3.0; + break; + case 0x04: + bus_clk = cpu_busspeed / 4.0; + break; + case 0x08: + bus_clk = cpu_busspeed / 5.0; + break; + default: + case 0x0c: + bus_clk = 7159091.0; + break; + case 0x10: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x18: + bus_clk = cpu_busspeed / 2.5; + break; + case 0x1c: + bus_clk = cpu_busspeed / 2.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + break; + } case 0x2d: + switch (val & 0xc0) { + case 0xc0: + mem_remap_top(384); + break; + case 0x80: + mem_remap_top(256); + break; + default: + case 0x00: + mem_remap_top(0); + break; + } + break; + case 0x2e ... 0x31: + sl82c461_recalcmapping(dev); + break; + case 0x33: + switch (val & 0x09) { + default: + case 0x00: + cpu_waitstates = 0; + break; + case 0x08: + cpu_waitstates = 1; + break; + case 0x09: + cpu_waitstates = 2; + break; + } + cpu_update_waitstates(); + break; + case 0x40: + cpu_cache_ext_enabled = !(val & 0x08); + cpu_update_waitstates(); + break; + } + } else + dev->index = val; +} + +static uint8_t +sl82c461_read(uint16_t addr, void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + uint8_t ret = 0x00; + + if (addr & 0x0001) + if (dev->index == 0x00) + ret = dev->regs[dev->index] | 0x40; + else + ret = dev->regs[dev->index]; + else + ret = dev->index; + + sl82c461_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + + return ret; +} + +static void +sl82c461_close(void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + + free(dev); +} + +static void * +sl82c461_init(const device_t *info) +{ + sl82c461_t *dev = (sl82c461_t *) calloc(1, sizeof(sl82c461_t)); + + dev->regs[0x00] = 0x40; + + dev->regs[0x02] = 0x0c; + dev->regs[0x40] = 0x08; + + memset(dev->shadow, 0xff, 4 * sizeof(uint8_t)); + + mem_a20_alt = 0x00; + mem_a20_recalc(); + + cpu_set_isa_speed(7159091.0); + + sl82c461_recalcmapping(dev); + + cpu_waitstates = 0; + cpu_cache_ext_enabled = 0; + + cpu_update_waitstates(); + + io_sethandler(0x00a8, 2, + sl82c461_read, NULL, NULL, + sl82c461_write, NULL, NULL, dev); + + return dev; +} + +const device_t sl82c461_device = { + .name = "Symphony SL82C461 (Haydn II)", + .internal_name = "sis_85c471", + .flags = 0, + .local = 0, + .init = sl82c461_init, + .close = sl82c461_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 496544c63..6354ac15a 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -24,14 +24,16 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/io.h> +#include <86box/machine.h> #include <86box/mem.h> #include <86box/nmi.h> #include <86box/port_92.h> #include <86box/chipset.h> typedef struct vl82c480_t { - uint8_t idx; - uint8_t regs[256]; + uint8_t idx; + uint8_t regs[256]; + uint32_t banks[4]; } vl82c480_t; static int @@ -59,7 +61,7 @@ vl82c480_shflags(uint8_t access) } static void -vl82c480_recalc(vl82c480_t *dev) +vl82c480_recalc_shadow(vl82c480_t *dev) { uint32_t base; uint8_t access; @@ -69,8 +71,8 @@ vl82c480_recalc(vl82c480_t *dev) for (uint8_t i = 0; i < 6; i++) { for (uint8_t j = 0; j < 8; j += 2) { - base = 0x000a0000 + (i << 16) + (j << 13); - access = (dev->regs[0x0d + i] >> j) & 3; + base = 0x000a0000 + (i << 16) + (j << 13); + access = (dev->regs[0x0d + i] >> j) & 3; mem_set_mem_state(base, 0x4000, vl82c480_shflags(access)); shadowbios |= ((base >= 0xe0000) && (access & 0x02)); shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); @@ -80,6 +82,37 @@ vl82c480_recalc(vl82c480_t *dev) flushmmucache(); } +static void +vl82c480_recalc_banks(vl82c480_t *dev) +{ + uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 }; + uint8_t shifts[4] = { 0, 4, 0, 4 }; + uint8_t regs[4] = { 0x02, 0x02, 0x03, 0x03 }; + uint32_t total = 0; + + for (uint8_t i = 0; i < 4; i++) { + uint8_t shift = shifts[i]; + uint8_t reg = regs[i]; + uint8_t cfg = (dev->regs[reg] >> shift) & 0x7; + uint32_t size = sizes[cfg]; + + total += MIN(dev->banks[i], size); + } + + if (total > 1024) { + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (total - 1024) << 10); + } else { + if (total >= 1024) + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + else + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_high_mapping); + } + + flushmmucache(); +} + static void vl82c480_write(uint16_t addr, uint8_t val, void *priv) { @@ -91,16 +124,24 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) break; case 0xed: - if (dev->idx >= 0x01 && dev->idx <= 0x24) { + if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) || + ((dev->idx >= 0x20) && (dev->idx <= 0x24))) { switch (dev->idx) { default: dev->regs[dev->idx] = val; break; + case 0x02: case 0x03: + dev->regs[dev->idx] = val; + if (!strcmp(machine_get_internal_name(), "martin")) + vl82c480_recalc_banks(dev); + break; case 0x04: if (dev->regs[0x00] == 0x98) dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7); else dev->regs[dev->idx] = val; + if (!strcmp(machine_get_internal_name(), "martin")) + dev->regs[dev->idx] &= 0x1f; break; case 0x05: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef); @@ -108,14 +149,9 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) case 0x07: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); break; - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: + case 0x0d ... 0x12: dev->regs[dev->idx] = val; - vl82c480_recalc(dev); + vl82c480_recalc_shadow(dev); break; } } @@ -124,8 +160,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) /* TODO: This is actually Fast A20 disable. */ #if 0 case 0xee: - if (mem_a20_alt) - outb(0x92, inb(0x92) & ~2); + mem_a20_alt = 0x00; + mem_a20_recalc(); break; #endif @@ -146,14 +182,16 @@ vl82c480_read(uint16_t addr, void *priv) break; case 0xed: - ret = dev->regs[dev->idx]; + if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) || + ((dev->idx >= 0x20) && (dev->idx <= 0x24))) + ret = dev->regs[dev->idx]; break; /* TODO: This is actually Fast A20 enable. */ #if 0 case 0xee: - if (!mem_a20_alt) - outb(0x92, inb(0x92) | 2); + mem_a20_alt = 0x02; + mem_a20_recalc(); break; #endif @@ -180,7 +218,9 @@ vl82c480_close(void *priv) static void * vl82c480_init(const device_t *info) { - vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); + vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); + uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 }; + uint32_t ms = mem_size; dev->regs[0x00] = info->local; dev->regs[0x01] = 0xff; @@ -191,9 +231,23 @@ vl82c480_init(const device_t *info) dev->regs[0x07] = 0x21; dev->regs[0x08] = 0x38; + for (uint8_t i = 0; i < 4; i++) { + for (uint8_t j = 2; j < 7; j++) { + if (ms >= sizes[j]) + dev->banks[i] = sizes[j]; + else + break; + } + + ms -= dev->banks[i]; + + if ((ms == 0) || (dev->banks[i] == 0)) + break; + } + io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev); - device_add(&port_92_device); + device_add(&port_92_pci_device); return dev; } diff --git a/src/codegen_new/codegen_ops_stack.c b/src/codegen_new/codegen_ops_stack.c index fca9c9efa..f93289197 100644 --- a/src/codegen_new/codegen_ops_stack.c +++ b/src/codegen_new/codegen_ops_stack.c @@ -390,6 +390,8 @@ ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUS uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); uop_CALL_FUNC(ir, flags_rebuild); sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5); + uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002); uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); SUB_SP(ir, 2); @@ -406,6 +408,8 @@ ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNU uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); uop_CALL_FUNC(ir, flags_rebuild); + uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5); + uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002); if (cpu_CR4_mask & CR4_VME) uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); else if (CPUID) diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index a0fa612a8..7e7324341 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) temp = (cpu_state.flags & ~I_FLAG) | 0x3000; if (cpu_state.eflags & VIF_FLAG) temp |= I_FLAG; + temp = (temp & 0x7fd5) | 2; PUSH_W(temp); } else { x86gpf(NULL, 0); @@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) } } else { flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_W(cpu_state.flags); } CLOCK_CYCLES(4); @@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat)) else tempw = cpu_state.eflags & 4; flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_L(cpu_state.flags | (tempw << 16)); CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); @@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { - x86gpf(NULL, 0); - return 1; - } - tempw = POP_W(); if (cpu_state.abrt) return 1; - if (!(msw & 1)) - cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; flags_extract(); #ifdef USE_DEBUG_REGS_486 rf_flag_no_clear = 1; diff --git a/src/cpu/x86_ops_flag_2386.h b/src/cpu/x86_ops_flag_2386.h index c9a2d5ab2..787b268dc 100644 --- a/src/cpu/x86_ops_flag_2386.h +++ b/src/cpu/x86_ops_flag_2386.h @@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) temp = (cpu_state.flags & ~I_FLAG) | 0x3000; if (cpu_state.eflags & VIF_FLAG) temp |= I_FLAG; + temp = (temp & 0x7fd5) | 2; PUSH_W(temp); } else { x86gpf(NULL, 0); @@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) } } else { flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_W(cpu_state.flags); } CLOCK_CYCLES(4); @@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat)) else tempw = cpu_state.eflags & 4; flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_L(cpu_state.flags | (tempw << 16)); CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); @@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { - x86gpf(NULL, 0); - return 1; - } - tempw = POP_W(); if (cpu_state.abrt) return 1; - if (!(msw & 1)) - cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; flags_extract(); rf_flag_no_clear = 1; diff --git a/src/device.c b/src/device.c index 1922806b9..910ff4ff9 100644 --- a/src/device.c +++ b/src/device.c @@ -897,8 +897,14 @@ device_is_valid(const device_t *device, int mch) { int ret = 1; - if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) - ret = machine_has_bus(mch, device->flags & DEVICE_BUS); + if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) { + /* Hide PCI devices on machines with only an internal PCI bus. */ + if ((device->flags & DEVICE_PCI) && + machine_has_flags(mch, MACHINE_PCI_INTERNAL)) + ret = 0; + else + ret = machine_has_bus(mch, device->flags & DEVICE_BUS); + } return ret; } diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index aaa746570..a8a8c51cc 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1336,7 +1336,10 @@ write64_ami(void *priv, uint8_t val) kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n"); if (!(dev->flags & DEVICE_PCI)) write_p2(dev, dev->p2 & ~(4 << (val & 0x01))); - kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + if (strstr(machine_get_internal_name(), "sb486pv") != NULL) + kbc_delay_to_ob(dev, 0x03, 0, 0x00); + else + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; return 0; @@ -2149,6 +2152,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) dev->wantdata = 0; dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } break; @@ -2160,11 +2169,36 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) dev->wantdata = 1; dev->state = STATE_KBC_PARAM; dev->command = 0xd1; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } else if (fast_reset && ((val & 0xf0) == 0xf0)) { pulse_output(dev, val & 0x0f); dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; + } else if (val == 0xad) { + /* Fast track it because of the Bochs BIOS. */ + kbc_at_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + + dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } else if (val == 0xae) { /* Fast track it because of the LG MultiNet. */ @@ -2172,6 +2206,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) set_enable_kbd(dev, 1); dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } break; diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index c1041e6e1..b20e38860 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -58,7 +58,7 @@ kbc_at_dev_log(const char *fmt, ...) # define kbc_at_dev_log(fmt, ...) #endif -static void +void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main) { if (reset_main) { @@ -95,10 +95,6 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main) dev->cmd_queue[dev->cmd_queue_end] = val; dev->cmd_queue_end = (dev->cmd_queue_end + 1) & 0xf; } - - /* TODO: This should be done on actual send to host. */ - if (val != 0xfe) - dev->last_scan_code = val; } static void @@ -123,6 +119,8 @@ kbc_at_dev_poll(void *priv) (dev->queue_start != dev->queue_end)) { kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]); dev->port->out_new = dev->queue[dev->queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask; } if (dev->ignore || !(*dev->scan) || dev->port->wantcmd) @@ -143,6 +141,8 @@ kbc_at_dev_poll(void *priv) if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; } if (dev->cmd_queue_start == dev->cmd_queue_end) @@ -166,6 +166,8 @@ kbc_at_dev_poll(void *priv) if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; } if (dev->cmd_queue_start == dev->cmd_queue_end) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 4b1097df4..7fa2b9706 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -428,11 +428,11 @@ static const scancode scancode_set1[512] = { { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */ { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */ { .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */ - { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */ + { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xda, 0 } }, /* 15a */ { .mk = {0xe0, 0x5b, 0 }, .brk = { 0xe0, 0xdb, 0 } }, /* 15b */ { .mk = {0xe0, 0x5c, 0 }, .brk = { 0xe0, 0xdc, 0 } }, /* 15c */ { .mk = {0xe0, 0x5d, 0 }, .brk = { 0xe0, 0xdd, 0 } }, /* 15d */ - { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */ + { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xde, 0 } }, /* 15e */ { .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */ { .mk = { 0 }, .brk = { 0 } }, /* 160 */ { .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */ @@ -3494,7 +3494,6 @@ keyboard_at_invalid_cmd(atkbc_dev_t *dev) kbc_at_dev_queue_add(dev, inv_cmd_response, 0); } - static void keyboard_at_write(void *priv) { @@ -3643,6 +3642,13 @@ keyboard_at_write(void *priv) case 0xf6: /* set defaults */ keyboard_at_log("%s: set defaults%s\n", dev->name, (val == 0xf6) ? "" : " and disable keyboard"); + dev->port->out_new = -1; + dev->port->wantcmd = 0; + + kbc_at_dev_queue_reset(dev, 1); + + dev->last_scan_code = 0x00; + keyboard_scan = !(val & 0x01); keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n", dev->name, val, keyboard_scan); @@ -3712,7 +3718,6 @@ keyboard_at_write(void *priv) /* TODO: This is supposed to resend multiple bytes after some commands. */ case 0xfe: /* resend last scan code */ keyboard_at_log("%s: resend last scan code\n", dev->name); - kbc_at_dev_queue_add(dev, 0xfa, 0); kbc_at_dev_queue_add(dev, dev->last_scan_code, 0); break; @@ -3728,6 +3733,44 @@ keyboard_at_write(void *priv) } } +#ifdef SCAN_CODE_TABLES_COMPARISON +/* Non-translated to translated scan codes. */ +static const uint8_t nont_to_t[256] = { + 0x00, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, + 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, + 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, + 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, + 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, + 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, + 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, + 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, + 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, + 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, + 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, + 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, + 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, + 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, + 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, + 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, + 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; +#endif + /* * Initialize the device for use by the user. * @@ -3777,6 +3820,138 @@ keyboard_at_init(const device_t *info) inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa; +#ifdef SCAN_CODE_TABLES_COMPARISON + pclog_toggle_suppr(); + + pclog("Scan code set 01 vs. 81 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set1[i].mk[j] == scancode_set81[i].mk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].mk[j], scancode_set81[i].mk[j]); + j++; + } while ((scancode_set1[i].mk[j] != 0) && (scancode_set81[i].mk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 81 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set1[i].brk[j] == scancode_set81[i].brk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].brk[j], scancode_set81[i].brk[j]); + j++; + } while ((scancode_set1[i].brk[j] != 0) && (scancode_set81[i].brk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 02 vs. 82 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set2[i].mk[j] == scancode_set82[i].mk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set2[i].mk[j], scancode_set82[i].mk[j]); + j++; + } while ((scancode_set2[i].mk[j] != 0) && (scancode_set82[i].mk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 02 vs. 82 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set2[i].brk[j] == scancode_set82[i].brk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set2[i].brk[j], scancode_set82[i].brk[j]); + j++; + } while ((scancode_set2[i].brk[j] != 0) && (scancode_set82[i].brk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 02 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + int k = 0; + int was_f0 = 0; + do { + if (scancode_set2[i].mk[k] == 0xf0) + was_f0 = 1; + else { + uint8_t code = nont_to_t[scancode_set2[i].mk[k]]; + + if (was_f0) { + if (code & 0x80) + code = 0x00; + else + code |= 0x80; + + was_f0 = 0; + } + + if (scancode_set1[i].mk[j] == code) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].mk[j], code); + + j++; + } + + k++; + } while ((scancode_set1[i].mk[j] != 0) && (scancode_set2[i].mk[k] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 02 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + int k = 0; + int was_f0 = 0; + do { + if (scancode_set2[i].brk[k] == 0xf0) + was_f0 = 1; + else { + uint8_t code = nont_to_t[scancode_set2[i].brk[k]]; + + if (was_f0) { + if (code & 0x80) + code = 0x00; + else + code |= 0x80; + + was_f0 = 0; + } + + if (scancode_set1[i].brk[j] == code) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].brk[j], code); + + j++; + } + + k++; + } while ((scancode_set1[i].brk[j] != 0) && (scancode_set2[i].brk[k] != 0)); + pclog("\n"); + } + + pclog_toggle_suppr(); + + fatal("Comparison finished\n"); +#endif + /* Return our private data to the I/O layer. */ return dev; } diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 0d34235fe..2c1722f51 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -333,13 +333,13 @@ ps2_poll(void *priv) atkbc_dev_t *dev = (atkbc_dev_t *) priv; int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3; - int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || !mouse_state_changed()) || - ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size))); + int cond = (mouse_capture || video_fullscreen) && mouse_scan && (dev->mode == MODE_STREAM) && + mouse_state_changed() && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size)); - if (!cond && (dev->mode == MODE_STREAM)) + if (cond) ps2_report_coordinates(dev, 1); - return cond; + return !cond; } /* diff --git a/src/device/postcard.c b/src/device/postcard.c index b91d8b402..95a4df646 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -147,14 +147,17 @@ postcard_init(UNUSED(const device_t *info)) if (machine_has_bus(machine, MACHINE_BUS_MCA)) postcard_port = 0x680; /* MCA machines */ - else if (strstr(machines[machine].name, " PS/2 ") || strstr(machine_getname_ex(machine), " PS/1 ")) + else if (strstr(machines[machine].name, " PS/2 ") || + strstr(machine_getname_ex(machine), " PS/1 ")) postcard_port = 0x190; /* ISA PS/2 machines */ else if (strstr(machines[machine].name, " IBM XT ")) postcard_port = 0x60; /* IBM XT */ else if (strstr(machines[machine].name, " IBM PCjr")) { postcard_port = 0x10; /* IBM PCjr */ postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */ - } else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI)) + } else if (strstr(machines[machine].name, " Compaq ") && + !strstr(machines[machine].name, " Presario ") && + !strstr(machines[machine].name, " ProSignia ")) postcard_port = 0x84; /* ISA Compaq machines */ else if (strstr(machines[machine].name, "Olivetti")) postcard_port = 0x378; /* Olivetti machines */ diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index e779ea2d7..e7166d1ba 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -81,7 +81,6 @@ int fdc_current[FDC_MAX] = { 0, 0 }; volatile int fdcinited = 0; -// #define ENABLE_FDC_LOG 1 #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index fe088b209..94884383b 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -159,6 +159,9 @@ extern const device_t stpc_atlas_device; extern const device_t stpc_serial_device; extern const device_t stpc_lpt_device; +/* Symphony */ +extern const device_t sl82c461_device; + /* UMC */ extern const device_t umc_8886f_device; extern const device_t umc_8886af_device; diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index dd8cae54b..9dfb1c8e4 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -291,6 +291,7 @@ extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t v extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); extern void kbc_at_handler(int set, void *priv); +extern void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main); extern uint8_t kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main); extern void kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main); extern void kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c28add516..febce3fa1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -105,7 +105,7 @@ /* Feature flags for advanced devices. */ #define MACHINE_APM 0x00080000 /* sys has APM */ #define MACHINE_ACPI 0x00100000 /* sys has ACPI */ -#define MACHINE_HWM 0x00200000 /* sys has hw monitor */ +#define MACHINE_PCI_INTERNAL 0x00200000 /* sys has only internal PCI */ #define MACHINE_CARTRIDGE 0x00400000 /* sys has cartridge bays */ /* Feature flags for internal storage controllers. */ #define MACHINE_MFM 0x00800000 /* sys has int MFM/RLL */ @@ -519,6 +519,7 @@ extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); extern int machine_at_spc6000a_init(const machine_t *); extern int machine_at_micronics386_init(const machine_t *); +extern int machine_at_micronics386px_init(const machine_t *); extern int machine_at_ecs386v_init(const machine_t *); extern int machine_at_tandy4000_init(const machine_t *); @@ -544,6 +545,7 @@ extern int machine_at_exp4349_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_d824_init(const machine_t *); +extern int machine_at_martin_init(const machine_t *); extern int machine_at_403tg_init(const machine_t *); extern int machine_at_403tg_d_init(const machine_t *); @@ -554,6 +556,7 @@ extern int machine_at_aptiva510_init(const machine_t *); extern int machine_at_pc330_6573_init(const machine_t *); extern int machine_at_mvi486_init(const machine_t *); +extern int machine_at_dtk461_init(const machine_t *); extern int machine_at_sis401_init(const machine_t *); extern int machine_at_isa486_init(const machine_t *); extern int machine_at_av4_init(const machine_t *); @@ -585,6 +588,7 @@ extern int machine_at_sb486p_init(const machine_t *); extern int machine_at_486sp3_init(const machine_t *); extern int machine_at_486sp3c_init(const machine_t *); extern int machine_at_486sp3g_init(const machine_t *); +extern int machine_at_sb486pv_init(const machine_t *); extern int machine_at_486ap4_init(const machine_t *); extern int machine_at_g486vpa_init(const machine_t *); extern int machine_at_486vipio2_init(const machine_t *); diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 0f7d22172..273fc0a37 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -99,6 +99,7 @@ extern const device_t ami_1994_nvr_device; extern const device_t ami_1995_nvr_device; extern const device_t via_nvr_device; extern const device_t p6rp4_nvr_device; +extern const device_t martin_nvr_device; extern const device_t elt_nvr_device; #endif diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index bdff29f7f..06bf57f8f 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -71,7 +71,10 @@ extern const device_t fdc37m60x_370_device; /* ITE */ extern const device_t it8661f_device; extern const device_t it8671f_device; + +/* Intel */ extern const device_t i82091aa_device; +extern const device_t i82091aa_26e_device; extern const device_t i82091aa_398_device; extern const device_t i82091aa_ide_pri_device; extern const device_t i82091aa_ide_device; diff --git a/src/include/86box/snd_ac97.h b/src/include/86box/snd_ac97.h index 45a921863..a365f5afa 100644 --- a/src/include/86box/snd_ac97.h +++ b/src/include/86box/snd_ac97.h @@ -100,6 +100,7 @@ #define AC97_CODEC_STAC9708 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x08) #define AC97_CODEC_STAC9721 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x09) #define AC97_CODEC_TR28023 AC97_VENDOR_ID('T', 'R', 'A', 0x03) +#define AC97_CODEC_W83971D AC97_VENDOR_ID('W', 'E', 'C', 0x01) #define AC97_CODEC_WM9701A AC97_VENDOR_ID('W', 'M', 'L', 0x00) typedef struct ac97_vendor_reg_t { @@ -150,6 +151,7 @@ extern const device_t cs4297a_device; extern const device_t stac9708_device; extern const device_t stac9721_device; extern const device_t tr28023_device; +extern const device_t w83971d_device; extern const device_t wm9701a_device; extern const device_t ac97_via_device; diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index b084bfbbd..e7aa66662 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -281,6 +281,26 @@ machine_at_micronics386_init(const machine_t *model) return ret; } +int +machine_at_micronics386px_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/micronics386/386-Micronics-09-00021-LO.BIN", + "roms/machines/micronics386/386-Micronics-09-00021-HI.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_init(model); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_scat_init(const machine_t *model, int is_v4, int is_ami) { @@ -704,7 +724,9 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5402_onboard_device); - machine_at_common_ide_init(model); + machine_at_common_init_ex(model, 2); + + device_add(&ide_isa_device); device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */ device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */ diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index e75c5414e..c2cf82352 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -134,6 +134,27 @@ machine_at_tandy4000_init(const machine_t *model) return ret; } +int +machine_at_dtk461_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dtk461/DTK.BIO", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sl82c461_device); + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_sis401_common_init(const machine_t *model) { @@ -391,14 +412,16 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); - - device_add(&vl82c480_device); - if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + device_add(&vl82c113_device); + + device_add(&ide_isa_device); device_add(&fdc37c651_ide_device); return ret; @@ -415,14 +438,18 @@ machine_at_d824_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); - - device_add(&vl82c480_device); - if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); - device_add(&keyboard_ps2_device); + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + + /* + Technically, it should be the VL82C114 but we do not have + a proper datasheet of it that tells us the registers. + */ + device_add(&vl82c113_device); device_add(&ide_isa_device); device_add(&fdc37c651_device); @@ -430,6 +457,30 @@ machine_at_d824_init(const machine_t *model) return ret; } +int +machine_at_martin_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/martin/NONSCSI.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + device_add(&vl82c113_device); + + device_add(&ide_vlb_device); + device_add(&fdc37c651_ide_device); + + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_acera1g_init(const machine_t *model) { @@ -705,7 +756,6 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } - static const device_config_t pb450_config[] = { // clang-format off { @@ -1589,6 +1639,91 @@ machine_at_486sp3g_init(const machine_t *model) return ret; } +static const device_config_t sb486pv_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "sb486pv", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "AMI 062594 (0108)", .internal_name = "sb486pv", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/41-0108-062594-SATURN2.rom", "" } }, + { .name = "AMI 062594 (0301)", .internal_name = "sb486pv_94", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/0301-062594-SATURN2.rom", "" } }, + { .name = "AMI 071595 (1301)", .internal_name = "sb486pv_95", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/amiboot.rom", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t sb486pv_device = { + .name = "ICS SB486PV", + .internal_name = "sb486pv_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = sb486pv_config +}; + +int +machine_at_sb486pv_init(const machine_t *model) +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + else + ret = bios_load_linear_inverted(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init(model); + // machine_at_common_init_ex(model, 2); + + // device_add(&amstrad_megapc_nvr_device); + device_add(&ide_pci_device); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0e, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0f, PCI_CARD_VIDEO, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sio_zb_device); + device_add(&ide_rz1000_pci_single_channel_device); + device_add(&i82091aa_26e_device); + if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) + device_add(&intel_flash_bxt_device); + else + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420zx_device); + + return ret; +} + int machine_at_486ap4_init(const machine_t *model) { @@ -1782,12 +1917,11 @@ machine_at_sbc490_init(const machine_t *model) pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + device_add(&ali1489_device); device_add(&fdc37c665_device); - - if (gfxcard[0] == VID_INTERNAL) - device_add(&tgui9440_onboard_pci_device); - device_add(&keyboard_ps2_ami_device); device_add(&sst_flash_29ee010_device); diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 904122bad..1f5ecdb58 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -61,11 +61,6 @@ enum { /*Very rough estimate*/ #define VID_CLOCK (double) (651 * 416 * 60) -static uint8_t cga_crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - /* Mapping of attributes to colours */ static uint32_t amber; static uint32_t black; @@ -89,17 +84,14 @@ compaq_plasma_display_set(uint8_t internal) cpq_st_display_internal = internal; } -static uint8_t -compaq_plasma_display_get(void) -{ - return cpq_st_display_internal; -} - typedef struct compaq_plasma_t { cga_t cga; + mem_mapping_t font_ram_mapping; + uint8_t *font_ram; + uint8_t port_13c6; uint8_t port_23c6; + uint8_t port_27c6; uint8_t internal_monitor; - uint8_t attrmap; } compaq_plasma_t; static int compaq_machine_type = 0; @@ -116,14 +108,14 @@ compaq_plasma_recalctimings(compaq_plasma_t *self) double _dispofftime; double disptime; - if (!self->internal_monitor && !(self->port_23c6 & 1)) { + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { cga_recalctimings(&self->cga); return; } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); } @@ -143,10 +135,13 @@ compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - self->cga.vram[addr & 0x7fff] = val; + if (self->port_23c6 & 0x08) + self->font_ram[addr & 0x1fff] = val; + else + self->cga.vram[addr & 0x7fff] = val; + compaq_plasma_waitstates(&self->cga); } - static uint8_t compaq_plasma_read(uint32_t addr, void *priv) { @@ -154,7 +149,11 @@ compaq_plasma_read(uint32_t addr, void *priv) uint8_t ret; compaq_plasma_waitstates(&self->cga); - ret = (self->cga.vram[addr & 0x7fff]); + + if (self->port_23c6 & 0x08) + ret = (self->font_ram[addr & 0x1fff]); + else + ret = (self->cga.vram[addr & 0x7fff]); return ret; } @@ -163,33 +162,23 @@ static void compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t old; switch (addr) { /* Emulated CRTC, register select */ + case 0x3d0: + case 0x3d2: case 0x3d4: + case 0x3d6: cga_out(addr, val, &self->cga); break; /* Emulated CRTC, value */ + case 0x3d1: + case 0x3d3: case 0x3d5: - old = self->cga.crtc[self->cga.crtcreg]; - self->cga.crtc[self->cga.crtcreg] = val & cga_crtcmask[self->cga.crtcreg]; - - /* Register 0x12 controls the attribute mappings for the - * plasma screen. */ - if (self->cga.crtcreg == 0x12) { - self->attrmap = val; - compaq_plasma_recalcattrs(self); - break; - } - - if (old != val) { - if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) { - self->cga.fullchange = changeframecount; - compaq_plasma_recalctimings(self); - } - } + case 0x3d7: + cga_out(addr, val, &self->cga); + compaq_plasma_recalctimings(self); break; case 0x3d8: case 0x3d9: @@ -197,15 +186,26 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) break; case 0x13c6: - compaq_plasma_display_set((val & 8) ? 1 : 0); + self->port_13c6 = val; + compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0); + /* + For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA; + Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA; + This leads me to believe bit 2 is not relevant to the mode. + */ + if ((val & 0x03) == 0x03) + mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000); + else + mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000); break; case 0x23c6: self->port_23c6 = val; - if (val & 8) /* Disable internal CGA */ - mem_mapping_disable(&self->cga.mapping); - else - mem_mapping_enable(&self->cga.mapping); + compaq_plasma_recalcattrs(self); + break; + + case 0x27c6: + self->port_27c6 = val; break; default: @@ -222,37 +222,44 @@ compaq_plasma_in(uint16_t addr, void *priv) switch (addr) { case 0x3d4: case 0x3da: + case 0x3db: + case 0x3dc: ret = cga_in(addr, &self->cga); break; + case 0x3d1: + case 0x3d3: case 0x3d5: - if (self->cga.crtcreg == 0x12) { - ret = self->attrmap & 0x0f; - if (self->internal_monitor) - ret |= 0x30; /* Plasma / CRT */ - } else - ret = cga_in(addr, &self->cga); + case 0x3d7: + ret = cga_in(addr, &self->cga); + break; + + case 0x3d8: + ret = self->cga.cgamode; break; case 0x13c6: - ret = compaq_plasma_display_get() ? 8 : 0; - ret |= 4; + ret = self->port_13c6; +#if 0 + if ((self->cga.cgamode & 0x28) == 0x00) + ret |= 0x04; +#endif + break; + + case 0x17c6: + ret = 0xe6; break; case 0x1bc6: - ret = 0; - if (compaq_plasma_display_get()) { - if ((self->cga.cgamode & 0x12) == 0x12) { - if (self->port_23c6 & 8) - ret |= 0x40; - else - ret |= 0x20; - } - } + ret = 0x40; break; case 0x23c6: - ret = 0; + ret = self->port_23c6; + break; + + case 0x27c6: + ret = self->port_27c6 & 0x3f; break; default: @@ -276,6 +283,8 @@ compaq_plasma_poll(void *priv) int cursorline; int blink = 0; int underline = 0; + int c; + int x; uint32_t ink = 0; uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black; uint32_t bg = black; @@ -292,230 +301,303 @@ compaq_plasma_poll(void *priv) } /* graphic mode and not mode 40h */ - if (!self->internal_monitor && !(self->port_23c6 & 1)) { + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { + /* standard cga mode */ cga_poll(&self->cga); return; - } + } else { + /* mode 40h or text mode */ + if (!self->cga.linepos) { + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); + self->cga.cgastat |= 1; + self->cga.linepos = 1; + if (self->cga.cgadispon) { + if (self->cga.displine == 0) + video_wait_for_buffer(); - /* mode 40h or text mode */ - if (!self->cga.linepos) { - timer_advance_u64(&self->cga.timer, self->cga.dispofftime); - self->cga.cgastat |= 1; - self->cga.linepos = 1; - if (self->cga.cgadispon) { - if (self->cga.displine == 0) { - video_wait_for_buffer(); - } - if (self->cga.cgamode & 2) { - if (self->cga.cgamode & 0x10) { - /* 640x400 mode */ - if (self->port_23c6 & 1) /* 640*400 */ { - addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7FFF]; - addr++; + /* 80-col */ + if (self->cga.cgamode & 0x01) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1; + ma += (self->cga.displine >> 4) * 80; - for (uint8_t c = 0; c < 8; c++) { - ink = (dat & 0x80) ? fg : bg; - if (!(self->cga.cgamode & 8)) - ink = black; - (buffer32->line[self->cga.displine])[x * 8 + c] = ink; - dat <<= 1; + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + + /* for each text column */ + for (x = 0; x < 80; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else { + chr = 0x00; + attr = 0x00; } + uint8_t hi_bit = attr & 0x08; + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = ((attr & 0x07) == 0x01); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + } + + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && hi_bit) + chr_addr |= 0x1000; + + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + + if (hi_bit) { + if ((self->port_23c6 >> 5) == 1) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); + } else if ((self->port_23c6 >> 5) == 4) { + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16); + } + } + } + ma++; + } + } + /* 40-col */ + else if (!(self->cga.cgamode & 0x02)) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1; + ma += (self->cga.displine >> 4) * 40; + + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + + for (x = 0; x < 40; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else { + chr = 0x00; + attr = 0x00; + } + uint8_t hi_bit = attr & 0x08; + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = ((attr & 0x07) == 0x01); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + } + + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && hi_bit) + chr_addr |= 0x1000; + + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; + } + + if (hi_bit) { + if ((self->port_23c6 >> 5) == 1) + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black); + } + else if ((self->port_23c6 >> 5) == 4) + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16); + } + } + ma++; } } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7fff]; - addr++; + if (self->cga.cgamode & 0x10) { + /* 640x400 mode */ + if (self->port_23c6 & 0x01) /* 640*400 */ { + addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; - for (uint8_t c = 0; c < 4; c++) { - pattern = (dat & 0xC0) >> 6; - if (!(self->cga.cgamode & 8)) - pattern = 0; - - switch (pattern & 3) { - case 0: - ink0 = ink1 = black; - break; - case 1: - if (self->cga.displine & 1) { - ink0 = black; - ink1 = black; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 2: - if (self->cga.displine & 1) { - ink0 = black; - ink1 = amber; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 3: - ink0 = ink1 = amber; - break; - - default: - break; + for (uint8_t c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(self->cga.cgamode & 0x08)) + ink = black; + buffer32->line[self->cga.displine][(x << 3) + c] = ink; + dat <<= 1; } - buffer32->line[self->cga.displine][x * 8 + 2 * c] = ink0; - buffer32->line[self->cga.displine][x * 8 + 2 * c + 1] = ink1; - dat <<= 2; - } - } - } - } else if (self->cga.cgamode & 1) { - /* 80-col */ - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) * 2; - ma += (self->cga.displine >> 4) * 80; - - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); - - /* for each text column */ - for (uint8_t x = 0; x < 80; x++) { - /* video output enabled */ - chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; - attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); - /* blink active */ - if (self->cga.cgamode & 0x20) { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if (blink) { - /* set blinking */ - cols[1] = cols[0]; } } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; - ++ma; - } - } else { /* 40-col */ - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) * 2; - ma += (self->cga.displine >> 4) * 40; + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(self->cga.cgamode & 0x08)) + pattern = 0; - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); + switch (pattern & 3) { + case 0: + ink0 = ink1 = black; + break; + case 1: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = black; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 2: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = amber; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 3: + ink0 = ink1 = amber; + break; - for (uint8_t x = 0; x < 40; x++) { - chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; - attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); - /* blink active */ - if (self->cga.cgamode & 0x20) { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if (blink) { - /* set blinking */ - cols[1] = cols[0]; + default: + break; + } + buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0; + buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1; + dat <<= 2; + } } - } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; } - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c * 2)] = buffer32->line[self->cga.displine][(x << 4) + (c * 2) + 1] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; } } - } - self->cga.displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (self->cga.displine == 400) { /* Start of VSYNC */ - self->cga.cgastat |= 8; - self->cga.cgadispon = 0; - } - if (self->cga.displine == 416) { /* End of VSYNC */ - self->cga.displine = 0; - self->cga.cgastat &= ~8; - self->cga.cgadispon = 1; - } - } else { - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; + self->cga.displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (self->cga.displine == 400) { /* Start of VSYNC */ + self->cga.cgastat |= 8; + self->cga.cgadispon = 0; + } + if (self->cga.displine == 416) { /* End of VSYNC */ + self->cga.displine = 0; + self->cga.cgastat &= ~8; + self->cga.cgadispon = 1; + } + } else { + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + if (self->cga.cgadispon) + self->cga.cgastat &= ~1; - timer_advance_u64(&self->cga.timer, self->cga.dispontime); - self->cga.linepos = 0; + self->cga.linepos = 0; - if (self->cga.displine == 400) { - /* Hardcode 640x400 window size */ - if ((640 != xsize) || (400 != ysize) || video_force_resize_get()) { + if (self->cga.displine == 400) { xsize = 640; ysize = 400; - if (xsize < 64) - xsize = 656; - if (ysize < 32) - ysize = 200; - set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); + if ((self->cga.cgamode & 0x08) || video_force_resize_get()) { + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + /* Plasma specific */ + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; + + /* Fixed 640x400 resolution */ + video_res_x = 640; + video_res_y = 400; + + if (self->cga.cgamode & 0x02) { + if (self->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + + self->cga.cgablink++; } - video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; - - /* Fixed 640x400 resolution */ - video_res_x = 640; - video_res_y = 400; - - if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & 0x10) - video_bpp = 1; - else - video_bpp = 2; - } else - video_bpp = 0; - - self->cga.cgablink++; } } } @@ -560,7 +642,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) /* Set up colours */ amber = makecol(0xff, 0x7d, 0x00); - black = makecol(0x64, 0x0c, 0x00); + black = makecol(0x64, 0x19, 0x00); /* Initialize the attribute mapping. Start by defaulting everything * to black on amber, and with bold set by bit 3 */ @@ -575,7 +657,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) for (n = 0x11; n <= 0xFF; n++) { if ((n & 7) == 0) continue; - if (self->attrmap & 4) { /* Inverse */ + if ((self->port_23c6 >> 5) == 1) { /* Inverse */ blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; } else { /* Normal */ @@ -588,7 +670,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) for (n = 0x01; n <= 0x0E; n++) { if (n == 7) continue; - if (self->attrmap & 1) { + if ((self->port_23c6 >> 5) == 1) { blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; blinkcols[n + 128][0] = amber; @@ -631,31 +713,31 @@ compaq_plasma_init(UNUSED(const device_t *info)) { compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); + cga_init(&self->cga); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); - if (compaq_machine_type == COMPAQ_PORTABLEIII) - loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2); - else - loadfont_ex("roms/machines/portableiii/P.2 Combined.bin", 11, 0x4b49); self->cga.composite = 0; self->cga.revision = 0; self->cga.vram = malloc(0x8000); self->internal_monitor = 1; + self->font_ram = malloc(0x2000); cga_comp_init(self->cga.revision); - timer_add(&self->cga.timer, compaq_plasma_poll, self, 1); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); + timer_set_callback(&self->cga.timer, compaq_plasma_poll); + timer_set_p(&self->cga.timer, self); + + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, + compaq_plasma_read, NULL, NULL, + compaq_plasma_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, self); + for (int i = 1; i <= 2; i++) { + io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + } io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x13c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x1bc6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x23c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - /* Default attribute mapping is 4 */ - self->attrmap = 4; - compaq_plasma_recalcattrs(self); - - self->cga.cgastat = 0xf4; overscan_x = overscan_y = 16; self->cga.rgb_type = device_get_config_int("rgb_type"); @@ -672,6 +754,7 @@ compaq_plasma_close(void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; free(self->cga.vram); + free(self->font_ram); free(self); } @@ -793,7 +876,8 @@ machine_at_compaq_init(const machine_t *model, int type) switch (type) { case COMPAQ_PORTABLEII: - machine_at_init(model); + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); break; case COMPAQ_PORTABLEIII: @@ -801,7 +885,9 @@ machine_at_compaq_init(const machine_t *model, int type) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); - machine_at_init(model); + + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); break; case COMPAQ_PORTABLEIII386: diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 34e69ed24..9b53257bf 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -69,6 +69,7 @@ extern const device_t pb450_device; extern const device_t jukopc_device; extern const device_t vendex_device; extern const device_t c5sbm2_device; +extern const device_t sb486pv_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -5435,7 +5436,7 @@ const machine_t machines[] = { }, /* Has IBM AT KBC firmware. */ { - .name = "[ISA] Micronics 09-00021", + .name = "[ISA] Micronics 09-00021 (Tandon BIOS)", .internal_name = "micronics386", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_DISCRETE, @@ -5474,6 +5475,46 @@ const machine_t machines[] = { .net_device = NULL }, /* Has IBM AT KBC firmware. */ + { + .name = "[ISA] Micronics 09-00021 (Phoenix BIOS)", + .internal_name = "micronics386px", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_micronics386px_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_APM, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has IBM AT KBC firmware. */ { .name = "[ISA] Tandy 4000", .internal_name = "tandy4000", @@ -6363,6 +6404,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMIKey F KBC firmware. */ + { + .name = "[Symphony SL42C460] DTK PKM-0031Y", + .internal_name = "dtk461", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SYMPHONY_SL82C460, + .init = machine_at_dtk461_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, but it does not write a byte after C9, which is consistent with AMIKey, so @@ -6446,7 +6527,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a standard IBM PS/2 KBC firmware or a clone thereof. */ + /* Has a VLSI VL82C114 Combination I/O which holds the KBC. */ { .name = "[VLSI 82C481] Siemens Nixdorf D824", .internal_name = "d824", @@ -6474,7 +6555,7 @@ const machine_t machines[] = { .max = 32768, .step = 2048 }, - .nvrmask = 127, + .nvrmask = 255, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -6693,6 +6774,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMI MegaKey KBC. */ + { + .name = "[i420TX] J-Bond PCI400C-A", + .internal_name = "pci400ca", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_pci400ca_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_SCSI, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = &keyboard_at_ami_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a standalone AMI Megakey 1993, which is type 'P'. */ { .name = "[IMS 8848] Tekram G486IP", @@ -6854,13 +6975,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMI MegaKey KBC. */ + /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ { - .name = "[i420TX] J-Bond PCI400C-A", - .internal_name = "pci400ca", + .name = "[VLSI 82C480] ZEOS Martin", + .internal_name = "martin", .type = MACHINE_TYPE_486_S2, - .chipset = MACHINE_CHIPSET_INTEL_420TX, - .init = machine_at_pci400ca_init, + .chipset = MACHINE_CHIPSET_VLSI_VL82C480, + .init = machine_at_martin_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -6875,15 +6996,15 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI, - .flags = MACHINE_SCSI, + .bus_flags = MACHINE_PS2_VLB, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { - .min = 1024, + .min = 2048, .max = 65536, - .step = 1024 + .step = 2048 }, .nvrmask = 127, - .kbc_device = &keyboard_at_ami_device, + .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, @@ -6895,7 +7016,6 @@ const machine_t machines[] = { .net_device = NULL }, - /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ /* Has a Fujitsu MBL8042H KBC. */ @@ -8396,6 +8516,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has an AMI MEGAKey 'P' or 'R' keyboard controller. */ + { + .name = "[i420ZX] ICS SB486PV", + .internal_name = "sb486pv", + .type = MACHINE_TYPE_486_S3_PCI, + .chipset = MACHINE_CHIPSET_INTEL_420ZX, + .init = machine_at_sb486pv_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + /* Has PCI but no user-facing slots. */ + .bus_flags = MACHINE_PCI, + .flags = MACHINE_PS2_KBC | MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM | MACHINE_PCI_INTERNAL, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &sb486pv_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5436_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */ { .name = "[IMS 8848] J-Bond PCI400C-B", diff --git a/src/nvr_at.c b/src/nvr_at.c index bde80b434..2acfa47a4 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -296,6 +296,7 @@ #define FLAG_P6RP4_HACK 0x10 #define FLAG_PIIX4 0x20 #define FLAG_MULTI_BANK 0x40 +#define FLAG_MARTIN_HACK 0x80 typedef struct local_t { int8_t stat; @@ -733,6 +734,13 @@ nvr_read(uint16_t addr, void *priv) ret = REGD_VRT; break; + case 0x11: + if (local->flags & FLAG_MARTIN_HACK) + ret = nvr->regs[local->addr[addr_id]] | 0x02; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + case 0x2c: if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK)) ret = nvr->regs[local->addr[addr_id]] & 0x7f; @@ -771,6 +779,17 @@ nvr_read(uint16_t addr, void *priv) ret = checksum >> 8; else ret = checksum & 0xff; + } else if (!nvr->is_new && (local->flags & FLAG_MARTIN_HACK)) { + for (i = 0x10; i <= 0x2d; i++) { + if (i == 0x11) + checksum += (nvr->regs[i] | 0x02); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x2e) + ret = checksum >> 8; + else + ret = checksum & 0xff; } else ret = nvr->regs[local->addr[addr_id]]; break; @@ -1123,9 +1142,11 @@ nvr_at_init(const device_t *info) if (info->local & 0x10) { local->def = 0x00; local->flags |= FLAG_AMI_1992_HACK; - } else if (info->local == 36) + } else if ((info->local == 36) || (info->local == 68)) { local->def = 0x00; - else + if (info->local == 68) + local->flags |= FLAG_MARTIN_HACK; + } else local->def = 0xff; nvr->irq = 8; local->cent = RTC_CENTURY_AT; @@ -1160,6 +1181,9 @@ nvr_at_init(const device_t *info) /* Initialize the generic NVR. */ nvr_init(nvr); + if (nvr->is_new && (local->flags & FLAG_MARTIN_HACK)) + nvr->regs[0x11] = nvr->regs[0x2f] = 0x02; + if (nvr_at_inited == 0) { /* Start the timers. */ timer_add(&local->update_timer, timer_update, nvr, 0); @@ -1426,6 +1450,20 @@ const device_t amstrad_megapc_nvr_device = { .config = NULL }; +const device_t martin_nvr_device = { + .name = "Zeos Martin NVRAM", + .internal_name = "martin_nvr", + .flags = DEVICE_ISA16, + .local = 68, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + .available = NULL, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + const device_t elt_nvr_device = { .name = "Epson Equity LT NVRAM", .internal_name = "elt_nvr", diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index d2ed7ce71..2af5abef9 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -849,8 +849,8 @@ msgstr "一个旧式计算机模拟器\n\n作者: Miran Grča (OBattler)、Richa msgid "Hardware not available" msgstr "硬件不可用" -msgid "Make sure %1 is installed and that you are on a libpcap-compatible network connection." -msgstr "请确认 %1 已安装且使用兼容 libpcap 的网络连接。" +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "请确认 %1 已安装且使用兼容 %1 的网络连接。" msgid "Invalid configuration" msgstr "无效配置" @@ -1240,7 +1240,7 @@ msgid "Host CD/DVD Drive (%1:)" msgstr "主机 CD/DVD 驱动器 (%1:)" msgid "&Connected" -msgstr "" +msgstr "已连接(&C)" msgid "Clear image history" msgstr "清除映像历史记录" @@ -1300,7 +1300,7 @@ msgid "\nFalling back to software rendering." msgstr "\n回到软件渲染。" msgid "

When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.

" -msgstr "

选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。

选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。

" msgid "This machine might have been moved or copied." msgstr "这台机器可能被移动或复制过。" @@ -1315,7 +1315,7 @@ msgid "I Copied It" msgstr "我已复制这台机器" msgid "86Box Monitor #" -msgstr "86Box 监测器 " +msgstr "86Box 监测器 #" msgid "No MCA devices." msgstr "无 MCA 设备。" @@ -1804,7 +1804,7 @@ msgid "Five + Wheel" msgstr "五键+滚轮" msgid "Five + 2 Wheels" -msgstr "" +msgstr "五键+双滚轮" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 串行 / SMT3(R)V" @@ -2050,25 +2050,25 @@ msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM 磁盘 (最大速度)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Generic] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Generic] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Generic] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Generic] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 克隆 (ISA)" @@ -2076,6 +2076,12 @@ msgstr "IBM 8514/A 克隆 (ISA)" msgid "Vendor" msgstr "制造商" +msgid "30 Hz (JMP2 = 1)" +msgstr "30 Hz (JMP2 = 1)" + +msgid "60 Hz (JMP2 = 2)" +msgstr "60 Hz (JMP2 = 2)" + msgid "Generic PC/XT Memory Expansion" msgstr "通用 PC/XT 内存扩展" @@ -2089,61 +2095,61 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t msgstr "仿真通用 ESC/P 点阵打印机需要使用 \"roms/printer/fonts\" 目录中的 TrueType 字体。" msgid "Inhibit multimedia keys" -msgstr "" +msgstr "禁止多媒体按键" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "保存设置前要求用户确认" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "硬重置前要求用户确认" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "退出前要求用户确认" msgid "Options" -msgstr "" +msgstr "选项" msgid "Model" -msgstr "" +msgstr "模型" msgid "Model:" -msgstr "" +msgstr "模型:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Vulkan 渲染器初始化失败。" msgid "GLSL Error" -msgstr "" +msgstr "GLSL 错误" msgid "Could not load shader: %1" -msgstr "" +msgstr "无法加载着色器:%1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "OpenGL 版本需要达到 3.0 或更高。当前 GLSL 版本为 %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "无法加载材质:%1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "无法编译着色器:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "程序未链接:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "着色器管理器" msgid "Shader Configuration" -msgstr "" +msgstr "着色器配置" msgid "Add" -msgstr "" +msgstr "添加" msgid "Move up" -msgstr "" +msgstr "上移" msgid "Move down" -msgstr "" +msgstr "下移" msgid "Could not load file %1" -msgstr "" +msgstr "无法加载文件 %1" diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index d3cd5017a..71f8749f2 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -295,6 +295,20 @@ const device_t i82091aa_device = { .config = NULL }; +const device_t i82091aa_26e_device = { + .name = "Intel 82091AA Super I/O (Port 26Eh)", + .internal_name = "i82091aa_26e", + .flags = 0, + .local = 0x140, + .init = i82091aa_init, + .close = i82091aa_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t i82091aa_398_device = { .name = "Intel 82091AA Super I/O (Port 398h)", .internal_name = "i82091aa_398", diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c index ee18b1893..b000fe5dd 100644 --- a/src/sio/sio_vl82c113.c +++ b/src/sio/sio_vl82c113.c @@ -22,6 +22,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/keyboard.h> +#include <86box/machine.h> #include <86box/nvr.h> #include <86box/sio.h> #include <86box/plat_unused.h> @@ -133,7 +134,10 @@ vl82c113_init(UNUSED(const device_t *info)) { vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t)); - dev->nvr = device_add(&at_nvr_device); + if (!strcmp(machine_get_internal_name(), "martin")) + dev->nvr = device_add(&martin_nvr_device); + else + dev->nvr = device_add(&amstrad_megapc_nvr_device); dev->nvr_enabled = 1; dev->nvr_base = 0x0070; diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index e92830f67..1b28a8aab 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -68,7 +68,6 @@ static const struct { .device = &cs4297_device, .misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_AUXOUT_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, .reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, .pcsr_mask = 0x7f, .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x5a, 0x0301, 0x0000}, {0}} }, @@ -100,15 +99,18 @@ static const struct { { .device = &tr28023_device, .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_POP | AC97_MS | AC97_LPBK, - .reset_flags = 0, - .extid_flags = 0, + .pcsr_mask = 0x3f + }, + { + .device = &w83971d_device, + .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = (27 << AC97_3D_SHIFT), .pcsr_mask = 0x3f }, { .device = &wm9701a_device, .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, .reset_flags = AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, .pcsr_mask = 0x3f } // clang-format on @@ -284,8 +286,9 @@ line_gain: case 0x22: /* 3D Control */ switch (ac97_codecs[dev->model].reset_flags >> AC97_3D_SHIFT) { - case 1: /* Analog Devices */ - case 6: /* Crystal */ + case 1: /* Analog Devices */ + case 6: /* Crystal */ + case 27: /* Winbond */ val &= 0x000f; break; @@ -764,6 +767,20 @@ const device_t tr28023_device = { .config = NULL }; +const device_t w83971d_device = { + .name = "Winbond W83971D", + .internal_name = "w83971d", + .flags = DEVICE_AC97, + .local = AC97_CODEC_W83971D, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t wm9701a_device = { .name = "Wolfson WM9701A", .internal_name = "wm9701a", diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 43c4e22b2..dbb9d5993 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -33,6 +33,7 @@ #include <86box/pci.h> #include <86box/rom.h> #include <86box/device.h> +#include <86box/machine.h> #include <86box/timer.h> #include <86box/video.h> #include <86box/i2c.h> @@ -4316,7 +4317,8 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5436: - if (info->local & 0x200) { + if ((info->local & 0x200) && + !strstr(machine_get_internal_name(), "sb486pv")) { romfn = NULL; gd54xx->has_bios = 0; } else @@ -4461,8 +4463,8 @@ gd54xx_init(const device_t *info) } io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); - if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430) { - if (romfn == NULL) + if (gd54xx->pci && (id >= CIRRUS_ID_CLGD5430)) { + if (info->local & 0x200) pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); else pci_add_card(PCI_ADD_NORMAL, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot);