From b7e2e239e849ef109ef5f3198f4051f3825b26d0 Mon Sep 17 00:00:00 2001 From: EngiNerd89 Date: Sat, 6 Feb 2021 23:58:39 +0100 Subject: [PATCH 01/34] Added chipset and xta interface to Philips machines. Major refactoring. --- src/chipset/CMakeLists.txt | 1 + src/chipset/gc100.c | 256 +++++++++++++++++++++++++++ src/device/olivetti_m290_registers.c | 117 ------------ src/include/86box/chipset.h | 4 + src/include/86box/machine.h | 13 +- src/machine/CMakeLists.txt | 1 + src/machine/m_at_286_386sx.c | 219 +---------------------- src/machine/m_xt.c | 58 +----- src/machine/m_xt_olivetti.c | 38 +--- src/machine/m_xt_philips.c | 204 +++++++++++++++++++++ src/machine/machine_table.c | 11 +- src/win/Makefile.mingw | 6 +- 12 files changed, 481 insertions(+), 447 deletions(-) create mode 100644 src/chipset/gc100.c delete mode 100644 src/device/olivetti_m290_registers.c create mode 100644 src/machine/m_xt_philips.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index c3a0b18e2..f8c01a631 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c headland.c int cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti495.c opti895.c opti5x7.c scamp.c scat.c via_vt82c49x.c via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c + gc100.c opti283.c opti291.c via_apollo.c via_pipc.c wd76c10.c vl82c480.c) diff --git a/src/chipset/gc100.c b/src/chipset/gc100.c new file mode 100644 index 000000000..97c944f74 --- /dev/null +++ b/src/chipset/gc100.c @@ -0,0 +1,256 @@ +/* + * 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 G2 GC100/GC100A chipset. + * NOTE: As documentation is currently available only for the + * CG100 chipset, the GC100A chipset has been reverese-engineered. + * Thus, its behavior may not be fully accurate. + * + * Authors: EngiNerd + * + * Copyright 2020-2021 EngiNerd + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/nmi.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/mem.h> +#include <86box/device.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/hdc.h> +#include <86box/gameport.h> +#include <86box/ibm_5161.h> +#include <86box/keyboard.h> +#include <86box/rom.h> +#include <86box/machine.h> +#include <86box/chipset.h> +#include <86box/io.h> +#include <86box/video.h> + +typedef struct +{ + uint8_t reg[0x10]; +} gc100_t; + +#define ENABLE_GC100_LOG 1 + +#ifdef ENABLE_GC100_LOG +int gc100_do_log = ENABLE_GC100_LOG; +static void +gc100_log(const char *fmt, ...) +{ + va_list ap; + + if (gc100_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define gc100_log(fmt, ...) +#endif + +static uint8_t +get_fdd_switch_settings(){ + + int i, fdd_count = 0; + + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + + if (!fdd_count) + return 0x00; + else + return ((fdd_count - 1) << 6) | 0x01; + +} + +static uint8_t +get_videomode_switch_settings(){ + + if (video_is_mda()) + return 0x30; + else if (video_is_cga()) + return 0x20; /* 0x10 would be 40x25 */ + else + return 0x00; + +} + +static void +gc100_write(uint16_t port, uint8_t val, void *priv) +{ + gc100_t *dev = (gc100_t *) priv; + + uint16_t addr = port & 0xf; + + dev->reg[addr] = val; + + switch (addr) + { + /* addr 0x2 + * bits 5-7: not used + * bit 4: intenal memory wait states + * bits 2-3: external memory wait states + * bits 0-1: i/o access wait states + */ + case 0x2: + break; + + /* addr 0x3 + * bits 1-7: not used + * bit 0: turbo 0 xt 1 + */ + case 0x3: + if (val & 0x1) + cpu_dynamic_switch(0); + else + cpu_dynamic_switch(cpu); + break; + + /* addr 0x5 + * programmable dip-switches + * bits 6-7: floppy drive number + * bits 4-5: video mode + * bits 2-3: memory size + * bit 1: fpu + * bit 0: not used + */ + + /* addr 0x6 */ + + /* addr 0x7 */ + + } + + gc100_log("GC100: Write %02x at %02x\n", val, port); + +} + +static uint8_t +gc100_read(uint16_t port, void *priv) +{ + gc100_t *dev = (gc100_t *) priv; + uint8_t ret = 0xff; + + uint16_t addr = port & 0xf; + + ret = dev->reg[addr]; + + gc100_log("GC100: Read %02x at %02x\n", ret, port); + + switch (addr) + { + /* addr 0x2 + * bits 5-7: not used + * bit 4: intenal memory wait states + * bits 2-3: external memory wait states + * bits 0-1: i/o access wait states + */ + case 0x2: + break; + + /* addr 0x3 + * bits 1-7: not used + * bit 0: turbo 0 xt 1 + */ + case 0x3: + break; + + /* addr 0x5 + * programmable dip-switches + * bits 6-7: floppy drive number + * bits 4-5: video mode + * bits 2-3: memory size + * bit 1: fpu + * bit 0: not used + */ + case 0x5: + ret = ret & 0x0c; + ret |= get_fdd_switch_settings(); + ret |= get_videomode_switch_settings(); + if (hasfpu) + ret |= 0x02; + + break; + + /* addr 0x6 */ + + /* addr 0x7 */ + + } + + return ret; +} + + +static void +gc100_close(void *priv) +{ + gc100_t *dev = (gc100_t *) priv; + + free(dev); +} + +static void * +gc100_init(const device_t *info) +{ + gc100_t *dev = (gc100_t *) malloc(sizeof(gc100_t)); + memset(dev, 0, sizeof(gc100_t)); + + dev->reg[0x2] = 0xff; + dev->reg[0x3] = 0x0; + dev->reg[0x5] = 0x0; + dev->reg[0x6] = 0x0; + dev->reg[0x7] = 0x0; + + /* GC100A */ + if(info->local) { + io_sethandler(0x0c2, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); + io_sethandler(0x0c5, 0x03, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); + } + /* GC100 */ + else { + io_sethandler(0x022, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); + io_sethandler(0x025, 0x01, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev); + } + + return dev; +} + +const device_t gc100_device = { + "G2 GC100", + 0, + 0, + gc100_init, gc100_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + +const device_t gc100a_device = { + "G2 GC100A", + 0, + 1, + gc100_init, gc100_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + diff --git a/src/device/olivetti_m290_registers.c b/src/device/olivetti_m290_registers.c deleted file mode 100644 index abe931c91..000000000 --- a/src/device/olivetti_m290_registers.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 Olivetti M290 registers Readout - * - * Authors: EngiNerd - * - * Copyright 2020-2021 EngiNerd - */ - - -#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/chipset.h> -#include <86box/video.h> - -typedef struct -{ - uint8_t reg_067; - uint8_t reg_069; -} olivetti_m290_registers_t; - -#ifdef ENABLE_OLIVETTI_M290_REGISTERS_LOG -int olivetti_m290_registers_do_log = ENABLE_OLIVETTI_M290_REGISTERS_LOG; -static void -olivetti_m290_registers_log(const char *fmt, ...) -{ - va_list ap; - - if (olivetti_m290_registers_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define olivetti_m290_registers_log(fmt, ...) -#endif - -static void -olivetti_m290_registers_write(uint16_t addr, uint8_t val, void *priv) -{ - olivetti_m290_registers_t *dev = (olivetti_m290_registers_t *) priv; - olivetti_m290_registers_log("Olivetti M290 registers: Write %02x at %02x\n", val, addr); - switch (addr) { - case 0x067: - dev->reg_067 = val; - break; - case 0x069: - dev->reg_069 = val; - break; - } -} - -static uint8_t -olivetti_m290_registers_read(uint16_t addr, void *priv) -{ - olivetti_m290_registers_t *dev = (olivetti_m290_registers_t *) priv; - uint8_t ret = 0xff; - switch (addr) { - case 0x067: - ret = dev->reg_067; - break; - case 0x069: - ret = dev->reg_069; - break; - } - olivetti_m290_registers_log("Olivetti M290 registers: Read %02x at %02x\n", ret, addr); - return ret; -} - - -static void -olivetti_m290_registers_close(void *priv) -{ - olivetti_m290_registers_t *dev = (olivetti_m290_registers_t *) priv; - - free(dev); -} - -static void * -olivetti_m290_registers_init(const device_t *info) -{ - olivetti_m290_registers_t *dev = (olivetti_m290_registers_t *) malloc(sizeof(olivetti_m290_registers_t)); - memset(dev, 0, sizeof(olivetti_m290_registers_t)); - - dev->reg_067 = 0x0; - dev->reg_069 = 0x0; - - io_sethandler(0x0067, 0x0003, olivetti_m290_registers_read, NULL, NULL, olivetti_m290_registers_write, NULL, NULL, dev); - - return dev; -} - -const device_t olivetti_m290_registers_device = { - "Olivetti M290 registers Readout", - 0, - 0, - olivetti_m290_registers_init, olivetti_m290_registers_close, NULL, - { NULL }, NULL, NULL, - NULL -}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index c2db87326..449602130 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -46,6 +46,10 @@ extern const device_t scat_sx_device; extern const device_t cs8230_device; extern const device_t cs4031_device; +/* G2 */ +extern const device_t gc100_device; +extern const device_t gc100a_device; + /* Headland */ extern const device_t headland_gc10x_device; extern const device_t headland_ht18a_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 5ab578d04..1e7bb2cac 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -255,9 +255,6 @@ extern int machine_at_spc4620p_init(const machine_t *); extern int machine_at_kmxc02_init(const machine_t *); extern int machine_at_deskmaster286_init(const machine_t *); -extern int machine_at_olim290_init(const machine_t *); -extern int machine_at_olim290s_init(const machine_t *); - extern int machine_at_ncrpc8_init(const machine_t *); extern int machine_at_ncr3302_init(const machine_t *); @@ -269,13 +266,6 @@ extern int machine_at_spc6033p_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); extern int machine_at_flytech386_init(const machine_t *); -extern int machine_at_olim300_05_init(const machine_t *); -extern int machine_at_olim300_10_init(const machine_t *); -extern int machine_at_olim300_08_init(const machine_t *); -extern int machine_at_olim300_15_init(const machine_t *); - -extern int machine_at_ncrpc916sx_init(const machine_t *); - extern int machine_at_awardsx_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_M6117) extern int machine_at_arb1375_init(const machine_t *); @@ -643,6 +633,9 @@ extern int machine_xt_laserxt_init(const machine_t *); extern int machine_xt_lxt3_init(const machine_t *); #endif +/* m_xt_philips.c */ +extern int machine_xt_p3105_init(const machine_t *); +extern int machine_xt_p3120_init(const machine_t *); /* m_xt_t1000.c */ extern int machine_xt_t1000_init(const machine_t *); extern int machine_xt_t1200_init(const machine_t *); diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 7576ae130..846ab6074 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -14,6 +14,7 @@ # add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c + m_xt_philips.c m_xt_t1000.c m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_at.c m_at_commodore.c m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 1c2b6526c..409f74c3e 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -40,6 +40,7 @@ #include <86box/sio.h> #include <86box/serial.h> #include <86box/video.h> +#include <86box/vid_cga.h> #include <86box/flash.h> #include <86box/machine.h> @@ -694,7 +695,7 @@ machine_at_ncrpc8_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); - + return ret; } @@ -735,218 +736,4 @@ machine_at_ncr3302_init(const machine_t *model) device_add(¶dise_pvga1a_ncr3302_device); return ret; -} - - -/* - * Current bugs: - * - soft-reboot after saving CMOS settings/pressing ctrl-alt-del produces an 8042 error - */ -int -machine_at_ncrpc916sx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_interleaved(L"roms/machines/ncr_pc916sx/ncr_386sx_u46-17_7.3.bin", - L"roms/machines/ncr_pc916sx/ncr_386sx_u12-19_7.3.bin", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&keyboard_at_ncr_device); - mem_remap_top(384); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - - - return ret; -} - -/* - * Current bugs: - * - no EMS management due to missing chipset implementation (custom ASIC) - */ -int -machine_at_olim290_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/olivetti_m290/m290_pep3_1.25.bin", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - device_add(&keyboard_at_olivetti_device); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - - device_add(&olivetti_m290_registers_device); - - return ret; -} - - -/* - * Current bugs: - * - no EMS management due to missing chipset implementation (unidentified chip) - */ -int -machine_at_olim290s_init(const machine_t *model) -{ - int ret; - - ret = bios_load_interleaved(L"roms/machines/olivetti_m290s/286-olivetti-m203-low.bin", - L"roms/machines/olivetti_m290s/286-olivetti-m203-high.bin", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_ide_init(model); - - /* replace with correct chipset implementation */ - mem_remap_top(384); - - device_add(&keyboard_ps2_olivetti_device); - device_add(&fdc_at_device); - - /* should use custom BIOS */ - if (gfxcard == VID_INTERNAL) - device_add(¶dise_pvga1a_device); - - return ret; -} - -const device_t * -at_m300_08_get_device(void) -{ - return &oti067_m300_device; -} - -int -machine_at_olim300_08_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/olivetti_m300_08/BIOS.ROM", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&opti283_device); - device_add(&keyboard_ps2_olivetti_device); - device_add(&pc87310_ide_device); - - if (gfxcard == VID_INTERNAL) - device_add(&oti067_m300_device); - - return ret; -} - -/* Almost identical to M300-08, save for CPU speed, VRAM, and BIOS identification string */ -int -machine_at_olim300_15_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/olivetti_m300_15/BIOS.ROM", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&opti283_device); - device_add(&keyboard_ps2_olivetti_device); - device_add(&pc87310_ide_device); - - /* Stock VRAM is maxed out, so no need to expose video card config */ - if (gfxcard == VID_INTERNAL) - device_add(&oti067_m300_device); - - return ret; -} - - -/* - * Current bugs: - * - soft-reboot causes a fatal error - * - BIOS complains about FPU if not installed, pressing F1 allows to continue booting. - * - BIOS throws a cache memory error (since L2 cache is not implemented yet), pressing F1 allows to continue booting. - * - no shadow memory due to missing chipset implementation (custom ASIC) - */ -//todo: check if fdc can be disabled -int -machine_at_olim300_10_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/olivetti_m300_10/BIOS.ROM", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_ide_init(model); - - /* replace with correct chipset implementation */ - mem_remap_top(384); - - device_add(&keyboard_ps2_olivetti_device); - /* fdc should be dp8473, however it does not work. Instead, standard AT fdc works. */ - device_add(&fdc_at_device); - - /* should be a PVGA1B/WD90C00 with custom BIOS */ - if (gfxcard == VID_INTERNAL) - device_add(¶dise_wd90c11_device); - - - return ret; -} - -/* - * Current bugs: - * - soft-reboot causes a fatal error - * - BIOS complains about FPU if not installed, pressing F1 allows to continue booting. - * - no shadow memory due to missing chipset implementation (custom ASIC) - */ -int -machine_at_olim300_05_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/olivetti_m300_05/BIOS.ROM", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_ide_init(model); - - /* replace with correct chipset implementation */ - mem_remap_top(384); - - device_add(&keyboard_ps2_olivetti_device); - /* fdc should be dp8473, however it does not work. Instead, standard AT fdc works. */ - device_add(&fdc_at_device); - - /* should be a PVGA1B/WD90C00 with custom BIOS */ - if (gfxcard == VID_INTERNAL) - device_add(¶dise_wd90c11_device); - - - return ret; -} - - +} \ No newline at end of file diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 7640b0932..698cc46ca 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -11,12 +11,13 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> +#include <86box/hdc.h> #include <86box/gameport.h> #include <86box/ibm_5161.h> #include <86box/keyboard.h> #include <86box/rom.h> #include <86box/machine.h> - +#include <86box/chipset.h> static void machine_xt_common_init(const machine_t *model) @@ -399,58 +400,3 @@ machine_xt_multitechpc700_init(const machine_t *model) return ret; } - -/* - * Current bugs and limitations: - * - 640-768 conventional memory not usable (should be mapped at address d0000-effff) - */ -int -machine_xt_p3105_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/philips_p3105/philipsnms9100.bin", - 0x000fc000, 16384, 0); - - if (bios_only || !ret) - return ret; - - device_add(&keyboard_pc_device); - - machine_xt_common_init(model); - - return ret; -} - -/* - * Current bugs and limitations: - * - 640-768 conventional memory not usable (should be mapped at address d0000-effff) - * - BIOS detects 4 fdds, so hdd letter is E instead of C - */ -int -machine_xt_p3120_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/philips_p3120/philips_p3120.bin", - 0x000f8000, 32768, 0); - - if (bios_only || !ret) - return ret; - - device_add(&keyboard_pc_device); - - machine_common_init(model); - - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - - nmi_init(); - - if (joystick_type) - device_add(&gameport_device); - - return ret; -} \ No newline at end of file diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 27716cd8c..ec2cfb8e9 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -771,7 +771,7 @@ machine_xt_olim240_init(const machine_t *model) */ device_add(&keyboard_at_olivetti_device); - /* FIXME: make sure this is correct?? */ + /* FIXME: make sure this is correct?? */ device_add(&at_nvr_device); if (fdc_type == FDC_INTERNAL) @@ -822,39 +822,3 @@ machine_xt_olim19_init(const machine_t *model) return ret; } - - -/* not working, returns timer error */ -/* it appears to be a rebadged Hitachi HL 320 laptop */ -int -machine_xt_olim15_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/olivetti_m15/oliv_m15.bin", - 0x000fc000, 16384, 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_olivetti_device); - - device_add(&cga_device); - - /* FIXME: make sure this is correct?? */ - //device_add(&at_nvr_device); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); - - if (joystick_type) - device_add(&gameport_device); - - nmi_init(); - - return ret; -} \ No newline at end of file diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c new file mode 100644 index 000000000..722b117ee --- /dev/null +++ b/src/machine/m_xt_philips.c @@ -0,0 +1,204 @@ +/* + * 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. + * + * Emulation of the Philips XT-compatible machines. + * + * + * + * Authors: EngiNerd + * + * Copyright 2020-2021 EngiNerd. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/nmi.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/mem.h> +#include <86box/device.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/hdc.h> +#include <86box/gameport.h> +#include <86box/ibm_5161.h> +#include <86box/keyboard.h> +#include <86box/rom.h> +#include <86box/machine.h> +#include <86box/chipset.h> +#include <86box/io.h> +#include <86box/video.h> + +typedef struct +{ + uint8_t reg; +} philips_t; + +#define ENABLE_philips_LOG 1 + +#ifdef ENABLE_philips_LOG +int philips_do_log = ENABLE_philips_LOG; +static void +philips_log(const char *fmt, ...) +{ + va_list ap; + + if (philips_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define philips_log(fmt, ...) +#endif + +static void +philips_write(uint16_t port, uint8_t val, void *priv) +{ + philips_t *dev = (philips_t *) priv; + + switch (port) + { + /* port 0xc0 + * bit 7: turbo + * bits 4-5: rtc read/set + * bit 2: parity disabled + */ + case 0xc0: + dev->reg = val; + if (val & 0x80) + cpu_dynamic_switch(cpu); + else + cpu_dynamic_switch(0); + break; + } + + philips_log("Philips XT Mainboard: Write %02x at %02x\n", val, port); + +} + +static uint8_t +philips_read(uint16_t port, void *priv) +{ + philips_t *dev = (philips_t *) priv; + uint8_t ret = 0xff; + + switch (port) + { + /* port 0xc0 + * bit 7: turbo + * bits 4-5: rtc read/set + * bit 2: parity disabled + */ + case 0xc0: + ret = dev->reg; + break; + + } + + philips_log("Philips XT Mainboard: Read %02x at %02x\n", ret, port); + + return ret; +} + + +static void +philips_close(void *priv) +{ + philips_t *dev = (philips_t *) priv; + + free(dev); +} + +static void * +philips_init(const device_t *info) +{ + philips_t *dev = (philips_t *) malloc(sizeof(philips_t)); + memset(dev, 0, sizeof(philips_t)); + + dev->reg = 0x40; + + io_sethandler(0x0c0, 0x01, philips_read, NULL, NULL, philips_write, NULL, NULL, dev); + + return dev; +} + +const device_t philips_device = { + "Philips XT Mainboard", + 0, + 0, + philips_init, philips_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + +void +machine_xt_philips_common_init(const machine_t *model) +{ + machine_common_init(model); + + pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + nmi_init(); + + if (joystick_type) + device_add(&gameport_device); + + device_add(&keyboard_pc_device); + + device_add(&philips_device); + + device_add(&xta_hd20_device); + +} + +machine_xt_p3105_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/philips_p3105/philipsnms9100.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_philips_common_init(model); + + return ret; +} + +int +machine_xt_p3120_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/philips_p3120/philips_p3120.bin", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_philips_common_init(model); + + device_add(&gc100a_device); + + return ret; +} + diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 6c7928da4..80633bacc 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -73,8 +73,7 @@ const machine_t machines[] = { { "[8088] NCR PC4i", "ncr_pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_ncrpc4i_init, NULL }, { "[8088] Olivetti M19", "olivetti_m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_olim19_init, NULL }, { "[8088] OpenXT", "open_xt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_open_xt_init, NULL }, - { "[8088] Philips P3105/NMS9100", "philips_p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3105_init, NULL }, - { "[8088] Philips P3120", "philips_p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3120_init, NULL }, + { "[8088] Philips P3105/NMS9100", "philips_p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA, 256, 768, 128, 0, machine_xt_p3105_init, NULL }, { "[8088] Phoenix XT clone", "pxxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_pxxt_init, NULL }, { "[8088] Schneider EuroPC", "europc", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, { "[8088] Tandy 1000", "tandy", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_tandy_init, tandy1k_get_device }, @@ -87,6 +86,7 @@ const machine_t machines[] = { { "[8088] Zenith Data Systems Z-151/152/161", "zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, { "[8088] Zenith Data Systems SupersPort (Z-184)", "zdsupers", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_xt_z184_init, z184_get_device }, + { "[GC100A] Philips P3120", "philips_p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA, 256, 768, 128, 0, machine_xt_p3120_init, NULL }, /* 8086 Machines */ { "[8086] Amstrad PC1512", "pc1512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 8000000, 8000000, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device }, @@ -122,7 +122,6 @@ const machine_t machines[] = { { "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device }, { "[ISA] MR 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL }, { "[ISA] NCR PC8/810/710/3390/3392", "ncr_pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_ncrpc8_init, NULL }, - { "[ISA] Olivetti M290", "olivetti_m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_olim290_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) { "[ISA] OpenAT", "open_at", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_open_at_init, NULL }, #endif @@ -143,7 +142,6 @@ const machine_t machines[] = { { "[SCAT] Samsung SPC-4216P", "spc4216p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 1024, 5120,1024, 127, machine_at_spc4216p_init, NULL }, { "[SCAT] Samsung SPC-4620P", "spc4620p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 5120,1024, 127, machine_at_spc4620p_init, NULL }, { "[SCAT] Samsung Deskmaster 286", "deskmaster286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_deskmaster286_init, NULL }, - { "[TACT82300] Olivetti M290S", "olivetti_m290s", MACHINE_TYPE_286, CPU_PKG_286, 0, 16000000, 16000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024,16384, 512, 127, machine_at_olim290s_init, NULL }, /* 286 machines that utilize the MCA bus */ { "[MCA] IBM PS/2 model 50", "ibmps2_m50", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 10240,1024, 63, machine_ps2_model_50_init, NULL }, @@ -151,8 +149,6 @@ const machine_t machines[] = { /* 386SX machines */ { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO_FIXED, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, { "[ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, - { "[ISA] Olivetti M300-01/05", "olivetti_m300_05", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 16000000, 16000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 11264,1024, 127, machine_at_olim300_05_init, NULL }, - { "[ISA] Olivetti M300-10", "olivetti_m300_10", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288,1024, 127, machine_at_olim300_10_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_M6117) { "[ALi M6117D] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL }, { "[ALi M6117D] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, @@ -163,13 +159,10 @@ const machine_t machines[] = { { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, { "[NEAT] Commodore SL386SX-16", "cbm_sl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_commodore_sl386sx16_init, NULL }, { "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL }, - { "[OPTi 283] Olivetti M300-08", "olivetti_m300_08", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_08_init, at_m300_08_get_device }, - { "[OPTi 283] Olivetti M300-15", "olivetti_m300_15", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 25000000, 25000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_15_init, NULL }, { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, { "[SCAMP] Commodore SL386SX-25", "cbm_sl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_commodore_sl386sx25_init, at_commodore_sl386sx25_get_device }, { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, { "[SCAT] KMX-C-02", "kmxc02", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 512, 127, machine_at_kmxc02_init, NULL }, - { "[TACT82300] NCR PC916SX", "ncr_pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_ncrpc916sx_init, NULL }, { "[WD76C10] Amstrad MegaPC", "megapc", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_wd76c10_init, NULL }, /* 386SX machines which utilize the MCA bus */ diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 241e0e2c2..67247e886 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -619,10 +619,12 @@ CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o headland.o intel_82335.o cs intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o opti283.o opti291.o \ + gc100.o \ via_apollo.o via_pipc.o wd76c10.o vl82c480.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ + m_xt_philips.o \ m_xt_t1000.o m_xt_t1000_vid.o \ m_xt_xi8088.o m_xt_zenith.o \ m_pcjr.o \ @@ -644,9 +646,9 @@ DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm keyboard.o \ keyboard_xt.o keyboard_at.o \ mouse.o \ - mouse_bus.o \ + mouse_bus.o \ mouse_serial.o mouse_ps2.o \ - phoenix_486_jumper.o olivetti_m290_registers.o + phoenix_486_jumper.o SIOOBJ := sio_acc3221.o \ sio_f82c710.o sio_82091aa.o \ From a0a7ee67ccb4b400e3f2c8c7697ea3d5ebe56347 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 7 Feb 2021 17:27:14 +0200 Subject: [PATCH 02/34] FDC workaround The Internal FDC is added when needed for AT machines too. Some speculative "work" on the main FDC code --- src/floppy/fdc.c | 2 +- src/floppy/fdc_magitronic.c | 2 +- src/floppy/fdc_pii15xb.c | 4 ++-- src/machine/m_at_286_386sx.c | 39 ++++++++++++++++++++++++++++++++++++ src/machine/m_at_386dx_486.c | 39 +++++++++++++++++++++++++++++++++++- src/machine/m_at_commodore.c | 3 +++ src/machine/m_at_socket4_5.c | 4 ++++ src/machine/m_at_t3100e.c | 7 ++++++- src/machine/m_ps2_mca.c | 3 +++ src/machine/m_xt_laserxt.c | 3 +++ src/machine/m_xt_olivetti.c | 4 ++++ src/machine/m_xt_xi8088.c | 4 ++++ 12 files changed, 108 insertions(+), 6 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 459370724..6fd73d57b 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -2326,7 +2326,7 @@ fdc_3f1_enable(fdc_t *fdc, int enable) const device_t fdc_xt_device = { "PC/XT Floppy Drive Controller", 0, - 0, + FDC_FLAG_AT, fdc_init, fdc_close, fdc_reset, diff --git a/src/floppy/fdc_magitronic.c b/src/floppy/fdc_magitronic.c index 3b7ceb64d..bdc8149ef 100644 --- a/src/floppy/fdc_magitronic.c +++ b/src/floppy/fdc_magitronic.c @@ -56,7 +56,7 @@ b215_init(const device_t *info) rom_init(&dev->rom, ROM_B215, ROM_ADDR, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - device_add(&fdc_at_device); + device_add(&fdc_xt_device); return dev; } diff --git a/src/floppy/fdc_pii15xb.c b/src/floppy/fdc_pii15xb.c index 1a6fc8fad..cf97a1fba 100644 --- a/src/floppy/fdc_pii15xb.c +++ b/src/floppy/fdc_pii15xb.c @@ -54,7 +54,7 @@ MiniMicro 4 uses a Zilog Z0765A08PSC(Clone of the NEC 765) MiniMicro 1 uses a National Semiconductor DP8473(Clone of the NEC 765 with additional NSC commands) Issues: -MiniMicro 4 WON'T WORK with XT machines. This statement has to be confirmed by someone with the real card itself. +MiniMicro 4 works only with a few XT machines. This statement has to be confirmed by someone with the real card itself. MiniMicro 4 also won't work with the XT FDC which the Zilog claims to be. */ @@ -77,7 +77,7 @@ MiniMicro 4 also won't work with the XT FDC which the Zilog claims to be. #include <86box/fdc_ext.h> #define DTK_VARIANT ((info->local == 158) ? ROM_PII_158B : ROM_PII_151B) -#define DTK_CHIP ((info->local == 158) ? &fdc_at_device : &fdc_dp8473_device) +#define DTK_CHIP ((info->local == 158) ? &fdc_xt_device : &fdc_dp8473_device) #define BIOS_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) #define ROM_PII_151B L"roms/floppy/dtk/pii-151b.rom" #define ROM_PII_158B L"roms/floppy/dtk/pii-158b.rom" diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 9aac75d6a..274eedad0 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -35,6 +35,7 @@ #include <86box/rom.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/fdc_ext.h> #include <86box/hdc.h> #include <86box/sio.h> #include <86box/serial.h> @@ -56,6 +57,8 @@ machine_at_mr286_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -66,6 +69,8 @@ static void machine_at_headland_common_init(int ht386) { device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); if (ht386) @@ -136,7 +141,10 @@ machine_at_quadt286_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&headland_gc10x_device); return ret; @@ -157,6 +165,8 @@ machine_at_neat_init(const machine_t *model) machine_at_init(model); device_add(&neat_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -177,6 +187,8 @@ machine_at_neat_ami_init(const machine_t *model) machine_at_common_init(model); device_add(&neat_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&keyboard_at_ami_device); @@ -198,7 +210,10 @@ machine_at_px286_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&neat_device); return ret; @@ -219,6 +234,8 @@ machine_at_micronics386_init(const machine_t *model) machine_at_init(model); device_add(&neat_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -230,6 +247,8 @@ machine_at_scat_init(const machine_t *model, int is_v4) { machine_at_common_init(model); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); if (is_v4) @@ -245,6 +264,8 @@ machine_at_scatsx_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&scat_sx_device); @@ -434,6 +455,8 @@ machine_at_shuttle386sx_init(const machine_t *model) device_add(&intel_82335_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -456,6 +479,8 @@ machine_at_adi386sx_init(const machine_t *model) device_add(&intel_82335_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -502,7 +527,10 @@ machine_at_commodore_sl386sx16_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&neat_device); /* Two serial ports - on the real hardware SL386SX-16, they are on the single UMC UM82C452. */ device_add_inst(&ns16450_device, 1); @@ -518,7 +546,10 @@ machine_at_scamp_common_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&keyboard_ps2_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&vlsi_scamp_device); } @@ -591,6 +622,8 @@ machine_at_awardsx_init(const machine_t *model) machine_at_init(model); device_add(&opti291_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -704,6 +737,8 @@ machine_at_olim290_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); io_sethandler(0x069, 1, m290_read, NULL, NULL, NULL, NULL, NULL, NULL); @@ -730,6 +765,8 @@ machine_at_ncrpc8_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_ncr_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -758,6 +795,8 @@ machine_at_ncr3302_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&neat_device); device_add(&keyboard_at_ncr_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); if (gfxcard == VID_INTERNAL) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index a0f8494b3..6cbfa1fa1 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -34,6 +34,7 @@ #include <86box/pci.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/fdc_ext.h> #include <86box/rom.h> #include <86box/sio.h> #include <86box/hdc.h> @@ -57,6 +58,8 @@ machine_at_acc386_init(const machine_t *model) machine_at_common_init(model); device_add(&acc2168_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -77,6 +80,8 @@ machine_at_asus386_init(const machine_t *model) machine_at_common_init(model); device_add(&rabbit_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -97,6 +102,8 @@ machine_at_sis401_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&sis_85c401_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -117,6 +124,8 @@ machine_at_av4_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&sis_85c460_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -137,6 +146,8 @@ machine_at_valuepoint433_init(const machine_t *model) // hangs without the PS/2 machine_at_common_ide_init(model); device_add(&sis_85c461_device); device_add(&keyboard_ps2_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -157,7 +168,10 @@ machine_at_ecs386_init(const machine_t *model) machine_at_common_init(model); device_add(&cs8230_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&keyboard_at_ami_device); return ret; @@ -178,7 +192,10 @@ machine_at_spc6000a_init(const machine_t *model) machine_at_common_init_ex(model, 1); device_add(&cs8230_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&keyboard_at_samsung_device); return ret; @@ -200,6 +217,8 @@ machine_at_rycleopardlx_init(const machine_t *model) device_add(&opti283_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -221,6 +240,8 @@ machine_at_486vchd_init(const machine_t *model) device_add(&via_vt82c49x_device); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -241,6 +262,8 @@ machine_at_cs4031_init(const machine_t *model) machine_at_common_init(model); device_add(&cs4031_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -326,9 +349,11 @@ machine_at_acera1g_init(const machine_t *model) device_add(&ali1429_device); device_add(&keyboard_ps2_acer_pci_device); - device_add(&fdc_at_device); device_add(&ide_isa_2ch_device); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + return ret; } @@ -348,6 +373,8 @@ machine_at_ali1429_common_init(const machine_t *model) device_add(&ali1429_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); } @@ -402,6 +429,8 @@ machine_at_opti495_init(const machine_t *model) device_add(&opti495_device); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -416,6 +445,8 @@ machine_at_opti495_ami_common_init(const machine_t *model) device_add(&opti495_device); device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); } @@ -469,6 +500,8 @@ machine_at_403tg_init(const machine_t *model) device_add(&opti895_device); device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -522,6 +555,8 @@ static void machine_at_sis_85c471_common_init(const machine_t *model) { machine_at_common_init(model); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&sis_85c471_device); @@ -884,6 +919,8 @@ machine_at_486ap4_init(const machine_t *model) pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0b = Slot 3 */ pci_register_slot(0x0c, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 0c = Slot 4 */ device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&i420ex_device); diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index 51f8e56b4..eaf847602 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -45,6 +45,7 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/mem.h> +#include <86box/fdc_ext.h> #include <86box/lpt.h> #include <86box/rom.h> #include <86box/serial.h> @@ -108,7 +109,9 @@ machine_at_cmdpc_init(const machine_t *model) mem_remap_top(384); + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + cmd_uart = device_add(&i8250_device); cbm_io_init(); diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index 84c6e97d2..3fdea739d 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -28,6 +28,7 @@ #include <86box/pci.h> #include <86box/device.h> #include <86box/chipset.h> +#include <86box/fdc_ext.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/timer.h> @@ -98,7 +99,10 @@ machine_at_award_common_init(const machine_t *model) pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&keyboard_ps2_pci_device); } diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index a5a7b9903..d04c4e2a0 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -163,6 +163,7 @@ #include "cpu.h" #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/fdc_ext.h> #include <86box/machine.h> #include <86box/m_at_t3100e.h> @@ -761,8 +762,12 @@ int machine_at_t3100e_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&keyboard_at_toshiba_device); - device_add(&fdc_at_device); + if (fdc_type == FDC_INTERNAL) + { + device_add(&fdc_at_device); + } + /* Hook up system control port */ io_sethandler(0x8084, 0x0001, t3100e_sys_in, NULL, NULL, diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 3295fc884..bb87bfb85 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -57,6 +57,7 @@ #include <86box/device.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/fdc_ext.h> #include <86box/nvr.h> #include <86box/nvr_ps2.h> #include <86box/keyboard.h> @@ -1259,6 +1260,8 @@ static void machine_ps2_common_init(const machine_t *model) { machine_common_init(model); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); dma16_init(); diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 20c0e21ff..6b360353d 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -16,6 +16,7 @@ #include <86box/timer.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/fdc_ext.h> #include <86box/gameport.h> #include <86box/keyboard.h> @@ -169,6 +170,8 @@ machine_xt_lxt3_init(const machine_t *model) pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); device_add(&keyboard_xt_lxt3_device); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_xt_device); nmi_init(); if (joystick_type) diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index a2f3d2725..cd0790a3c 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -724,6 +724,8 @@ machine_xt_olim24_init(const machine_t *model) memset(m24_kbd, 0x00, sizeof(olim24_kbd_t)); machine_common_init(model); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_xt_device); /* Address 66-67 = mainboard dip-switch settings */ @@ -809,6 +811,8 @@ machine_xt_olim19_init(const machine_t *model) memset(vid, 0x00, sizeof(olim19_vid_t)); machine_common_init(model); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_xt_device); m19_vid_init(vid); diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index 39fe5e2cf..93948bddf 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -11,6 +11,7 @@ #include <86box/device.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/fdc_ext.h> #include <86box/nmi.h> #include <86box/nvr.h> #include <86box/gameport.h> @@ -172,7 +173,10 @@ machine_xt_xi8088_init(const machine_t *model) /* TODO: set UMBs? See if PCem always sets when we have > 640KB ram and avoids conflicts when a peripheral uses the same memory space */ machine_common_init(model); + + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&keyboard_ps2_xi8088_device); nmi_init(); device_add(&ibmat_nvr_device); From 259db0979eb6455472d12d8b1de6f7283bf51f9c Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 7 Feb 2021 19:18:15 +0200 Subject: [PATCH 03/34] Reverted the XT FDC with no flags Turns out it was working as intended --- src/floppy/fdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 6fd73d57b..459370724 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -2326,7 +2326,7 @@ fdc_3f1_enable(fdc_t *fdc, int enable) const device_t fdc_xt_device = { "PC/XT Floppy Drive Controller", 0, - FDC_FLAG_AT, + 0, fdc_init, fdc_close, fdc_reset, From 3d5072dab2bf1a8427e2479e025ec1e87ffbff56 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Mon, 8 Feb 2021 18:01:43 +0200 Subject: [PATCH 04/34] Implemented the Magitronics B215 Jumper Readout Also added a preliminary UMC 8398 --- src/floppy/fdc.c | 27 ++++++++++++++++++--- src/floppy/fdc_magitronic.c | 47 ++++++++++++++++++++++++++++++++++++- src/include/86box/fdc.h | 2 ++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 459370724..d87193538 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1245,7 +1245,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } return; case 7: - if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT)) + if (!(fdc->flags & FDC_FLAG_TOSHIBA) && !(fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_UMC)) return; fdc->rate = val & 0x03; if (fdc->flags & FDC_FLAG_PS1) @@ -1294,7 +1294,7 @@ fdc_read(uint16_t addr, void *priv) ret = 0x00; /* -Drive 2 Installed */ if (!fdd_get_type(1)) - ret |= 80; + ret |= 0x80; /* -Drive Select 1,0 */ switch (drive) { case 0: @@ -1313,6 +1313,12 @@ fdc_read(uint16_t addr, void *priv) } else { if (is486 || !fdc->enable_3f1) ret = 0xff; + else{ + if(fdc->flags & FDC_FLAG_UMC) + { + drive = real_drive(fdc, fdc->dor & 1); + ret = !fdd_is_dd(drive) ? ((fdc->dor & 1) ? 2 : 1) : 0; + } else { ret = 0x70; @@ -1328,6 +1334,7 @@ fdc_read(uint16_t addr, void *priv) if (fdc->dor & 0x20) ret |= 2; } + } } break; case 2: @@ -2173,10 +2180,12 @@ fdc_set_base(fdc_t *fdc, int base) if (fdc->flags & FDC_FLAG_PCJR) io_sethandler(base, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); else { + if(fdc->flags & FDC_FLAG_UMC) + io_sethandler(base + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); io_sethandler(base + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc); io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - if (fdc->flags & FDC_FLAG_TOSHIBA) + if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC)) io_sethandler(base + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } } @@ -2198,6 +2207,8 @@ fdc_remove(fdc_t *fdc) if (fdc->flags & FDC_FLAG_PCJR) io_removehandler(fdc->base_address, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); else { + if(fdc->flags & FDC_FLAG_UMC) + io_removehandler(fdc->base_address + 0x0001, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); io_removehandler(fdc->base_address + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc); io_removehandler(fdc->base_address + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); io_removehandler(fdc->base_address + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); @@ -2433,3 +2444,13 @@ const device_t fdc_dp8473_device = { fdc_reset, { NULL }, NULL, NULL }; + +const device_t fdc_um8398_device = { + "UMC UM8398 Floppy Drive Controller", + 0, + FDC_FLAG_UMC, + fdc_init, + fdc_close, + fdc_reset, + { NULL }, NULL, NULL +}; diff --git a/src/floppy/fdc_magitronic.c b/src/floppy/fdc_magitronic.c index bdc8149ef..ea754187e 100644 --- a/src/floppy/fdc_magitronic.c +++ b/src/floppy/fdc_magitronic.c @@ -34,12 +34,56 @@ #define ROM_B215 L"roms/floppy/magitronic/Magitronic B215 - BIOS ROM.bin" #define ROM_ADDR (uint32_t)(device_get_config_hex20("bios_addr") & 0x000fffff) +#define DRIVE_SELECT (int)(real_drive(dev->fdc_controller, i)) typedef struct { fdc_t *fdc_controller; rom_t rom; } b215_t; +static uint8_t +b215_read(uint16_t addr, void *priv) +{ + b215_t *dev = (b215_t *)priv; + + /* + Register 3F0h + + Bit (3-2) for Drive B: + Bit (1-0) for Drive A: + 0: 360KB + 1: 1.2MB + 2: 720KB + 3: 1.44MB + 4: +*/ + int drive_spec[2]; + + for (int i = 0; i <= 1; i++) + { + if (fdd_is_525(DRIVE_SELECT)) + { + if (!fdd_is_dd(DRIVE_SELECT)) + drive_spec[i] = 1; + else if (fdd_doublestep_40(DRIVE_SELECT)) + drive_spec[i] = 2; + else + drive_spec[i] = 0; + } + else + { + if (fdd_is_dd(DRIVE_SELECT) && !fdd_is_double_sided(DRIVE_SELECT)) + drive_spec[i] = 0; + else if (fdd_is_dd(DRIVE_SELECT) && fdd_is_double_sided(DRIVE_SELECT)) + drive_spec[i] = 2; + else + drive_spec[i] = 3; + } + } + + return ((drive_spec[1] << 2) | drive_spec[0]) & 0x0f; +} + static void b215_close(void *priv) { @@ -56,7 +100,8 @@ b215_init(const device_t *info) rom_init(&dev->rom, ROM_B215, ROM_ADDR, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - device_add(&fdc_xt_device); + dev->fdc_controller = device_add(&fdc_um8398_device); + io_sethandler(0x03f0, 1, b215_read, NULL, NULL, NULL, NULL, NULL, dev); return dev; } diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index b818258de..b51f93625 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -34,6 +34,7 @@ extern int fdc_type; #define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ #define FDC_FLAG_TOSHIBA 0x100 /* T1000, T1200 */ #define FDC_FLAG_AMSTRAD 0x200 /* Non-AT Amstrad machines */ +#define FDC_FLAG_UMC 0x400 /* UMC UM8398 */ typedef struct { @@ -179,6 +180,7 @@ extern const device_t fdc_at_smc_device; extern const device_t fdc_at_winbond_device; extern const device_t fdc_at_nsc_device; extern const device_t fdc_dp8473_device; +extern const device_t fdc_um8398_device; #endif #endif /*EMU_FDC_H*/ From 6fd19ef4f7b89a24e9a74b1c2669e00ac3ab05b9 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Mon, 8 Feb 2021 18:04:15 +0200 Subject: [PATCH 05/34] The UMC 8398 can now remove port 3F7h --- src/floppy/fdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index d87193538..0f7bea3a1 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -2212,7 +2212,7 @@ fdc_remove(fdc_t *fdc) io_removehandler(fdc->base_address + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc); io_removehandler(fdc->base_address + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); io_removehandler(fdc->base_address + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); - if (fdc->flags & FDC_FLAG_TOSHIBA) + if ((fdc->flags & FDC_FLAG_TOSHIBA) || (fdc->flags & FDC_FLAG_UMC)) io_removehandler(fdc->base_address + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } } From a2c53e1a944dd28f74f2378becb5fb31f98e11de Mon Sep 17 00:00:00 2001 From: EngiNerd89 Date: Thu, 11 Feb 2021 19:07:24 +0100 Subject: [PATCH 06/34] Re-added fully complete and working Olivetti and NCR 386SX-class machines. Moved Olivetti M290 to dev branch. (Very) partially implemented Olivetti EVA gate array (used in M290). --- src/chipset/CMakeLists.txt | 1 + src/chipset/olivetti_eva.c | 166 +++++++++++++++++++++++++++++++++++ src/include/86box/chipset.h | 3 + src/include/86box/machine.h | 12 ++- src/machine/m_at_286_386sx.c | 147 ++++++++++++++++++++++--------- src/machine/m_xt_philips.c | 2 - src/machine/machine_table.c | 6 ++ src/win/Makefile.mingw | 12 +++ 8 files changed, 304 insertions(+), 45 deletions(-) create mode 100644 src/chipset/olivetti_eva.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index f8c01a631..c68d5475a 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c headland.c int neat.c opti495.c opti895.c opti5x7.c scamp.c scat.c via_vt82c49x.c via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c + olivetti_eva.c opti283.c opti291.c via_apollo.c via_pipc.c wd76c10.c vl82c480.c) diff --git a/src/chipset/olivetti_eva.c b/src/chipset/olivetti_eva.c new file mode 100644 index 000000000..34b09c622 --- /dev/null +++ b/src/chipset/olivetti_eva.c @@ -0,0 +1,166 @@ +/* + * 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 Olivetti EVA (98/86) Gate Array. + * + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. + * + * Authors: EngiNerd + * + * Copyright 2020-2021 EngiNerd + */ + + +#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/chipset.h> +#include <86box/video.h> +#include <86box/mem.h> + +typedef struct +{ + uint8_t reg_065; + uint8_t reg_067; + uint8_t reg_069; +} olivetti_eva_t; + +#ifdef ENABLE_OLIVETTI_EVA_LOG +int olivetti_eva_do_log = ENABLE_OLIVETTI_EVA_LOG; +static void +olivetti_eva_log(const char *fmt, ...) +{ + va_list ap; + + if (olivetti_eva_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define olivetti_eva_log(fmt, ...) +#endif + +static void +olivetti_eva_write(uint16_t addr, uint8_t val, void *priv) +{ + olivetti_eva_t *dev = (olivetti_eva_t *) priv; + olivetti_eva_log("Olivetti EVA Gate Array: Write %02x at %02x\n", val, addr); + + switch (addr) { + case 0x065: + dev->reg_065 = val; + break; + case 0x067: + dev->reg_067 = val; + break; + case 0x069: + dev->reg_069 = val; + /* + * Unfortunately, if triggered, the BIOS remapping function fails causing + * a fatal error. Therefore, this code section is currently commented. + */ + // if (val & 1){ + // /* + // * Set the register to 7 or above for the BIOS to trigger the + // * memory remapping function if shadowing is active. + // */ + // dev->reg_069 = 0x7; + // } + // if (val & 8) { + // /* + // * Activate shadowing for region e0000-fffff + // */ + // mem_remap_top(256); + // mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + // } + break; + } +} + +static uint8_t +olivetti_eva_read(uint16_t addr, void *priv) +{ + olivetti_eva_t *dev = (olivetti_eva_t *) priv; + uint8_t ret = 0xff; + switch (addr) { + case 0x065: + ret = dev->reg_065; + break; + case 0x067: + /* never happens */ + ret = dev->reg_067; + break; + case 0x069: + ret = dev->reg_069; + break; + } + olivetti_eva_log("Olivetti EVA Gate Array: Read %02x at %02x\n", ret, addr); + return ret; +} + + +static void +olivetti_eva_close(void *priv) +{ + olivetti_eva_t *dev = (olivetti_eva_t *) priv; + + free(dev); +} + +static void * +olivetti_eva_init(const device_t *info) +{ + olivetti_eva_t *dev = (olivetti_eva_t *) malloc(sizeof(olivetti_eva_t)); + memset(dev, 0, sizeof(olivetti_eva_t)); + + /* GA98 registers */ + dev->reg_065 = 0x00; + + /* RAM page registers: never read, only set */ + dev->reg_067 = 0x00; + + /* RAM enable registers */ + dev->reg_069 = 0x0; + + io_sethandler(0x0065, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); + io_sethandler(0x0067, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); + io_sethandler(0x0069, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev); + + /* When shadowing is not enabled in BIOS, all upper memory is available as XMS */ + mem_remap_top(384); + + /* + * Default settings when NVRAM is cleared activate shadowing. + * Thus, to avoid boot errors, remap only 256k from UMB to XMS. + * Remove this block once BIOS memory remapping works. + */ + mem_remap_top(256); + + return dev; +} + +const device_t olivetti_eva_device = { + "Olivetti EVA Gate Array", + 0, + 0, + olivetti_eva_init, olivetti_eva_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index a4534334a..f5c7e5f37 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -147,4 +147,7 @@ extern const device_t wd76c10_device; extern const device_t phoenix_486_jumper_device; extern const device_t vpc2007_device; +#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) +extern const device_t olivetti_eva_device; +#endif #endif /*EMU_CHIPSET_H*/ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 623cfddbb..57dc8ee3c 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -258,6 +258,10 @@ extern int machine_at_deskmaster286_init(const machine_t *); extern int machine_at_ncrpc8_init(const machine_t *); extern int machine_at_ncr3302_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) +extern int machine_at_olim290_init(const machine_t *); +#endif + extern int machine_at_shuttle386sx_init(const machine_t *); extern int machine_at_adi386sx_init(const machine_t *); extern int machine_at_commodore_sl386sx16_init(const machine_t *); @@ -272,12 +276,18 @@ extern int machine_at_arb1375_init(const machine_t *); extern int machine_at_pja511m_init(const machine_t *); #endif +extern int machine_at_ncrpc916sx_init(const machine_t *); + +extern int machine_at_olim300_08_init(const machine_t *); +extern int machine_at_olim300_15_init(const machine_t *); + #ifdef EMU_DEVICE_H extern const device_t *at_ama932j_get_device(void); extern const device_t *at_flytech386_get_device(void); extern const device_t *at_commodore_sl386sx25_get_device(void); extern const device_t *at_spc4620p_get_device(void); extern const device_t *at_spc6033p_get_device(void); +extern const device_t *at_m300_08_get_device(void); #endif /* m_at_386dx_486.c */ @@ -612,8 +622,6 @@ extern int machine_xt_ncrpc4i_init(const machine_t *); extern int machine_xt_mpc1600_init(const machine_t *); extern int machine_xt_eaglepcspirit_init(const machine_t *); extern int machine_xt_multitechpc700_init(const machine_t *); -extern int machine_xt_p3105_init(const machine_t *); -extern int machine_xt_p3120_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 1197b7d99..1a0db4d98 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -35,6 +35,7 @@ #include <86box/rom.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/fdc_ext.h> #include <86box/hdc.h> #include <86box/sio.h> #include <86box/serial.h> @@ -672,47 +673,6 @@ machine_at_pja511m_init(const machine_t *model) } #endif - - -static uint8_t -m290_read(uint16_t port, void *priv) -{ - uint8_t ret = 0x0; - switch (port) { - /* - * port 69: - * dip-switch bank on mainboard (off=1) - * bit 3 - use OCG/CGA display adapter (off) / other display adapter (on) - */ - case 0x69: - if(video_is_cga()) - ret |= 0x8|0x4; - ret |= 0x1|0x2; - } - return (ret); -} - -int -machine_at_olim290_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/olivetti_m290/m290_pep3_1.25.bin", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - device_add(&keyboard_at_device); - device_add(&fdc_at_device); - - io_sethandler(0x069, 1, m290_read, NULL, NULL, NULL, NULL, NULL, NULL); - - return ret; -} - - /* * Current bugs: * - ctrl-alt-del produces an 8042 error @@ -766,3 +726,108 @@ machine_at_ncr3302_init(const machine_t *model) return ret; } + +/* + * Current bugs: + * - soft-reboot after saving CMOS settings/pressing ctrl-alt-del produces an 8042 error + */ +int +machine_at_ncrpc916sx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved(L"roms/machines/ncr_pc916sx/ncr_386sx_u46-17_7.3.bin", + L"roms/machines/ncr_pc916sx/ncr_386sx_u12-19_7.3.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&keyboard_at_ncr_device); + mem_remap_top(384); + + device_add(&fdc_at_device); + + return ret; +} + +#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) +int +machine_at_olim290_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/olivetti_m290/m290_pep3_1.25.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&keyboard_at_olivetti_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&olivetti_eva_device); + + return ret; +} +#endif + +const device_t * +at_m300_08_get_device(void) +{ + return &oti067_m300_device; +} + +int +machine_at_olim300_08_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/olivetti_m300_08/BIOS.ROM", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&opti283_device); + device_add(&keyboard_ps2_olivetti_device); + device_add(&pc87310_ide_device); + + if (gfxcard == VID_INTERNAL) + device_add(&oti067_m300_device); + + return ret; +} + +/* Almost identical to M300-08, save for CPU speed, VRAM, and BIOS identification string */ +int +machine_at_olim300_15_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/olivetti_m300_15/BIOS.ROM", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&opti283_device); + device_add(&keyboard_ps2_olivetti_device); + device_add(&pc87310_ide_device); + + /* Stock VRAM is maxed out, so no need to expose video card config */ + if (gfxcard == VID_INTERNAL) + device_add(&oti067_m300_device); + + return ret; +} + diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c index 722b117ee..11af6835d 100644 --- a/src/machine/m_xt_philips.c +++ b/src/machine/m_xt_philips.c @@ -46,8 +46,6 @@ typedef struct uint8_t reg; } philips_t; -#define ENABLE_philips_LOG 1 - #ifdef ENABLE_philips_LOG int philips_do_log = ENABLE_philips_LOG; static void diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b0db65429..959962e1d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -122,6 +122,9 @@ const machine_t machines[] = { { "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device }, { "[ISA] MR 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL }, { "[ISA] NCR PC8/810/710/3390/3392", "ncr_pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_ncrpc8_init, NULL }, +#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) + { "[ISA] Olivetti M290", "olivetti_m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_olim290_init, NULL }, +#endif #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) { "[ISA] OpenAT", "open_at", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_open_at_init, NULL }, #endif @@ -149,6 +152,7 @@ const machine_t machines[] = { /* 386SX machines */ { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO_FIXED, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, { "[ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, + { "[ISA] NCR PC916SX", "ncr_pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_ncrpc916sx_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_M6117) { "[ALi M6117D] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL }, { "[ALi M6117D] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, @@ -159,6 +163,8 @@ const machine_t machines[] = { { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, { "[NEAT] Commodore SL386SX-16", "cbm_sl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_commodore_sl386sx16_init, NULL }, { "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL }, + { "[OPTi 283] Olivetti M300-08", "olivetti_m300_08", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_08_init, at_m300_08_get_device }, + { "[OPTi 283] Olivetti M300-15", "olivetti_m300_15", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 25000000, 25000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_olim300_15_init, NULL }, { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, { "[SCAMP] Commodore SL386SX-25", "cbm_sl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_commodore_sl386sx25_init, at_commodore_sl386sx25_get_device }, { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index db72f9bb7..282f1998f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -102,6 +102,9 @@ ifeq ($(DEV_BUILD), y) ifndef USE_VECT486VL USE_VECT486VL := y endif + ifndef OLIVETTI + OLIVETTI := y + endif else ifndef DEBUG DEBUG := n @@ -178,6 +181,9 @@ else ifndef USE_VECT486VL USE_VECT486VL := n endif + ifndef OLIVETTI + OLIVETTI := n + endif endif # Defaults for several build options (possibly defined in a chained file.) @@ -586,6 +592,11 @@ ifeq ($(USE_VECT486VL), y) OPTS += -DUSE_VECT486VL endif +ifeq ($(OLIVETTI), y) +OPTS += -DUSE_OLIVETTI +endif + + endif @@ -620,6 +631,7 @@ CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o headland.o intel_82335.o cs neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o opti283.o opti291.o \ gc100.o \ + olivetti_eva.o \ via_apollo.o via_pipc.o wd76c10.o vl82c480.o MCHOBJ := machine.o machine_table.o \ From 1c364735f1526d84decf7ca1a5fd6572034f31f0 Mon Sep 17 00:00:00 2001 From: EngiNerd89 Date: Thu, 11 Feb 2021 20:39:29 +0100 Subject: [PATCH 07/34] Minor fix in Philips code. --- src/machine/m_xt_philips.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c index d5e003712..9adfc82d7 100644 --- a/src/machine/m_xt_philips.c +++ b/src/machine/m_xt_philips.c @@ -167,6 +167,7 @@ machine_xt_philips_common_init(const machine_t *model) } +int machine_xt_p3105_init(const machine_t *model) { int ret; From e3fc96738ade483598bd08cb76d92dcde6e3e50c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Fri, 12 Feb 2021 21:29:58 +0100 Subject: [PATCH 08/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f60231134..12a5d27ca 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ operating systems and software designed for IBM PC systems and compatibles from 1981 through fairly recent system designs based on the PCI bus. -86Box is released under the GNU General Public License, version 2 or later. +86Box is released under the GNU General Public License, version 2. For more information, see the `COPYING` file. The project maintainer is [OBattler](https://github.com/OBattler). From 8b7d643452e531a97019776dbcfb78baa8e3768f Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sat, 13 Feb 2021 12:31:04 +0200 Subject: [PATCH 09/34] Sanitize some old chipset code (Part 3) Fixed the Indentation of the Intel 82335, removed useless includes and numerous bugfixes on the OPTi Python. --- src/chipset/intel_82335.c | 126 ++++++++++++++------------- src/chipset/opti5x7.c | 175 +++++++++++++++++++------------------- 2 files changed, 148 insertions(+), 153 deletions(-) diff --git a/src/chipset/intel_82335.c b/src/chipset/intel_82335.c index edb8f266a..d123b4bdc 100644 --- a/src/chipset/intel_82335.c +++ b/src/chipset/intel_82335.c @@ -8,7 +8,7 @@ * * Implementation of the Intel 82335(KU82335) chipset. * - * Copyright 2020 Tiseno100 + * Copyright 2021 Tiseno100 * */ @@ -24,10 +24,7 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> -#include <86box/keyboard.h> #include <86box/mem.h> -#include <86box/fdd.h> -#include <86box/fdc.h> #include <86box/chipset.h> /* Shadow capabilities */ @@ -38,7 +35,7 @@ /* Granularity Register Enable & Recalc */ #define EXTENDED_GRANULARITY_ENABLED (dev->regs[0x2c] & 0x01) -#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i+8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW) +#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i + 8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW) /* R/W operator for the Video RAM region */ #define DETERMINE_VIDEO_RAM_WRITE_ACCESS ((dev->regs[0x22] & (0x08 << 8)) ? RW_SHADOW : RO_SHADOW) @@ -61,8 +58,8 @@ typedef struct { uint16_t regs[256], - - cfg_locked; + + cfg_locked; } intel_82335_t; @@ -73,10 +70,11 @@ intel_82335_log(const char *fmt, ...) { va_list ap; - if (intel_82335_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (intel_82335_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else @@ -86,92 +84,90 @@ intel_82335_log(const char *fmt, ...) static void intel_82335_write(uint16_t addr, uint16_t val, void *priv) { - intel_82335_t *dev = (intel_82335_t *) priv; + intel_82335_t *dev = (intel_82335_t *)priv; uint32_t romsize = 0, base = 0, i = 0, rc1_remap = 0, rc2_remap = 0; dev->regs[addr] = val; - if(!dev->cfg_locked) + if (!dev->cfg_locked) { - intel_82335_log("Register %02x: Write %04x\n", addr, val); + intel_82335_log("Register %02x: Write %04x\n", addr, val); - switch (addr) { - case 0x22: /* Memory Controller */ + switch (addr) + { + case 0x22: /* Memory Controller */ - /* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */ - romsize = ROM_SIZE; + /* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */ + romsize = ROM_SIZE; - if (!EXTENDED_GRANULARITY_ENABLED) - { - shadowbios = !!(dev->regs[0x22] & 0x01); - shadowbios_write = !!(dev->regs[0x22] & 0x01); + if (!EXTENDED_GRANULARITY_ENABLED) + { + shadowbios = !!(dev->regs[0x22] & 0x01); + shadowbios_write = !!(dev->regs[0x22] & 0x01); - /* Base System 512/640KB set */ - mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB); + /* Base System 512/640KB set */ + mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB); - /* Video RAM shadow*/ - mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW); + /* Video RAM shadow*/ + mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW); - /* Option ROM shadow */ - mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW); + /* Option ROM shadow */ + mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW); - /* System ROM shadow */ - mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW); - } - break; + /* System ROM shadow */ + mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW); + } + break; - case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */ - case 0x26: - rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0; - rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0; - mem_remap_top(rc1_remap+rc2_remap); - break; + case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */ + case 0x26: + rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0; + rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0; + mem_remap_top(rc1_remap + rc2_remap); + break; - case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */ - if(EXTENDED_GRANULARITY_ENABLED) - { - for(i=0; i<8; i++) - { - base = 0xc0000 + (i << 15); - shadowbios = (dev->regs[0x2e] & (1 << (i+8))) && (base == romsize); - shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize); - mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC); - } - break; - } - } + case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */ + if (EXTENDED_GRANULARITY_ENABLED) + { + for (i = 0; i < 8; i++) + { + base = 0xc0000 + (i << 15); + shadowbios = (dev->regs[0x2e] & (1 << (i + 8))) && (base == romsize); + shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize); + mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC); + } + break; + } + } } /* Unlock/Lock configuration registers */ dev->cfg_locked = LOCK_STATUS; } - static uint16_t intel_82335_read(uint16_t addr, void *priv) { - intel_82335_t *dev = (intel_82335_t *) priv; + intel_82335_t *dev = (intel_82335_t *)priv; intel_82335_log("Register %02x: Read %04x\n", addr, dev->regs[addr]); return dev->regs[addr]; - } static void intel_82335_close(void *priv) { - intel_82335_t *dev = (intel_82335_t *) priv; + intel_82335_t *dev = (intel_82335_t *)priv; free(dev); } - static void * intel_82335_init(const device_t *info) { - intel_82335_t *dev = (intel_82335_t *) malloc(sizeof(intel_82335_t)); + intel_82335_t *dev = (intel_82335_t *)malloc(sizeof(intel_82335_t)); memset(dev, 0, sizeof(intel_82335_t)); memset(dev->regs, 0, sizeof(dev->regs)); @@ -195,17 +191,19 @@ intel_82335_init(const device_t *info) io_sethandler(0x002c, 0x0001, NULL, intel_82335_read, NULL, NULL, intel_82335_write, NULL, dev); /* Extended Granularity */ - io_sethandler(0x002e, 0x0001, NULL, intel_82335_read, NULL, NULL, intel_82335_write, NULL, dev); - + io_sethandler(0x002e, 0x0001, NULL, intel_82335_read, NULL, NULL, intel_82335_write, NULL, dev); + return dev; } - const device_t intel_82335_device = { "Intel 82335", 0, 0, - intel_82335_init, intel_82335_close, NULL, - { NULL }, NULL, NULL, - NULL -}; + intel_82335_init, + intel_82335_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index 8b232e682..f4231c8de 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -6,13 +6,15 @@ * * This file is part of the 86Box distribution. * - * Implementation of the OPTi 82C546/82C547 & 82C596/82C597 chipsets. + * Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets. - * Authors: plant/nerd73 - * Miran Grca, + * Authors: plant/nerd73, + * Miran Grca, + * Tiseno100 * - * Copyright 2020 plant/nerd73. - * Copyright 2020 Miran Grca. + * Copyright 2020 plant/nerd73. + * Copyright 2020 Miran Grca. + * Copyright 2021 Tiseno100. */ #include #include @@ -26,142 +28,134 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> -#include <86box/keyboard.h> #include <86box/mem.h> -#include <86box/fdd.h> -#include <86box/fdc.h> #include <86box/port_92.h> #include <86box/chipset.h> +/* Shadow RAM */ +#define SHADOW_RECALC (((dev->regs[(i < 4) ? 4 : 5] & (1 << ((i < 4) ? i : i - 4) * 2)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[(i < 4) ? 4 : 5] & (1 << (((i < 4) ? i : i - 4) * 2 + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) +#define SHADOW_E_RECALC (((dev->regs[0x06] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) +#define SHADOW_F_RECALC (((dev->regs[0x06] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) typedef struct { - uint8_t idx, - regs[16]; - port_92_t *port_92; + uint8_t idx, regs[16]; } opti5x7_t; - #ifdef ENABLE_OPTI5X7_LOG int opti5x7_do_log = ENABLE_OPTI5X7_LOG; - static void opti5x7_log(const char *fmt, ...) { va_list ap; - if (opti5x7_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (opti5x7_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else #define opti5x7_log(fmt, ...) #endif - static void -opti5x7_recalc(opti5x7_t *dev) +shadow_map(opti5x7_t *dev) { - uint32_t base; - uint32_t i, shflags = 0; - uint32_t reg, lowest_bit; - - shadowbios = 0; - shadowbios_write = 0; - - for (i = 0; i < 8; i++) { - base = 0xc0000 + (i << 14); - - lowest_bit = (i << 1) & 0x07; - reg = 0x04 + ((base >> 16) & 0x01); - - shflags = (dev->regs[reg] & (1 << lowest_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= (dev->regs[reg] & (1 << (lowest_bit + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state(base, 0x4000, shflags); - } - - shadowbios |= !!(dev->regs[0x06] & 0x05); - shadowbios_write |= !!(dev->regs[0x06] & 0x0a); - - shflags = (dev->regs[0x06] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state(0xe0000, 0x10000, shflags); - - shflags = (dev->regs[0x06] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= (dev->regs[0x06] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state(0xf0000, 0x10000, shflags); + for (int i = 0; i < 8; i++) + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, SHADOW_RECALC); + mem_set_mem_state_both(0xe0000, 0x10000, SHADOW_E_RECALC); + shadowbios = !!(dev->regs[0x06] & 5); + shadowbios_write = !!(dev->regs[0x06] & 0x0a); + mem_set_mem_state_both(0xf0000, 0x10000, SHADOW_F_RECALC); flushmmucache(); } - static void opti5x7_write(uint16_t addr, uint8_t val, void *priv) -{ - opti5x7_t *dev = (opti5x7_t *) priv; - opti5x7_log("Write %02x to OPTi 5x7 address %02x\n", val, addr); - - switch (addr) { - case 0x22: - dev->idx = val; - break; - case 0x24: - dev->regs[dev->idx] = val; - switch(dev->idx) { - case 0x02: - cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x04 & 0x08); - break; +{ + opti5x7_t *dev = (opti5x7_t *)priv; - case 0x04: - case 0x05: - case 0x06: - opti5x7_recalc(dev); - break; - } - break; + switch (addr) + { + case 0x22: + dev->idx = val; + break; + case 0x24: + opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, val); + switch (dev->idx) + { + case 0x00: /* DRAM Configuration Register #1 */ + dev->regs[dev->idx] = val & 0x7f; + break; + case 0x01: /* DRAM Control Register #1 */ + dev->regs[dev->idx] = val; + break; + case 0x02: /* Cache Control Register #1 */ + dev->regs[dev->idx] = val; + cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x0c); + cpu_update_waitstates(); + break; + case 0x03: /* Cache Control Register #2 */ + dev->regs[dev->idx] = val; + break; + case 0x04: /* Shadow RAM Control Register #1 */ + case 0x05: /* Shadow RAM Control Register #2 */ + case 0x06: /* Shadow RAM Control Register #3 */ + dev->regs[dev->idx] = val; + shadow_map(dev); + break; + case 0x07: /* Tag Test Register */ + case 0x08: /* CPU Cache Control Register #1 */ + case 0x09: /* System Memory Function Register #1 */ + case 0x0a: /* System Memory Address Decode Register #1 */ + case 0x0b: /* System Memory Address Decode Register #2 */ + dev->regs[dev->idx] = val; + break; + case 0x0c: /* Extended DMA Register */ + dev->regs[dev->idx] = val & 0xcf; + break; + case 0x0d: /* ROMCS# Register */ + case 0x0e: /* Local Master Preemption Register */ + case 0x0f: /* Deturbo Control Register #1 */ + case 0x10: /* Cache Write-Hit Control Register */ + case 0x11: /* Master Cycle Control Register */ + dev->regs[dev->idx] = val; + break; + } + break; } } - static uint8_t opti5x7_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - opti5x7_t *dev = (opti5x7_t *) priv; + opti5x7_t *dev = (opti5x7_t *)priv; - switch (addr) { - case 0x24: - opti5x7_log("Read from OPTi 5x7 register %02x\n", dev->idx); - ret = dev->regs[dev->idx]; - break; - } - - return ret; + return (addr == 0x24) ? dev->regs[dev->idx] : 0xff; } - static void opti5x7_close(void *priv) { - opti5x7_t *dev = (opti5x7_t *) priv; + opti5x7_t *dev = (opti5x7_t *)priv; free(dev); } - static void * opti5x7_init(const device_t *info) { - opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t)); + opti5x7_t *dev = (opti5x7_t *)malloc(sizeof(opti5x7_t)); memset(dev, 0, sizeof(opti5x7_t)); io_sethandler(0x0022, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev); io_sethandler(0x0024, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev); - dev->port_92 = device_add(&port_92_device); + device_add(&port_92_device); return dev; } @@ -170,7 +164,10 @@ const device_t opti5x7_device = { "OPTi 82C5x6/82C5x7", 0, 0, - opti5x7_init, opti5x7_close, NULL, - { NULL }, NULL, NULL, - NULL -}; + opti5x7_init, + opti5x7_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; From bbfb8a35cd36b75f6a401aa80535d56d3f6e596f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Sun, 14 Feb 2021 00:41:55 +0100 Subject: [PATCH 10/34] cmake: install PDB files --- src/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 69784b1e1..f33ab0958 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -95,6 +95,12 @@ if(VCPKG_TOOLCHAIN) x_vcpkg_install_local_dependencies(TARGETS 86Box DESTINATION "bin") endif() +if(MSVC) + install(FILES $ + CONFIGURATIONS Debug RelWithDebInfo + DESTINATION "bin") +endif() + add_subdirectory(device) add_subdirectory(disk) add_subdirectory(floppy) From 0e24b636479298b5aa00667d315f02d6e8fcdd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Sun, 14 Feb 2021 01:36:45 +0100 Subject: [PATCH 11/34] clarify license --- README.md | 2 +- vcpkg.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 12a5d27ca..12d9c48f9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ operating systems and software designed for IBM PC systems and compatibles from 1981 through fairly recent system designs based on the PCI bus. -86Box is released under the GNU General Public License, version 2. +86Box is released under the GNU General Public License, version 2 only. For more information, see the `COPYING` file. The project maintainer is [OBattler](https://github.com/OBattler). diff --git a/vcpkg.json b/vcpkg.json index e57a7db16..9fba60a48 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -3,7 +3,7 @@ "version-string": "3.0", "homepage": "https://86box.net/", "documentation": "http://86box.readthedocs.io/", - "license": "GPL-2.0-or-later", + "license": "GPL-2.0-only", "dependencies": [ "freetype", "libpng", From 6a00fd700a7673b25174ed9cdf98241a9a77e570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Sun, 14 Feb 2021 03:34:45 +0100 Subject: [PATCH 12/34] workflows: remove Windows ARM32 build --- .github/workflows/cmake.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2ae0f9ec7..11216cc74 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -74,7 +74,7 @@ jobs: fail-fast: false matrix: build: - - name: Regular + - name: Debug dev-build: off new-dynarec: off type: Debug @@ -82,17 +82,12 @@ jobs: dev-build: on new-dynarec: on type: Debug - target-arch: ['Win32', 'x64', 'ARM', 'ARM64'] + target-arch: ['Win32', 'x64', 'ARM64'] toolset: ['clangcl', 'v142'] exclude: - - target-arch: 'ARM' - build: - new-dynarec: off - target-arch: 'ARM64' build: new-dynarec: off - - target-arch: 'ARM' - toolset: 'clangcl' steps: - uses: actions/checkout@v2 From 79513c170951c85f5303faaa308f27b3a8866251 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Feb 2021 03:37:21 +0100 Subject: [PATCH 13/34] 53c8xx PCI SCSI controller BIOS BAR fixes (WIP, more will come later). --- src/scsi/scsi_ncr53c8xx.c | 129 +++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 52 deletions(-) diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 2ec5932c2..8c11a3a7a 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -56,6 +56,7 @@ #define SYM53C860_SDMS4_ROM L"roms/scsi/ncr53c8xx/860/8XX_64.ROM" #define NCR53C875_SDMS3_ROM L"roms/scsi/ncr53c8xx/875/NCR307.BIN" #define SYM53C875_SDMS4_ROM L"roms/scsi/ncr53c8xx/875/8XX_64.ROM" +// #define SYM53C875_SDMS4_ROM L"roms/scsi/ncr53c8xx/875/8xx_64.rom.419" #define HA_ID 7 @@ -217,7 +218,7 @@ typedef enum typedef struct { wchar_t *nvr_path; uint8_t pci_slot; - uint8_t chip; + uint8_t chip, wide; int has_bios; int BIOSBase; rom_t bios; @@ -314,6 +315,8 @@ typedef struct { uint8_t regop; uint32_t adder; + uint32_t bios_mask; + pc_timer_t timer; #ifdef USE_WDTR @@ -412,7 +415,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) dev->scntl0 = 0xc0; dev->scntl1 = 0; dev->scntl2 = 0; - if (dev->chip >= CHIP_825) + if (dev->wide) dev->scntl3 = 8; else dev->scntl3 = 0; @@ -439,7 +442,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) dev->sstop = 1; dev->gpcntl = 0x03; - if (dev->chip >= CHIP_825) { + if (dev->wide) { /* This *IS* a wide SCSI controller, so reset all SCSI devices. */ for (i = 0; i < 16; i++) { @@ -1671,7 +1674,7 @@ ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val) dev->respid0 = val; break; case 0x4b: /* RESPID1 */ - if (dev->chip >= CHIP_825) + if (dev->wide) dev->respid1 = val; break; case 0x4d: /* STEST1 */ @@ -1723,19 +1726,19 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) case addr + 3: return (dev->name >> 24) & 0xff; #define CASE_GET_REG32_COND(name, addr) \ - case addr: if (dev->chip >= CHIP_825) \ + case addr: if (dev->wide) \ return dev->name & 0xff; \ else \ return 0x00; \ - case addr + 1: if (dev->chip >= CHIP_825) \ + case addr + 1: if (dev->wide) \ return (dev->name >> 8) & 0xff; \ else \ return 0x00; \ - case addr + 2: if (dev->chip >= CHIP_825) \ + case addr + 2: if (dev->wide) \ return (dev->name >> 16) & 0xff; \ else \ return 0x00; \ - case addr + 3: if (dev->chip >= CHIP_825) \ + case addr + 3: if (dev->wide) \ return (dev->name >> 24) & 0xff; \ else \ return 0x00; @@ -1819,12 +1822,12 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) tmp = dev->istat; return tmp; case 0x16: /* MBOX0 */ - if (dev->chip >= CHIP_825) + if (dev->wide) return 0x00; ncr53c8xx_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0); return dev->mbox0; case 0x17: /* MBOX1 */ - if (dev->chip >= CHIP_825) + if (dev->wide) return 0x00; ncr53c8xx_log("NCR 810: Read MBOX1 %02X\n", dev->mbox1); return dev->mbox1; @@ -1899,12 +1902,12 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) ncr53c8xx_log("NCR 810: Read SIST1 %02X\n", tmp); return tmp; case 0x44: /* SLPAR */ - if (dev->chip < CHIP_825) + if (!dev->wide) return 0x00; ncr53c8xx_log("NCR 810: Read SLPAR %02X\n", dev->stime0); return dev->slpar; case 0x45: /* SWIDE */ - if (dev->chip < CHIP_825) + if (!dev->wide) return 0x00; ncr53c8xx_log("NCR 810: Read SWIDE %02X\n", dev->stime0); return dev->swide; @@ -1918,13 +1921,14 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) ncr53c8xx_log("NCR 810: Read STIME0 %02X\n", dev->stime0); return dev->stime0; case 0x4a: /* RESPID0 */ - if (dev->chip >= CHIP_825) + if (dev->wide) { ncr53c8xx_log("NCR 810: Read RESPID0 %02X\n", dev->respid0); - else + } else { ncr53c8xx_log("NCR 810: Read RESPID %02X\n", dev->respid0); + } return dev->respid0; case 0x4b: /* RESPID1 */ - if (dev->chip < CHIP_825) + if (!dev->wide) return 0x00; ncr53c8xx_log("NCR 810: Read RESPID1 %02X\n", dev->respid1); return dev->respid1; @@ -1943,13 +1947,14 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) case 0x50: /* SIDL0 */ /* This is needed by the linux drivers. We currently only update it during the MSG IN phase. */ - if (dev->chip >= CHIP_825) + if (dev->wide) { ncr53c8xx_log("NCR 810: Read SIDL0 %02X\n", dev->sidl0); - else + } else { ncr53c8xx_log("NCR 810: Read SIDL %02X\n", dev->sidl0); + } return dev->sidl0; case 0x51: /* SIDL1 */ - if (dev->chip < CHIP_825) + if (!dev->wide) return 0x00; ncr53c8xx_log("NCR 810: Read SIDL1 %02X\n", dev->sidl1); return dev->sidl1; @@ -2241,7 +2246,10 @@ ncr53c8xx_ram_set_addr(ncr53c8xx_t *dev, uint32_t base) static void ncr53c8xx_bios_set_addr(ncr53c8xx_t *dev, uint32_t base) { - mem_mapping_set_addr(&dev->bios.mapping, base, 0x10000); + if (dev->has_bios == 2) + mem_mapping_set_addr(&dev->bios.mapping, base, 0x10000); + else if (dev->has_bios == 1) + mem_mapping_set_addr(&dev->bios.mapping, base, 0x04000); } @@ -2327,25 +2335,25 @@ ncr53c8xx_pci_read(int func, int addr, void *p) case 0x18: return 0; /*Memory space*/ case 0x19: - if (dev->chip == CHIP_815 || dev->chip < CHIP_825) + if (!dev->wide) return 0; return ncr53c8xx_pci_bar[2].addr_regs[1]; case 0x1A: - if (dev->chip == CHIP_815 || dev->chip < CHIP_825) + if (!dev->wide) return 0; return ncr53c8xx_pci_bar[2].addr_regs[2]; case 0x1B: - if (dev->chip == CHIP_815 || dev->chip < CHIP_825) + if (!dev->wide) return 0; return ncr53c8xx_pci_bar[2].addr_regs[3]; case 0x2C: return 0x00; case 0x2D: - if (dev->chip >= CHIP_825 || dev->chip != CHIP_815) + if (dev->wide) return 0; return 0x10; case 0x2E: - if (dev->chip >= CHIP_825 || dev->chip != CHIP_815) + if (dev->wide) return 0; return 0x01; case 0x2F: @@ -2398,7 +2406,7 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) ncr53c8xx_mem_disable(dev); if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) ncr53c8xx_mem_set_addr(dev, dev->MMIOBase); - if (dev->chip != CHIP_815 || dev->chip >= CHIP_825) { + if (dev->wide) { ncr53c8xx_ram_disable(dev); if ((dev->RAMBase != 0) && (val & PCI_COMMAND_MEM)) ncr53c8xx_ram_set_addr(dev, dev->RAMBase); @@ -2442,8 +2450,8 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) /* Then let's set the PCI regs. */ ncr53c8xx_pci_bar[1].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[1].addr &= 0xfffcf000; - dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xfffcf000; + ncr53c8xx_pci_bar[1].addr &= 0xffffc000; + dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xffffc000; /* Log the new base. */ ncr53c8xx_log("NCR53c8xx: New MMIO base is %08X\n" , dev->MMIOBase); /* We're done, so get out of the here. */ @@ -2454,7 +2462,7 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) return; case 0x19: case 0x1A: case 0x1B: - if (dev->chip == CHIP_815 || dev->chip < CHIP_825) + if (!dev->wide) return; /* RAM Base set. */ /* First, remove the old I/O. */ @@ -2462,8 +2470,8 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) /* Then let's set the PCI regs. */ ncr53c8xx_pci_bar[2].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[2].addr &= 0xfffcf000; - dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xfffcf000; + ncr53c8xx_pci_bar[2].addr &= 0xfffff000; + dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xfffff000; /* Log the new base. */ ncr53c8xx_log("NCR53c8xx: New RAM base is %08X\n" , dev->RAMBase); /* We're done, so get out of the here. */ @@ -2482,14 +2490,14 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) /* Then let's set the PCI regs. */ ncr53c8xx_pci_bar[3].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[3].addr &= 0xfffcf001; - dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & 0xfffcf000; + ncr53c8xx_pci_bar[3].addr &= (dev->bios_mask | 0x00000001); + dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & dev->bios_mask; + pclog("BIOS BAR: %08X\n", dev->BIOSBase | ncr53c8xx_pci_bar[3].addr_regs[0]); /* Log the new base. */ ncr53c8xx_log("NCR53c8xx: New BIOS base is %08X\n" , dev->BIOSBase); /* We're done, so get out of the here. */ - if (ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01) { + if (ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01) ncr53c8xx_bios_set_addr(dev, dev->BIOSBase); - } return; case 0x3C: @@ -2513,54 +2521,63 @@ ncr53c8xx_init(const device_t *info) dev->chip = info->local & 0xff; - if (info->local & 0x8000) - dev->has_bios = 0; - else + if ((dev->chip != CHIP_810) && (dev->chip != CHIP_820) && !(info->local & 0x8000)) dev->has_bios = device_get_config_int("bios"); + else + dev->has_bios = 0; if (dev->chip == CHIP_875) { if (dev->has_bios == 2) - rom_init(&dev->bios, SYM53C875_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios, SYM53C875_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); else if (dev->has_bios == 1) rom_init(&dev->bios, NCR53C875_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); dev->chip_rev = 0x04; dev->nvr_path = L"ncr53c875.nvr"; + dev->wide = 1; } else if (dev->chip == CHIP_860) { if (dev->has_bios == 2) - rom_init(&dev->bios, SYM53C860_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios, SYM53C860_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); else if (dev->has_bios == 1) rom_init(&dev->bios, NCR53C860_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); dev->chip_rev = 0x04; dev->nvr_path = L"ncr53c860.nvr"; + dev->wide = 1; + } else if (dev->chip == CHIP_820) { + dev->nvr_path = L"ncr53c820.nvr"; + dev->wide = 1; } else if (dev->chip == CHIP_825) { if (dev->has_bios == 2) - rom_init(&dev->bios, SYM53C825A_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios, SYM53C825A_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); else if (dev->has_bios == 1) rom_init(&dev->bios, NCR53C825A_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); dev->chip_rev = 0x26; dev->nvr_path = L"ncr53c825a.nvr"; + dev->wide = 1; } else if (dev->chip == CHIP_810) { - if (dev->has_bios == 2) - rom_init(&dev->bios, SYM53C810_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); - else if (dev->has_bios == 1) - rom_init(&dev->bios, NCR53C810_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); dev->nvr_path = L"ncr53c810.nvr"; + dev->wide = 0; } else if (dev->chip == CHIP_815) { if (dev->has_bios == 2) - rom_init(&dev->bios, SYM53C815_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios, SYM53C815_SDMS4_ROM, 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); else if (dev->has_bios == 1) rom_init(&dev->bios, NCR53C815_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); dev->chip_rev = 0x04; dev->nvr_path = L"ncr53c815.nvr"; + dev->wide = 0; } ncr53c8xx_pci_bar[0].addr_regs[0] = 1; ncr53c8xx_pci_bar[1].addr_regs[0] = 0; ncr53c8xx_pci_regs[0x04] = 3; - if (dev->has_bios) { + if (dev->has_bios == 2) { + ncr53c8xx_pci_bar[3].addr = 0xffff0000; + dev->bios_mask = 0xffff0000; + } else if (dev->has_bios == 1) { ncr53c8xx_pci_bar[3].addr = 0xffffc000; + dev->bios_mask = 0xffffc000; } else { - ncr53c8xx_pci_bar[3].addr = 0; + ncr53c8xx_pci_bar[3].addr = 0x00000000; + dev->bios_mask = 0x00000000; } ncr53c8xx_mem_init(dev, 0x0fffff00); @@ -2568,10 +2585,8 @@ ncr53c8xx_init(const device_t *info) ncr53c8xx_pci_bar[2].addr_regs[0] = 0; - if (dev->chip >= CHIP_825 || (dev->chip != CHIP_815)) { - /* Need to make it align on a 16k boundary as that's this emulator's - memory mapping granularity. */ - ncr53c8xx_ram_init(dev, 0x0fffc000); + if (dev->wide) { + ncr53c8xx_ram_init(dev, 0x0ffff000); ncr53c8xx_ram_disable(dev); } @@ -2643,7 +2658,7 @@ const device_t ncr53c810_pci_device = CHIP_810, ncr53c8xx_init, ncr53c8xx_close, NULL, { NULL }, NULL, NULL, - ncr53c8xx_pci_config + NULL }; const device_t ncr53c810_onboard_pci_device = @@ -2666,6 +2681,16 @@ const device_t ncr53c815_pci_device = ncr53c8xx_pci_config }; +const device_t ncr53c820_pci_device = +{ + "NCR 53c820", + DEVICE_PCI, + CHIP_820, + ncr53c8xx_init, ncr53c8xx_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + const device_t ncr53c825a_pci_device = { "NCR 53c825A", From 54a36d82b9a8b1f4b7d7cea374439bd354409f1a Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 14 Feb 2021 11:14:11 +0200 Subject: [PATCH 14/34] Shadow recalc on the Python doesn't need ternaries --- src/chipset/opti5x7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index f4231c8de..7eb23f96a 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -33,7 +33,7 @@ #include <86box/chipset.h> /* Shadow RAM */ -#define SHADOW_RECALC (((dev->regs[(i < 4) ? 4 : 5] & (1 << ((i < 4) ? i : i - 4) * 2)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[(i < 4) ? 4 : 5] & (1 << (((i < 4) ? i : i - 4) * 2 + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) +#define SHADOW_RECALC (((dev->regs[4 + !!(i & 4)] & (1 << (i - (4 * !!(i & 4))) * 2)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[4 + !!(i & 4)] & (1 << ((i - (4 * !!(i & 4))) * 2 + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) #define SHADOW_E_RECALC (((dev->regs[0x06] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) #define SHADOW_F_RECALC (((dev->regs[0x06] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) From 41cd6b48f8853ae3c41266321841516a574313dd Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 14 Feb 2021 11:46:22 +0200 Subject: [PATCH 15/34] More work at the Shadow recalc code of the Python Divided and documented into multiple macros --- src/chipset/opti5x7.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index 7eb23f96a..e97a08fe5 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -33,8 +33,31 @@ #include <86box/chipset.h> /* Shadow RAM */ -#define SHADOW_RECALC (((dev->regs[4 + !!(i & 4)] & (1 << (i - (4 * !!(i & 4))) * 2)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[4 + !!(i & 4)] & (1 << ((i - (4 * !!(i & 4))) * 2 + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) + +/* Register 4h: C0000-CFFFF range | Register 5h: D0000-DFFFF range */ +#define CURRENT_REGISTER dev->regs[4 + !!(i & 4)] + +/* +Bits 7-6: xC000-xFFFF +Bits 5-4: x8000-xBFFF +Bits 3-2: x4000-x7FFF +Bits 0-1: x0000-x3FFF + + x-y + 0 0 Read/Write AT bus + 1 0 Read from AT - Write to DRAM + 1 1 Read from DRAM - Write to DRAM + 0 1 Read from DRAM (write protected) +*/ +#define CAN_READ (1 << (i - (4 * !!(i & 4))) * 2) +#define CAN_WRITE (1 << ((i - (4 * !!(i & 4))) * 2 + 1)) + +#define SHADOW_RECALC (((CURRENT_REGISTER & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((CURRENT_REGISTER & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) + +/* Recalc the E Segment */ #define SHADOW_E_RECALC (((dev->regs[0x06] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) + +/* Recalc the F Segment */ #define SHADOW_F_RECALC (((dev->regs[0x06] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) typedef struct From db4ef02a88a44fe0210461d1e51e4600398d2cb5 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 14 Feb 2021 11:55:16 +0200 Subject: [PATCH 16/34] Unite the E & F segment recalcs into one Macro --- src/chipset/opti5x7.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index e97a08fe5..1b2d00798 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -52,13 +52,11 @@ Bits 0-1: x0000-x3FFF #define CAN_READ (1 << (i - (4 * !!(i & 4))) * 2) #define CAN_WRITE (1 << ((i - (4 * !!(i & 4))) * 2 + 1)) +/* Shadow Recalc for the C/D segments */ #define SHADOW_RECALC (((CURRENT_REGISTER & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((CURRENT_REGISTER & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) -/* Recalc the E Segment */ -#define SHADOW_E_RECALC (((dev->regs[0x06] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) - -/* Recalc the F Segment */ -#define SHADOW_F_RECALC (((dev->regs[0x06] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) +/* Shadow Recalc for the E/F segments */ +#define SHADOW_EF_RECALC (((dev->regs[6] & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) typedef struct { @@ -88,12 +86,13 @@ static void shadow_map(opti5x7_t *dev) { for (int i = 0; i < 8; i++) + { mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, SHADOW_RECALC); - - mem_set_mem_state_both(0xe0000, 0x10000, SHADOW_E_RECALC); + if (i < 2) + mem_set_mem_state_both(0xe0000 + (i << 16), 0x10000, SHADOW_EF_RECALC); + } shadowbios = !!(dev->regs[0x06] & 5); shadowbios_write = !!(dev->regs[0x06] & 0x0a); - mem_set_mem_state_both(0xf0000, 0x10000, SHADOW_F_RECALC); flushmmucache(); } From 988478a095c28291570d58e387cf9b84ac446d8e Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 14 Feb 2021 11:57:03 +0200 Subject: [PATCH 17/34] Tiny typo fix --- src/chipset/opti5x7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index 1b2d00798..1199c634f 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -56,7 +56,7 @@ Bits 0-1: x0000-x3FFF #define SHADOW_RECALC (((CURRENT_REGISTER & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((CURRENT_REGISTER & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) /* Shadow Recalc for the E/F segments */ -#define SHADOW_EF_RECALC (((dev->regs[6] & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x06] & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) +#define SHADOW_EF_RECALC (((dev->regs[6] & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) typedef struct { From c0e7ac3762e5f2f07216f228ec1927a4915c578a Mon Sep 17 00:00:00 2001 From: luisjoseromero Date: Wed, 10 Feb 2021 20:22:51 +0000 Subject: [PATCH 18/34] Integrated Chrome tracing Added support for chrome tracing by integrating the minitrace library (github.com/hrydgard/minitrace), and modified it with a background flushing thread that allows tracing to continue automatically after the predefined 1 million event limit. Menu items and an accelerator (Ctr+T) have also been added. Starting and stopping the trace simply replaces trace.json with the new trace data. The feature is disabled by default. Pass MINITRACE=y to the build command to enable it. Some traces are already added as an example, however they won't have any effect if the feature is disabled. --- CMakeLists.txt | 2 + src/CMakeLists.txt | 6 + src/include/86box/plat.h | 10 + src/include/86box/resource.h | 5 + src/include/minitrace/minitrace.h | 270 +++++++++++++++ src/minitrace/minitrace.c | 541 ++++++++++++++++++++++++++++++ src/pc.c | 3 + src/video/video.c | 5 + src/win/86Box.rc | 8 + src/win/Makefile.mingw | 10 +- src/win/win.c | 19 +- src/win/win_ui.c | 28 ++ 12 files changed, 904 insertions(+), 3 deletions(-) create mode 100644 src/include/minitrace/minitrace.h create mode 100644 src/minitrace/minitrace.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fde8c8514..5d420a5e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,8 @@ option(DISCORD "Discord integration" ON) option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF) +option(MINITRACE "Enable Chrome tracing using the modified minitrace library" OFF) + option(DEV_BRANCH "Development branch" OFF) CMAKE_DEPENDENT_OPTION(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(CL5422 "Cirrus Logic CL-GD 5402/5420/5422" ON "DEV_BRANCH" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f33ab0958..3e0b0515d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -90,6 +90,12 @@ else() add_subdirectory(codegen) endif() +if(MINITRACE) + add_compile_definitions(MTR_ENABLED) + add_library(minitrace OBJECT minitrace/minitrace.c) + target_link_libraries(86Box minitrace) +endif() + install(TARGETS 86Box) if(VCPKG_TOOLCHAIN) x_vcpkg_install_local_dependencies(TARGETS 86Box DESTINATION "bin") diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index aac21111f..af7434d09 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -66,6 +66,11 @@ extern int dopause, /* system is paused */ doresize, /* screen resize requested */ quited, /* system exit requested */ mouse_capture; /* mouse is captured in app */ + +#ifdef MTR_ENABLED +extern int tracing_on; +#endif + extern uint64_t timer_freq; extern int infocus; extern char emu_version[200]; /* version ID string */ @@ -165,6 +170,11 @@ extern void startblit(void); extern void endblit(void); extern void take_screenshot(void); +#ifdef MTR_ENABLED +extern void init_trace(void); +extern void shutdown_trace(void); +#endif + #ifdef __cplusplus } #endif diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 24ede722a..28abd983b 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -287,6 +287,11 @@ #define IDM_ACTION_EXIT 40014 #define IDM_ACTION_CTRL_ALT_ESC 40015 #define IDM_ACTION_PAUSE 40016 +#ifdef MTR_ENABLED +#define IDM_ACTION_BEGIN_TRACE 40017 +#define IDM_ACTION_END_TRACE 40018 +#define IDM_ACTION_TRACE 40019 +#endif #define IDM_CONFIG 40020 #define IDM_CONFIG_LOAD 40021 #define IDM_CONFIG_SAVE 40022 diff --git a/src/include/minitrace/minitrace.h b/src/include/minitrace/minitrace.h new file mode 100644 index 000000000..2047eedb7 --- /dev/null +++ b/src/include/minitrace/minitrace.h @@ -0,0 +1,270 @@ +// Minitrace +// +// Copyright 2014 by Henrik RydgÃ¥rd +// http://www.github.com/hrydgard/minitrace +// Released under the MIT license. +// +// Ultra-light dependency free library for performance tracing C/C++ applications. +// Produces traces compatible with Google Chrome's trace viewer. +// Simply open "about:tracing" in Chrome and load the produced JSON. +// +// This contains far less template magic than the original libraries from Chrome +// because this is meant to be usable from C. +// +// See README.md for a tutorial. +// +// The trace format is documented here: +// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit +// More: +// http://www.altdevblogaday.com/2012/08/21/using-chrometracing-to-view-your-inline-profiling-data/ + +#ifndef MINITRACE_H +#define MINITRACE_H + +#include + +// If MTR_ENABLED is not defined, Minitrace does nothing and has near zero overhead. +// Preferably, set this flag in your build system. If you can't just uncomment this line. +// #define MTR_ENABLED + +// By default, will collect up to 1000000 events, then you must flush. +// It's recommended that you simply call mtr_flush on a background thread +// occasionally. It's safe...ish. +#define INTERNAL_MINITRACE_BUFFER_SIZE 1000000 + +#ifdef __cplusplus +extern "C" { +#endif + +// Initializes Minitrace. Must be called very early during startup of your executable, +// before any MTR_ statements. +void mtr_init(const char *json_file); +// Same as above, but allows passing in a custom stream (FILE *), as returned by +// fopen(). It should be opened for writing, preferably in binary mode to avoid +// processing of line endings (i.e. the "wb" mode). +void mtr_init_from_stream(void *stream); + +// Shuts down minitrace cleanly, flushing the trace buffer. +void mtr_shutdown(void); + +// Lets you enable and disable Minitrace at runtime. +// May cause strange discontinuities in the output. +// Minitrace is enabled on startup by default. +void mtr_start(void); +void mtr_stop(void); + +// Flushes the collected data to disk, clearing the buffer for new data. +void mtr_flush(void); + +// Returns the current time in seconds. Used internally by Minitrace. No caching. +double mtr_time_s(void); + +// Registers a handler that will flush the trace on Ctrl+C. +// Works on Linux and MacOSX, and in Win32 console applications. +void mtr_register_sigint_handler(void); + +// Utility function that should rarely be used. +// If str is semi dynamic, store it permanently in a small pool so we don't need to malloc it. +// The pool fills up fast though and performance isn't great. +// Returns a fixed string if the pool is full. +const char *mtr_pool_string(const char *str); + +// Commented-out types will be supported in the future. +typedef enum { + MTR_ARG_TYPE_NONE = 0, + MTR_ARG_TYPE_INT = 1, // I + // MTR_ARG_TYPE_FLOAT = 2, // TODO + // MTR_ARG_TYPE_DOUBLE = 3, // TODO + MTR_ARG_TYPE_STRING_CONST = 8, // C + MTR_ARG_TYPE_STRING_COPY = 9, + // MTR_ARG_TYPE_JSON_COPY = 10, +} mtr_arg_type; + +// TODO: Add support for more than one argument (metadata) per event +// Having more costs speed and memory. +#define MTR_MAX_ARGS 1 + +// Only use the macros to call these. +void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id); +void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value); + +#ifdef MTR_ENABLED + +// c - category. Can be filtered by in trace viewer (or at least that's the intention). +// A good use is to pass __FILE__, there are macros further below that will do it for you. +// n - name. Pass __FUNCTION__ in most cases, unless you are marking up parts of one. + +// Scopes. In C++, use MTR_SCOPE. In C, always match them within the same scope. +#define MTR_BEGIN(c, n) internal_mtr_raw_event(c, n, 'B', 0) +#define MTR_END(c, n) internal_mtr_raw_event(c, n, 'E', 0) +#define MTR_SCOPE(c, n) MTRScopedTrace ____mtr_scope(c, n) +#define MTR_SCOPE_LIMIT(c, n, l) MTRScopedTraceLimit ____mtr_scope(c, n, l) + +// Async events. Can span threads. ID identifies which events to connect in the view. +#define MTR_START(c, n, id) internal_mtr_raw_event(c, n, 'S', (void *)(id)) +#define MTR_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 'T', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step)) +#define MTR_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'F', (void *)(id)) + +// Flow events. Like async events, but displayed in a more fancy way in the viewer. +#define MTR_FLOW_START(c, n, id) internal_mtr_raw_event(c, n, 's', (void *)(id)) +#define MTR_FLOW_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 't', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step)) +#define MTR_FLOW_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'f', (void *)(id)) + +// The same macros, but with a single named argument which shows up as metadata in the viewer. +// _I for int. +// _C is for a const string arg. +// _S will copy the string, freeing on flush (expensive but sometimes necessary). +// but required if the string was generated dynamically. + +// Note that it's fine to match BEGIN_S with END and BEGIN with END_S, etc. +#define MTR_BEGIN_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) +#define MTR_END_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) +#define MTR_SCOPE_C(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) + +#define MTR_BEGIN_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval)) +#define MTR_END_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval)) +#define MTR_SCOPE_S(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval)) + +#define MTR_BEGIN_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval)) +#define MTR_END_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval)) +#define MTR_SCOPE_I(c, n, aname, aintval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval)) + +// Instant events. For things with no duration. +#define MTR_INSTANT(c, n) internal_mtr_raw_event(c, n, 'I', 0) +#define MTR_INSTANT_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) +#define MTR_INSTANT_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_INT, aname, (void *)(aintval)) + +// Counters (can't do multi-value counters yet) +#define MTR_COUNTER(c, n, val) internal_mtr_raw_event_arg(c, n, 'C', 0, MTR_ARG_TYPE_INT, n, (void *)(intptr_t)(val)) + +// Metadata. Call at the start preferably. Must be const strings. + +#define MTR_META_PROCESS_NAME(n) internal_mtr_raw_event_arg("", "process_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n)) +#define MTR_META_THREAD_NAME(n) internal_mtr_raw_event_arg("", "thread_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n)) +#define MTR_META_THREAD_SORT_INDEX(i) internal_mtr_raw_event_arg("", "thread_sort_index", 'M', 0, MTR_ARG_TYPE_INT, "sort_index", (void *)(i)) + +#else + +#define MTR_BEGIN(c, n) +#define MTR_END(c, n) +#define MTR_SCOPE(c, n) +#define MTR_START(c, n, id) +#define MTR_STEP(c, n, id, step) +#define MTR_FINISH(c, n, id) +#define MTR_FLOW_START(c, n, id) +#define MTR_FLOW_STEP(c, n, id, step) +#define MTR_FLOW_FINISH(c, n, id) +#define MTR_INSTANT(c, n) + +#define MTR_BEGIN_C(c, n, aname, astrval) +#define MTR_END_C(c, n, aname, astrval) +#define MTR_SCOPE_C(c, n, aname, astrval) + +#define MTR_BEGIN_S(c, n, aname, astrval) +#define MTR_END_S(c, n, aname, astrval) +#define MTR_SCOPE_S(c, n, aname, astrval) + +#define MTR_BEGIN_I(c, n, aname, aintval) +#define MTR_END_I(c, n, aname, aintval) +#define MTR_SCOPE_I(c, n, aname, aintval) + +#define MTR_INSTANT(c, n) +#define MTR_INSTANT_C(c, n, aname, astrval) +#define MTR_INSTANT_I(c, n, aname, aintval) + +// Counters (can't do multi-value counters yet) +#define MTR_COUNTER(c, n, val) + +// Metadata. Call at the start preferably. Must be const strings. + +#define MTR_META_PROCESS_NAME(n) + +#define MTR_META_THREAD_NAME(n) +#define MTR_META_THREAD_SORT_INDEX(i) + +#endif + +// Shortcuts for simple function timing with automatic categories and names. + +#define MTR_BEGIN_FUNC() MTR_BEGIN(__FILE__, __FUNCTION__) +#define MTR_END_FUNC() MTR_END(__FILE__, __FUNCTION__) +#define MTR_SCOPE_FUNC() MTR_SCOPE(__FILE__, __FUNCTION__) +#define MTR_INSTANT_FUNC() MTR_INSTANT(__FILE__, __FUNCTION__) +#define MTR_SCOPE_FUNC_LIMIT_S(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, l) +#define MTR_SCOPE_FUNC_LIMIT_MS(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, (double)l * 0.000001) + +// Same, but with a single argument of the usual types. +#define MTR_BEGIN_FUNC_S(aname, arg) MTR_BEGIN_S(__FILE__, __FUNCTION__, aname, arg) +#define MTR_END_FUNC_S(aname, arg) MTR_END_S(__FILE__, __FUNCTION__, aname, arg) +#define MTR_SCOPE_FUNC_S(aname, arg) MTR_SCOPE_S(__FILE__, __FUNCTION__, aname, arg) + +#define MTR_BEGIN_FUNC_C(aname, arg) MTR_BEGIN_C(__FILE__, __FUNCTION__, aname, arg) +#define MTR_END_FUNC_C(aname, arg) MTR_END_C(__FILE__, __FUNCTION__, aname, arg) +#define MTR_SCOPE_FUNC_C(aname, arg) MTR_SCOPE_C(__FILE__, __FUNCTION__, aname, arg) + +#define MTR_BEGIN_FUNC_I(aname, arg) MTR_BEGIN_I(__FILE__, __FUNCTION__, aname, arg) +#define MTR_END_FUNC_I(aname, arg) MTR_END_I(__FILE__, __FUNCTION__, aname, arg) +#define MTR_SCOPE_FUNC_I(aname, arg) MTR_SCOPE_I(__FILE__, __FUNCTION__, aname, arg) + +#ifdef __cplusplus +} + +#ifdef MTR_ENABLED +// These are optimized to use X events (combined B and E). Much easier to do in C++ than in C. +class MTRScopedTrace { +public: + MTRScopedTrace(const char *category, const char *name) + : category_(category), name_(name) { + start_time_ = mtr_time_s(); + } + ~MTRScopedTrace() { + internal_mtr_raw_event(category_, name_, 'X', &start_time_); + } + +private: + const char *category_; + const char *name_; + double start_time_; +}; + +// Only outputs a block if execution time exceeded the limit. +// TODO: This will effectively call mtr_time_s twice at the end, which is bad. +class MTRScopedTraceLimit { +public: + MTRScopedTraceLimit(const char *category, const char *name, double limit_s) + : category_(category), name_(name), limit_(limit_s) { + start_time_ = mtr_time_s(); + } + ~MTRScopedTraceLimit() { + double end_time = mtr_time_s(); + if (end_time - start_time_ >= limit_) { + internal_mtr_raw_event(category_, name_, 'X', &start_time_); + } + } + +private: + const char *category_; + const char *name_; + double start_time_; + double limit_; +}; + +class MTRScopedTraceArg { +public: + MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value) + : category_(category), name_(name) { + internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value); + } + ~MTRScopedTraceArg() { + internal_mtr_raw_event(category_, name_, 'E', 0); + } + +private: + const char *category_; + const char *name_; +}; +#endif + +#endif + +#endif diff --git a/src/minitrace/minitrace.c b/src/minitrace/minitrace.c new file mode 100644 index 000000000..11cae6b9a --- /dev/null +++ b/src/minitrace/minitrace.c @@ -0,0 +1,541 @@ +// minitrace +// Copyright 2014 by Henrik RydgÃ¥rd +// http://www.github.com/hrydgard/minitrace +// Released under the MIT license. + +// See minitrace.h for basic documentation. + +#include +#include +#include + +#ifdef _WIN32 +#pragma warning (disable:4996) +#define WIN32_LEAN_AND_MEAN +#include +#ifndef __MINGW32__ +#define __thread __declspec(thread) +#endif +#define pthread_cond_t CONDITION_VARIABLE +#define pthread_cond_init(a) InitializeConditionVariable(a) +#define pthread_cond_wait(a, b) SleepConditionVariableCS(a, b, INFINITE) +#define pthread_cond_signal(a) WakeConditionVariable(a) +#define pthread_mutex_t CRITICAL_SECTION +#define pthread_mutex_init(a, b) InitializeCriticalSection(a) +#define pthread_mutex_lock(a) EnterCriticalSection(a) +#define pthread_mutex_unlock(a) LeaveCriticalSection(a) +#define pthread_mutex_destroy(a) DeleteCriticalSection(a) +#else +#include +#include +#include +#include +#endif + +#include + +#ifdef __GNUC__ +#define ATTR_NORETURN __attribute__((noreturn)) +#else +#define ATTR_NORETURN +#endif + +#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0]) +#define TRUE 1 +#define FALSE 0 + +// Ugh, this struct is already pretty heavy. +// Will probably need to move arguments to a second buffer to support more than one. +typedef struct raw_event { + const char *name; + const char *cat; + void *id; + int64_t ts; + uint32_t pid; + uint32_t tid; + char ph; + mtr_arg_type arg_type; + const char *arg_name; + union { + const char *a_str; + int a_int; + double a_double; + }; +} raw_event_t; + +static raw_event_t *event_buffer; +static raw_event_t *flush_buffer; +static volatile int event_count; +static __attribute__ ((aligned (32))) volatile long is_tracing = FALSE; +static __attribute__ ((aligned (32))) volatile long stop_flushing_requested = FALSE; +static int is_flushing = FALSE; +static int events_in_progress = 0; +static int64_t time_offset; +static int first_line = 1; +static FILE *f; +static __thread int cur_thread_id; // Thread local storage +static int cur_process_id; +static pthread_mutex_t mutex; +static pthread_mutex_t event_mutex; +static pthread_cond_t buffer_not_full_cond; +static pthread_cond_t buffer_full_cond; + +#define STRING_POOL_SIZE 100 +static char *str_pool[100]; + +// forward declaration +void mtr_flush_with_state(int); + +// Tiny portability layer. +// Exposes: +// get_cur_thread_id() +// get_cur_process_id() +// mtr_time_s() +// pthread basics +#ifdef _WIN32 +#define atomic_load(a) InterlockedOr((a), 0) +#define atomic_store(a, b) InterlockedExchange((a), b) + +static int get_cur_thread_id() { + return (int)GetCurrentThreadId(); +} +static int get_cur_process_id() { + return (int)GetCurrentProcessId(); +} + +static uint64_t _frequency = 0; +static uint64_t _starttime = 0; +double mtr_time_s() { + if (_frequency == 0) { + QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); + QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); + } + __int64 time; + QueryPerformanceCounter((LARGE_INTEGER*)&time); + return ((double) (time - _starttime) / (double) _frequency); +} + +// Ctrl+C handling for Windows console apps +static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { + if (atomic_load(&is_tracing) && fdwCtrlType == CTRL_C_EVENT) { + printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); + mtr_flush(); + mtr_shutdown(); + } + ExitProcess(1); +} + +void mtr_register_sigint_handler() { + // For console apps: + SetConsoleCtrlHandler(&CtrlHandler, TRUE); +} + +HANDLE thread_handle; + +static DWORD WINAPI thread_flush_proc(void* param) { + while(TRUE) { + mtr_flush_with_state(FALSE); + if(atomic_load(&stop_flushing_requested)) { + break; + } + } + return 0; +} + +static void init_flushing_thread(void) { + pthread_mutex_lock(&mutex); + is_flushing = FALSE; + pthread_mutex_unlock(&mutex); + thread_handle = CreateThread(NULL, 0, thread_flush_proc, (void*)0, 0, NULL); +} + +static void join_flushing_thread(void) { + WaitForSingleObject(thread_handle, INFINITE); +} + +#else + +static inline int get_cur_thread_id() { + return (int)(intptr_t)pthread_self(); +} +static inline int get_cur_process_id() { + return (int)getpid(); +} + +#if defined(BLACKBERRY) +double mtr_time_s() { + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); // Linux must use CLOCK_MONOTONIC_RAW due to time warps + return time.tv_sec + time.tv_nsec / 1.0e9; +} +#else +double mtr_time_s() { + static time_t start; + struct timeval tv; + gettimeofday(&tv, NULL); + if (start == 0) { + start = tv.tv_sec; + } + tv.tv_sec -= start; + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +} +#endif // !BLACKBERRY + +static void termination_handler(int signum) ATTR_NORETURN; +static void termination_handler(int signum) { + (void) signum; + if (is_tracing) { + printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); + mtr_flush(); + fwrite("\n]}\n", 1, 4, f); + fclose(f); + } + exit(1); +} + +void mtr_register_sigint_handler() { +#ifndef MTR_ENABLED + return; +#endif + // Avoid altering set-to-be-ignored handlers while registering. + if (signal(SIGINT, &termination_handler) == SIG_IGN) + signal(SIGINT, SIG_IGN); +} + +#endif + +void mtr_init_from_stream(void *stream) { +#ifndef MTR_ENABLED + return; +#endif + event_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); + flush_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); + event_count = 0; + f = (FILE *)stream; + const char *header = "{\"traceEvents\":[\n"; + fwrite(header, 1, strlen(header), f); + time_offset = (uint64_t)(mtr_time_s() * 1000000); + first_line = 1; + pthread_mutex_init(&mutex, 0); + pthread_mutex_init(&event_mutex, 0); +} + +void mtr_init(const char *json_file) { +#ifndef MTR_ENABLED + return; +#endif + mtr_init_from_stream(fopen(json_file, "wb")); +} + +void mtr_shutdown() { + int i; +#ifndef MTR_ENABLED + return; +#endif + + mtr_flush_with_state(TRUE); + + fwrite("\n]}\n", 1, 4, f); + fclose(f); + pthread_mutex_destroy(&mutex); + pthread_mutex_destroy(&event_mutex); + f = 0; + free(event_buffer); + event_buffer = 0; + for (i = 0; i < STRING_POOL_SIZE; i++) { + if (str_pool[i]) { + free(str_pool[i]); + str_pool[i] = 0; + } + } +} + +const char *mtr_pool_string(const char *str) { + int i; + for (i = 0; i < STRING_POOL_SIZE; i++) { + if (!str_pool[i]) { + str_pool[i] = (char*)malloc(strlen(str) + 1); + strcpy(str_pool[i], str); + return str_pool[i]; + } else { + if (!strcmp(str, str_pool[i])) + return str_pool[i]; + } + } + return "string pool full"; +} + +void mtr_start() { +#ifndef MTR_ENABLED + return; +#endif + pthread_cond_init(&buffer_not_full_cond); + pthread_cond_init(&buffer_full_cond); + atomic_store(&is_tracing, TRUE); + init_flushing_thread(); +} + +void mtr_stop() { +#ifndef MTR_ENABLED + return; +#endif + atomic_store(&is_tracing, FALSE); + atomic_store(&stop_flushing_requested, TRUE); + pthread_cond_signal(&buffer_not_full_cond); + pthread_cond_signal(&buffer_full_cond); + join_flushing_thread(); + atomic_store(&stop_flushing_requested, FALSE); +} + +// TODO: fwrite more than one line at a time. +// Flushing is thread safe and process async +// using double-buffering mechanism. +// Aware: only one flushing process may be +// running at any point of time +void mtr_flush_with_state(int is_last) { +#ifndef MTR_ENABLED + return; +#endif + int i = 0; + char linebuf[1024]; + char arg_buf[1024]; + char id_buf[256]; + int event_count_copy = 0; + int events_in_progress_copy = 1; + raw_event_t *event_buffer_tmp = NULL; + + // small critical section to swap buffers + // - no any new events can be spawn while + // swapping since they tied to the same mutex + // - checks for any flushing in process + pthread_mutex_lock(&mutex); + // if not flushing already + if (is_flushing) { + pthread_mutex_unlock(&mutex); + return; + } + is_flushing = TRUE; + if(!is_last) { + while(event_count < INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { + pthread_cond_wait(&buffer_full_cond, &mutex); + } + } + event_count_copy = event_count; + event_buffer_tmp = flush_buffer; + flush_buffer = event_buffer; + event_buffer = event_buffer_tmp; + event_count = 0; + // waiting for any unfinished events before swap + while (events_in_progress_copy != 0) { + pthread_mutex_lock(&event_mutex); + events_in_progress_copy = events_in_progress; + pthread_mutex_unlock(&event_mutex); + } + pthread_mutex_unlock(&mutex); + pthread_cond_signal(&buffer_not_full_cond); + + for (i = 0; i < event_count_copy; i++) { + raw_event_t *raw = &flush_buffer[i]; + int len; + switch (raw->arg_type) { + case MTR_ARG_TYPE_INT: + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":%i", raw->arg_name, raw->a_int); + break; + case MTR_ARG_TYPE_STRING_CONST: + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); + break; + case MTR_ARG_TYPE_STRING_COPY: + if (strlen(raw->a_str) > 700) { + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%.*s\"", raw->arg_name, 700, raw->a_str); + } else { + snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); + } + break; + case MTR_ARG_TYPE_NONE: + arg_buf[0] = '\0'; + break; + } + if (raw->id) { + switch (raw->ph) { + case 'S': + case 'T': + case 'F': + // TODO: Support full 64-bit pointers + snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"id\":\"0x%08x\"", (uint32_t)(uintptr_t)raw->id); + break; + case 'X': + snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"dur\":%i", (int)raw->a_double); + break; + } + } else { + id_buf[0] = 0; + } + const char *cat = raw->cat; +#ifdef _WIN32 + // On Windows, we often end up with backslashes in category. + char temp[256]; + { + int len = (int)strlen(cat); + int i; + if (len > 255) len = 255; + for (i = 0; i < len; i++) { + temp[i] = cat[i] == '\\' ? '/' : cat[i]; + } + temp[len] = 0; + cat = temp; + } +#endif + + len = snprintf(linebuf, ARRAY_SIZE(linebuf), "%s{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ",\"ph\":\"%c\",\"name\":\"%s\",\"args\":{%s}%s}", + first_line ? "" : ",\n", + cat, raw->pid, raw->tid, raw->ts - time_offset, raw->ph, raw->name, arg_buf, id_buf); + fwrite(linebuf, 1, len, f); + first_line = 0; + + if (raw->arg_type == MTR_ARG_TYPE_STRING_COPY) { + free((void*)raw->a_str); + } + #ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME + free(raw->name); + free(raw->cat); + #endif + } + + pthread_mutex_lock(&mutex); + is_flushing = is_last; + pthread_mutex_unlock(&mutex); +} + +void mtr_flush() { + mtr_flush_with_state(FALSE); +} + +void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id) { +#ifndef MTR_ENABLED + return; +#endif + + if (!atomic_load(&is_tracing)) { + return; + } + pthread_mutex_lock(&mutex); + while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { + pthread_cond_wait(&buffer_not_full_cond, &mutex); + } + raw_event_t *ev = &event_buffer[event_count]; + ++event_count; + pthread_mutex_lock(&event_mutex); + ++events_in_progress; + pthread_mutex_unlock(&event_mutex); + int local_event_count = event_count; + pthread_mutex_unlock(&mutex); + if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { + pthread_cond_signal(&buffer_full_cond); + } + + double ts = mtr_time_s(); + + if (!cur_thread_id) { + cur_thread_id = get_cur_thread_id(); + } + if (!cur_process_id) { + cur_process_id = get_cur_process_id(); + } + +#ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME + const size_t category_len = strlen(category); + ev->cat = malloc(category_len + 1); + strcpy(ev->cat, category); + + const size_t name_len = strlen(name); + ev->name = malloc(name_len + 1); + strcpy(ev->name, name); + +#else + ev->cat = category; + ev->name = name; +#endif + + ev->id = id; + ev->ph = ph; + if (ev->ph == 'X') { + double x; + memcpy(&x, id, sizeof(double)); + ev->ts = (int64_t)(x * 1000000); + ev->a_double = (ts - x) * 1000000; + } else { + ev->ts = (int64_t)(ts * 1000000); + } + ev->tid = cur_thread_id; + ev->pid = cur_process_id; + ev->arg_type = MTR_ARG_TYPE_NONE; + + pthread_mutex_lock(&event_mutex); + --events_in_progress; + pthread_mutex_unlock(&event_mutex); +} + +void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value) { +#ifndef MTR_ENABLED + return; +#endif + if (!atomic_load(&is_tracing)) { + return; + } + pthread_mutex_lock(&mutex); + while(event_count >= INTERNAL_MINITRACE_BUFFER_SIZE && atomic_load(&is_tracing)) { + pthread_cond_wait(&buffer_not_full_cond, &mutex); + } + raw_event_t *ev = &event_buffer[event_count]; + ++event_count; + pthread_mutex_lock(&event_mutex); + ++events_in_progress; + pthread_mutex_unlock(&event_mutex); + int local_event_count = event_count; + pthread_mutex_unlock(&mutex); + if(local_event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { + pthread_cond_signal(&buffer_full_cond); + } + + + if (!cur_thread_id) { + cur_thread_id = get_cur_thread_id(); + } + if (!cur_process_id) { + cur_process_id = get_cur_process_id(); + } + double ts = mtr_time_s(); + +#ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME + const size_t category_len = strlen(category); + ev->cat = malloc(category_len + 1); + strcpy(ev->cat, category); + + const size_t name_len = strlen(name); + ev->name = malloc(name_len + 1); + strcpy(ev->name, name); + +#else + ev->cat = category; + ev->name = name; +#endif + + ev->id = id; + ev->ts = (int64_t)(ts * 1000000); + ev->ph = ph; + ev->tid = cur_thread_id; + ev->pid = cur_process_id; + ev->arg_type = arg_type; + ev->arg_name = arg_name; + switch (arg_type) { + case MTR_ARG_TYPE_INT: ev->a_int = (int)(uintptr_t)arg_value; break; + case MTR_ARG_TYPE_STRING_CONST: ev->a_str = (const char*)arg_value; break; + case MTR_ARG_TYPE_STRING_COPY: ev->a_str = strdup((const char*)arg_value); break; + case MTR_ARG_TYPE_NONE: break; + } + + pthread_mutex_lock(&event_mutex); + --events_in_progress; + pthread_mutex_unlock(&event_mutex); +} + diff --git a/src/pc.c b/src/pc.c index ef1005091..efe6f0967 100644 --- a/src/pc.c +++ b/src/pc.c @@ -89,6 +89,9 @@ int dopause, /* system is paused */ uint64_t timer_freq; char emu_version[200]; /* version ID string */ +#ifdef MTR_ENABLED +int tracing_on = 0; +#endif /* Commandline options. */ int dump_on_exit = 0; /* (O) dump regs on exit */ diff --git a/src/video/video.c b/src/video/video.c index 678e7771b..7d9c85def 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -70,6 +70,7 @@ #include <86box/video.h> #include <86box/vid_svga.h> +#include volatile int screenshots = 0; bitmap_t *buffer32 = NULL; @@ -285,6 +286,7 @@ void blit_thread(void *param) while (1) { thread_wait_event(blit_data.wake_blit_thread, -1); thread_reset_event(blit_data.wake_blit_thread); + MTR_BEGIN("video", "blit_thread"); if (blit_func) blit_func(blit_data.x, blit_data.y, @@ -292,6 +294,7 @@ void blit_thread(void *param) blit_data.w, blit_data.h); blit_data.busy = 0; + MTR_END("video", "blit_thread"); thread_set_event(blit_data.blit_complete); } } @@ -448,6 +451,7 @@ void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) { int yy; + MTR_BEGIN("video", "video_blit_memtoscreen"); if (y2 > 0) { for (yy = y1; yy < y2; yy++) { @@ -482,6 +486,7 @@ video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) blit_data.h = h; thread_set_event(blit_data.wake_blit_thread); + MTR_END("video", "video_blit_memtoscreen"); } diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 8dfa152db..7bc70a1ef 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -122,6 +122,11 @@ BEGIN # endif MENUITEM SEPARATOR MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT +#ifdef MTR_ENABLED + MENUITEM SEPARATOR + MENUITEM "Begin trace\tCtrl+T", IDM_ACTION_BEGIN_TRACE + MENUITEM "End trace\tCtrl+T", IDM_ACTION_END_TRACE +#endif END #if defined(ENABLE_LOG_TOGGLES) || defined(ENABLE_LOG_COMMANDS) POPUP "&Logging" @@ -262,6 +267,9 @@ BEGIN #endif #ifdef ENABLE_LOG_BREAKPOINT VK_F10, IDM_LOG_BREAKPOINT, CONTROL, VIRTKEY +#endif +#ifdef MTR_ENABLED + "T", IDM_ACTION_TRACE, CONTROL, VIRTKEY #endif VK_PRIOR,IDM_VID_FULLSCREEN, VIRTKEY, CONTROL , ALT VK_F11, IDM_ACTION_SCREENSHOT, VIRTKEY, CONTROL diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 5aaad9a86..a5eedf84f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -284,7 +284,7 @@ endif ######################################################################### # Nothing should need changing from here on.. # ######################################################################### -VPATH := $(EXPATH) . $(CODEGEN) cpu \ +VPATH := $(EXPATH) . $(CODEGEN) minitrace cpu \ cdrom chipset device disk disk/minivhd floppy \ game machine mem printer \ sio sound \ @@ -482,6 +482,12 @@ RFLAGS += -DUSE_DISCORD DISCORDOBJ := win_discord.o endif +ifeq ($(MINITRACE), y) +OPTS += -DMTR_ENABLED +RFLAGS += -DMTR_ENABLED +MINITRACEOBJ := minitrace.o +endif + # Options for the DEV branch. ifeq ($(DEV_BRANCH), y) OPTS += -DDEV_BRANCH @@ -781,7 +787,7 @@ OBJ := $(MAINOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \ $(FDDOBJ) $(GAMEOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) $(MINIVHDOBJ) \ $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SIOOBJ) $(SNDOBJ) $(VIDOBJ) \ $(PLATOBJ) $(UIOBJ) $(FSYNTHOBJ) $(MUNTOBJ) $(DEVBROBJ) \ - $(DISCORDOBJ) + $(DISCORDOBJ) $(MINITRACEOBJ) ifdef EXOBJ OBJ += $(EXOBJ) endif diff --git a/src/win/win.c b/src/win/win.c index 3e29062eb..da9e4028b 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -49,7 +49,9 @@ #include <86box/win_sdl.h> #include <86box/win.h> #include <86box/version.h> - +#ifdef MTR_ENABLED +#include +#endif typedef struct { WCHAR str[512]; @@ -217,6 +219,21 @@ plat_get_string(int i) return((wchar_t *)str); } +#ifdef MTR_ENABLED +void +init_trace(void) +{ + mtr_init("trace.json"); + mtr_start(); +} + +void +shutdown_trace(void) +{ + mtr_stop(); + mtr_shutdown(); +} +#endif /* Create a console if we don't already have one. */ static void diff --git a/src/win/win_ui.c b/src/win/win_ui.c index e72307d9b..9e156f67c 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -48,6 +48,9 @@ # include <86box/win_discord.h> #endif +#ifdef MTR_ENABLED +#include +#endif #define TIMER_1SEC 1 /* ID of the one-second timer */ @@ -294,6 +297,9 @@ ResetAllMenus(void) else EnableMenuItem(menuMain, IDM_DISCORD, MF_DISABLED); #endif +#ifdef MTR_ENABLED + EnableMenuItem(menuMain, IDM_ACTION_END_TRACE, MF_DISABLED); +#endif } @@ -378,6 +384,19 @@ plat_power_off(void) exit(-1); } +#ifdef MTR_ENABLED +static void +handle_trace(HMENU hmenu, int trace) +{ + EnableMenuItem(hmenu, IDM_ACTION_BEGIN_TRACE, trace? MF_GRAYED : MF_ENABLED); + EnableMenuItem(hmenu, IDM_ACTION_END_TRACE, trace? MF_ENABLED : MF_GRAYED); + if (trace) { + init_trace(); + } else { + shutdown_trace(); + } +} +#endif /* Catch WM_INPUT messages for 'current focus' window. */ #if defined(__amd64__) || defined(__aarch64__) @@ -489,6 +508,15 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) take_screenshot(); break; +#ifdef MTR_ENABLED + case IDM_ACTION_BEGIN_TRACE: + case IDM_ACTION_END_TRACE: + case IDM_ACTION_TRACE: + tracing_on = !tracing_on; + handle_trace(hmenu, tracing_on); + break; +#endif + case IDM_ACTION_HRESET: win_notify_dlg_open(); if (confirm_reset) From f7a7ed9683e25db80c924f8a2cc9078c3a1f9fdc Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 15 Feb 2021 22:43:37 +0100 Subject: [PATCH 19/34] Removed the recently introduced excess breaks from the Voodoo code. --- src/video/vid_voodoo_reg.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/video/vid_voodoo_reg.c b/src/video/vid_voodoo_reg.c index 3aa231f8e..2f3460e65 100644 --- a/src/video/vid_voodoo_reg.c +++ b/src/video/vid_voodoo_reg.c @@ -1071,7 +1071,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) } break; } - break; case SST_nccTable0_I2: if (!(val & (1 << 31))) { @@ -1087,7 +1086,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) } break; } - break; case SST_nccTable0_Q0: if (!(val & (1 << 31))) { @@ -1103,7 +1101,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) } break; } - break; case SST_nccTable0_Q2: if (!(val & (1 << 31))) { @@ -1150,7 +1147,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) } break; } - break; case SST_nccTable0_I3: if (!(val & (1 << 31))) { @@ -1166,7 +1162,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) } break; } - break; case SST_nccTable0_Q1: if (!(val & (1 << 31))) { @@ -1182,7 +1177,6 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) } break; } - break; case SST_nccTable0_Q3: if (!(val & (1 << 31))) { From 828a935e67866e6f88d2decd66bedc3d2a34e61e Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 18 Feb 2021 19:02:32 +0100 Subject: [PATCH 20/34] Fixed V7 HT216 mapping on OS/2 and implemented fast latch load to make sure there won't be corruption all over the place on Win3.0 RC2. --- src/video/vid_ht216.c | 67 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index b3393aed4..d2c380527 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -53,8 +53,12 @@ typedef struct ht216_t uint32_t read_banks[2], write_banks[2]; uint8_t bg_latch[8]; + uint8_t fg_latch[4]; + uint8_t bg_plane_sel, fg_plane_sel; uint8_t ht_regs[256]; + + uint8_t pos_regs[8]; } ht216_t; @@ -94,7 +98,7 @@ uint8_t ht216_in(uint16_t addr, void *p); #define BIOS_VIDEO7_VGA_1024I_PATH L"roms/video/video7/Video Seven VGA 1024i - BIOS - v2.19 - 435-0062-05 - U17 - 27C256.BIN" static video_timings_t timing_v7vga_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; -static video_timings_t timing_v7vga_vlb = {VIDEO_ISA, 5, 5, 9, 20, 20, 30}; +static video_timings_t timing_v7vga_vlb = {VIDEO_BUS, 5, 5, 9, 20, 20, 30}; #ifdef ENABLE_HT216_LOG @@ -203,6 +207,34 @@ ht216_out(uint16_t addr, uint8_t val, void *p) case 0xe9: ht216_remap(ht216); break; + + case 0xec: + ht216->fg_latch[0] = val; + break; + case 0xed: + ht216->fg_latch[1] = val; + break; + case 0xee: + ht216->fg_latch[2] = val; + break; + case 0xef: + ht216->fg_latch[3] = val; + break; + + case 0xf0: + ht216->fg_latch[ht216->fg_plane_sel] = val; + ht216->fg_plane_sel = (ht216->fg_plane_sel + 1) & 3; + break; + + case 0xf1: + ht216->bg_plane_sel = val & 3; + ht216->fg_plane_sel = (val & 0x30) >> 4; + break; + + case 0xf2: + svga->latch.b[ht216->bg_plane_sel] = val; + ht216->bg_plane_sel = (ht216->bg_plane_sel + 1) & 3; + break; case 0xf6: svga->vram_display_mask = (val & 0x40) ? ht216->vram_mask : 0x3ffff; @@ -289,6 +321,7 @@ ht216_in(uint16_t addr, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; + uint8_t ret = 0xff; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -319,6 +352,16 @@ ht216_in(uint16_t addr, void *p) return svga->latch.b[2]; case 0xa3: return svga->latch.b[3]; + + case 0xf0: + ret = ht216->fg_latch[ht216->fg_plane_sel]; + ht216->fg_plane_sel = 0; + return ret; + + case 0xf2: + ret = svga->latch.b[ht216->bg_plane_sel]; + ht216->bg_plane_sel = 0; + return ret; } return ht216->ht_regs[svga->seqaddr & 0xff]; } else @@ -463,6 +506,11 @@ ht216_remap(ht216_t *ht216) ht216->write_bank_reg[0] &= ~0x30; } + if (svga->chain4) { + ht216->read_bank_reg[0] |= ht216->ht_regs[0xe8]; + ht216->write_bank_reg[0] |= ht216->ht_regs[0xe8]; + } + ht216->read_banks[0] = ht216->read_bank_reg[0] << 12; ht216->write_banks[0] = ht216->write_bank_reg[0] << 12; ht216->read_banks[1] = ht216->read_banks[0] + (svga->chain4 ? 0x8000 : 0x20000); @@ -473,7 +521,7 @@ ht216_remap(ht216_t *ht216) ht216->read_banks[1] >>= 2; ht216->write_banks[0] >>= 2; ht216->write_banks[1] >>= 2; - } + } } ht216_log("ReadBank0 = %06x, ReadBank1 = %06x, Misc Page Sel = %02x, F6 reg = %02x, F9 Sel = %02x, FC = %02x, E0 split = %02x, E8 = %02x, E9 = %02x, chain4 = %02x, banked mask = %04x\n", ht216->read_banks[0], ht216->read_banks[1], ht216->misc & HT_MISC_PAGE_SEL, bank, ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL, ht216->ht_regs[0xfc] & (HT_REG_FC_ECOLRE | 2), ht216->ht_regs[0xe0] & HT_REG_E0_SBAE, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], svga->chain4, svga->banked_mask); @@ -651,7 +699,7 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u case 0x08: case 0x0c: for (i = 0; i < count; i++) - fg_data[i] = ht216->ht_regs[0xec + i]; + fg_data[i] = ht216->fg_latch[i]; break; } @@ -805,7 +853,7 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi input_a = (ht216->ht_regs[0xf5] & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; break; case 0x08: - input_a = ht216->ht_regs[0xec + (addr & 3)]; + input_a = ht216->fg_latch[addr & 3]; break; case 0x0c: input_a = ht216->bg_latch[addr & 7]; @@ -968,10 +1016,11 @@ ht216_write(uint32_t addr, uint8_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) { svga_write_linear(addr, val, svga); - else + } else { ht216_write_common(ht216, addr, val); + } } @@ -1132,6 +1181,7 @@ ht216_read_common(ht216_t *ht216, uint32_t addr) or = addr & 4; svga->latch.d[0] = ht216->bg_latch[0 | or] | (ht216->bg_latch[1 | or] << 8) | (ht216->bg_latch[2 | or] << 16) | (ht216->bg_latch[3 | or] << 24); + if (svga->readmode) { temp = 0xff; @@ -1177,7 +1227,6 @@ ht216_read_linear(uint32_t addr, void *p) return ht216_read_common(ht216, (addr & 0xffff) | ((addr & 0xc0000) >> 2)); } - void *ht216_init(const device_t *info, uint32_t mem_size, int has_rom) { @@ -1254,7 +1303,7 @@ v7_vga_1024i_init(const device_t *info) static void * ht216_pb410a_init(const device_t *info) { - ht216_t *ht216 = ht216_init(info, 1 << 20, 0); + ht216_t *ht216 = ht216_init(info, device_get_config_int("memory") << 10, 0); return ht216; } @@ -1358,7 +1407,7 @@ const device_t g2_gc205_device = const device_t v7_vga_1024i_device = { - "Video 7 VGA 1024i", + "Video 7 VGA 1024i (HT208)", DEVICE_ISA, 0x7140, v7_vga_1024i_init, From ec8d46ae61fcccf34cf281ee0606584c620c5522 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 18 Feb 2021 19:04:46 +0100 Subject: [PATCH 21/34] Fix memory size on the ht216 pb410a card. --- src/video/vid_ht216.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index d2c380527..59229a4eb 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1303,7 +1303,7 @@ v7_vga_1024i_init(const device_t *info) static void * ht216_pb410a_init(const device_t *info) { - ht216_t *ht216 = ht216_init(info, device_get_config_int("memory") << 10, 0); + ht216_t *ht216 = ht216_init(info, 1 << 20, 0); return ht216; } From fb167f6f98a04778b123f2f570875da0abd749d6 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 18 Feb 2021 19:07:57 +0100 Subject: [PATCH 22/34] Improved code style as well as fixed the video memory size on the ht216-32 (pb410a). --- src/video/vid_ht216.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 59229a4eb..d7ecacc64 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -1016,11 +1016,10 @@ ht216_write(uint32_t addr, uint8_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) { + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) svga_write_linear(addr, val, svga); - } else { + else ht216_write_common(ht216, addr, val); - } } From cd0f34422191a365cc3010ccccbaf1db5d636993 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 18 Feb 2021 21:55:39 +0100 Subject: [PATCH 23/34] Video fixes and added the Tseng ET2000. --- src/video/CMakeLists.txt | 4 -- src/video/vid_cga.c | 2 - src/video/vid_colorplus.c | 2 - src/video/vid_ega.c | 78 +++++++++++++++++++++++++++------- src/video/vid_genius.c | 2 - src/video/vid_ht216.c | 4 -- src/video/vid_mda.c | 2 - src/video/vid_mga.c | 12 ------ src/video/vid_nga.c | 2 - src/video/vid_ogc.c | 2 - src/video/vid_sigma.c | 2 - src/video/vid_table.c | 1 + src/video/vid_vga.c | 9 +++- src/video/vid_voodoo_banshee.c | 9 ---- src/video/vid_wy700.c | 2 - src/video/video.c | 4 +- 16 files changed, 71 insertions(+), 66 deletions(-) diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 9419e3e4a..f05efe9ab 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -33,10 +33,6 @@ if(NOT MSVC) target_compile_options(vid PRIVATE "-msse2") endif() -if(CL5422) - target_compile_definitions(vid PRIVATE USE_CL5422) -endif() - if(MGA) target_compile_definitions(vid PRIVATE USE_MGA) target_sources(vid PRIVATE vid_mga.c) diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 60a662490..51e0ac6af 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -138,7 +138,6 @@ cga_write(uint32_t addr, uint8_t val, void *p) cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } - egawrites++; cga_waitstates(cga); } @@ -154,7 +153,6 @@ cga_read(uint32_t addr, void *p) cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; } - egareads++; return cga->vram[addr & 0x3fff]; } diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 223c4d1c6..ed5cd6f00 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -99,7 +99,6 @@ void colorplus_write(uint32_t addr, uint8_t val, void *p) colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff]; colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff]; } - egawrites++; cycles -= 4; } @@ -124,7 +123,6 @@ uint8_t colorplus_read(uint32_t addr, void *p) colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff]; colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff]; } - egareads++; return colorplus->cga.vram[addr & 0x7fff]; } diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index bbd8e7da9..094425430 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -43,6 +43,7 @@ void ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega); #define BIOS_SEGA_PATH L"roms/video/ega/lega.vbi" #define BIOS_ATIEGA_PATH L"roms/video/ega/ATI EGA Wonder 800+ N1.00.BIN" #define BIOS_ISKRA_PATH L"roms/video/ega/143-02.bin", L"roms/video/ega/143-03.bin" +#define BIOS_TSENG_PATH L"roms/video/ega/EGA ET2000.BIN" enum { @@ -50,14 +51,15 @@ enum { EGA_COMPAQ, EGA_SUPEREGA, EGA_ATI, - EGA_ISKRA + EGA_ISKRA, + EGA_TSENG }; static video_timings_t timing_ega = {VIDEO_ISA, 8, 16, 32, 8, 16, 32}; static uint8_t ega_rotate[8][256]; static uint32_t pallook16[256], pallook64[256]; -static int old_overscan_color = 0; +static int ega_type = 0, old_overscan_color = 0; extern uint8_t edatlookup[4][4]; @@ -256,38 +258,48 @@ uint8_t ega_in(uint16_t addr, void *p) break; case 0x3c0: - ret = ega->attraddr | ega->attr_palette_enable; + if (ega_type) + ret = ega->attraddr | ega->attr_palette_enable; break; case 0x3c1: - ret = ega->attrregs[ega->attraddr]; + if (ega_type) + ret = ega->attrregs[ega->attraddr]; break; case 0x3c2: ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; break; case 0x3c4: - ret = ega->seqaddr; + if (ega_type) + ret = ega->seqaddr; break; case 0x3c5: - ret = ega->seqregs[ega->seqaddr & 0xf]; + if (ega_type) + ret = ega->seqregs[ega->seqaddr & 0xf]; break; case 0x3c8: - ret = 2; + if (ega_type) + ret = 2; break; case 0x3cc: - ret = ega->miscout; + if (ega_type) + ret = ega->miscout; break; case 0x3ce: - ret = ega->gdcaddr; + if (ega_type) + ret = ega->gdcaddr; break; case 0x3cf: - ret = ega->gdcreg[ega->gdcaddr & 0xf]; + if (ega_type) + ret = ega->gdcreg[ega->gdcaddr & 0xf]; break; case 0x3d0: case 0x3d4: - ret = ega->crtcreg; + if (ega_type) + ret = ega->crtcreg; break; case 0x3d1: case 0x3d5: - ret = ega->crtc[ega->crtcreg]; + if (ega_type) + ret = ega->crtc[ega->crtcreg]; break; case 0x3da: ega->attrff = 0; @@ -731,7 +743,6 @@ ega_write(uint32_t addr, uint8_t val, void *p) uint8_t vala, valb, valc, vald; int writemask2 = ega->writemask; - egawrites++; cycles -= video_timing_write_b; if (addr >= 0xB0000) addr &= 0x7fff; @@ -858,7 +869,6 @@ ega_read(uint32_t addr, void *p) uint8_t temp, temp2, temp3, temp4; int readplane = ega->readplane; - egareads++; cycles -= video_timing_read_b; if (addr >= 0xb0000) addr &= 0x7fff; else addr &= 0xffff; @@ -1021,6 +1031,12 @@ ega_standalone_init(const device_t *info) ega->x_add = 8; ega->y_add = 14; + if ((info->local == EGA_IBM) || (info->local == EGA_ISKRA) || + (info->local == EGA_TSENG)) + ega_type = 0; + else + ega_type = 1; + switch(info->local) { case EGA_IBM: default: @@ -1043,6 +1059,10 @@ ega_standalone_init(const device_t *info) rom_init_interleaved(&ega->bios_rom, BIOS_ISKRA_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; + case EGA_TSENG: + rom_init(&ega->bios_rom, BIOS_TSENG_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; } if ((ega->bios_rom.rom[0x3ffe] == 0xaa) && (ega->bios_rom.rom[0x3fff] == 0x55)) { @@ -1101,6 +1121,20 @@ atiega_standalone_available(void) } +static int +iskra_ega_standalone_available(void) +{ + return rom_present(L"roms/video/ega/143-02.bin") && rom_present(L"roms/video/ega/143-03.bin"); +} + + +static int +et2000_standalone_available(void) +{ + return rom_present(BIOS_TSENG_PATH); +} + + static void ega_close(void *p) { @@ -1250,8 +1284,20 @@ const device_t iskra_ega_device = DEVICE_ISA, EGA_ISKRA, ega_standalone_init, ega_close, NULL, - { ega_standalone_available }, + { iskra_ega_standalone_available }, ega_speed_changed, NULL, ega_config -}; \ No newline at end of file +}; + +const device_t et2000_device = +{ + "Tseng Labs ET2000", + DEVICE_ISA, + EGA_TSENG, + ega_standalone_init, ega_close, NULL, + { et2000_standalone_available }, + ega_speed_changed, + NULL, + ega_config +}; diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index d6afc1863..b3807acf5 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -261,7 +261,6 @@ void genius_write(uint32_t addr, uint8_t val, void *p) { genius_t *genius = (genius_t *)p; - egawrites++; genius_waitstates(); if (genius->genius_control & 1) { @@ -288,7 +287,6 @@ genius_read(uint32_t addr, void *p) { genius_t *genius = (genius_t *)p; uint8_t ret; - egareads++; genius_waitstates(); if (genius->genius_control & 1) { diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index b3393aed4..4c11f2527 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -904,8 +904,6 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) cycles -= video_timing_write_b; - egawrites++; - addr &= 0xfffff; val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); @@ -1084,8 +1082,6 @@ ht216_read_common(ht216_t *ht216, uint32_t addr) cycles -= video_timing_read_b; - egareads++; - addr &= 0xfffff; count = 2; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 7220346bd..c05744b01 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -79,14 +79,12 @@ uint8_t mda_in(uint16_t addr, void *p) void mda_write(uint32_t addr, uint8_t val, void *p) { mda_t *mda = (mda_t *)p; - egawrites++; mda->vram[addr & 0xfff] = val; } uint8_t mda_read(uint32_t addr, void *p) { mda_t *mda = (mda_t *)p; - egareads++; return mda->vram[addr & 0xfff]; } diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 3433b7539..16e0b390c 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -2130,8 +2130,6 @@ mystique_readb_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *)p; - egareads++; - cycles -= video_timing_read_b; addr &= svga->decode_mask; @@ -2147,8 +2145,6 @@ mystique_readw_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *)p; - egareads += 2; - cycles -= video_timing_read_w; addr &= svga->decode_mask; @@ -2164,8 +2160,6 @@ mystique_readl_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *)p; - egareads += 4; - cycles -= video_timing_read_l; addr &= svga->decode_mask; @@ -2181,8 +2175,6 @@ mystique_writeb_linear(uint32_t addr, uint8_t val, void *p) { svga_t *svga = (svga_t *)p; - egawrites++; - cycles -= video_timing_write_b; addr &= svga->decode_mask; @@ -2199,8 +2191,6 @@ mystique_writew_linear(uint32_t addr, uint16_t val, void *p) { svga_t *svga = (svga_t *)p; - egawrites += 2; - cycles -= video_timing_write_w; addr &= svga->decode_mask; @@ -2217,8 +2207,6 @@ mystique_writel_linear(uint32_t addr, uint32_t val, void *p) { svga_t *svga = (svga_t *)p; - egawrites += 4; - cycles -= video_timing_write_l; addr &= svga->decode_mask; diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 6b1b60dcb..cdd72ecb2 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -118,7 +118,6 @@ nga_write(uint32_t addr, uint8_t val, void *priv) nga->cga.charbuffer[offset] = nga->cga.vram[addr & 0x7fff]; nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff]; } - egawrites++; nga_waitstates(&nga->cga); } @@ -144,7 +143,6 @@ nga_read(uint32_t addr, void *priv) nga->cga.charbuffer[offset | 1] = nga->cga.vram[addr & 0x7fff]; } - egareads++; return(ret); } diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index b15565718..65630653c 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -166,7 +166,6 @@ ogc_write(uint32_t addr, uint8_t val, void *priv) ogc->cga.charbuffer[offset] = ogc->cga.vram[addr & 0x7fff]; ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff]; } - egawrites++; ogc_waitstates(&ogc->cga); } @@ -186,7 +185,6 @@ ogc_read(uint32_t addr, void *priv) ogc->cga.charbuffer[offset | 1] = ogc->cga.vram[addr & 0x7fff]; } - egareads++; return(ogc->cga.vram[addr & 0x7FFF]); } diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 78812d27d..777389ce6 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -343,7 +343,6 @@ sigma_write(uint32_t addr, uint8_t val, void *p) sigma_t *sigma = (sigma_t *)p; sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)] = val; - egawrites++; cycles -= 4; } @@ -354,7 +353,6 @@ sigma_read(uint32_t addr, void *p) sigma_t *sigma = (sigma_t *)p; cycles -= 4; - egareads++; return sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)]; } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 065988089..d81e19147 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -108,6 +108,7 @@ video_cards[] = { { "tvga8900d", &tvga8900d_device }, { "tvga9000b", &tvga9000b_device }, { "tgkorvga", &et4000k_isa_device }, + { "et2000", &et2000_device }, { "et4000ax", &et4000_isa_device }, { "vga", &vga_device }, { "v7_vga_1024i", &v7_vga_1024i_device }, diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index f4e38e7fd..978a154c4 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -69,8 +69,13 @@ void vga_out(uint16_t addr, uint8_t val, void *p) { if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); + if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { + svga->fullchange = 3; + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + } else { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } } } break; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index b749e0cf2..bb9f00de3 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -1424,7 +1424,6 @@ static uint8_t banshee_read_linear(uint32_t addr, void *p) if (addr >= svga->vram_max) return 0xff; - egareads++; cycles -= video_timing_read_b; // banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); @@ -1457,7 +1456,6 @@ static uint16_t banshee_read_linear_w(uint32_t addr, void *p) if (addr >= svga->vram_max) return 0xff; - egareads++; cycles -= video_timing_read_w; // banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); @@ -1491,7 +1489,6 @@ static uint32_t banshee_read_linear_l(uint32_t addr, void *p) if (addr >= svga->vram_max) return 0xff; - egareads++; cycles -= video_timing_read_l; // banshee_log("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]); @@ -1523,8 +1520,6 @@ static void banshee_write_linear(uint32_t addr, uint8_t val, void *p) if (addr >= svga->vram_max) return; - egawrites++; - cycles -= video_timing_write_b; svga->changedvram[addr >> 12] = changeframecount; @@ -1561,8 +1556,6 @@ static void banshee_write_linear_w(uint32_t addr, uint16_t val, void *p) if (addr >= svga->vram_max) return; - egawrites++; - cycles -= video_timing_write_w; svga->changedvram[addr >> 12] = changeframecount; @@ -1607,8 +1600,6 @@ static void banshee_write_linear_l(uint32_t addr, uint32_t val, void *p) if (addr >= svga->vram_max) return; - egawrites += 4; - cycles -= video_timing_write_l; svga->changedvram[addr >> 12] = changeframecount; diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index 44aacc277..404958d98 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -459,7 +459,6 @@ void wy700_checkchanges(wy700_t *wy700) void wy700_write(uint32_t addr, uint8_t val, void *p) { wy700_t *wy700 = (wy700_t *)p; - egawrites++; if (wy700->wy700_mode & 0x80) /* High-res mode. */ { @@ -483,7 +482,6 @@ void wy700_write(uint32_t addr, uint8_t val, void *p) uint8_t wy700_read(uint32_t addr, void *p) { wy700_t *wy700 = (wy700_t *)p; - egareads++; if (wy700->wy700_mode & 0x80) /* High-res mode. */ { addr &= 0xFFFF; diff --git a/src/video/video.c b/src/video/video.c index 7d9c85def..da5e89f8d 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -92,9 +92,7 @@ uint32_t *video_6to8 = NULL, *video_8to32 = NULL, *video_15to32 = NULL, *video_16to32 = NULL; -int egareads = 0, - egawrites = 0, - changeframecount = 2; +int changeframecount = 2; int frames = 0; int fullchange = 0; uint8_t edatlookup[4][4]; From 6c8cb06a42a34ec2b3745b4ebde6d051cf0fa18e Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 18 Feb 2021 21:57:19 +0100 Subject: [PATCH 24/34] Missing file for the Tseng ET2000. --- src/include/86box/vid_ega.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 078a5e823..bc378704b 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -77,6 +77,7 @@ extern const device_t cpqega_device; extern const device_t sega_device; extern const device_t atiega_device; extern const device_t iskra_ega_device; +extern const device_t et2000_device; #endif extern int update_overscan; From dab4cab222945c558f95abbab6918d951edd5c4f Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 18 Feb 2021 22:06:26 +0100 Subject: [PATCH 25/34] Briefly readded the egareads and egawrites variables to fix compile errors. --- src/video/video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/video.c b/src/video/video.c index da5e89f8d..66fb1d024 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -85,6 +85,7 @@ dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */ uint32_t pal_lookup[256]; int xsize = 1, ysize = 1; +int egareads = 0, egawrites = 0; int cga_palette = 0, herc_blend = 0; uint32_t *video_6to8 = NULL, From 1136e2b715c62fdcf3241e5a5777c1b901604d44 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Mon, 22 Feb 2021 11:40:48 +0200 Subject: [PATCH 26/34] Implemented the VIA EBGA 368 platform --- src/cpu/cpu.c | 64 ++++++++++++++++++++++++++++++++- src/cpu/cpu.h | 4 ++- src/cpu/cpu_table.c | 10 ++++++ src/include/86box/machine.h | 4 +++ src/machine/CMakeLists.txt | 3 +- src/machine/m_at_ebga368.c | 71 +++++++++++++++++++++++++++++++++++++ src/machine/machine_table.c | 5 +++ src/win/Makefile.mingw | 1 + 8 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 src/machine/m_at_ebga368.c diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 3fc4d43df..98b885cd7 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -537,7 +537,7 @@ cpu_set(void) is_p6 = (cpu_s->cpu_type == CPU_PENTIUMPRO) || (cpu_s->cpu_type == CPU_PENTIUM2) || (cpu_s->cpu_type == CPU_PENTIUM2D); /* The Samuel 2 datasheet claims it's Celeron-compatible. */ - is_p6 |= (cpu_s->cpu_type == CPU_CYRIX3S); + is_p6 |= (cpu_s->cpu_type == CPU_CYRIX3S) || (cpu_s->cpu_type == CPU_EDEN); #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) is_cx6x86 = (cpu_s->cpu_type == CPU_Cx6x86) || (cpu_s->cpu_type == CPU_Cx6x86MX) || (cpu_s->cpu_type == CPU_Cx6x86L) || (cpu_s->cpu_type == CPU_CxGX1); @@ -1807,6 +1807,7 @@ cpu_set(void) break; case CPU_CYRIX3S: + case CPU_EDEN: /* This till proper timings get discovered */ #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); #else @@ -2600,6 +2601,65 @@ cpu_CPUID(void) break; } break; + + case CPU_EDEN: + switch (EAX) + { + case 0: + EAX = 1; + if (msr.fcr2 & (1 << 14)) + { + EBX = msr.fcr3 >> 32; + ECX = msr.fcr3 & 0xffffffff; + EDX = msr.fcr2 >> 32; + } + else + { + EBX = 0x746e6543; /*CentaurHauls*/ + ECX = 0x736c7561; + EDX = 0x48727561; + } + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MMX | CPUID_MTRR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + break; + case 0x80000000: + EAX = 0x80000006; + break; + case 0x80000001: + EAX = CPUID; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + break; + case 0x80000002: /*Processor name string*/ + case 0x80000003: + case 0x80000004: + EAX = 0x20414956; /*VIA Samuel 2*/ + EBX = 0x756d6153; + ECX = 0x32206c65; + EDX = 0x00000000; + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x08800880; /*TLBs*/ + ECX = 0x40040120; /*L1 data cache*/ + EDX = 0x40020120; /*L1 instruction cache*/ + break; + + case 0x80000006: + ECX = 0x40040120; /*L2 data cache*/ + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; } } @@ -2714,6 +2774,7 @@ void cpu_RDMSR() break; case CPU_CYRIX3S: + case CPU_EDEN: EAX = EDX = 0; switch (ECX) { @@ -3318,6 +3379,7 @@ void cpu_WRMSR() } break; case CPU_CYRIX3S: + case CPU_EDEN: switch (ECX) { case 0x10: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index ffe4c129e..061f8154c 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -81,6 +81,7 @@ enum { CPU_K6_2P, CPU_K6_3P, CPU_CYRIX3S, + CPU_EDEN, CPU_PENTIUMPRO, /* 686 class CPUs */ CPU_PENTIUM2, CPU_PENTIUM2D @@ -108,7 +109,8 @@ enum { CPU_PKG_SOCKET8 = (1 << 18), CPU_PKG_SLOT1 = (1 << 19), CPU_PKG_SLOT2 = (1 << 20), - CPU_PKG_SOCKET370 = (1 << 21) + CPU_PKG_SOCKET370 = (1 << 21), + CPU_PKG_EBGA368 = (1 << 22) }; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index dda032c19..94cc0d169 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -967,6 +967,16 @@ const cpu_family_t cpu_families[] = { {"733", CPU_CYRIX3S, fpus_internal, 733333333, 5.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 66, 66, 18, 18, 88}, {"", 0} } + }, { + .package = CPU_PKG_SOCKET370, + .manufacturer = "VIA", + .name = "Eden(Model 7)", + .internal_name = "c3_eden", + .cpus = (const CPU[]) { + {"100", CPU_EDEN, fpus_internal, 100000000, 1.5, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of spec */ + {"400", CPU_EDEN, fpus_internal, 400000000, 6.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 17, 17, 48}, + {"600", CPU_EDEN, fpus_internal, 600000000, 6.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72}, + } }, { .package = 0, } diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index a419de290..4673d37f5 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -106,6 +106,7 @@ enum { MACHINE_TYPE_SLOT1, MACHINE_TYPE_SLOT2, MACHINE_TYPE_SOCKET370, + MACHINE_TYPE_EBGA368, MACHINE_TYPE_MISC, MACHINE_TYPE_MAX }; @@ -532,6 +533,9 @@ extern int machine_at_603tcf_init(const machine_t *); extern int machine_at_trinity371_init(const machine_t *); extern int machine_at_p6bap_init(const machine_t *); +/* m_at_ebga368.c */ +extern int machine_at_arb9673_init(const machine_t *); + /* m_at_misc.c */ extern int machine_at_vpc2007_init(const machine_t *); diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 846ab6074..9df45ef05 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -20,7 +20,8 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c m_at_socket4_5.c m_at_socket7.c m_at_sockets7.c m_at_socket8.c - m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_misc.c) + m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_ebga368.c + m_at_misc.c) if(HEDAKA) target_compile_definitions(mch PRIVATE USE_HEDAKA) diff --git a/src/machine/m_at_ebga368.c b/src/machine/m_at_ebga368.c new file mode 100644 index 000000000..b6ac02418 --- /dev/null +++ b/src/machine/m_at_ebga368.c @@ -0,0 +1,71 @@ +/* + * 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 VIA EBGA368 Based Single Board Computers. + * + * Note: 86Box doesn't emulate all the components a SBC may have. + * + * Authors: Miran Grca, + * Tiseno100 + * + * Copyright 2016-2019 Miran Grca. + * Copyright 2021 Tiseno100. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include <86box/io.h> +#include <86box/rom.h> +#include <86box/pci.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/keyboard.h> +#include <86box/flash.h> +#include <86box/sio.h> +#include <86box/hwm.h> +#include <86box/spd.h> +#include <86box/video.h> +#include "cpu.h" +#include <86box/machine.h> + +int +machine_at_arb9673_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/arb9673/W9673.v12", + 0x00080000, 524288, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&via_vt8601_device); + device_add(&via_vt82c686b_device); + device_add(&via_vt82c686_sio_device); + device_add(&via_vt82c686_hwm_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf040_device); + spd_register(SPD_TYPE_SDRAM, 0xf, 32); + + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8c7b6cd71..02115cafa 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -50,6 +50,7 @@ const machine_type_t machine_types[] = { { "Slot 1", MACHINE_TYPE_SLOT1 }, { "Slot 2", MACHINE_TYPE_SLOT2 }, { "Socket 370", MACHINE_TYPE_SOCKET370 }, + { "EBGA 368", MACHINE_TYPE_EBGA368 }, { "Miscellaneous", MACHINE_TYPE_MISC } }; @@ -433,6 +434,10 @@ const machine_t machines[] = { { "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL }, { "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_603tcf_init, NULL }, + /* PGA370 machines */ + /* VIA Apollo Pro */ + { "[VIA Apollo ProMedia] Acrosser AR-B9673", "arb9673", MACHINE_TYPE_EBGA368, CPU_PKG_EBGA368, 0, 66666667, 150000000, 1300, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 131072,131072, 0, 31, machine_at_arb9673_init, NULL }, + /* Miscellaneous/Fake/Hypervisor machines */ { "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, CPU_PKG_SLOT1, CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), 0, 0, 0, 0, 0, 0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vpc2007_init, NULL }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 162512e66..9124db63f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -644,6 +644,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_286_386sx.o m_at_386dx_486.o \ m_at_socket4_5.o m_at_socket7.o m_at_sockets7.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ + m_at_ebga368.o \ m_at_misc.o DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \ From b7707917ac8f3028ba27380e4bb0955d81797751 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Mon, 22 Feb 2021 11:42:33 +0200 Subject: [PATCH 27/34] Fix EBGA368 naming on the table --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 02115cafa..f19e368c6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -434,7 +434,7 @@ const machine_t machines[] = { { "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL }, { "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_603tcf_init, NULL }, - /* PGA370 machines */ + /* EBGA368 machines */ /* VIA Apollo Pro */ { "[VIA Apollo ProMedia] Acrosser AR-B9673", "arb9673", MACHINE_TYPE_EBGA368, CPU_PKG_EBGA368, 0, 66666667, 150000000, 1300, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 131072,131072, 0, 31, machine_at_arb9673_init, NULL }, From 126102f638011a66a444c196b4719d2297334f3b Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Mon, 22 Feb 2021 11:55:38 +0200 Subject: [PATCH 28/34] Fix CPU Table --- src/cpu/cpu_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 94cc0d169..56685cbf8 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -968,7 +968,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET370, + .package = CPU_PKG_EBGA368, .manufacturer = "VIA", .name = "Eden(Model 7)", .internal_name = "c3_eden", From 15b79fa0acec40e1af8451ceeb0fb3a27e7013cb Mon Sep 17 00:00:00 2001 From: TC1995 Date: Wed, 24 Feb 2021 20:16:15 +0100 Subject: [PATCH 29/34] Reworked some stuff to make the ht216-32 640x400 8bpp mode working, alongside the 1024x768 mono driver as well as the standard VGA 320x200 8bpp mode. --- src/video/vid_ht216.c | 220 +++++++++++++++++++++++++++++++++--------- 1 file changed, 174 insertions(+), 46 deletions(-) diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 631c5ad1d..7f26650e7 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -144,6 +144,10 @@ ht216_out(uint16_t addr, uint8_t val, void *p) svga_recalctimings(svga); break; + case 0x3c4: + svga->seqaddr = val; + break; + case 0x3c5: if (svga->seqaddr == 4) { svga->chain4 = val & 8; @@ -156,6 +160,7 @@ ht216_out(uint16_t addr, uint8_t val, void *p) } else if (svga->seqaddr >= 0x80 && ht216->ext_reg_enable) { old = ht216->ht_regs[svga->seqaddr & 0xff]; ht216->ht_regs[svga->seqaddr & 0xff] = val; + switch (svga->seqaddr & 0xff) { case 0x83: svga->attraddr = val & 0x1f; @@ -165,6 +170,8 @@ ht216_out(uint16_t addr, uint8_t val, void *p) case 0x94: case 0xff: svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | (3 << 14) | ((ht216->ht_regs[0xff] & 0x60) << 11)) << 2; + if (svga->crtc[0x17] == 0xeb) /*Looks like that 1024x768 mono mode expects 512K of video memory*/ + svga->hwcursor.addr += 0x40000; break; case 0x9c: case 0x9d: svga->hwcursor.x = ht216->ht_regs[0x9d] | ((ht216->ht_regs[0x9c] & 7) << 8); @@ -237,12 +244,11 @@ ht216_out(uint16_t addr, uint8_t val, void *p) break; case 0xf6: - svga->vram_display_mask = (val & 0x40) ? ht216->vram_mask : 0x3ffff; /*Bits 18 and 19 of the display memory address*/ - ht216_log("HT216 reg 0xf6 write = %02x, vram mask = %08x\n", val & 0x40, svga->vram_display_mask); + ht216_log("HT216 reg 0xf6 write = %02x, vram mask = %08x, cr17 = %02x\n", val & 0x40, svga->vram_display_mask, svga->crtc[0x17]); ht216_remap(ht216); svga->fullchange = changeframecount; - svga_recalctimings(svga); + svga_recalctimings(svga); break; case 0xf9: @@ -250,10 +256,10 @@ ht216_out(uint16_t addr, uint8_t val, void *p) ht216_log("HT216 reg 0xf9 write = %02x\n", val & HT_REG_F9_XPSEL); ht216_remap(ht216); break; - + case 0xfc: svga->fullchange = changeframecount; - svga_recalctimings(svga); + svga_recalctimings(svga); break; } switch (svga->seqaddr & 0xff) { @@ -271,14 +277,14 @@ ht216_out(uint16_t addr, uint8_t val, void *p) } break; - case 0x3cf: - if (svga->gdcaddr == 6) { - if (val & 8) - svga->banked_mask = 0x7fff; - else - svga->banked_mask = 0xffff; - } - break; + case 0x3cf: + if (svga->gdcaddr == 6) { + if (val & 8) + svga->banked_mask = 0x7fff; + else + svga->banked_mask = 0xffff; + } + break; case 0x3D4: svga->crtcreg = val & 0x3f; @@ -295,7 +301,7 @@ ht216_out(uint16_t addr, uint8_t val, void *p) if (old != val) { if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { svga->fullchange = changeframecount; - svga_recalctimings(&ht216->svga); + svga_recalctimings(svga); } } break; @@ -329,11 +335,14 @@ ht216_in(uint16_t addr, void *p) switch (addr) { case 0x3c2: break; + + case 0x3c4: + return svga->seqaddr; case 0x3c5: - if (svga->seqaddr == 6) + if (svga->seqaddr == 6) { return ht216->ext_reg_enable; - if (svga->seqaddr >= 0x80) { + } else if (svga->seqaddr >= 0x80) { if (ht216->ext_reg_enable) { switch (svga->seqaddr & 0xff) { case 0x83: @@ -369,6 +378,9 @@ ht216_in(uint16_t addr, void *p) } break; + case 0x3cc: + return ht216->misc; + case 0x3D4: return svga->crtcreg; case 0x3D5: @@ -449,9 +461,16 @@ ht216_remap(ht216_t *ht216) } else { /*One bank used*/ /*Bit 17 of the video memory address*/ - if (ht216->misc & HT_MISC_PAGE_SEL) { - ht216->read_bank_reg[0] |= 0x20; - ht216->write_bank_reg[0] |= 0x20; + if ((ht216->misc & HT_MISC_PAGE_SEL)) { + ht216_log("MISC = %02x, lowres = %02x, CR17 = %02x\n", ht216->misc, svga->lowres, svga->crtc[0x17]); + if ((ht216->misc == 0x63 && svga->crtc[0x17] != 0xa3 && ((svga->crtc[0x17] != 0xe3 && !(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) || + (ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE))) || (ht216->misc != 0x63)) { + ht216->read_bank_reg[0] |= 0x20; + ht216->write_bank_reg[0] |= 0x20; + } else { + ht216->read_bank_reg[0] &= ~0x20; + ht216->write_bank_reg[0] &= ~0x20; + } } else { ht216->read_bank_reg[0] &= ~0x20; ht216->write_bank_reg[0] &= ~0x20; @@ -482,12 +501,12 @@ ht216_remap(ht216_t *ht216) if (bank & 4) ht216->read_bank_reg[0] |= 0x40; else - ht216->read_bank_reg[0] &= ~0x40; + ht216->read_bank_reg[0] &= ~0x40; if (bank & 8) ht216->read_bank_reg[0] |= 0x80; else - ht216->read_bank_reg[0] &= ~0x80; + ht216->read_bank_reg[0] &= ~0x80; if (svga->chain4) { /*Bit 16 of the video memory address*/ @@ -499,7 +518,7 @@ ht216_remap(ht216_t *ht216) ht216->write_bank_reg[0] &= ~0x10; } } - + if (!svga->chain4) { /*In linear modes, bits 4 and 5 are ignored*/ ht216->read_bank_reg[0] &= ~0x30; @@ -510,12 +529,12 @@ ht216_remap(ht216_t *ht216) ht216->read_bank_reg[0] |= ht216->ht_regs[0xe8]; ht216->write_bank_reg[0] |= ht216->ht_regs[0xe8]; } - + ht216->read_banks[0] = ht216->read_bank_reg[0] << 12; - ht216->write_banks[0] = ht216->write_bank_reg[0] << 12; + ht216->write_banks[0] = ht216->write_bank_reg[0] << 12; ht216->read_banks[1] = ht216->read_banks[0] + (svga->chain4 ? 0x8000 : 0x20000); ht216->write_banks[1] = ht216->write_banks[0] + (svga->chain4 ? 0x8000 : 0x20000); - + if (!svga->chain4) { ht216->read_banks[0] >>= 2; ht216->read_banks[1] >>= 2; @@ -524,10 +543,84 @@ ht216_remap(ht216_t *ht216) } } - ht216_log("ReadBank0 = %06x, ReadBank1 = %06x, Misc Page Sel = %02x, F6 reg = %02x, F9 Sel = %02x, FC = %02x, E0 split = %02x, E8 = %02x, E9 = %02x, chain4 = %02x, banked mask = %04x\n", ht216->read_banks[0], ht216->read_banks[1], ht216->misc & HT_MISC_PAGE_SEL, bank, ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL, ht216->ht_regs[0xfc] & (HT_REG_FC_ECOLRE | 2), ht216->ht_regs[0xe0] & HT_REG_E0_SBAE, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], svga->chain4, svga->banked_mask); + ht216_log("ReadBank0 = %06x, ReadBank1 = %06x, Misc Page Sel = %02x, FF DRAM/VRAM = %02x, F6 reg = %02x, F9 Sel = %02x, FC = %02x, E0 split = %02x, E8 = %02x, E9 = %02x, chain4 = %02x, lowres = %02x, banked mask = %04x\n", ht216->read_banks[0], ht216->read_banks[1], ht216->misc & HT_MISC_PAGE_SEL, ht216->ht_regs[0xff] & 0x10, bank, ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL, ht216->ht_regs[0xfc] & (HT_REG_FC_ECOLRE | 2), ht216->ht_regs[0xe0] & HT_REG_E0_SBAE, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], svga->chain4, svga->lowres, svga->banked_mask); } } +void +ht216_1_2bpp_highres(svga_t *svga) +{ + int changed_offset, x; + int oddeven; + uint32_t addr, *p; + uint8_t edat[4]; + uint8_t dat; + + if ((svga->displine + svga->y_add) < 0) + return; + + changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->ma; + oddeven = 0; + + if (!(svga->crtc[0x17] & 0x40)) { + addr = (addr << 1) & svga->vram_mask; + + if (svga->seqregs[1] & 4) + oddeven = (addr & 4) ? 1 : 0; + + addr &= ~7; + + if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + addr |= 4; + if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + addr |= 4; + } + + if (!(svga->crtc[0x17] & 0x01)) + addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + if (!(svga->crtc[0x17] & 0x02)) + addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + + if (svga->seqregs[1] & 4) { + edat[0] = svga->vram[addr | oddeven]; + edat[2] = svga->vram[addr | oddeven | 0x2]; + edat[1] = edat[3] = 0; + } else { + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]); + } + svga->ma += 4; + svga->ma &= svga->vram_mask; + + if (svga->crtc[0x17] & 0x80) { + dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + } else + memset(p, 0x00, 8 * sizeof(uint32_t)); + + p += 8; + } + } +} void ht216_recalctimings(svga_t *svga) @@ -540,8 +633,7 @@ ht216_recalctimings(svga_t *svga) case 6: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break; case 10: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; } - svga->lowres = !(ht216->ht_regs[0xc8] & HT_REG_C8_E256); - + svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); svga->interlace = ht216->ht_regs[0xe0] & 1; @@ -552,13 +644,34 @@ ht216_recalctimings(svga_t *svga) high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2); ht216->adjust_cursor = 0; - if ((svga->bpp == 8) && (!svga->lowres || high_res_256)) { - if (high_res_256) { - svga->hdisp /= 2; - ht216->adjust_cursor = 1; - } - svga->render = svga_render_8bpp_highres; + + if (svga->crtc[0x17] == 0xeb) { + svga->rowoffset <<= 1; + svga->render = ht216_1_2bpp_highres; } + + if (svga->bpp == 8) { + if (((ht216->ht_regs[0xc8] & HT_REG_C8_E256) || (svga->gdcreg[5] & 0x40)) && (!svga->lowres || (ht216->ht_regs[0xf6] & 0x80))) { + if (high_res_256) { + svga->hdisp >>= 1; + ht216->adjust_cursor = 1; + } + svga->render = svga_render_8bpp_highres; + } else if (svga->lowres) { + if (high_res_256) { + svga->hdisp >>= 1; + ht216->adjust_cursor = 1; + svga->render = svga_render_8bpp_highres; + } else { + svga->render = svga_render_8bpp_lowres; + } + } + } + + if (svga->crtc[0x17] == 0xeb) /*Looks like that 1024x768 mono mode expects 512K of video memory*/ + svga->vram_display_mask = 0x7ffff; + else + svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff; } @@ -629,7 +742,6 @@ extalu(int op, uint8_t input_a, uint8_t input_b) return val; } - static void ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded) { @@ -651,7 +763,7 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { writemask2 = 1 << (addr & 3); addr &= ~3; - } else if (svga->chain2_write) { + } else if (svga->chain2_write && (svga->crtc[0x17] != 0xeb)) { writemask2 &= ~0xa; if (addr & 1) writemask2 <<= 1; @@ -1010,13 +1122,17 @@ ht216_write(uint32_t addr, uint8_t val, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; + uint32_t prev_addr = addr; addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) - svga_write_linear(addr, val, svga); - else + if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) + addr += 0x10000; + + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) { + svga_write_linear(addr, val, svga); + } else ht216_write_common(ht216, addr, val); } @@ -1026,11 +1142,15 @@ ht216_writew(uint32_t addr, uint16_t val, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; - + uint32_t prev_addr = addr; + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) + if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) + addr += 0x10000; + + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) svga_writew_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); @@ -1044,11 +1164,15 @@ ht216_writel(uint32_t addr, uint32_t val, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; + uint32_t prev_addr = addr; addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; + addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) + if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) + addr += 0x10000; + + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3] && svga->crtc[0x17] != 0xeb) svga_writel_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); @@ -1149,7 +1273,7 @@ ht216_read_common(ht216_t *ht216, uint32_t addr) for (i = 0; i < 8; i++) ht216->bg_latch[i] = svga->vram[latch_addr | i]; return svga->vram[addr & svga->vram_mask]; - } else if (svga->chain2_read) { + } else if (svga->chain2_read && (svga->crtc[0x17] != 0xeb)) { readplane = (readplane & 2) | (addr & 1); addr &= ~1; addr <<= 2; @@ -1179,7 +1303,7 @@ ht216_read_common(ht216_t *ht216, uint32_t addr) if (svga->readmode) { temp = 0xff; - + for (pixel = 0; pixel < 8; pixel++) { for (plane = 0; plane < 4; plane++) { if (svga->colournocare & (1 << plane)) { @@ -1203,10 +1327,14 @@ ht216_read(uint32_t addr, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; - + uint32_t prev_addr = addr; + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->read_banks[(addr >> 15) & 1]; + if (svga->crtc[0x17] == 0xeb && !(svga->gdcreg[6] & 0xc) && prev_addr >= 0xb0000) + addr += 0x10000; + return ht216_read_common(ht216, addr); } From 220fffc4a211c688f3aeaf77038a447a8eb5e295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Wed, 24 Feb 2021 21:00:14 +0100 Subject: [PATCH 30/34] win_ui: rewrite resizing using WM_WINDOWPOSCHANGED --- src/win/win_ui.c | 87 ++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 9e156f67c..daf2fafd9 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -485,6 +485,8 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) int i; RECT rect, *rect_p; + WINDOWPOS *pos; + int temp_x, temp_y; if (input_proc(hwnd, message, wParam, lParam) == 0) @@ -840,70 +842,53 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) doresize = 1; break; - case WM_SIZE: - if (user_resize && !vid_resize) - break; + case WM_WINDOWPOSCHANGED: + pos = (WINDOWPOS*)lParam; + GetClientRect(hwndMain, &rect); - temp_x = (lParam & 0xFFFF); - temp_y = (lParam >> 16); - - if ((temp_x <= 0) || (temp_y <= 0)) { + if (IsIconic(hwndMain)) { plat_vidapi_enable(0); minimized = 1; - break; - } else if (minimized == 1) { + return(0); + } else if (minimized) { minimized = 0; video_force_resize_set(1); } - plat_vidapi_enable(0); - temp_y -= sbar_height; - if (temp_y < 1) - temp_y = 1; - - if (vid_resize && ((temp_x != scrnsz_x) || (temp_y != scrnsz_y))) { - scrnsz_x = temp_x; - scrnsz_y = temp_y; - doresize = 1; - } - - MoveWindow(hwndRender, 0, 0, temp_x, temp_y, TRUE); - - GetWindowRect(hwndRender, &rect); - - /* Status bar. */ - MoveWindow(hwndSBAR, 0, rect.bottom, temp_x, 17, TRUE); - - plat_vidsize(temp_x, temp_y); - - if (mouse_capture) { - ClipCursor(&rect); - } - if (window_remember) { - GetWindowRect(hwnd, &rect); - window_x = rect.left; - window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; + window_x = pos->x; + window_y = pos->y; + window_w = pos->cx; + window_h = pos->cy; save_window_pos = 1; + config_save(); } - plat_vidapi_enable(2); - config_save(); - break; + if (!(pos->flags & SWP_NOSIZE)) { + plat_vidapi_enable(0); - case WM_MOVE: - if (window_remember) { - GetWindowRect(hwnd, &rect); - window_x = rect.left; - window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; - save_window_pos = 1; + MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, sbar_height, rect.right, TRUE); + MoveWindow(hwndRender, 0, 0, rect.right, rect.bottom - sbar_height, TRUE); + + GetClientRect(hwndRender, &rect); + if (rect.right != scrnsz_x || rect.bottom != scrnsz_y) { + scrnsz_x = rect.right; + scrnsz_y = rect.bottom; + doresize = 1; + } + + plat_vidsize(rect.right, rect.bottom); + + if (mouse_capture) { + GetWindowRect(hwndRender, &rect); + ClipCursor(&rect); + } + + plat_vidapi_enable(2); } - break; - + + return(0); + case WM_TIMER: if (wParam == TIMER_1SEC) pc_onesec(); From 3bc409876ea82fb0d3eb4d013f5babeafa3ea42e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Wed, 24 Feb 2021 21:01:31 +0100 Subject: [PATCH 31/34] win_ui: fix status bar with resizable windows --- src/win/win_ui.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/win/win_ui.c b/src/win/win_ui.c index daf2fafd9..6328d1d63 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -1244,6 +1244,13 @@ ui_init(int nCmdShow) SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)); + /* Create the Machine Rendering window. */ + hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD|SS_BITMAP, + 0, 0, 1, 1, hwnd, NULL, hinstance, NULL); + + /* Initiate a resize in order to properly arrange all controls. */ + ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); + /* Move to the last-saved position if needed. */ if (window_remember) MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); @@ -1287,11 +1294,6 @@ ui_init(int nCmdShow) */ ghMutex = CreateMutex(NULL, FALSE, NULL); - /* Create the Machine Rendering window. */ - hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD|SS_BITMAP, - 0, 0, 1, 1, hwnd, NULL, hinstance, NULL); - MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE); - /* All done, fire up the actual emulated machine. */ if (! pc_init_modules()) { /* Dang, no ROMs found at all! */ From 014f16731e63ad51c6b98288dff77b6a4c27df21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Wed, 24 Feb 2021 21:04:42 +0100 Subject: [PATCH 32/34] win_ui: remove redundant resizing code the resize handler already takes care of resizing the render window and status bar, so there is no need to do it after each `ResizeWindowByClientArea` call --- src/win/win_ui.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 6328d1d63..d13a01b5e 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -611,16 +611,9 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) temp_x = unscaled_size_x; temp_y = unscaled_size_y; } - /* Main Window. */ + ResizeWindowByClientArea(hwnd, temp_x, temp_y + sbar_height); - /* Render window. */ - MoveWindow(hwndRender, 0, 0, temp_x, temp_y, TRUE); - GetWindowRect(hwndRender, &rect); - - /* Status bar. */ - MoveWindow(hwndSBAR, 0, rect.bottom, temp_x, 17, TRUE); - if (mouse_capture) { ClipCursor(&rect); } @@ -1478,8 +1471,6 @@ plat_pause(int p) void plat_resize(int x, int y) { - RECT r; - /* First, see if we should resize the UI window. */ if (!vid_resize) { @@ -1489,15 +1480,6 @@ plat_resize(int x, int y) y = MulDiv(y, dpi, 96); } ResizeWindowByClientArea(hwndMain, x, y + sbar_height); - - MoveWindow(hwndRender, 0, 0, x, y, TRUE); - GetWindowRect(hwndRender, &r); - - MoveWindow(hwndSBAR, 0, y, x, 17, TRUE); - - if (mouse_capture) { - ClipCursor(&r); - } } } From 533b7a5f308699e6101700f2449ca5cb64e25ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Fri, 26 Feb 2021 17:23:59 +0100 Subject: [PATCH 33/34] win_ui: don't reset remembered window size fixes #1291 --- src/win/win_ui.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/win/win_ui.c b/src/win/win_ui.c index d13a01b5e..7f7f66e5e 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -1241,12 +1241,12 @@ ui_init(int nCmdShow) hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD|SS_BITMAP, 0, 0, 1, 1, hwnd, NULL, hinstance, NULL); - /* Initiate a resize in order to properly arrange all controls. */ - ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); - - /* Move to the last-saved position if needed. */ + /* Initiate a resize in order to properly arrange all controls. + Move to the last-saved position if needed. */ if (window_remember) MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); + else + ResizeWindowByClientArea(hwndMain, scrnsz_x, scrnsz_y + sbar_height); /* Reset all menus to their defaults. */ ResetAllMenus(); From 87161c63ddc5b9c28ce02a2294d07c32727c4d12 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 4 Mar 2021 21:56:43 +0100 Subject: [PATCH 34/34] Only bits 4 to 2 of LSR are now writable, and only in loopback mode. --- src/device/serial.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/device/serial.c b/src/device/serial.c index ed6915438..4cda5841f 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -484,14 +484,16 @@ serial_write(uint16_t addr, uint8_t val, void *p) } break; case 5: - dev->lsr = val; - if (dev->lsr & 0x01) - dev->int_status |= SERIAL_INT_RECEIVE; - if (dev->lsr & 0x1e) - dev->int_status |= SERIAL_INT_LSR; - if (dev->lsr & 0x20) - dev->int_status |= SERIAL_INT_TRANSMIT; - serial_update_ints(dev); + if (dev->mctrl & 0x10) { + dev->lsr = (dev->lsr & 0xe3) | (val & 0x1c); + if (dev->lsr & 0x01) + dev->int_status |= SERIAL_INT_RECEIVE; + if (dev->lsr & 0x1e) + dev->int_status |= SERIAL_INT_LSR; + if (dev->lsr & 0x20) + dev->int_status |= SERIAL_INT_TRANSMIT; + serial_update_ints(dev); + } break; case 6: dev->msr = val;