ISA ROM Board Support
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
26
src/config.c
26
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
|
||||
|
||||
@@ -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
|
||||
|
||||
643
src/device/isarom.c
Normal file
643
src/device/isarom.c
Normal file
@@ -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, <jriwanek@gmail.com>
|
||||
*
|
||||
* Copyright 2025 Jasmine Iwanek.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#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);
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
37
src/include/86box/isarom.h
Normal file
37
src/include/86box/isarom.h
Normal file
@@ -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, <jriwanek@gmail.com>
|
||||
*
|
||||
* 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*/
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<QComboBox *>(QString("comboBoxIsaMemCard%1").arg(i + 1)))
|
||||
cb->clear();
|
||||
|
||||
for (uint8_t i = 0; i < ISAROM_MAX; ++i)
|
||||
if (auto *cb = findChild<QComboBox *>(QString("comboBoxIsaRomCard%1").arg(i + 1)))
|
||||
cb->clear();
|
||||
|
||||
int c = 0;
|
||||
int selectedRow = 0;
|
||||
|
||||
@@ -127,6 +132,47 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId)
|
||||
findChild<QPushButton *>(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<QComboBox *>(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<QPushButton *>(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<QComboBox *>(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<QComboBox *>(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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -174,6 +174,123 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxRom">
|
||||
<property name="title">
|
||||
<string>ISA ROM Cards</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutRom">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelIsaRomCard1">
|
||||
<property name="text">
|
||||
<string>Card 1:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIsaRomCard1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureIsaRomCard1">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelIsaRomCard2">
|
||||
<property name="text">
|
||||
<string>Card 2:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIsaRomCard2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureIsaRomCard2">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelIsaRomCard3">
|
||||
<property name="text">
|
||||
<string>Card 3:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIsaRomCard3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureIsaRomCard3">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelIsaRomCard4">
|
||||
<property name="text">
|
||||
<string>Card 4:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxIsaRomCard4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureIsaRomCard4">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayoutIBPC">
|
||||
<item>
|
||||
|
||||
Reference in New Issue
Block a user