diff --git a/src/86box.c b/src/86box.c index f54a69b79..92e2f0c24 100644 --- a/src/86box.c +++ b/src/86box.c @@ -70,6 +70,7 @@ #include <86box/unittester.h> #include <86box/novell_cardkey.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/isartc.h> #include <86box/lpt.h> #include <86box/serial.h> @@ -181,6 +182,7 @@ int postcard_enabled = 0; /* (C) enable int unittester_enabled = 0; /* (C) enable unit tester device */ int gameport_type[GAMEPORT_MAX] = { 0, 0 }; /* (C) enable gameports */ int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */ +int isarom_type[ISAROM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA ROM cards */ int isartc_type = 0; /* (C) enable ISA RTC card */ int gfxcard[GFXCARD_MAX] = { 0, 0 }; /* (C) graphics/video card */ int show_second_monitors = 1; /* (C) show non-primary monitors */ @@ -1472,6 +1474,10 @@ pc_reset_hard_init(void) zip_hard_reset(); + + /* Reset any ISA ROM cards. */ + isarom_reset(); + /* Reset any ISA RTC cards. */ isartc_reset(); @@ -1901,4 +1907,4 @@ int FindAccelerator(const char *name) { } // No key was found return -1; -} \ No newline at end of file +} diff --git a/src/config.c b/src/config.c index dfe0190ac..8039b9887 100644 --- a/src/config.c +++ b/src/config.c @@ -46,6 +46,7 @@ #include <86box/ini.h> #include <86box/config.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/isartc.h> #include <86box/lpt.h> #include <86box/serial.h> @@ -1699,6 +1700,7 @@ load_other_peripherals(void) if (!novell_keycard_enabled) ini_section_delete_var(cat, "novell_keycard_enabled"); + // ISA RAM Boards for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); @@ -1709,6 +1711,17 @@ load_other_peripherals(void) ini_section_delete_var(cat, temp); } + // ISA ROM Boards + for (uint8_t c = 0; c < ISAROM_MAX; c++) { + sprintf(temp, "isarom%d_type", c); + + p = ini_section_get_string(cat, temp, "none"); + isarom_type[c] = isarom_get_from_internal_name(p); + + if (!strcmp(p, "none")) + ini_section_delete_var(cat, temp); + } + p = ini_section_get_string(cat, "isartc_type", "none"); isartc_type = isartc_get_from_internal_name(p); @@ -1858,6 +1871,8 @@ config_load(void) cdrom[0].sound_on = 1; mem_size = 64; isartc_type = 0; + for (i = 0; i < ISAROM_MAX; i++) + isarom_type[i] = 0; for (i = 0; i < ISAMEM_MAX; i++) isamem_type[i] = 0; @@ -2706,6 +2721,7 @@ save_other_peripherals(void) else ini_section_set_int(cat, "novell_keycard_enabled", novell_keycard_enabled); + // ISA RAM Boards for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); if (isamem_type[c] == 0) @@ -2715,6 +2731,16 @@ save_other_peripherals(void) isamem_get_internal_name(isamem_type[c])); } + // ISA ROM Boards + for (uint8_t c = 0; c < ISAROM_MAX; c++) { + sprintf(temp, "isarom%d_type", c); + if (isarom_type[c] == 0) + ini_section_delete_var(cat, temp); + else + ini_section_set_string(cat, temp, + isarom_get_internal_name(isarom_type[c])); + } + if (isartc_type == 0) ini_section_delete_var(cat, "isartc_type"); else diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 486d40b07..ea89f5cd9 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(dev OBJECT i2c_gpio.c ibm_5161.c isamem.c + isarom.c isartc.c isapnp.c kbc_at.c diff --git a/src/device/isarom.c b/src/device/isarom.c new file mode 100644 index 000000000..238314c87 --- /dev/null +++ b/src/device/isarom.c @@ -0,0 +1,643 @@ +/* + * 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 ISA ROM card Expansions. + * + * Authors: Jasmine Iwanek, + * + * Copyright 2025 Jasmine Iwanek. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/nvr.h> +#include <86box/isarom.h> + +#define ISAROM_CARD 0 +#define ISAROM_CARD_DUAL 1 +#define ISAROM_CARD_QUAD 2 + +#ifdef ENABLE_ISAROM_LOG +int isarom_do_log = ENABLE_ISAROM_LOG; + +static void +isarom_log(const char *fmt, ...) +{ + va_list ap; + + if (isarom_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define isarom_log(fmt, ...) +#endif + +typedef struct isarom_t { + struct { + rom_t rom; + uint32_t addr; + const char *fn; + uint32_t size; + uint32_t len; + char nvr_path[64]; + uint8_t wp; + } socket[4]; + uint8_t inst; + uint8_t type; +} isarom_t; + +static inline uint8_t +get_limit(uint8_t type) +{ + if (type == ISAROM_CARD_DUAL) + return 2; + if (type == ISAROM_CARD_QUAD) + return 4; + return 1; +} + +static inline void +isarom_save_nvr(char *path, uint8_t *data, size_t size) +{ + if (path[0] == 0x00) + return; + + FILE *fp = nvr_fopen(path, "wb"); + if (fp) { + fwrite(data, 1, size, fp); + fclose(fp); + } +} + +void +isarom_close(void *priv) +{ + isarom_t *dev = (isarom_t *) priv; + if (!priv) + return; + + for (uint8_t i = 0; i < get_limit(dev->type); i++) + if (dev->socket[i].rom.rom) { + isarom_log("isarom[%u]: saving NVR for socket %u -> %s (%u bytes)\n", + dev->inst, i, dev->socket[i].nvr_path, dev->socket[i].size); + isarom_save_nvr(dev->socket[i].nvr_path, dev->socket[i].rom.rom, dev->socket[i].size); + } + + free(dev); +} + +static void * +isarom_init(const device_t *info) +{ + isarom_t *dev = (isarom_t *) calloc(1, sizeof(isarom_t)); + if (!dev) + return NULL; + + dev->inst = device_get_instance(); + dev->type = (uint8_t) info->local; + + isarom_log("isarom[%u]: initializing device (type=%u)\n", dev->inst, dev->type); + + for (uint8_t i = 0; i < get_limit(dev->type); i++) { + char key_fn[12]; + char key_addr[14]; + char key_size[14]; + char key_writes[22]; + char suffix[4] = ""; + if (i > 0) + snprintf(suffix, sizeof(suffix), "%d", i + 1); + + snprintf(key_fn, sizeof(key_fn), "bios_fn%s", suffix); + snprintf(key_addr, sizeof(key_addr), "bios_addr%s", suffix); + snprintf(key_size, sizeof(key_size), "bios_size%s", suffix); + snprintf(key_writes, sizeof(key_writes), "rom_writes_enabled%s", suffix); + + dev->socket[i].fn = device_get_config_string(key_fn); + dev->socket[i].addr = device_get_config_hex20(key_addr); + dev->socket[i].size = device_get_config_int(key_size); + // Note: 2K is the smallest ROM I've found, but 86box's memory granularity is 4k, the number below is fine + // as we'll end up allocating no less than 4k due to the device config limits. + dev->socket[i].len = (dev->socket[i].size > 2048) ? dev->socket[i].size - 1 : 0; + dev->socket[i].wp = (uint8_t) device_get_config_int(key_writes) ? 1 : 0; + + isarom_log("isarom[%u]: socket %u: addr=0x%05X size=%u wp=%u fn=%s\n", + dev->inst, i, dev->socket[i].addr, dev->socket[i].size, + dev->socket[i].wp, dev->socket[i].fn ? dev->socket[i].fn : "(null)"); + + if (dev->socket[i].addr != 0 && dev->socket[i].fn != NULL) { + rom_init(&dev->socket[i].rom, + dev->socket[i].fn, + dev->socket[i].addr, + dev->socket[i].size, + dev->socket[i].len, + 0, + MEM_MAPPING_EXTERNAL); + + isarom_log("isarom[%u]: ROM initialized for socket %u\n", dev->inst, i); + + if (dev->socket[i].wp) { + mem_mapping_set_write_handler(&dev->socket[i].rom.mapping, rom_write, rom_writew, rom_writel); + snprintf(dev->socket[i].nvr_path, sizeof(dev->socket[i].nvr_path), "isarom_%i_%i.nvr", dev->inst, i + 1); + FILE *fp = nvr_fopen(dev->socket[i].nvr_path, "rb"); + if (fp != NULL) { + fread(dev->socket[i].rom.rom, 1, dev->socket[i].size, fp); + fclose(fp); + isarom_log("isarom[%u]: loaded %zu bytes from %s\n", dev->inst, read_bytes, dev->socket[i].nvr_path); + } else + isarom_log("isarom[%u]: NVR not found, skipping load (%s)\n", dev->inst, dev->socket[i].nvr_path); + } + } + } + + return dev; +} + +#define BIOS_FILE_FILTER "ROM files (*.bin *.rom)|*.bin,*.rom" + +#define BIOS_ADDR_SELECTION { \ + { "Disabled", 0x00000 }, \ + { "C000H", 0xc0000 }, \ + { "C200H", 0xc2000 }, \ + { "C400H", 0xc4000 }, \ + { "C600H", 0xc6000 }, \ + { "C800H", 0xc8000 }, \ + { "CA00H", 0xca000 }, \ + { "CC00H", 0xcc000 }, \ + { "CE00H", 0xce000 }, \ + { "D000H", 0xd0000 }, \ + { "D200H", 0xd2000 }, \ + { "D400H", 0xd4000 }, \ + { "D600H", 0xd6000 }, \ + { "D800H", 0xd8000 }, \ + { "DA00H", 0xda000 }, \ + { "DC00H", 0xdc000 }, \ + { "DE00H", 0xde000 }, \ + { "E000H", 0xe0000 }, \ + { "E200H", 0xe2000 }, \ + { "E400H", 0xe4000 }, \ + { "E600H", 0xe6000 }, \ + { "E800H", 0xe8000 }, \ + { "EA00H", 0xea000 }, \ + { "EC00H", 0xec000 }, \ + { "EE00H", 0xee000 }, \ + { "", 0 } \ +} + +#define BIOS_SIZE_SELECTION { \ + { "4K", 4096 }, \ + { "8K", 8192 }, \ + { "16K", 16384 }, \ + { "32K", 32768 }, \ + { "64K", 65536 }, \ + { "", 0 } \ +} + +// clang-format off +static const device_config_t isarom_config[] = { + { + .name = "bios_fn", + .description = "BIOS File", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size", + .description = "BIOS Size:", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t isarom_dual_config[] = { + { + .name = "bios_fn", + .description = "BIOS File (ROM #1)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address (ROM #1)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size", + .description = "BIOS Size (ROM #1):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes (ROM #1)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn2", + .description = "BIOS File (ROM #2)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr2", + .description = "BIOS Address (ROM #2)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size2", + .description = "BIOS Size (ROM #2):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled2", + .description = "Enable BIOS extension ROM Writes (ROM #2)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t isarom_quad_config[] = { + { + .name = "bios_fn", + .description = "BIOS File (ROM #1)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr", + .description = "BIOS Address (ROM #1)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size", + .description = "BIOS Size (ROM #1):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled", + .description = "Enable BIOS extension ROM Writes (ROM #1)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn2", + .description = "BIOS File (ROM #2)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr2", + .description = "BIOS Address (ROM #2)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size2", + .description = "BIOS Size (ROM #2):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled2", + .description = "Enable BIOS extension ROM Writes (ROM #2)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn3", + .description = "BIOS File (ROM #3)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = "ROM files (*.bin *.rom)|*.bin,*.rom", + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr3", + .description = "BIOS Address (ROM #3)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size3", + .description = "BIOS Size (ROM #3):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled3", + .description = "Enable BIOS extension ROM Writes (ROM #3)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "bios_fn4", + .description = "BIOS File (ROM #4)", + .type = CONFIG_FNAME, + .default_string = NULL, + .default_int = 0, + .file_filter = BIOS_FILE_FILTER, + .spinner = { 0 }, + .selection = { }, + .bios = { { 0 } } + }, + { + .name = "bios_addr4", + .description = "BIOS Address (ROM #4)", + .type = CONFIG_HEX20, + .default_string = NULL, + .default_int = 0x00000, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_ADDR_SELECTION, + .bios = { { 0 } } + }, + { + .name = "bios_size4", + .description = "BIOS Size (ROM #4):", + .type = CONFIG_INT, + .default_string = NULL, + .default_int = 8192, + .file_filter = NULL, + .spinner = { 0 }, + .selection = BIOS_SIZE_SELECTION, + .bios = { { 0 } } + }, + { + .name = "rom_writes_enabled4", + .description = "Enable BIOS extension ROM Writes (ROM #4)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +static const device_t isarom_device = { + .name = "Generic ISA ROM Board", + .internal_name = "isarom", + .flags = DEVICE_ISA, + .local = ISAROM_CARD, + .init = isarom_init, + .close = isarom_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = isarom_config +}; + +static const device_t isarom_dual_device = { + .name = "Generic Dual ISA ROM Board", + .internal_name = "isarom_dual", + .flags = DEVICE_ISA, + .local = ISAROM_CARD_DUAL, + .init = isarom_init, + .close = isarom_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = isarom_dual_config +}; + +static const device_t isarom_quad_device = { + .name = "Generic Quad ISA ROM Board", + .internal_name = "isarom_quad", + .flags = DEVICE_ISA, + .local = ISAROM_CARD_QUAD, + .init = isarom_init, + .close = isarom_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = isarom_quad_config +}; + +static const struct { + const device_t *dev; +} boards[] = { + // clang-format off + { &device_none }, + { &isarom_device }, + { &isarom_dual_device }, + { &isarom_quad_device }, + { NULL } + // clang-format on +}; + +void +isarom_reset(void) +{ + for (uint8_t i = 0; i < ISAROM_MAX; i++) { + if (isarom_type[i] == 0) + continue; + + /* Add the device instance to the system. */ + device_add_inst(boards[isarom_type[i]].dev, i + 1); + } +} + +const char * +isarom_get_name(int board) +{ + if (boards[board].dev == NULL) + return NULL; + + return (boards[board].dev->name); +} + +const char * +isarom_get_internal_name(int board) +{ + return device_get_internal_name(boards[board].dev); +} + +int +isarom_get_from_internal_name(const char *str) +{ + int c = 0; + + while (boards[c].dev != NULL) { + if (!strcmp(boards[c].dev->internal_name, str)) + return c; + c++; + } + + /* Not found. */ + return 0; +} + +const device_t * +isarom_get_device(int board) +{ + /* Add the device instance to the system. */ + return boards[board].dev; +} + +int +isarom_has_config(int board) +{ + if (boards[board].dev == NULL) + return 0; + + return (boards[board].dev->config ? 1 : 0); +} diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 76f311d17..8bf303961 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -134,6 +134,7 @@ extern int postcard_enabled; /* (C) enable POST card */ extern int unittester_enabled; /* (C) enable unit tester device */ extern int gameport_type[]; /* (C) enable gameports */ extern int isamem_type[]; /* (C) enable ISA mem cards */ +extern int isarom_type[]; /* (C) enable ISA ROM cards */ extern int isartc_type; /* (C) enable ISA RTC card */ extern int sound_is_float; /* (C) sound uses FP values */ extern int voodoo_enabled; /* (C) video option */ diff --git a/src/include/86box/config.h b/src/include/86box/config.h index 693f38ab7..34447266b 100644 --- a/src/include/86box/config.h +++ b/src/include/86box/config.h @@ -122,6 +122,7 @@ typedef struct config_t { int ide_qua_enabled; /* Quaternary IDE controller enabled */ int bugger_enabled; /* ISA bugger device enabled */ int isa_rtc_type; /* ISA RTC card */ + int isa_rom_type[ISAROM_MAX]; /* ISA ROM boards */ int isa_mem_type[ISAMEM_MAX]; /* ISA memory boards */ /* Hard disks category */ diff --git a/src/include/86box/isarom.h b/src/include/86box/isarom.h new file mode 100644 index 000000000..91cfa15a9 --- /dev/null +++ b/src/include/86box/isarom.h @@ -0,0 +1,37 @@ +/* + * 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 ISA ROM card Expansions. + * + * Authors: Jasmine Iwanek, + * + * Copyright 2025 Jasmine Iwanek. + */ +#ifndef EMU_ISAROM_H +#define EMU_ISAROM_H + +#define ISAROM_MAX 4 /* max #cards in system */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions. */ +extern void isarom_reset(void); + +extern const char *isarom_get_name(int t); +extern const char *isarom_get_internal_name(int t); +extern int isarom_get_from_internal_name(const char *str); +extern const device_t *isarom_get_device(int t); +extern int isarom_has_config(int board); + +#ifdef __cplusplus +} +#endif + +#endif /*EMU_ISAROM_H*/ diff --git a/src/machine/machine.c b/src/machine/machine.c index 505674000..6a86b785f 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -39,6 +39,7 @@ #include <86box/video.h> #include <86box/machine.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/pci.h> #include <86box/plat_unused.h> @@ -111,6 +112,11 @@ machine_init_ex(int m) /* Reset any ISA memory cards. */ isamem_reset(); +#if 0 + /* Reset any ISA ROM cards. */ + isarom_reset(); +#endif + /* Reset the fast off stuff. */ cpu_fast_off_reset(); diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index b8a347f25..0ecdc30d3 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -24,6 +24,7 @@ extern "C" { #include <86box/device.h> #include <86box/machine.h> #include <86box/isamem.h> +#include <86box/isarom.h> #include <86box/isartc.h> #include <86box/unittester.h> #include <86box/novell_cardkey.h> @@ -65,6 +66,10 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) if (auto *cb = findChild(QString("comboBoxIsaMemCard%1").arg(i + 1))) cb->clear(); + for (uint8_t i = 0; i < ISAROM_MAX; ++i) + if (auto *cb = findChild(QString("comboBoxIsaRomCard%1").arg(i + 1))) + cb->clear(); + int c = 0; int selectedRow = 0; @@ -127,6 +132,47 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) findChild(QString("pushButtonConfigureIsaMemCard%1").arg(i + 1))->setEnabled((isamem_type[i] != 0) && isamem_has_config(isamem_type[i]) && machineHasIsa); } + + // ISA ROM Expansion Cards + QComboBox *isarom_cbox[ISAROM_MAX] = { 0 }; + QAbstractItemModel *isarom_models[ISAROM_MAX] = { 0 }; + int isarom_removeRows_[ISAROM_MAX] = { 0 }; + int isarom_selectedRows[ISAROM_MAX] = { 0 }; + + for (uint8_t i = 0; i < ISAROM_MAX; ++i) { + isarom_cbox[i] = findChild(QString("comboBoxIsaRomCard%1").arg(i + 1)); + isarom_models[i] = isarom_cbox[i]->model(); + isarom_removeRows_[i] = isarom_models[i]->rowCount(); + } + + c = 0; + while (true) { + const QString name = DeviceConfig::DeviceName(isarom_get_device(c), + isarom_get_internal_name(c), 0); + + if (name.isEmpty()) + break; + + if (device_is_valid(isarom_get_device(c), machineId)) { + for (uint8_t i = 0; i < ISAROM_MAX; ++i) { + int row = Models::AddEntry(isarom_models[i], name, c); + + if (c == isarom_type[i]) + isarom_selectedRows[i] = row - isarom_removeRows_[i]; + } + } + + c++; + } + + for (uint8_t i = 0; i < ISAROM_MAX; ++i) { + isarom_models[i]->removeRows(0, isarom_removeRows_[i]); + isarom_cbox[i]->setEnabled(isarom_models[i]->rowCount() > 1); + isarom_cbox[i]->setCurrentIndex(-1); + isarom_cbox[i]->setCurrentIndex(isarom_selectedRows[i]); + findChild(QString("pushButtonConfigureIsaRomCard%1").arg(i + 1))->setEnabled((isarom_type[i] != 0) && + isarom_has_config(isarom_type[i]) && machineHasIsa); + } } SettingsOtherPeripherals::~SettingsOtherPeripherals() @@ -149,6 +195,12 @@ SettingsOtherPeripherals::save() auto *cbox = findChild(QString("comboBoxIsaMemCard%1").arg(i + 1)); isamem_type[i] = cbox->currentData().toInt(); } + + /* ISA ROM boards. */ + for (int i = 0; i < ISAROM_MAX; i++) { + auto *cbox = findChild(QString("comboBoxIsaRomCard%1").arg(i + 1)); + isarom_type[i] = cbox->currentData().toInt(); + } } void @@ -226,6 +278,66 @@ SettingsOtherPeripherals::on_pushButtonConfigureIsaMemCard4_clicked() DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxIsaMemCard4->currentData().toInt()), 4); } +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard1_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard1->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard1_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard1->currentData().toInt()), 1); +} + +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard2_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard2->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard2_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard2->currentData().toInt()), 2); +} + +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard3_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard3->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard3_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard3->currentData().toInt()), 3); +} + +void +SettingsOtherPeripherals::on_comboBoxIsaRomCard4_currentIndexChanged(int index) +{ + if (index < 0) + return; + + ui->pushButtonConfigureIsaRomCard4->setEnabled((index != 0) && isarom_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureIsaRomCard4_clicked() +{ + DeviceConfig::ConfigureDevice(isarom_get_device(ui->comboBoxIsaRomCard4->currentData().toInt()), 4); +} + void SettingsOtherPeripherals::on_checkBoxUnitTester_stateChanged(int arg1) { diff --git a/src/qt/qt_settingsotherperipherals.hpp b/src/qt/qt_settingsotherperipherals.hpp index e87219ab7..991759259 100644 --- a/src/qt/qt_settingsotherperipherals.hpp +++ b/src/qt/qt_settingsotherperipherals.hpp @@ -32,6 +32,15 @@ private slots: void on_comboBoxIsaMemCard4_currentIndexChanged(int index); void on_pushButtonConfigureIsaMemCard4_clicked(); + void on_comboBoxIsaRomCard1_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard1_clicked(); + void on_comboBoxIsaRomCard2_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard2_clicked(); + void on_comboBoxIsaRomCard3_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard3_clicked(); + void on_comboBoxIsaRomCard4_currentIndexChanged(int index); + void on_pushButtonConfigureIsaRomCard4_clicked(); + void on_checkBoxUnitTester_stateChanged(int arg1); void on_pushButtonConfigureUT_clicked(); diff --git a/src/qt/qt_settingsotherperipherals.ui b/src/qt/qt_settingsotherperipherals.ui index 81b0e0018..5c6b8fbf0 100644 --- a/src/qt/qt_settingsotherperipherals.ui +++ b/src/qt/qt_settingsotherperipherals.ui @@ -174,6 +174,123 @@ + + + + ISA ROM Cards + + + + + + Card 1: + + + + + + + + 0 + 0 + + + + 30 + + + + + + + Configure + + + + + + + Card 2: + + + + + + + + 0 + 0 + + + + 30 + + + + + + + Configure + + + + + + + Card 3: + + + + + + + + 0 + 0 + + + + 30 + + + + + + + Configure + + + + + + + Card 4: + + + + + + + + 0 + 0 + + + + 30 + + + + + + + Configure + + + + + +