Merge branch 'master' of https://github.com/86Box/86Box
This commit is contained in:
@@ -188,7 +188,6 @@ int gfxcard[GFXCARD_MAX] = { 0, 0 }; /* (C) graphic
|
||||
int show_second_monitors = 1; /* (C) show non-primary monitors */
|
||||
int sound_is_float = 1; /* (C) sound uses FP values */
|
||||
int voodoo_enabled = 0; /* (C) video option */
|
||||
int lba_enhancer_enabled = 0; /* (C) enable Vision Systems LBA Enhancer */
|
||||
int ibm8514_standalone_enabled = 0; /* (C) video option */
|
||||
int xga_standalone_enabled = 0; /* (C) video option */
|
||||
int da2_standalone_enabled = 0; /* (C) video option */
|
||||
@@ -1535,9 +1534,6 @@ pc_reset_hard_init(void)
|
||||
if (unittester_enabled)
|
||||
device_add(&unittester_device);
|
||||
|
||||
if (lba_enhancer_enabled)
|
||||
device_add(&lba_enhancer_device);
|
||||
|
||||
if (novell_keycard_enabled)
|
||||
device_add(&novell_keycard_device);
|
||||
|
||||
|
||||
46
src/config.c
46
src/config.c
@@ -265,7 +265,9 @@ load_machine(void)
|
||||
if (p != NULL) {
|
||||
migrate_from = p;
|
||||
/* Migrate renamed machines. */
|
||||
if (!strcmp(p, "430nx"))
|
||||
if (!strcmp(p, "tandy"))
|
||||
machine = machine_get_machine_from_internal_name("tandy1000sx");
|
||||
else if (!strcmp(p, "430nx"))
|
||||
machine = machine_get_machine_from_internal_name("586ip");
|
||||
else if (!strcmp(p, "586mc1"))
|
||||
machine = machine_get_machine_from_internal_name("586is");
|
||||
@@ -992,11 +994,6 @@ load_storage_controllers(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lba_enhancer_enabled = !!ini_section_get_int(cat, "lba_enhancer_enabled", 0);
|
||||
|
||||
if (!lba_enhancer_enabled)
|
||||
ini_section_delete_var(cat, "lba_enhancer_enabled");
|
||||
}
|
||||
|
||||
/* Load "Hard Disks" section. */
|
||||
@@ -1213,14 +1210,20 @@ load_floppy_and_cdrom_drives(void)
|
||||
unsigned int board = 0;
|
||||
unsigned int dev = 0;
|
||||
int c;
|
||||
int d = 0;
|
||||
int d;
|
||||
int count = cdrom_get_type_count();
|
||||
|
||||
memset(temp, 0x00, sizeof(temp));
|
||||
for (c = 0; c < FDD_NUM; c++) {
|
||||
sprintf(temp, "fdd_%02i_type", c + 1);
|
||||
p = ini_section_get_string(cat, temp, (c < 2) ? "525_2dd" : "none");
|
||||
fdd_set_type(c, fdd_get_from_internal_name(p));
|
||||
if (!strcmp(p, "525_2hd_ps2"))
|
||||
d = fdd_get_from_internal_name("525_2hd");
|
||||
else if (!strcmp(p, "35_2hd_ps2"))
|
||||
d = fdd_get_from_internal_name("35_2hd");
|
||||
else
|
||||
d = fdd_get_from_internal_name(p);
|
||||
fdd_set_type(c, d);
|
||||
if (fdd_get_type(c) > 13)
|
||||
fdd_set_type(c, 13);
|
||||
|
||||
@@ -1299,6 +1302,7 @@ load_floppy_and_cdrom_drives(void)
|
||||
ini_section_delete_var(cat, temp);
|
||||
|
||||
sprintf(temp, "cdrom_%02i_parameters", c + 1);
|
||||
d = 0;
|
||||
p = ini_section_get_string(cat, temp, NULL);
|
||||
if (p != NULL)
|
||||
sscanf(p, "%01u, %s", &d, s);
|
||||
@@ -1727,6 +1731,17 @@ load_other_peripherals(void)
|
||||
ini_section_delete_var(cat, temp);
|
||||
}
|
||||
|
||||
/* Backwards compatibility for standalone LBA Enhancer from v4.2 and older. */
|
||||
if (ini_section_get_int(ini_find_section(config, "Storage controllers"), "lba_enhancer_enabled", 0) == 1) {
|
||||
/* Migrate to the first available ISA ROM slot. */
|
||||
for (uint8_t c = 0; c < ISAROM_MAX; c++) {
|
||||
if (!isarom_type[c]) {
|
||||
isarom_type[c] = isarom_get_from_internal_name("lba_enhancer");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p = ini_section_get_string(cat, "isartc_type", "none");
|
||||
isartc_type = isartc_get_from_internal_name(p);
|
||||
|
||||
@@ -2697,10 +2712,19 @@ save_storage_controllers(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (lba_enhancer_enabled == 0)
|
||||
/* Downgrade compatibility for standalone LBA Enhancer from v4.2 and older. */
|
||||
int card_id = isarom_get_from_internal_name("lba_enhancer");
|
||||
for (c = 0; c < ISAROM_MAX; c++) {
|
||||
if (isarom_type[c] == card_id) {
|
||||
/* A special value of 2 still enables the cards on older versions,
|
||||
but lets newer versions know that they've already been migrated. */
|
||||
ini_section_set_int(cat, "lba_enhancer_enabled", 2);
|
||||
card_id = 0; /* mark as found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (card_id > 0) /* not found */
|
||||
ini_section_delete_var(cat, "lba_enhancer_enabled");
|
||||
else
|
||||
ini_section_set_int(cat, "lba_enhancer_enabled", 1);
|
||||
|
||||
ini_delete_section_if_empty(config, cat);
|
||||
}
|
||||
|
||||
@@ -26,9 +26,14 @@
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/isarom.h>
|
||||
|
||||
#define ISAROM_CARD 0
|
||||
#define ISAROM_CARD_DUAL 1
|
||||
#define ISAROM_CARD_QUAD 2
|
||||
enum {
|
||||
ISAROM_CARD = 0,
|
||||
ISAROM_CARD_DUAL,
|
||||
ISAROM_CARD_QUAD,
|
||||
ISAROM_CARD_LBA_ENHANCER
|
||||
};
|
||||
|
||||
#define BIOS_LBA_ENHANCER "roms/hdd/misc/lbaenhancer.bin"
|
||||
|
||||
#ifdef ENABLE_ISAROM_LOG
|
||||
int isarom_do_log = ENABLE_ISAROM_LOG;
|
||||
@@ -56,7 +61,7 @@ typedef struct isarom_t {
|
||||
uint32_t size;
|
||||
uint32_t len;
|
||||
char nvr_path[64];
|
||||
uint8_t wp;
|
||||
uint8_t writable;
|
||||
} socket[4];
|
||||
uint8_t inst;
|
||||
uint8_t type;
|
||||
@@ -65,11 +70,14 @@ typedef struct 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;
|
||||
switch (type) {
|
||||
case ISAROM_CARD_DUAL:
|
||||
return 2;
|
||||
case ISAROM_CARD_QUAD:
|
||||
return 4;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -92,12 +100,13 @@ isarom_close(void *priv)
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
for (uint8_t i = 0; i < get_limit(dev->type); i++)
|
||||
if (dev->socket[i].rom.rom) {
|
||||
for (uint8_t i = 0; i < get_limit(dev->type); i++) {
|
||||
if (dev->socket[i].writable) {
|
||||
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);
|
||||
}
|
||||
@@ -115,32 +124,42 @@ isarom_init(const device_t *info)
|
||||
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 str[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);
|
||||
snprintf(str, sizeof(str), "bios_addr%s", suffix);
|
||||
dev->socket[i].addr = device_get_config_hex20(str);
|
||||
|
||||
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;
|
||||
switch (dev->type) {
|
||||
case ISAROM_CARD_LBA_ENHANCER:
|
||||
dev->socket[i].fn = BIOS_LBA_ENHANCER;
|
||||
dev->socket[i].size = 0x4000;
|
||||
break;
|
||||
|
||||
isarom_log("isarom[%u]: socket %u: addr=0x%05X size=%u wp=%u fn=%s\n",
|
||||
default:
|
||||
snprintf(str, sizeof(str), "bios_fn%s", suffix);
|
||||
dev->socket[i].fn = device_get_config_string(str);
|
||||
|
||||
snprintf(str, sizeof(str), "bios_size%s", suffix);
|
||||
dev->socket[i].size = device_get_config_int(str);
|
||||
|
||||
snprintf(str, sizeof(str), "rom_writes_enabled%s", suffix);
|
||||
if (device_get_config_int(str))
|
||||
dev->socket[i].writable = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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 > 0) ? ((dev->socket[i].size - 1) | MEM_GRANULARITY_MASK) : 0;
|
||||
|
||||
isarom_log("isarom[%u]: socket %u: addr=0x%05X size=%u writable=%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)");
|
||||
dev->socket[i].writable, dev->socket[i].fn ? dev->socket[i].fn : "(null)");
|
||||
|
||||
if (dev->socket[i].addr != 0 && 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,
|
||||
@@ -151,7 +170,7 @@ isarom_init(const device_t *info)
|
||||
|
||||
isarom_log("isarom[%u]: ROM initialized for socket %u\n", dev->inst, i);
|
||||
|
||||
if (dev->socket[i].wp) {
|
||||
if (dev->socket[i].writable) {
|
||||
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");
|
||||
@@ -168,6 +187,12 @@ isarom_init(const device_t *info)
|
||||
return dev;
|
||||
}
|
||||
|
||||
static int
|
||||
isarom_lba_enhancer_available(void)
|
||||
{
|
||||
return rom_present(BIOS_LBA_ENHANCER);
|
||||
}
|
||||
|
||||
#define BIOS_FILE_FILTER "ROM files (*.bin *.rom)|*.bin,*.rom"
|
||||
|
||||
#define BIOS_ADDR_SELECTION { \
|
||||
@@ -444,7 +469,7 @@ static const device_config_t isarom_quad_config[] = {
|
||||
.type = CONFIG_FNAME,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = "ROM files (*.bin *.rom)|*.bin,*.rom",
|
||||
.file_filter = BIOS_FILE_FILTER,
|
||||
.spinner = { 0 },
|
||||
.selection = { },
|
||||
.bios = { { 0 } }
|
||||
@@ -528,6 +553,29 @@ static const device_config_t isarom_quad_config[] = {
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
static const device_config_t lba_enhancer_config[] = {
|
||||
{
|
||||
.name = "bios_addr",
|
||||
.description = "BIOS Address",
|
||||
.type = CONFIG_HEX20,
|
||||
.default_string = NULL,
|
||||
.default_int = 0xc8000,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "C800H", .value = 0xc8000 },
|
||||
{ .description = "CC00H", .value = 0xcc000 },
|
||||
{ .description = "D000H", .value = 0xd0000 },
|
||||
{ .description = "D400H", .value = 0xd4000 },
|
||||
{ .description = "D800H", .value = 0xd8000 },
|
||||
{ .description = "DC00H", .value = 0xdc000 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static const device_t isarom_device = {
|
||||
@@ -572,15 +620,30 @@ static const device_t isarom_quad_device = {
|
||||
.config = isarom_quad_config
|
||||
};
|
||||
|
||||
static const device_t lba_enhancer_device = {
|
||||
.name = "Vision Systems LBA Enhancer",
|
||||
.internal_name = "lba_enhancer",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = ISAROM_CARD_LBA_ENHANCER,
|
||||
.init = isarom_init,
|
||||
.close = isarom_close,
|
||||
.reset = NULL,
|
||||
.available = isarom_lba_enhancer_available,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = lba_enhancer_config
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const device_t *dev;
|
||||
} boards[] = {
|
||||
// clang-format off
|
||||
{ &device_none },
|
||||
{ &isarom_device },
|
||||
{ &isarom_dual_device },
|
||||
{ &isarom_quad_device },
|
||||
{ NULL }
|
||||
{ &device_none },
|
||||
{ &isarom_device },
|
||||
{ &isarom_dual_device },
|
||||
{ &isarom_quad_device },
|
||||
{ &lba_enhancer_device },
|
||||
{ NULL }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ add_library(hdd OBJECT
|
||||
hdc_ide_sff8038i.c
|
||||
hdc_ide_um8673f.c
|
||||
hdc_ide_w83769f.c
|
||||
lba_enhancer.c
|
||||
)
|
||||
|
||||
add_library(zip OBJECT zip.c)
|
||||
|
||||
@@ -1,100 +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.
|
||||
*
|
||||
* Vision Systems LBA Enhancer emulation.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Cacodemon345
|
||||
*
|
||||
* Copyright 2024 Cacodemon345
|
||||
*/
|
||||
|
||||
#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/plat_unused.h>
|
||||
|
||||
typedef struct lba_enhancer_t
|
||||
{
|
||||
rom_t rom;
|
||||
} lba_enhancer_t;
|
||||
|
||||
#define BIOS_LBA_ENHANCER "roms/hdd/misc/lbaenhancer.bin"
|
||||
|
||||
void
|
||||
lba_enhancer_close(void* priv)
|
||||
{
|
||||
free(priv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
lba_enhancer_init(UNUSED(const device_t *info))
|
||||
{
|
||||
lba_enhancer_t *dev = (lba_enhancer_t *) calloc(1, sizeof(lba_enhancer_t));
|
||||
|
||||
rom_init(&dev->rom, BIOS_LBA_ENHANCER,
|
||||
device_get_config_hex20("bios_addr"), 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static int
|
||||
lba_enhancer_available(void)
|
||||
{
|
||||
return rom_present(BIOS_LBA_ENHANCER);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static const device_config_t lba_enhancer_config[] = {
|
||||
{
|
||||
.name = "bios_addr",
|
||||
.description = "BIOS Address",
|
||||
.type = CONFIG_HEX20,
|
||||
.default_string = NULL,
|
||||
.default_int = 0xc8000,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "C800H", .value = 0xc8000 },
|
||||
{ .description = "CC00H", .value = 0xcc000 },
|
||||
{ .description = "D000H", .value = 0xd0000 },
|
||||
{ .description = "D400H", .value = 0xd4000 },
|
||||
{ .description = "D800H", .value = 0xd8000 },
|
||||
{ .description = "DC00H", .value = 0xdc000 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const device_t lba_enhancer_device = {
|
||||
.name = "Vision Systems LBA Enhancer",
|
||||
.internal_name = "lba_enhancer",
|
||||
.flags = DEVICE_ISA16,
|
||||
.local = 0,
|
||||
.init = lba_enhancer_init,
|
||||
.close = lba_enhancer_close,
|
||||
.reset = NULL,
|
||||
.available = lba_enhancer_available,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = lba_enhancer_config
|
||||
};
|
||||
@@ -212,18 +212,9 @@ int
|
||||
fdd_get_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
char *n;
|
||||
|
||||
/* TODO: Remove this once the migration period is over. */
|
||||
if (!strcmp(s, "525_2hd_ps2"))
|
||||
n = "525_2hd";
|
||||
else if (!strcmp(s, "35_2hd_ps2"))
|
||||
n = "35_2hd";
|
||||
else
|
||||
n = s;
|
||||
|
||||
while (strlen(drive_types[c].internal_name)) {
|
||||
if (!strcmp((char *) drive_types[c].internal_name, n))
|
||||
if (!strcmp((char *) drive_types[c].internal_name, s))
|
||||
return c;
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,6 @@ extern int fpu_type; /* (C) fpu type */
|
||||
extern int fpu_softfloat; /* (C) fpu uses softfloat */
|
||||
extern int time_sync; /* (C) enable time sync */
|
||||
extern int hdd_format_type; /* (C) hard disk file format */
|
||||
extern int lba_enhancer_enabled; /* (C) enable Vision Systems LBA Enhancer */
|
||||
extern int confirm_reset; /* (C) enable reset confirmation */
|
||||
extern int confirm_exit; /* (C) enable exit confirmation */
|
||||
extern int confirm_save; /* (C) enable save confirmation */
|
||||
|
||||
@@ -112,9 +112,6 @@ extern const device_t xtide_acculogic_device; /* xtide_ps2 */
|
||||
extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */
|
||||
extern const device_t xtide_at_ps2_2ch_device; /* xtide_at_ps2_2ch */
|
||||
|
||||
/* Miscellaneous */
|
||||
extern const device_t lba_enhancer_device;
|
||||
|
||||
extern void hdc_init(void);
|
||||
extern void hdc_reset(void);
|
||||
|
||||
|
||||
@@ -1564,7 +1564,7 @@ const machine_t machines[] = {
|
||||
},
|
||||
{
|
||||
.name = "[8088] Tandy 1000 SX",
|
||||
.internal_name = "tandy",
|
||||
.internal_name = "tandy1000sx",
|
||||
.type = MACHINE_TYPE_8088,
|
||||
.chipset = MACHINE_CHIPSET_PROPRIETARY,
|
||||
.init = machine_tandy1000sx_init,
|
||||
|
||||
@@ -455,6 +455,7 @@ endif()
|
||||
|
||||
if (UNIX AND NOT APPLE AND NOT HAIKU)
|
||||
target_sources(ui PRIVATE x11_util.c)
|
||||
target_link_libraries(plat PRIVATE ${CMAKE_DL_LIBS})
|
||||
|
||||
find_package(X11 REQUIRED)
|
||||
target_link_libraries(ui PRIVATE X11::X11 X11::Xi)
|
||||
|
||||
@@ -56,6 +56,10 @@ extern "C" {
|
||||
#include <86box/gdbstub.h>
|
||||
#include <86box/version.h>
|
||||
#include <86box/renderdefs.h>
|
||||
#ifdef Q_OS_LINUX
|
||||
#define GAMEMODE_AUTO
|
||||
#include "../unix/gamemode/gamemode_client.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
||||
@@ -62,7 +62,6 @@ SettingsStorageControllers::save()
|
||||
ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0;
|
||||
ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0;
|
||||
cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0;
|
||||
lba_enhancer_enabled = ui->checkBoxLbaEnhancer->isChecked() ? 1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -232,9 +231,6 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
|
||||
ui->checkBoxCassette->setChecked(false);
|
||||
ui->checkBoxCassette->setEnabled(false);
|
||||
}
|
||||
|
||||
ui->checkBoxLbaEnhancer->setChecked(lba_enhancer_enabled > 0 && device_available(&lba_enhancer_device));
|
||||
ui->pushButtonConfigureLbaEnhancer->setEnabled(ui->checkBoxLbaEnhancer->isChecked());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -365,15 +361,3 @@ SettingsStorageControllers::on_pushButtonSCSI4_clicked()
|
||||
{
|
||||
DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsStorageControllers::on_checkBoxLbaEnhancer_stateChanged(int arg1)
|
||||
{
|
||||
ui->pushButtonConfigureLbaEnhancer->setEnabled(arg1 != 0);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsStorageControllers::on_pushButtonConfigureLbaEnhancer_clicked()
|
||||
{
|
||||
DeviceConfig::ConfigureDevice(&lba_enhancer_device);
|
||||
}
|
||||
|
||||
@@ -44,9 +44,6 @@ private slots:
|
||||
void on_comboBoxSCSI4_currentIndexChanged(int index);
|
||||
void on_pushButtonSCSI4_clicked();
|
||||
|
||||
void on_checkBoxLbaEnhancer_stateChanged(int arg1);
|
||||
void on_pushButtonConfigureLbaEnhancer_clicked();
|
||||
|
||||
private:
|
||||
Ui::SettingsStorageControllers *ui;
|
||||
int machineId = 0;
|
||||
|
||||
@@ -257,43 +257,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxLbaEnhancer">
|
||||
<property name="text">
|
||||
<string>Vision Systems LBA Enhancer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonConfigureLbaEnhancer">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
376
src/unix/gamemode/gamemode_client.h
Normal file
376
src/unix/gamemode/gamemode_client.h
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017-2025, Feral Interactive and the GameMode contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Feral Interactive nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef CLIENT_GAMEMODE_H
|
||||
#define CLIENT_GAMEMODE_H
|
||||
/*
|
||||
* GameMode supports the following client functions
|
||||
* Requests are refcounted in the daemon
|
||||
*
|
||||
* int gamemode_request_start() - Request gamemode starts
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
*
|
||||
* int gamemode_request_end() - Request gamemode ends
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
*
|
||||
* GAMEMODE_AUTO can be defined to make the above two functions apply during static init and
|
||||
* destruction, as appropriate. In this configuration, errors will be printed to stderr
|
||||
*
|
||||
* int gamemode_query_status() - Query the current status of gamemode
|
||||
* 0 if gamemode is inactive
|
||||
* 1 if gamemode is active
|
||||
* 2 if gamemode is active and this client is registered
|
||||
* -1 if the query failed
|
||||
*
|
||||
* int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
* -2 if the request was rejected
|
||||
*
|
||||
* int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
* -2 if the request was rejected
|
||||
*
|
||||
* int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process
|
||||
* 0 if gamemode is inactive
|
||||
* 1 if gamemode is active
|
||||
* 2 if gamemode is active and this client is registered
|
||||
* -1 if the query failed
|
||||
*
|
||||
* const char* gamemode_error_string() - Get an error string
|
||||
* returns a string describing any of the above errors
|
||||
*
|
||||
* Note: All the above requests can be blocking - dbus requests can and will block while the daemon
|
||||
* handles the request. It is not recommended to make these calls in performance critical code
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
static char internal_gamemode_client_error_string[512] = { 0 };
|
||||
|
||||
/**
|
||||
* Load libgamemode dynamically to dislodge us from most dependencies.
|
||||
* This allows clients to link and/or use this regardless of runtime.
|
||||
* See SDL2 for an example of the reasoning behind this in terms of
|
||||
* dynamic versioning as well.
|
||||
*/
|
||||
static volatile int internal_libgamemode_loaded = 1;
|
||||
|
||||
/* Typedefs for the functions to load */
|
||||
typedef int (*api_call_return_int)(void);
|
||||
typedef const char *(*api_call_return_cstring)(void);
|
||||
typedef int (*api_call_pid_return_int)(pid_t);
|
||||
|
||||
/* Storage for functors */
|
||||
static api_call_return_int REAL_internal_gamemode_request_start = NULL;
|
||||
static api_call_return_int REAL_internal_gamemode_request_end = NULL;
|
||||
static api_call_return_int REAL_internal_gamemode_query_status = NULL;
|
||||
static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
|
||||
static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
|
||||
static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
|
||||
static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
|
||||
|
||||
/**
|
||||
* Internal helper to perform the symbol binding safely.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
|
||||
void *handle, const char *name, void **out_func, size_t func_size, bool required)
|
||||
{
|
||||
void *symbol_lookup = NULL;
|
||||
char *dl_error = NULL;
|
||||
|
||||
/* Safely look up the symbol */
|
||||
symbol_lookup = dlsym(handle, name);
|
||||
dl_error = dlerror();
|
||||
if (required && (dl_error || !symbol_lookup)) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"dlsym failed - %s",
|
||||
dl_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Have the symbol correctly, copy it to make it usable */
|
||||
memcpy(out_func, &symbol_lookup, func_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads libgamemode and needed functions
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
__attribute__((always_inline)) static inline int internal_load_libgamemode(void)
|
||||
{
|
||||
/* We start at 1, 0 is a success and -1 is a fail */
|
||||
if (internal_libgamemode_loaded != 1) {
|
||||
return internal_libgamemode_loaded;
|
||||
}
|
||||
|
||||
/* Anonymous struct type to define our bindings */
|
||||
struct binding {
|
||||
const char *name;
|
||||
void **functor;
|
||||
size_t func_size;
|
||||
bool required;
|
||||
} bindings[] = {
|
||||
{ "real_gamemode_request_start",
|
||||
(void **)&REAL_internal_gamemode_request_start,
|
||||
sizeof(REAL_internal_gamemode_request_start),
|
||||
true },
|
||||
{ "real_gamemode_request_end",
|
||||
(void **)&REAL_internal_gamemode_request_end,
|
||||
sizeof(REAL_internal_gamemode_request_end),
|
||||
true },
|
||||
{ "real_gamemode_query_status",
|
||||
(void **)&REAL_internal_gamemode_query_status,
|
||||
sizeof(REAL_internal_gamemode_query_status),
|
||||
false },
|
||||
{ "real_gamemode_error_string",
|
||||
(void **)&REAL_internal_gamemode_error_string,
|
||||
sizeof(REAL_internal_gamemode_error_string),
|
||||
true },
|
||||
{ "real_gamemode_request_start_for",
|
||||
(void **)&REAL_internal_gamemode_request_start_for,
|
||||
sizeof(REAL_internal_gamemode_request_start_for),
|
||||
false },
|
||||
{ "real_gamemode_request_end_for",
|
||||
(void **)&REAL_internal_gamemode_request_end_for,
|
||||
sizeof(REAL_internal_gamemode_request_end_for),
|
||||
false },
|
||||
{ "real_gamemode_query_status_for",
|
||||
(void **)&REAL_internal_gamemode_query_status_for,
|
||||
sizeof(REAL_internal_gamemode_query_status_for),
|
||||
false },
|
||||
};
|
||||
|
||||
void *libgamemode = NULL;
|
||||
|
||||
/* Try and load libgamemode */
|
||||
libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
/* Attempt to load unversioned library for compatibility with older
|
||||
* versions (as of writing, there are no ABI changes between the two -
|
||||
* this may need to change if ever ABI-breaking changes are made) */
|
||||
libgamemode = dlopen("libgamemode.so", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"dlopen failed - %s",
|
||||
dlerror());
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to bind all symbols */
|
||||
for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
|
||||
struct binding *binder = &bindings[i];
|
||||
|
||||
if (internal_bind_libgamemode_symbol(libgamemode,
|
||||
binder->name,
|
||||
binder->functor,
|
||||
binder->func_size,
|
||||
binder->required)) {
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
|
||||
/* Success */
|
||||
internal_libgamemode_loaded = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the real libgamemode
|
||||
*/
|
||||
__attribute__((always_inline)) static inline const char *gamemode_error_string(void)
|
||||
{
|
||||
/* If we fail to load the system gamemode, or we have an error string already, return our error
|
||||
* string instead of diverting to the system version */
|
||||
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
|
||||
return internal_gamemode_client_error_string;
|
||||
}
|
||||
|
||||
/* Assert for static analyser that the function is not NULL */
|
||||
assert(REAL_internal_gamemode_error_string != NULL);
|
||||
|
||||
return REAL_internal_gamemode_error_string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the real libgamemode
|
||||
* Allow automatically requesting game mode
|
||||
* Also prints errors as they happen.
|
||||
*/
|
||||
#ifdef GAMEMODE_AUTO
|
||||
__attribute__((constructor))
|
||||
#else
|
||||
__attribute__((always_inline)) static inline
|
||||
#endif
|
||||
int gamemode_request_start(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Assert for static analyser that the function is not NULL */
|
||||
assert(REAL_internal_gamemode_request_start != NULL);
|
||||
|
||||
if (REAL_internal_gamemode_request_start() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
#ifdef GAMEMODE_AUTO
|
||||
__attribute__((destructor))
|
||||
#else
|
||||
__attribute__((always_inline)) static inline
|
||||
#endif
|
||||
int gamemode_request_end(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Assert for static analyser that the function is not NULL */
|
||||
assert(REAL_internal_gamemode_request_end != NULL);
|
||||
|
||||
if (REAL_internal_gamemode_request_end() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_query_status(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_query_status == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_query_status();
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_start_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_start_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_request_start_for(pid);
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_end_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_end_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_request_end_for(pid);
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_query_status_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_query_status_for(pid);
|
||||
}
|
||||
|
||||
#endif // CLIENT_GAMEMODE_H
|
||||
@@ -576,7 +576,7 @@ main_thread(UNUSED(void *param))
|
||||
old_time = new_time;
|
||||
if (drawits > 0 && !dopause) {
|
||||
/* Yes, so do one frame now. */
|
||||
drawits -= 10;
|
||||
drawits -= force_10ms ? 10 : 1;
|
||||
if (drawits > 50)
|
||||
drawits = 0;
|
||||
|
||||
@@ -584,7 +584,7 @@ main_thread(UNUSED(void *param))
|
||||
pc_run();
|
||||
|
||||
/* Every 200 frames we save the machine status. */
|
||||
if (++frames >= 200 && nvr_dosave) {
|
||||
if (++frames >= (force_10ms ? 200 : 2000) && nvr_dosave) {
|
||||
nvr_save();
|
||||
nvr_dosave = 0;
|
||||
frames = 0;
|
||||
|
||||
Reference in New Issue
Block a user