mirror of https://github.com/xemu-project/xemu.git
config: Migrate to genconfig system
This commit is contained in:
parent
30fa9e1df1
commit
d14cdbc7ba
|
@ -0,0 +1,68 @@
|
||||||
|
general:
|
||||||
|
updates:
|
||||||
|
check:
|
||||||
|
type: bool
|
||||||
|
default: true
|
||||||
|
misc:
|
||||||
|
skip_boot_anim: bool
|
||||||
|
user_token: string
|
||||||
|
|
||||||
|
input:
|
||||||
|
bindings:
|
||||||
|
port1: string
|
||||||
|
port2: string
|
||||||
|
port3: string
|
||||||
|
port4: string
|
||||||
|
|
||||||
|
display:
|
||||||
|
quality:
|
||||||
|
surface_scale:
|
||||||
|
type: integer
|
||||||
|
default: 1
|
||||||
|
window:
|
||||||
|
last_width: integer
|
||||||
|
last_height: integer
|
||||||
|
ui:
|
||||||
|
fit:
|
||||||
|
type: enum
|
||||||
|
values: [center, scale, scale_16_9, scale_4_3, stretch]
|
||||||
|
default: scale
|
||||||
|
scale:
|
||||||
|
type: integer
|
||||||
|
default: 1
|
||||||
|
|
||||||
|
audio:
|
||||||
|
use_dsp: bool
|
||||||
|
|
||||||
|
net:
|
||||||
|
enable: bool
|
||||||
|
backend:
|
||||||
|
type: enum
|
||||||
|
values: [nat, udp, pcap]
|
||||||
|
default: nat
|
||||||
|
pcap:
|
||||||
|
netif: string
|
||||||
|
udp:
|
||||||
|
bind_addr:
|
||||||
|
type: string
|
||||||
|
default: 0.0.0.0:9368
|
||||||
|
remote_addr:
|
||||||
|
type: string
|
||||||
|
default: 1.2.3.4:9368
|
||||||
|
|
||||||
|
sys:
|
||||||
|
mem_limit:
|
||||||
|
type: enum
|
||||||
|
values: ['64', '128']
|
||||||
|
default: '64'
|
||||||
|
files:
|
||||||
|
bootrom_path: string
|
||||||
|
flashrom_path: string
|
||||||
|
eeprom_path: string
|
||||||
|
hdd_path: string
|
||||||
|
dvd_path: string
|
||||||
|
|
||||||
|
perf:
|
||||||
|
hard_fpu:
|
||||||
|
type: bool
|
||||||
|
default: true
|
|
@ -1 +1 @@
|
||||||
Subproject commit 218d283f65b96232518c252c792a9ff197aca995
|
Subproject commit 8220e8748922ddd9bba4cbacd608601586c9a4bb
|
|
@ -2624,9 +2624,7 @@ void mcpx_apu_init(PCIBus *bus, int devfn, MemoryRegion *ram)
|
||||||
/* Until DSP is more performant, a switch to decide whether or not we should
|
/* Until DSP is more performant, a switch to decide whether or not we should
|
||||||
* use the full audio pipeline or not.
|
* use the full audio pipeline or not.
|
||||||
*/
|
*/
|
||||||
int use_dsp;
|
if (g_config.audio.use_dsp) {
|
||||||
xemu_settings_get_bool(XEMU_SETTINGS_AUDIO_USE_DSP, &use_dsp);
|
|
||||||
if (use_dsp) {
|
|
||||||
d->mon = MCPX_APU_DEBUG_MON_GP_OR_EP;
|
d->mon = MCPX_APU_DEBUG_MON_GP_OR_EP;
|
||||||
d->gp.realtime = true;
|
d->gp.realtime = true;
|
||||||
d->ep.realtime = true;
|
d->ep.realtime = true;
|
||||||
|
|
|
@ -3707,9 +3707,7 @@ void nv2a_set_surface_scale_factor(unsigned int scale)
|
||||||
{
|
{
|
||||||
NV2AState *d = g_nv2a;
|
NV2AState *d = g_nv2a;
|
||||||
|
|
||||||
xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_RENDER_SCALE,
|
g_config.display.quality.surface_scale = scale < 1 ? 1 : scale;
|
||||||
scale < 1 ? 1 : scale);
|
|
||||||
xemu_settings_save();
|
|
||||||
|
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
|
@ -3750,8 +3748,7 @@ unsigned int nv2a_get_surface_scale_factor(void)
|
||||||
|
|
||||||
static void pgraph_reload_surface_scale_factor(NV2AState *d)
|
static void pgraph_reload_surface_scale_factor(NV2AState *d)
|
||||||
{
|
{
|
||||||
int factor;
|
int factor = g_config.display.quality.surface_scale;
|
||||||
xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_RENDER_SCALE, &factor);
|
|
||||||
d->pgraph.surface_scale_factor = factor < 1 ? 1 : factor;
|
d->pgraph.surface_scale_factor = factor < 1 ? 1 : factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
meson.build
18
meson.build
|
@ -837,6 +837,9 @@ if 'CONFIG_OPENGL' in config_host
|
||||||
link_args: config_host['OPENGL_LIBS'].split())
|
link_args: config_host['OPENGL_LIBS'].split())
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
tomlpp = declare_dependency(include_directories: 'tomlplusplus')
|
||||||
|
genconfig = declare_dependency(include_directories: 'genconfig')
|
||||||
|
|
||||||
xemu_gtk = declare_dependency(compile_args: config_host['XEMU_GTK_CFLAGS'].split(),
|
xemu_gtk = declare_dependency(compile_args: config_host['XEMU_GTK_CFLAGS'].split(),
|
||||||
link_args: config_host['XEMU_GTK_LIBS'].split())
|
link_args: config_host['XEMU_GTK_LIBS'].split())
|
||||||
|
|
||||||
|
@ -2056,8 +2059,20 @@ qemu_version = custom_target('qemu-version.h',
|
||||||
build_by_default: true,
|
build_by_default: true,
|
||||||
build_always_stale: true)
|
build_always_stale: true)
|
||||||
|
|
||||||
|
genconfig_cmd = [
|
||||||
|
python, files('genconfig/gen_config.py'),
|
||||||
|
meson.source_root() / 'config_spec.yml', 'xemu-config.h'
|
||||||
|
]
|
||||||
|
|
||||||
|
xemu_config = custom_target('xemu-config.h',
|
||||||
|
output: 'xemu-config.h',
|
||||||
|
input: [ files('config_spec.yml') ],
|
||||||
|
command: genconfig_cmd,
|
||||||
|
depend_files: files('config_spec.yml'))
|
||||||
|
|
||||||
genh += qemu_version
|
genh += qemu_version
|
||||||
genh += xemu_version
|
genh += xemu_version
|
||||||
|
genh += xemu_config
|
||||||
|
|
||||||
hxdep = []
|
hxdep = []
|
||||||
hx_headers = [
|
hx_headers = [
|
||||||
|
@ -2300,6 +2315,9 @@ specific_ss.add(files('xemu-xbe.c', 'xemu-version.c'))
|
||||||
|
|
||||||
common_ss.add(files('cpus-common.c'))
|
common_ss.add(files('cpus-common.c'))
|
||||||
|
|
||||||
|
common_ss.add(tomlpp)
|
||||||
|
common_ss.add(genconfig)
|
||||||
|
|
||||||
subdir('softmmu')
|
subdir('softmmu')
|
||||||
|
|
||||||
common_ss.add(capstone)
|
common_ss.add(capstone)
|
||||||
|
|
37
softmmu/vl.c
37
softmmu/vl.c
|
@ -1970,9 +1970,7 @@ static void qemu_create_late_backends(void)
|
||||||
net_init_clients(&error_fatal);
|
net_init_clients(&error_fatal);
|
||||||
|
|
||||||
#ifdef XBOX
|
#ifdef XBOX
|
||||||
int xemu_net_enabled;
|
if (g_config.net.enable) {
|
||||||
xemu_settings_get_bool(XEMU_SETTINGS_NETWORK_ENABLED, &xemu_net_enabled);
|
|
||||||
if (xemu_net_enabled) {
|
|
||||||
xemu_net_enable();
|
xemu_net_enable();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2801,8 +2799,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
fake_argv[fake_argc++] = strdup("-machine");
|
fake_argv[fake_argc++] = strdup("-machine");
|
||||||
|
|
||||||
char *bootrom_arg = NULL;
|
char *bootrom_arg = NULL;
|
||||||
const char *bootrom_path;
|
const char *bootrom_path = g_config.sys.files.bootrom_path;
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_BOOTROM_PATH, &bootrom_path);
|
|
||||||
|
|
||||||
if (strlen(bootrom_path) > 0) {
|
if (strlen(bootrom_path) > 0) {
|
||||||
int bootrom_size = get_image_size(bootrom_path);
|
int bootrom_size = get_image_size(bootrom_path);
|
||||||
|
@ -2828,12 +2825,9 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int short_animation;
|
|
||||||
xemu_settings_get_bool(XEMU_SETTINGS_SYSTEM_SHORTANIM, &short_animation);
|
|
||||||
|
|
||||||
fake_argv[fake_argc++] = g_strdup_printf("xbox%s%s%s",
|
fake_argv[fake_argc++] = g_strdup_printf("xbox%s%s%s",
|
||||||
(bootrom_arg != NULL) ? bootrom_arg : "",
|
(bootrom_arg != NULL) ? bootrom_arg : "",
|
||||||
short_animation ? ",short-animation=on" : "",
|
g_config.general.misc.skip_boot_anim ? ",short-animation=on" : "",
|
||||||
",kernel-irqchip=off"
|
",kernel-irqchip=off"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2841,8 +2835,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
g_free(bootrom_arg);
|
g_free(bootrom_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *eeprom_path;
|
const char *eeprom_path = g_config.sys.files.eeprom_path;
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_EEPROM_PATH, &eeprom_path);
|
|
||||||
|
|
||||||
// Sanity check EEPROM file
|
// Sanity check EEPROM file
|
||||||
if (strlen(eeprom_path) > 0) {
|
if (strlen(eeprom_path) > 0) {
|
||||||
|
@ -2875,8 +2868,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
if (strlen(eeprom_path) == 0) {
|
if (strlen(eeprom_path) == 0) {
|
||||||
eeprom_path = xemu_settings_get_default_eeprom_path();
|
eeprom_path = xemu_settings_get_default_eeprom_path();
|
||||||
if (xbox_eeprom_generate(eeprom_path, XBOX_EEPROM_VERSION_R1)) {
|
if (xbox_eeprom_generate(eeprom_path, XBOX_EEPROM_VERSION_R1)) {
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_EEPROM_PATH, eeprom_path);
|
xemu_settings_set_string(&g_config.sys.files.eeprom_path, eeprom_path);
|
||||||
xemu_settings_save();
|
|
||||||
fake_argv[fake_argc++] = strdup("-device");
|
fake_argv[fake_argc++] = strdup("-device");
|
||||||
char *escaped_eeprom_path = strdup_double_commas(eeprom_path);
|
char *escaped_eeprom_path = strdup_double_commas(eeprom_path);
|
||||||
fake_argv[fake_argc++] = g_strdup_printf("smbus-storage,file=%s",
|
fake_argv[fake_argc++] = g_strdup_printf("smbus-storage,file=%s",
|
||||||
|
@ -2889,29 +2881,26 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *flash_path;
|
const char *flashrom_path = g_config.sys.files.flashrom_path;
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_FLASH_PATH, &flash_path);
|
|
||||||
autostart = 0; // Do not auto-start the machine without a valid BIOS file
|
autostart = 0; // Do not auto-start the machine without a valid BIOS file
|
||||||
if (first_boot) {
|
if (first_boot) {
|
||||||
// Don't display an error if this is the first boot. Give user a chance
|
// Don't display an error if this is the first boot. Give user a chance
|
||||||
// to configure the path.
|
// to configure the path.
|
||||||
} else if (xemu_check_file(flash_path)) {
|
} else if (xemu_check_file(flashrom_path)) {
|
||||||
char *msg = g_strdup_printf("Failed to open flash file '%s'. Please check machine settings.", flash_path);
|
char *msg = g_strdup_printf("Failed to open flash file '%s'. Please check machine settings.", flashrom_path);
|
||||||
xemu_queue_error_message(msg);
|
xemu_queue_error_message(msg);
|
||||||
g_free(msg);
|
g_free(msg);
|
||||||
} else {
|
} else {
|
||||||
fake_argv[fake_argc++] = strdup("-bios");
|
fake_argv[fake_argc++] = strdup("-bios");
|
||||||
fake_argv[fake_argc++] = strdup(flash_path);
|
fake_argv[fake_argc++] = strdup(flashrom_path);
|
||||||
autostart = 1;
|
autostart = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mem;
|
int mem = ((int)g_config.sys.mem_limit + 1) * 64;
|
||||||
xemu_settings_get_int(XEMU_SETTINGS_SYSTEM_MEMORY, &mem);
|
|
||||||
fake_argv[fake_argc++] = strdup("-m");
|
fake_argv[fake_argc++] = strdup("-m");
|
||||||
fake_argv[fake_argc++] = g_strdup_printf("%d", mem);
|
fake_argv[fake_argc++] = g_strdup_printf("%d", mem);
|
||||||
|
|
||||||
const char *hdd_path;
|
const char *hdd_path = g_config.sys.files.hdd_path;
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_HDD_PATH, &hdd_path);
|
|
||||||
if (strlen(hdd_path) > 0) {
|
if (strlen(hdd_path) > 0) {
|
||||||
if (xemu_check_file(hdd_path)) {
|
if (xemu_check_file(hdd_path)) {
|
||||||
char *msg = g_strdup_printf("Failed to open hard disk image file '%s'. Please check machine settings.", hdd_path);
|
char *msg = g_strdup_printf("Failed to open hard disk image file '%s'. Please check machine settings.", hdd_path);
|
||||||
|
@ -2927,9 +2916,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *dvd_path = "";
|
const char *dvd_path = g_config.sys.files.dvd_path;
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_DVD_PATH, &dvd_path);
|
|
||||||
|
|
||||||
// Allow overriding the dvd path from command line
|
// Allow overriding the dvd path from command line
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
if (argv[i] && strcmp(argv[i], "-dvd_path") == 0) {
|
if (argv[i] && strcmp(argv[i], "-dvd_path") == 0) {
|
||||||
|
|
|
@ -9046,7 +9046,7 @@ void tcg_x86_init(void)
|
||||||
offsetof(CPUX86State, fpstt), "fpstt");
|
offsetof(CPUX86State, fpstt), "fpstt");
|
||||||
|
|
||||||
#if defined(XBOX) && defined(__x86_64__)
|
#if defined(XBOX) && defined(__x86_64__)
|
||||||
xemu_settings_get_bool(XEMU_SETTINGS_SYSTEM_HARD_FPU, &g_use_hard_fpu);
|
g_use_hard_fpu = g_config.perf.hard_fpu;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ xemu_ss.add(files(
|
||||||
'xemu-input.c',
|
'xemu-input.c',
|
||||||
'xemu-monitor.c',
|
'xemu-monitor.c',
|
||||||
'xemu-net.c',
|
'xemu-net.c',
|
||||||
'xemu-settings.c',
|
'xemu-settings.cc',
|
||||||
'xemu-shaders.c',
|
'xemu-shaders.c',
|
||||||
'xemu-hud.cc',
|
'xemu-hud.cc',
|
||||||
'xemu-reporting.cc',
|
'xemu-reporting.cc',
|
||||||
|
|
199
ui/xemu-hud.cc
199
ui/xemu-hud.cc
|
@ -632,15 +632,10 @@ private:
|
||||||
bool dirty;
|
bool dirty;
|
||||||
bool pending_restart;
|
bool pending_restart;
|
||||||
|
|
||||||
char flash_path[MAX_STRING_LEN];
|
char flashrom_path[MAX_STRING_LEN];
|
||||||
char bootrom_path[MAX_STRING_LEN];
|
char bootrom_path[MAX_STRING_LEN];
|
||||||
char hdd_path[MAX_STRING_LEN];
|
char hdd_path[MAX_STRING_LEN];
|
||||||
char eeprom_path[MAX_STRING_LEN];
|
char eeprom_path[MAX_STRING_LEN];
|
||||||
int memory_idx;
|
|
||||||
bool short_animation;
|
|
||||||
#if defined(_WIN32)
|
|
||||||
bool check_for_update;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SettingsWindow()
|
SettingsWindow()
|
||||||
|
@ -649,12 +644,10 @@ public:
|
||||||
dirty = false;
|
dirty = false;
|
||||||
pending_restart = false;
|
pending_restart = false;
|
||||||
|
|
||||||
flash_path[0] = '\0';
|
flashrom_path[0] = '\0';
|
||||||
bootrom_path[0] = '\0';
|
bootrom_path[0] = '\0';
|
||||||
hdd_path[0] = '\0';
|
hdd_path[0] = '\0';
|
||||||
eeprom_path[0] = '\0';
|
eeprom_path[0] = '\0';
|
||||||
memory_idx = 0;
|
|
||||||
short_animation = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~SettingsWindow()
|
~SettingsWindow()
|
||||||
|
@ -663,57 +656,20 @@ public:
|
||||||
|
|
||||||
void Load()
|
void Load()
|
||||||
{
|
{
|
||||||
const char *tmp;
|
strncpy(flashrom_path, g_config.sys.files.flashrom_path, sizeof(flashrom_path)-1);
|
||||||
int tmp_int;
|
strncpy(bootrom_path, g_config.sys.files.bootrom_path, sizeof(bootrom_path)-1);
|
||||||
size_t len;
|
strncpy(hdd_path, g_config.sys.files.hdd_path, sizeof(hdd_path)-1);
|
||||||
|
strncpy(eeprom_path, g_config.sys.files.eeprom_path, sizeof(eeprom_path)-1);
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_FLASH_PATH, &tmp);
|
|
||||||
len = strlen(tmp);
|
|
||||||
assert(len < MAX_STRING_LEN);
|
|
||||||
strncpy(flash_path, tmp, sizeof(flash_path));
|
|
||||||
|
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_BOOTROM_PATH, &tmp);
|
|
||||||
len = strlen(tmp);
|
|
||||||
assert(len < MAX_STRING_LEN);
|
|
||||||
strncpy(bootrom_path, tmp, sizeof(bootrom_path));
|
|
||||||
|
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_HDD_PATH, &tmp);
|
|
||||||
len = strlen(tmp);
|
|
||||||
assert(len < MAX_STRING_LEN);
|
|
||||||
strncpy(hdd_path, tmp, sizeof(hdd_path));
|
|
||||||
|
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_EEPROM_PATH, &tmp);
|
|
||||||
len = strlen(tmp);
|
|
||||||
assert(len < MAX_STRING_LEN);
|
|
||||||
strncpy(eeprom_path, tmp, sizeof(eeprom_path));
|
|
||||||
|
|
||||||
xemu_settings_get_int(XEMU_SETTINGS_SYSTEM_MEMORY, &tmp_int);
|
|
||||||
memory_idx = (tmp_int-64)/64;
|
|
||||||
|
|
||||||
xemu_settings_get_bool(XEMU_SETTINGS_SYSTEM_SHORTANIM, &tmp_int);
|
|
||||||
short_animation = !!tmp_int;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
xemu_settings_get_bool(XEMU_SETTINGS_MISC_CHECK_FOR_UPDATE, &tmp_int);
|
|
||||||
check_for_update = !!tmp_int;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dirty = false;
|
dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Save()
|
void Save()
|
||||||
{
|
{
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_FLASH_PATH, flash_path);
|
xemu_settings_set_string(&g_config.sys.files.flashrom_path, flashrom_path);
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_BOOTROM_PATH, bootrom_path);
|
xemu_settings_set_string(&g_config.sys.files.bootrom_path, bootrom_path);
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_HDD_PATH, hdd_path);
|
xemu_settings_set_string(&g_config.sys.files.hdd_path, hdd_path);
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_EEPROM_PATH, eeprom_path);
|
xemu_settings_set_string(&g_config.sys.files.eeprom_path, eeprom_path);
|
||||||
xemu_settings_set_int(XEMU_SETTINGS_SYSTEM_MEMORY, 64+memory_idx*64);
|
xemu_queue_notification("Settings saved. Restart to apply updates.");
|
||||||
xemu_settings_set_bool(XEMU_SETTINGS_SYSTEM_SHORTANIM, short_animation);
|
|
||||||
#if defined(_WIN32)
|
|
||||||
xemu_settings_set_bool(XEMU_SETTINGS_MISC_CHECK_FOR_UPDATE, check_for_update);
|
|
||||||
#endif
|
|
||||||
xemu_settings_save();
|
|
||||||
xemu_queue_notification("Settings saved! Restart to apply updates.");
|
|
||||||
pending_restart = true;
|
pending_restart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,7 +715,7 @@ public:
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
float picker_width = ImGui::GetColumnWidth()-120*g_ui_scale;
|
float picker_width = ImGui::GetColumnWidth()-120*g_ui_scale;
|
||||||
ImGui::SetNextItemWidth(picker_width);
|
ImGui::SetNextItemWidth(picker_width);
|
||||||
FilePicker("###Flash", flash_path, sizeof(flash_path), rom_file_filters);
|
FilePicker("###Flash", flashrom_path, sizeof(flashrom_path), rom_file_filters);
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
|
|
||||||
ImGui::Text("MCPX Boot ROM File");
|
ImGui::Text("MCPX Boot ROM File");
|
||||||
|
@ -783,24 +739,18 @@ public:
|
||||||
ImGui::Text("System Memory");
|
ImGui::Text("System Memory");
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetColumnWidth()*0.5);
|
ImGui::SetNextItemWidth(ImGui::GetColumnWidth()*0.5);
|
||||||
if (ImGui::Combo("###mem", &memory_idx, "64 MiB\0" "128 MiB\0")) {
|
ImGui::Combo("###mem", &g_config.sys.mem_limit, "64 MiB\0" "128 MiB\0");
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(0,0));
|
ImGui::Dummy(ImVec2(0,0));
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
if (ImGui::Checkbox("Skip startup animation", &short_animation)) {
|
ImGui::Checkbox("Skip startup animation", &g_config.general.misc.skip_boot_anim);
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
ImGui::Dummy(ImVec2(0,0));
|
ImGui::Dummy(ImVec2(0,0));
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
if (ImGui::Checkbox("Check for updates on startup", &check_for_update)) {
|
ImGui::Checkbox("Check for updates on startup", &g_config.general.updates.check);
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -943,14 +893,11 @@ class NetworkInterfaceManager
|
||||||
public:
|
public:
|
||||||
std::vector<std::unique_ptr<NetworkInterface>> ifaces;
|
std::vector<std::unique_ptr<NetworkInterface>> ifaces;
|
||||||
NetworkInterface *current_iface;
|
NetworkInterface *current_iface;
|
||||||
const char *current_iface_name;
|
|
||||||
bool failed_to_load_lib;
|
bool failed_to_load_lib;
|
||||||
|
|
||||||
NetworkInterfaceManager()
|
NetworkInterfaceManager()
|
||||||
{
|
{
|
||||||
current_iface = NULL;
|
current_iface = NULL;
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_NETWORK_PCAP_INTERFACE,
|
|
||||||
¤t_iface_name);
|
|
||||||
failed_to_load_lib = false;
|
failed_to_load_lib = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,7 +934,7 @@ public:
|
||||||
#else
|
#else
|
||||||
ifaces.emplace_back(new NetworkInterface(iter));
|
ifaces.emplace_back(new NetworkInterface(iter));
|
||||||
#endif
|
#endif
|
||||||
if (!strcmp(current_iface_name, iter->name)) {
|
if (!strcmp(g_config.net.pcap.netif, iter->name)) {
|
||||||
current_iface = ifaces.back().get();
|
current_iface = ifaces.back().get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -998,10 +945,8 @@ public:
|
||||||
void select(NetworkInterface &iface)
|
void select(NetworkInterface &iface)
|
||||||
{
|
{
|
||||||
current_iface = &iface;
|
current_iface = &iface;
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_NETWORK_PCAP_INTERFACE,
|
xemu_settings_set_string(&g_config.net.pcap.netif,
|
||||||
iface.pcap_name.c_str());
|
iface.pcap_name.c_str());
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_NETWORK_PCAP_INTERFACE,
|
|
||||||
¤t_iface_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_current(NetworkInterface &iface)
|
bool is_current(NetworkInterface &iface)
|
||||||
|
@ -1015,7 +960,6 @@ class NetworkWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool is_open;
|
bool is_open;
|
||||||
int backend;
|
|
||||||
char remote_addr[64];
|
char remote_addr[64];
|
||||||
char local_addr[64];
|
char local_addr[64];
|
||||||
std::unique_ptr<NetworkInterfaceManager> iface_mgr;
|
std::unique_ptr<NetworkInterfaceManager> iface_mgr;
|
||||||
|
@ -1040,12 +984,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::IsWindowAppearing()) {
|
if (ImGui::IsWindowAppearing()) {
|
||||||
const char *tmp;
|
strncpy(remote_addr, g_config.net.udp.remote_addr, sizeof(remote_addr)-1);
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_NETWORK_REMOTE_ADDR, &tmp);
|
strncpy(local_addr, g_config.net.udp.bind_addr, sizeof(local_addr)-1);
|
||||||
strncpy(remote_addr, tmp, sizeof(remote_addr)-1);
|
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_NETWORK_LOCAL_ADDR, &tmp);
|
|
||||||
strncpy(local_addr, tmp, sizeof(local_addr)-1);
|
|
||||||
xemu_settings_get_enum(XEMU_SETTINGS_NETWORK_BACKEND, &backend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiInputTextFlags flg = 0;
|
ImGuiInputTextFlags flg = 0;
|
||||||
|
@ -1061,23 +1001,20 @@ public:
|
||||||
ImGui::SameLine(); HelpMarker("The network backend which the emulated NIC interacts with");
|
ImGui::SameLine(); HelpMarker("The network backend which the emulated NIC interacts with");
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f);
|
if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f);
|
||||||
int temp_backend = backend; // Temporary to make backend combo read-only (FIXME: surely there's a nicer way)
|
int temp_backend = g_config.net.backend; // Temporary to make backend combo read-only (FIXME: surely there's a nicer way)
|
||||||
if (ImGui::Combo("##backend", is_enabled ? &temp_backend : &backend, "NAT\0UDP Tunnel\0Bridged Adapter\0") && !is_enabled) {
|
ImGui::Combo("##backend", is_enabled ? &temp_backend : &g_config.net.backend, "NAT\0UDP Tunnel\0Bridged Adapter\0");
|
||||||
xemu_settings_set_enum(XEMU_SETTINGS_NETWORK_BACKEND, backend);
|
|
||||||
xemu_settings_save();
|
|
||||||
}
|
|
||||||
if (is_enabled) ImGui::PopStyleVar();
|
if (is_enabled) ImGui::PopStyleVar();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (backend == XEMU_NET_BACKEND_USER) {
|
if (g_config.net.backend == CONFIG_NET_BACKEND_NAT) {
|
||||||
HelpMarker("User-mode TCP/IP stack with network address translation");
|
HelpMarker("User-mode TCP/IP stack with network address translation");
|
||||||
} else if (backend == XEMU_NET_BACKEND_SOCKET_UDP) {
|
} else if (g_config.net.backend == CONFIG_NET_BACKEND_UDP) {
|
||||||
HelpMarker("Tunnels link-layer traffic to a remote host via UDP");
|
HelpMarker("Tunnels link-layer traffic to a remote host via UDP");
|
||||||
} else if (backend == XEMU_NET_BACKEND_PCAP) {
|
} else if (g_config.net.backend == CONFIG_NET_BACKEND_PCAP) {
|
||||||
HelpMarker("Bridges with a host network interface");
|
HelpMarker("Bridges with a host network interface");
|
||||||
}
|
}
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
|
|
||||||
if (backend == XEMU_NET_BACKEND_SOCKET_UDP) {
|
if (g_config.net.backend == CONFIG_NET_BACKEND_UDP) {
|
||||||
ImGui::Text("Remote Host");
|
ImGui::Text("Remote Host");
|
||||||
ImGui::SameLine(); HelpMarker("The remote <IP address>:<Port> to forward packets to (e.g. 1.2.3.4:9368)");
|
ImGui::SameLine(); HelpMarker("The remote <IP address>:<Port> to forward packets to (e.g. 1.2.3.4:9368)");
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
|
@ -1096,7 +1033,7 @@ public:
|
||||||
ImGui::InputText("###local_host", local_addr, sizeof(local_addr), flg);
|
ImGui::InputText("###local_host", local_addr, sizeof(local_addr), flg);
|
||||||
if (is_enabled) ImGui::PopStyleVar();
|
if (is_enabled) ImGui::PopStyleVar();
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
} else if (backend == XEMU_NET_BACKEND_PCAP) {
|
} else if (g_config.net.backend == CONFIG_NET_BACKEND_PCAP) {
|
||||||
static bool should_refresh = true;
|
static bool should_refresh = true;
|
||||||
if (iface_mgr.get() == nullptr) {
|
if (iface_mgr.get() == nullptr) {
|
||||||
iface_mgr.reset(new NetworkInterfaceManager());
|
iface_mgr.reset(new NetworkInterfaceManager());
|
||||||
|
@ -1128,7 +1065,7 @@ public:
|
||||||
const char *selected_display_name = (
|
const char *selected_display_name = (
|
||||||
iface_mgr->current_iface
|
iface_mgr->current_iface
|
||||||
? iface_mgr->current_iface->friendlyname.c_str()
|
? iface_mgr->current_iface->friendlyname.c_str()
|
||||||
: iface_mgr->current_iface_name
|
: g_config.net.pcap.netif
|
||||||
);
|
);
|
||||||
if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f);
|
if (is_enabled) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f);
|
||||||
if (ImGui::BeginCombo("###network_iface", selected_display_name)) {
|
if (ImGui::BeginCombo("###network_iface", selected_display_name)) {
|
||||||
|
@ -1169,14 +1106,12 @@ public:
|
||||||
ImGui::SetItemDefaultFocus();
|
ImGui::SetItemDefaultFocus();
|
||||||
if (ImGui::Button(is_enabled ? "Disable" : "Enable", ImVec2(120*g_ui_scale, 0))) {
|
if (ImGui::Button(is_enabled ? "Disable" : "Enable", ImVec2(120*g_ui_scale, 0))) {
|
||||||
if (!is_enabled) {
|
if (!is_enabled) {
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_NETWORK_REMOTE_ADDR, remote_addr);
|
xemu_settings_set_string(&g_config.net.udp.remote_addr, remote_addr);
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_NETWORK_LOCAL_ADDR, local_addr);
|
xemu_settings_set_string(&g_config.net.udp.bind_addr, local_addr);
|
||||||
xemu_net_enable();
|
xemu_net_enable();
|
||||||
} else {
|
} else {
|
||||||
xemu_net_disable();
|
xemu_net_disable();
|
||||||
}
|
}
|
||||||
xemu_settings_set_bool(XEMU_SETTINGS_NETWORK_ENABLED, xemu_net_is_enabled());
|
|
||||||
xemu_settings_save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
@ -1290,10 +1225,7 @@ public:
|
||||||
description[0] = '\x00';
|
description[0] = '\x00';
|
||||||
report.compat_comments = description;
|
report.compat_comments = description;
|
||||||
|
|
||||||
const char *tmp;
|
strncpy(token_buf, g_config.general.user_token, sizeof(token_buf)-1);
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_MISC_USER_TOKEN, &tmp);
|
|
||||||
assert(strlen(tmp) < sizeof(token_buf));
|
|
||||||
strncpy(token_buf, tmp, sizeof(token_buf));
|
|
||||||
report.token = token_buf;
|
report.token = token_buf;
|
||||||
|
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
@ -1411,12 +1343,8 @@ public:
|
||||||
did_send = true;
|
did_send = true;
|
||||||
send_result = report.Send();
|
send_result = report.Send();
|
||||||
if (send_result) {
|
if (send_result) {
|
||||||
// Close window on success
|
|
||||||
is_open = false;
|
is_open = false;
|
||||||
|
xemu_settings_set_string(&g_config.general.user_token, token_buf);
|
||||||
// Save user token if it was used
|
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_MISC_USER_TOKEN, token_buf);
|
|
||||||
xemu_settings_save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1772,37 +1700,6 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_auto_update_selection(bool preference)
|
|
||||||
{
|
|
||||||
xemu_settings_set_bool(XEMU_SETTINGS_MISC_CHECK_FOR_UPDATE, preference);
|
|
||||||
xemu_settings_save();
|
|
||||||
should_prompt_auto_update_selection = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void prompt_auto_update_selection()
|
|
||||||
{
|
|
||||||
ImGui::Text("Would you like xemu to check for updates on startup?");
|
|
||||||
ImGui::SetNextItemWidth(-1.0f);
|
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(0.0f, ImGui::GetStyle().WindowPadding.y));
|
|
||||||
ImGui::Separator();
|
|
||||||
ImGui::Dummy(ImVec2(0.0f, ImGui::GetStyle().WindowPadding.y));
|
|
||||||
|
|
||||||
float w = (130)*g_ui_scale;
|
|
||||||
float bw = w + (10)*g_ui_scale;
|
|
||||||
ImGui::SetCursorPosX(ImGui::GetWindowWidth()-2*bw);
|
|
||||||
|
|
||||||
if (ImGui::Button("No", ImVec2(w, 0))) {
|
|
||||||
save_auto_update_selection(false);
|
|
||||||
is_open = false;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Yes", ImVec2(w, 0))) {
|
|
||||||
save_auto_update_selection(true);
|
|
||||||
check_for_updates_and_prompt_if_available();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_for_updates_and_prompt_if_available()
|
void check_for_updates_and_prompt_if_available()
|
||||||
{
|
{
|
||||||
updater.check_for_update([this](){
|
updater.check_for_update([this](){
|
||||||
|
@ -1819,12 +1716,6 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_prompt_auto_update_selection) {
|
|
||||||
prompt_auto_update_selection();
|
|
||||||
ImGui::End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::IsWindowAppearing() && !updater.is_update_available()) {
|
if (ImGui::IsWindowAppearing() && !updater.is_update_available()) {
|
||||||
updater.check_for_update();
|
updater.check_for_update();
|
||||||
}
|
}
|
||||||
|
@ -1993,23 +1884,19 @@ static bool is_shortcut_key_pressed(int scancode)
|
||||||
|
|
||||||
static void action_eject_disc(void)
|
static void action_eject_disc(void)
|
||||||
{
|
{
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_DVD_PATH, "");
|
xemu_settings_set_string(&g_config.sys.files.dvd_path, "");
|
||||||
xemu_settings_save();
|
|
||||||
xemu_eject_disc();
|
xemu_eject_disc();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void action_load_disc(void)
|
static void action_load_disc(void)
|
||||||
{
|
{
|
||||||
const char *iso_file_filters = ".iso Files\0*.iso\0All Files\0*.*\0";
|
const char *iso_file_filters = ".iso Files\0*.iso\0All Files\0*.*\0";
|
||||||
const char *current_disc_path;
|
const char *new_disc_path = paused_file_open(NOC_FILE_DIALOG_OPEN, iso_file_filters, g_config.sys.files.dvd_path, NULL);
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_DVD_PATH, ¤t_disc_path);
|
|
||||||
const char *new_disc_path = paused_file_open(NOC_FILE_DIALOG_OPEN, iso_file_filters, current_disc_path, NULL);
|
|
||||||
if (new_disc_path == NULL) {
|
if (new_disc_path == NULL) {
|
||||||
/* Cancelled */
|
/* Cancelled */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_DVD_PATH, new_disc_path);
|
xemu_settings_set_string(&g_config.sys.files.dvd_path, new_disc_path);
|
||||||
xemu_settings_save();
|
|
||||||
xemu_load_disc(new_disc_path);
|
xemu_load_disc(new_disc_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2120,8 +2007,7 @@ static void ShowMainMenu()
|
||||||
if (ui_scale_combo > 1) ui_scale_combo = 1;
|
if (ui_scale_combo > 1) ui_scale_combo = 1;
|
||||||
if (ImGui::Combo("UI Scale", &ui_scale_combo, "1x\0" "2x\0")) {
|
if (ImGui::Combo("UI Scale", &ui_scale_combo, "1x\0" "2x\0")) {
|
||||||
g_ui_scale = ui_scale_combo + 1;
|
g_ui_scale = ui_scale_combo + 1;
|
||||||
xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_UI_SCALE, g_ui_scale);
|
g_config.display.ui.scale = g_ui_scale;
|
||||||
xemu_settings_save();
|
|
||||||
g_trigger_style_update = true;
|
g_trigger_style_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2131,9 +2017,7 @@ static void ShowMainMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Combo(
|
if (ImGui::Combo(
|
||||||
"Scaling Mode", &scaling_mode, "Center\0Scale\0Scale (Widescreen 16:9)\0Scale (4:3)\0Stretch\0")) {
|
"Scaling Mode", &g_config.display.ui.fit, "Center\0Scale\0Scale (Widescreen 16:9)\0Scale (4:3)\0Stretch\0")) {
|
||||||
xemu_settings_set_enum(XEMU_SETTINGS_DISPLAY_SCALE, scaling_mode);
|
|
||||||
xemu_settings_save();
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine(); HelpMarker("Controls how the rendered content should be scaled into the window");
|
ImGui::SameLine(); HelpMarker("Controls how the rendered content should be scaled into the window");
|
||||||
if (ImGui::MenuItem("Fullscreen", SHORTCUT_MENU_TEXT(Alt+F), xemu_is_fullscreen(), true)) {
|
if (ImGui::MenuItem("Fullscreen", SHORTCUT_MENU_TEXT(Alt+F), xemu_is_fullscreen(), true)) {
|
||||||
|
@ -2289,8 +2173,7 @@ void xemu_hud_init(SDL_Window* window, void* sdl_gl_context)
|
||||||
|
|
||||||
first_boot_window.is_open = xemu_settings_did_fail_to_load();
|
first_boot_window.is_open = xemu_settings_did_fail_to_load();
|
||||||
|
|
||||||
int ui_scale_int = 1;
|
int ui_scale_int = g_config.display.ui.scale;
|
||||||
xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_UI_SCALE, &ui_scale_int);
|
|
||||||
if (ui_scale_int < 1) ui_scale_int = 1;
|
if (ui_scale_int < 1) ui_scale_int = 1;
|
||||||
g_ui_scale = ui_scale_int;
|
g_ui_scale = ui_scale_int;
|
||||||
|
|
||||||
|
@ -2299,13 +2182,7 @@ void xemu_hud_init(SDL_Window* window, void* sdl_gl_context)
|
||||||
ImPlot::CreateContext();
|
ImPlot::CreateContext();
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
int should_check_for_update;
|
if (g_config.general.updates.check) {
|
||||||
xemu_settings_get_bool(XEMU_SETTINGS_MISC_CHECK_FOR_UPDATE, &should_check_for_update);
|
|
||||||
if (should_check_for_update == -1) {
|
|
||||||
update_window.should_prompt_auto_update_selection =
|
|
||||||
update_window.is_open = !xemu_settings_did_fail_to_load();
|
|
||||||
|
|
||||||
} else if (should_check_for_update) {
|
|
||||||
update_window.check_for_updates_and_prompt_if_available();
|
update_window.check_for_updates_and_prompt_if_available();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -87,11 +87,11 @@ ControllerStateList available_controllers =
|
||||||
ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL };
|
ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL };
|
||||||
int test_mode;
|
int test_mode;
|
||||||
|
|
||||||
static const enum xemu_settings_keys port_index_to_settings_key_map[] = {
|
static const char **port_index_to_settings_key_map[] = {
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_1_GUID,
|
&g_config.input.bindings.port1,
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_2_GUID,
|
&g_config.input.bindings.port2,
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_3_GUID,
|
&g_config.input.bindings.port3,
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_4_GUID,
|
&g_config.input.bindings.port4,
|
||||||
};
|
};
|
||||||
|
|
||||||
void xemu_input_init(void)
|
void xemu_input_init(void)
|
||||||
|
@ -141,9 +141,7 @@ int xemu_input_get_controller_default_bind_port(ControllerState *state, int star
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = start; i < 4; i++) {
|
for (int i = start; i < 4; i++) {
|
||||||
const char *this_port;
|
if (strcmp(guid, *port_index_to_settings_key_map[i]) == 0) {
|
||||||
xemu_settings_get_string(port_index_to_settings_key_map[i], &this_port);
|
|
||||||
if (strcmp(guid, this_port) == 0) {
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,7 +432,6 @@ void xemu_input_bind(int index, ControllerState *state, int save)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xemu_settings_set_string(port_index_to_settings_key_map[index], guid_buf);
|
xemu_settings_set_string(port_index_to_settings_key_map[index], guid_buf);
|
||||||
xemu_settings_save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind new controller
|
// Bind new controller
|
||||||
|
|
|
@ -50,36 +50,28 @@ void xemu_net_enable(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int backend;
|
|
||||||
const char *local_addr, *remote_addr;
|
|
||||||
xemu_settings_get_enum(XEMU_SETTINGS_NETWORK_BACKEND, &backend);
|
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_NETWORK_REMOTE_ADDR, &remote_addr);
|
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_NETWORK_LOCAL_ADDR, &local_addr);
|
|
||||||
|
|
||||||
// Create the netdev
|
// Create the netdev
|
||||||
QDict *qdict;
|
QDict *qdict;
|
||||||
if (backend == XEMU_NET_BACKEND_USER) {
|
if (g_config.net.backend == CONFIG_NET_BACKEND_NAT) {
|
||||||
qdict = qdict_new();
|
qdict = qdict_new();
|
||||||
qdict_put_str(qdict, "id", id);
|
qdict_put_str(qdict, "id", id);
|
||||||
qdict_put_str(qdict, "type", "user");
|
qdict_put_str(qdict, "type", "user");
|
||||||
} else if (backend == XEMU_NET_BACKEND_SOCKET_UDP) {
|
} else if (g_config.net.backend == CONFIG_NET_BACKEND_UDP) {
|
||||||
qdict = qdict_new();
|
qdict = qdict_new();
|
||||||
qdict_put_str(qdict, "id", id);
|
qdict_put_str(qdict, "id", id);
|
||||||
qdict_put_str(qdict, "type", "socket");
|
qdict_put_str(qdict, "type", "socket");
|
||||||
qdict_put_str(qdict, "udp", remote_addr);
|
qdict_put_str(qdict, "udp", g_config.net.udp.remote_addr);
|
||||||
qdict_put_str(qdict, "localaddr", local_addr);
|
qdict_put_str(qdict, "localaddr", g_config.net.udp.bind_addr);
|
||||||
} else if (backend == XEMU_NET_BACKEND_PCAP) {
|
} else if (g_config.net.backend == CONFIG_NET_BACKEND_PCAP) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (pcap_load_library()) {
|
if (pcap_load_library()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const char *iface;
|
|
||||||
xemu_settings_get_string(XEMU_SETTINGS_NETWORK_PCAP_INTERFACE, &iface);
|
|
||||||
qdict = qdict_new();
|
qdict = qdict_new();
|
||||||
qdict_put_str(qdict, "id", id);
|
qdict_put_str(qdict, "id", id);
|
||||||
qdict_put_str(qdict, "type", "pcap");
|
qdict_put_str(qdict, "type", "pcap");
|
||||||
qdict_put_str(qdict, "ifname", iface);
|
qdict_put_str(qdict, "ifname", g_config.net.pcap.netif);
|
||||||
} else {
|
} else {
|
||||||
// Unsupported backend type
|
// Unsupported backend type
|
||||||
return;
|
return;
|
||||||
|
@ -111,6 +103,8 @@ void xemu_net_enable(void)
|
||||||
xemu_queue_error_message(error_get_pretty(local_err));
|
xemu_queue_error_message(error_get_pretty(local_err));
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_config.net.enable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_netdev(const char *name)
|
static void remove_netdev(const char *name)
|
||||||
|
@ -139,11 +133,13 @@ void xemu_net_disable(void)
|
||||||
{
|
{
|
||||||
remove_netdev(id);
|
remove_netdev(id);
|
||||||
remove_netdev(id_hubport);
|
remove_netdev(id_hubport);
|
||||||
|
g_config.net.enable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xemu_net_is_enabled(void)
|
int xemu_net_is_enabled(void)
|
||||||
{
|
{
|
||||||
NetClientState *nc;
|
NetClientState *nc;
|
||||||
nc = qemu_find_netdev(id);
|
nc = qemu_find_netdev(id);
|
||||||
return (nc != NULL);
|
g_config.net.enable = (nc != NULL);
|
||||||
|
return g_config.net.enable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,441 +0,0 @@
|
||||||
/*
|
|
||||||
* xemu Settings Management
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2021 Matt Borgerson
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <SDL_filesystem.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#include "xemu-settings.h"
|
|
||||||
#include "inih/ini.c" // FIXME
|
|
||||||
|
|
||||||
enum config_types {
|
|
||||||
CONFIG_TYPE_STRING,
|
|
||||||
CONFIG_TYPE_INT,
|
|
||||||
CONFIG_TYPE_BOOL,
|
|
||||||
CONFIG_TYPE_ENUM,
|
|
||||||
CONFIG_TYPE__MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
struct xemu_settings {
|
|
||||||
// [system]
|
|
||||||
char *flash_path;
|
|
||||||
char *bootrom_path;
|
|
||||||
char *hdd_path;
|
|
||||||
char *dvd_path;
|
|
||||||
char *eeprom_path;
|
|
||||||
int memory;
|
|
||||||
int short_animation; // Boolean
|
|
||||||
int hard_fpu; // Boolean
|
|
||||||
|
|
||||||
// [audio]
|
|
||||||
int use_dsp; // Boolean
|
|
||||||
|
|
||||||
// [display]
|
|
||||||
int scale;
|
|
||||||
int ui_scale;
|
|
||||||
int render_scale;
|
|
||||||
int window_width;
|
|
||||||
int window_height;
|
|
||||||
|
|
||||||
// [input]
|
|
||||||
char *controller_1_guid;
|
|
||||||
char *controller_2_guid;
|
|
||||||
char *controller_3_guid;
|
|
||||||
char *controller_4_guid;
|
|
||||||
|
|
||||||
// [network]
|
|
||||||
int net_enabled; // Boolean
|
|
||||||
int net_backend;
|
|
||||||
char *net_local_addr;
|
|
||||||
char *net_remote_addr;
|
|
||||||
char *net_pcap_iface;
|
|
||||||
|
|
||||||
// [misc]
|
|
||||||
char *user_token;
|
|
||||||
int check_for_update; // Boolean
|
|
||||||
};
|
|
||||||
|
|
||||||
struct enum_str_map {
|
|
||||||
int value;
|
|
||||||
const char *str;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct enum_str_map display_scale_map[DISPLAY_SCALE__COUNT+1] = {
|
|
||||||
{ DISPLAY_SCALE_CENTER, "center" },
|
|
||||||
{ DISPLAY_SCALE_SCALE, "scale" },
|
|
||||||
{ DISPLAY_SCALE_WS169, "scale_ws169" },
|
|
||||||
{ DISPLAY_SCALE_FS43, "scale_fs43" },
|
|
||||||
{ DISPLAY_SCALE_STRETCH, "stretch" },
|
|
||||||
{ 0, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct enum_str_map net_backend_map[XEMU_NET_BACKEND__COUNT+1] = {
|
|
||||||
{ XEMU_NET_BACKEND_USER, "user" },
|
|
||||||
{ XEMU_NET_BACKEND_SOCKET_UDP, "udp" },
|
|
||||||
{ XEMU_NET_BACKEND_PCAP, "pcap" },
|
|
||||||
{ 0, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
struct config_offset_table {
|
|
||||||
enum config_types type;
|
|
||||||
const char *section;
|
|
||||||
const char *name;
|
|
||||||
ptrdiff_t offset;
|
|
||||||
union {
|
|
||||||
const char *default_str;
|
|
||||||
int default_int;
|
|
||||||
int default_bool;
|
|
||||||
};
|
|
||||||
const struct enum_str_map *enum_map;
|
|
||||||
} config_items[XEMU_SETTINGS__COUNT] = {
|
|
||||||
// Please keep organized by section
|
|
||||||
[XEMU_SETTINGS_SYSTEM_FLASH_PATH] = { CONFIG_TYPE_STRING, "system", "flash_path", offsetof(struct xemu_settings, flash_path), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_SYSTEM_BOOTROM_PATH] = { CONFIG_TYPE_STRING, "system", "bootrom_path", offsetof(struct xemu_settings, bootrom_path), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_SYSTEM_HDD_PATH] = { CONFIG_TYPE_STRING, "system", "hdd_path", offsetof(struct xemu_settings, hdd_path), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_SYSTEM_DVD_PATH] = { CONFIG_TYPE_STRING, "system", "dvd_path", offsetof(struct xemu_settings, dvd_path), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_SYSTEM_EEPROM_PATH] = { CONFIG_TYPE_STRING, "system", "eeprom_path", offsetof(struct xemu_settings, eeprom_path), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_SYSTEM_MEMORY] = { CONFIG_TYPE_INT, "system", "memory", offsetof(struct xemu_settings, memory), { .default_int = 64 } },
|
|
||||||
[XEMU_SETTINGS_SYSTEM_SHORTANIM] = { CONFIG_TYPE_BOOL, "system", "shortanim", offsetof(struct xemu_settings, short_animation), { .default_bool = 0 } },
|
|
||||||
[XEMU_SETTINGS_SYSTEM_HARD_FPU] = { CONFIG_TYPE_BOOL, "system", "hard_fpu", offsetof(struct xemu_settings, hard_fpu), { .default_bool = 1 } },
|
|
||||||
|
|
||||||
[XEMU_SETTINGS_AUDIO_USE_DSP] = { CONFIG_TYPE_BOOL, "audio", "use_dsp", offsetof(struct xemu_settings, use_dsp), { .default_bool = 0 } },
|
|
||||||
|
|
||||||
[XEMU_SETTINGS_DISPLAY_SCALE] = { CONFIG_TYPE_ENUM, "display", "scale", offsetof(struct xemu_settings, scale), { .default_int = DISPLAY_SCALE_SCALE }, display_scale_map },
|
|
||||||
[XEMU_SETTINGS_DISPLAY_UI_SCALE] = { CONFIG_TYPE_INT, "display", "ui_scale", offsetof(struct xemu_settings, ui_scale), { .default_int = 1 } },
|
|
||||||
[XEMU_SETTINGS_DISPLAY_RENDER_SCALE] = { CONFIG_TYPE_INT, "display", "render_scale", offsetof(struct xemu_settings, render_scale), { .default_int = 1 } },
|
|
||||||
[XEMU_SETTINGS_DISPLAY_WINDOW_WIDTH] = { CONFIG_TYPE_INT, "display", "window_width", offsetof(struct xemu_settings, window_width), { .default_int = 1280 } },
|
|
||||||
[XEMU_SETTINGS_DISPLAY_WINDOW_HEIGHT] = { CONFIG_TYPE_INT, "display", "window_height", offsetof(struct xemu_settings, window_height), { .default_int = 960 } },
|
|
||||||
|
|
||||||
[XEMU_SETTINGS_INPUT_CONTROLLER_1_GUID] = { CONFIG_TYPE_STRING, "input", "controller_1_guid", offsetof(struct xemu_settings, controller_1_guid), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_INPUT_CONTROLLER_2_GUID] = { CONFIG_TYPE_STRING, "input", "controller_2_guid", offsetof(struct xemu_settings, controller_2_guid), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_INPUT_CONTROLLER_3_GUID] = { CONFIG_TYPE_STRING, "input", "controller_3_guid", offsetof(struct xemu_settings, controller_3_guid), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_INPUT_CONTROLLER_4_GUID] = { CONFIG_TYPE_STRING, "input", "controller_4_guid", offsetof(struct xemu_settings, controller_4_guid), { .default_str = "" } },
|
|
||||||
|
|
||||||
[XEMU_SETTINGS_NETWORK_ENABLED] = { CONFIG_TYPE_BOOL, "network", "enabled", offsetof(struct xemu_settings, net_enabled), { .default_bool = 0 } },
|
|
||||||
[XEMU_SETTINGS_NETWORK_BACKEND] = { CONFIG_TYPE_ENUM, "network", "backend", offsetof(struct xemu_settings, net_backend), { .default_int = XEMU_NET_BACKEND_USER }, net_backend_map },
|
|
||||||
[XEMU_SETTINGS_NETWORK_LOCAL_ADDR] = { CONFIG_TYPE_STRING, "network", "local_addr", offsetof(struct xemu_settings, net_local_addr), { .default_str = "0.0.0.0:9368" } },
|
|
||||||
[XEMU_SETTINGS_NETWORK_REMOTE_ADDR] = { CONFIG_TYPE_STRING, "network", "remote_addr", offsetof(struct xemu_settings, net_remote_addr), { .default_str = "1.2.3.4:9368" } },
|
|
||||||
[XEMU_SETTINGS_NETWORK_PCAP_INTERFACE] = { CONFIG_TYPE_STRING, "network", "pcap_iface", offsetof(struct xemu_settings, net_pcap_iface), { .default_str = "" } },
|
|
||||||
|
|
||||||
[XEMU_SETTINGS_MISC_USER_TOKEN] = { CONFIG_TYPE_STRING, "misc", "user_token", offsetof(struct xemu_settings, user_token), { .default_str = "" } },
|
|
||||||
[XEMU_SETTINGS_MISC_CHECK_FOR_UPDATE] = { CONFIG_TYPE_BOOL, "misc", "check_for_update", offsetof(struct xemu_settings, check_for_update), { .default_bool = -1 } },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *settings_path;
|
|
||||||
static const char *filename = "xemu.ini";
|
|
||||||
static struct xemu_settings *g_settings;
|
|
||||||
static int settings_failed_to_load = 0;
|
|
||||||
|
|
||||||
static void *xemu_settings_get_field(enum xemu_settings_keys key, enum config_types type)
|
|
||||||
{
|
|
||||||
assert(key < XEMU_SETTINGS__COUNT);
|
|
||||||
assert(config_items[key].type == type);
|
|
||||||
return (void *)((char*)g_settings + config_items[key].offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_set_string(enum xemu_settings_keys key, const char *str)
|
|
||||||
{
|
|
||||||
char **field_str = (char **)xemu_settings_get_field(key, CONFIG_TYPE_STRING);
|
|
||||||
if (*field_str) {
|
|
||||||
free(*field_str);
|
|
||||||
}
|
|
||||||
*field_str = strdup(str);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_get_string(enum xemu_settings_keys key, const char **str)
|
|
||||||
{
|
|
||||||
*str = *(const char **)xemu_settings_get_field(key, CONFIG_TYPE_STRING);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_set_int(enum xemu_settings_keys key, int val)
|
|
||||||
{
|
|
||||||
int *field_int = (int *)xemu_settings_get_field(key, CONFIG_TYPE_INT);
|
|
||||||
*field_int = val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_get_int(enum xemu_settings_keys key, int *val)
|
|
||||||
{
|
|
||||||
*val = *(int *)xemu_settings_get_field(key, CONFIG_TYPE_INT);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_set_bool(enum xemu_settings_keys key, int val)
|
|
||||||
{
|
|
||||||
int *field_int = (int *)xemu_settings_get_field(key, CONFIG_TYPE_BOOL);
|
|
||||||
*field_int = val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_get_bool(enum xemu_settings_keys key, int *val)
|
|
||||||
{
|
|
||||||
*val = *(int *)xemu_settings_get_field(key, CONFIG_TYPE_BOOL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_set_enum(enum xemu_settings_keys key, int val)
|
|
||||||
{
|
|
||||||
int *field_int = (int *)xemu_settings_get_field(key, CONFIG_TYPE_ENUM);
|
|
||||||
*field_int = val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_get_enum(enum xemu_settings_keys key, int *val)
|
|
||||||
{
|
|
||||||
*val = *(int *)xemu_settings_get_field(key, CONFIG_TYPE_ENUM);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool xemu_settings_detect_portable_mode(void)
|
|
||||||
{
|
|
||||||
bool val = false;
|
|
||||||
char *portable_path = g_strdup_printf("%s%s", SDL_GetBasePath(), filename);
|
|
||||||
FILE *tmpfile;
|
|
||||||
if ((tmpfile = qemu_fopen(portable_path, "r"))) {
|
|
||||||
fclose(tmpfile);
|
|
||||||
val = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(portable_path);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void xemu_settings_set_path(const char *path)
|
|
||||||
{
|
|
||||||
assert(path != NULL);
|
|
||||||
assert(settings_path == NULL);
|
|
||||||
settings_path = path;
|
|
||||||
fprintf(stderr, "%s: config path: %s\n", __func__, settings_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *xemu_settings_get_path(void)
|
|
||||||
{
|
|
||||||
if (settings_path != NULL) {
|
|
||||||
return settings_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *base = xemu_settings_detect_portable_mode()
|
|
||||||
? SDL_GetBasePath()
|
|
||||||
: SDL_GetPrefPath("xemu", "xemu");
|
|
||||||
assert(base != NULL);
|
|
||||||
settings_path = g_strdup_printf("%s%s", base, filename);
|
|
||||||
SDL_free(base);
|
|
||||||
fprintf(stderr, "%s: config path: %s\n", __func__, settings_path);
|
|
||||||
return settings_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *xemu_settings_get_default_eeprom_path(void)
|
|
||||||
{
|
|
||||||
static char *eeprom_path = NULL;
|
|
||||||
if (eeprom_path != NULL) {
|
|
||||||
return eeprom_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *base = xemu_settings_detect_portable_mode()
|
|
||||||
? SDL_GetBasePath()
|
|
||||||
: SDL_GetPrefPath("xemu", "xemu");
|
|
||||||
assert(base != NULL);
|
|
||||||
eeprom_path = g_strdup_printf("%s%s", base, "eeprom.bin");
|
|
||||||
SDL_free(base);
|
|
||||||
return eeprom_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int xemu_enum_str_to_int(const struct enum_str_map *map, const char *str, int *value)
|
|
||||||
{
|
|
||||||
for (int i = 0; map[i].str != NULL; i++) {
|
|
||||||
if (strcmp(map[i].str, str) == 0) {
|
|
||||||
*value = map[i].value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int xemu_enum_int_to_str(const struct enum_str_map *map, int value, const char **str)
|
|
||||||
{
|
|
||||||
for (int i = 0; map[i].str != NULL; i++) {
|
|
||||||
if (map[i].value == value) {
|
|
||||||
*str = map[i].str;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum xemu_settings_keys xemu_key_from_name(const char *section, const char *name)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < XEMU_SETTINGS__COUNT; i++) {
|
|
||||||
if ((strcmp(section, config_items[i].section) == 0) &&
|
|
||||||
(strcmp(name, config_items[i].name) == 0)) {
|
|
||||||
return i; // Found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return XEMU_SETTINGS_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int config_parse_callback(void *user, const char *section, const char *name, const char *value)
|
|
||||||
{
|
|
||||||
// struct xemu_settings *settings = (struct xemu_settings *)user;
|
|
||||||
fprintf(stderr, "%s: [%s] %s = %s\n", __func__, section, name, value);
|
|
||||||
|
|
||||||
enum xemu_settings_keys key = xemu_key_from_name(section, name);
|
|
||||||
|
|
||||||
if (key == XEMU_SETTINGS_INVALID) {
|
|
||||||
fprintf(stderr, "Ignoring unknown key %s.%s\n", section, name);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_items[key].type == CONFIG_TYPE_STRING) {
|
|
||||||
xemu_settings_set_string(key, value);
|
|
||||||
} else if (config_items[key].type == CONFIG_TYPE_INT) {
|
|
||||||
int int_val;
|
|
||||||
int converted = sscanf(value, "%d", &int_val);
|
|
||||||
if (converted != 1) {
|
|
||||||
fprintf(stderr, "Error parsing %s.%s as integer. Got '%s'\n", section, name, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
xemu_settings_set_int(key, int_val);
|
|
||||||
} else if (config_items[key].type == CONFIG_TYPE_BOOL) {
|
|
||||||
int int_val;
|
|
||||||
if (strcmp(value, "true") == 0) {
|
|
||||||
int_val = 1;
|
|
||||||
} else if (strcmp(value, "false") == 0) {
|
|
||||||
int_val = 0;
|
|
||||||
} else if (strcmp(value, "") == 0) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error parsing %s.%s as boolean. Got '%s'\n", section, name, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
xemu_settings_set_bool(key, int_val);
|
|
||||||
} else if (config_items[key].type == CONFIG_TYPE_ENUM) {
|
|
||||||
int int_val;
|
|
||||||
int status = xemu_enum_str_to_int(config_items[key].enum_map, value, &int_val);
|
|
||||||
if (status != 0) {
|
|
||||||
fprintf(stderr, "Error parsing %s.%s as enum. Got '%s'\n", section, name, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
xemu_settings_set_enum(key, int_val);
|
|
||||||
} else {
|
|
||||||
// Unimplemented
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xemu_settings_init_default(struct xemu_settings *settings)
|
|
||||||
{
|
|
||||||
memset(settings, 0, sizeof(struct xemu_settings));
|
|
||||||
for (int i = 0; i < XEMU_SETTINGS__COUNT; i++) {
|
|
||||||
if (config_items[i].type == CONFIG_TYPE_STRING) {
|
|
||||||
xemu_settings_set_string(i, config_items[i].default_str);
|
|
||||||
} else if (config_items[i].type == CONFIG_TYPE_INT) {
|
|
||||||
xemu_settings_set_int(i, config_items[i].default_int);
|
|
||||||
} else if (config_items[i].type == CONFIG_TYPE_BOOL) {
|
|
||||||
xemu_settings_set_bool(i, config_items[i].default_bool);
|
|
||||||
} else if (config_items[i].type == CONFIG_TYPE_ENUM) {
|
|
||||||
xemu_settings_set_enum(i, config_items[i].default_int);
|
|
||||||
} else {
|
|
||||||
// Unimplemented
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int xemu_settings_did_fail_to_load(void)
|
|
||||||
{
|
|
||||||
return settings_failed_to_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
void xemu_settings_load(void)
|
|
||||||
{
|
|
||||||
// Should only call this once, at startup
|
|
||||||
assert(g_settings == NULL);
|
|
||||||
|
|
||||||
g_settings = malloc(sizeof(struct xemu_settings));
|
|
||||||
assert(g_settings != NULL);
|
|
||||||
memset(g_settings, 0, sizeof(struct xemu_settings));
|
|
||||||
xemu_settings_init_default(g_settings);
|
|
||||||
|
|
||||||
// Parse configuration file
|
|
||||||
int status = ini_parse(xemu_settings_get_path(),
|
|
||||||
config_parse_callback,
|
|
||||||
g_settings);
|
|
||||||
if (status < 0) {
|
|
||||||
// fprintf(stderr, "Failed to load config! Using defaults\n");
|
|
||||||
settings_failed_to_load = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void xemu_settings_save(void)
|
|
||||||
{
|
|
||||||
FILE *fd = qemu_fopen(xemu_settings_get_path(), "wb");
|
|
||||||
assert(fd != NULL);
|
|
||||||
|
|
||||||
const char *last_section = "";
|
|
||||||
for (int i = 0; i < XEMU_SETTINGS__COUNT; i++) {
|
|
||||||
if (strcmp(last_section, config_items[i].section)) {
|
|
||||||
fprintf(fd, "[%s]\n", config_items[i].section);
|
|
||||||
last_section = config_items[i].section;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fd, "%s = ", config_items[i].name);
|
|
||||||
if (config_items[i].type == CONFIG_TYPE_STRING) {
|
|
||||||
const char *v;
|
|
||||||
xemu_settings_get_string(i, &v);
|
|
||||||
fprintf(fd, "%s\n", v);
|
|
||||||
} else if (config_items[i].type == CONFIG_TYPE_INT) {
|
|
||||||
int v;
|
|
||||||
xemu_settings_get_int(i, &v);
|
|
||||||
fprintf(fd, "%d\n", v);
|
|
||||||
} else if (config_items[i].type == CONFIG_TYPE_BOOL) {
|
|
||||||
int v;
|
|
||||||
xemu_settings_get_bool(i, &v);
|
|
||||||
if (v == 0 || v == 1) {
|
|
||||||
fprintf(fd, "%s\n", !!(v) ? "true" : "false");
|
|
||||||
} else {
|
|
||||||
// Other values are considered unset
|
|
||||||
}
|
|
||||||
} else if (config_items[i].type == CONFIG_TYPE_ENUM) {
|
|
||||||
int v;
|
|
||||||
xemu_settings_get_enum(i, &v);
|
|
||||||
const char *str = "";
|
|
||||||
xemu_enum_int_to_str(config_items[i].enum_map, v, &str);
|
|
||||||
fprintf(fd, "%s\n", str);
|
|
||||||
} else {
|
|
||||||
// Unimplemented
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fd);
|
|
||||||
}
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* xemu Settings Management
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020-2021 Matt Borgerson
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <SDL_filesystem.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <toml.hpp>
|
||||||
|
#include <cnode.h>
|
||||||
|
|
||||||
|
#include "xemu-settings.h"
|
||||||
|
#define DEFINE_CONFIG_TREE
|
||||||
|
#include "xemu-config.h"
|
||||||
|
|
||||||
|
struct config g_config;
|
||||||
|
static bool settings_failed_to_load = true;
|
||||||
|
static const char *filename = "xemu.ini";
|
||||||
|
static const char *settings_path;
|
||||||
|
|
||||||
|
static bool xemu_settings_detect_portable_mode(void)
|
||||||
|
{
|
||||||
|
bool val = false;
|
||||||
|
char *portable_path = g_strdup_printf("%s%s", SDL_GetBasePath(), filename);
|
||||||
|
FILE *tmpfile;
|
||||||
|
if ((tmpfile = qemu_fopen(portable_path, "r"))) {
|
||||||
|
fclose(tmpfile);
|
||||||
|
val = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(portable_path);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xemu_settings_set_path(const char *path)
|
||||||
|
{
|
||||||
|
assert(path != NULL);
|
||||||
|
assert(settings_path == NULL);
|
||||||
|
settings_path = path;
|
||||||
|
fprintf(stderr, "%s: config path: %s\n", __func__, settings_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *xemu_settings_get_path(void)
|
||||||
|
{
|
||||||
|
if (settings_path != NULL) {
|
||||||
|
return settings_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *base = xemu_settings_detect_portable_mode()
|
||||||
|
? SDL_GetBasePath()
|
||||||
|
: SDL_GetPrefPath("xemu", "xemu");
|
||||||
|
assert(base != NULL);
|
||||||
|
settings_path = g_strdup_printf("%s%s", base, filename);
|
||||||
|
SDL_free(base);
|
||||||
|
fprintf(stderr, "%s: config path: %s\n", __func__, settings_path);
|
||||||
|
return settings_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *xemu_settings_get_default_eeprom_path(void)
|
||||||
|
{
|
||||||
|
static char *eeprom_path = NULL;
|
||||||
|
if (eeprom_path != NULL) {
|
||||||
|
return eeprom_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *base = xemu_settings_detect_portable_mode()
|
||||||
|
? SDL_GetBasePath()
|
||||||
|
: SDL_GetPrefPath("xemu", "xemu");
|
||||||
|
assert(base != NULL);
|
||||||
|
eeprom_path = g_strdup_printf("%s%s", base, "eeprom.bin");
|
||||||
|
SDL_free(base);
|
||||||
|
return eeprom_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xemu_settings_load(void)
|
||||||
|
{
|
||||||
|
FILE *fd;
|
||||||
|
size_t file_size = 0;
|
||||||
|
char *file_buf = NULL;
|
||||||
|
const char *settings_path = xemu_settings_get_path();
|
||||||
|
|
||||||
|
fd = qemu_fopen(settings_path, "rb");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "Failed to open settings path %s for reading\n", settings_path);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fd, 0, SEEK_END);
|
||||||
|
file_size = ftell(fd);
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
file_buf = (char *)malloc(file_size + 1);
|
||||||
|
if (fread(file_buf, file_size, 1, fd) != 1) {
|
||||||
|
fprintf(stderr, "Failed to read settings\n");
|
||||||
|
fclose(fd);
|
||||||
|
fd = NULL;
|
||||||
|
free(file_buf);
|
||||||
|
file_buf = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
file_buf[file_size] = '\x00';
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto tbl = toml::parse(file_buf);
|
||||||
|
config_tree.update_from_table(tbl);
|
||||||
|
settings_failed_to_load = false;
|
||||||
|
}
|
||||||
|
catch (const toml::parse_error& err)
|
||||||
|
{
|
||||||
|
std::cerr
|
||||||
|
<< "Error parsing file '" << *err.source().path
|
||||||
|
<< "':\n" << err.description()
|
||||||
|
<< "\n (" << err.source().begin << ")\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
config_tree.store_to_struct(&g_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xemu_settings_did_fail_to_load(void)
|
||||||
|
{
|
||||||
|
return settings_failed_to_load;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xemu_settings_save(void)
|
||||||
|
{
|
||||||
|
FILE *fd = qemu_fopen(xemu_settings_get_path(), "wb");
|
||||||
|
assert(fd != NULL);
|
||||||
|
config_tree.update_from_struct(&g_config);
|
||||||
|
fprintf(fd, "%s", config_tree.generate_delta_toml().c_str());
|
||||||
|
fclose(fd);
|
||||||
|
}
|
|
@ -28,57 +28,12 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum xemu_settings_keys {
|
#include "xemu-config.h"
|
||||||
XEMU_SETTINGS_SYSTEM_FLASH_PATH,
|
|
||||||
XEMU_SETTINGS_SYSTEM_BOOTROM_PATH,
|
|
||||||
XEMU_SETTINGS_SYSTEM_HDD_PATH,
|
|
||||||
XEMU_SETTINGS_SYSTEM_EEPROM_PATH,
|
|
||||||
XEMU_SETTINGS_SYSTEM_DVD_PATH,
|
|
||||||
XEMU_SETTINGS_SYSTEM_MEMORY,
|
|
||||||
XEMU_SETTINGS_SYSTEM_SHORTANIM,
|
|
||||||
XEMU_SETTINGS_SYSTEM_HARD_FPU,
|
|
||||||
XEMU_SETTINGS_AUDIO_USE_DSP,
|
|
||||||
XEMU_SETTINGS_DISPLAY_SCALE,
|
|
||||||
XEMU_SETTINGS_DISPLAY_UI_SCALE,
|
|
||||||
XEMU_SETTINGS_DISPLAY_RENDER_SCALE,
|
|
||||||
XEMU_SETTINGS_DISPLAY_WINDOW_WIDTH,
|
|
||||||
XEMU_SETTINGS_DISPLAY_WINDOW_HEIGHT,
|
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_1_GUID,
|
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_2_GUID,
|
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_3_GUID,
|
|
||||||
XEMU_SETTINGS_INPUT_CONTROLLER_4_GUID,
|
|
||||||
XEMU_SETTINGS_NETWORK_ENABLED,
|
|
||||||
XEMU_SETTINGS_NETWORK_BACKEND,
|
|
||||||
XEMU_SETTINGS_NETWORK_LOCAL_ADDR,
|
|
||||||
XEMU_SETTINGS_NETWORK_REMOTE_ADDR,
|
|
||||||
XEMU_SETTINGS_NETWORK_PCAP_INTERFACE,
|
|
||||||
XEMU_SETTINGS_MISC_USER_TOKEN,
|
|
||||||
XEMU_SETTINGS_MISC_CHECK_FOR_UPDATE,
|
|
||||||
XEMU_SETTINGS__COUNT,
|
|
||||||
XEMU_SETTINGS_INVALID = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DISPLAY_SCALE
|
extern struct config g_config;
|
||||||
{
|
|
||||||
DISPLAY_SCALE_CENTER,
|
|
||||||
DISPLAY_SCALE_SCALE,
|
|
||||||
DISPLAY_SCALE_WS169,
|
|
||||||
DISPLAY_SCALE_FS43,
|
|
||||||
DISPLAY_SCALE_STRETCH,
|
|
||||||
DISPLAY_SCALE__COUNT,
|
|
||||||
DISPLAY_SCALE_INVALID = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum xemu_net_backend {
|
|
||||||
XEMU_NET_BACKEND_USER,
|
|
||||||
XEMU_NET_BACKEND_SOCKET_UDP,
|
|
||||||
XEMU_NET_BACKEND_PCAP,
|
|
||||||
XEMU_NET_BACKEND__COUNT,
|
|
||||||
XEMU_NET_BACKEND_INVALID = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determine whether settings were loaded or not
|
// Determine whether settings were loaded or not
|
||||||
int xemu_settings_did_fail_to_load(void);
|
bool xemu_settings_did_fail_to_load(void);
|
||||||
|
|
||||||
// Override the default config file paths
|
// Override the default config file paths
|
||||||
void xemu_settings_set_path(const char *path);
|
void xemu_settings_set_path(const char *path);
|
||||||
|
@ -95,15 +50,14 @@ void xemu_settings_load(void);
|
||||||
// Save config file to disk
|
// Save config file to disk
|
||||||
void xemu_settings_save(void);
|
void xemu_settings_save(void);
|
||||||
|
|
||||||
// Config item setters/getters
|
#include <stdlib.h>
|
||||||
int xemu_settings_set_string(enum xemu_settings_keys key, const char *str);
|
#include <string.h>
|
||||||
int xemu_settings_get_string(enum xemu_settings_keys key, const char **str);
|
|
||||||
int xemu_settings_set_int(enum xemu_settings_keys key, int val);
|
static inline void xemu_settings_set_string(const char **str, const char *new_str)
|
||||||
int xemu_settings_get_int(enum xemu_settings_keys key, int *val);
|
{
|
||||||
int xemu_settings_set_bool(enum xemu_settings_keys key, int val);
|
free((char*)*str);
|
||||||
int xemu_settings_get_bool(enum xemu_settings_keys key, int *val);
|
*str = strdup(new_str);
|
||||||
int xemu_settings_set_enum(enum xemu_settings_keys key, int val);
|
}
|
||||||
int xemu_settings_get_enum(enum xemu_settings_keys key, int *val);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
20
ui/xemu.c
20
ui/xemu.c
|
@ -108,7 +108,6 @@ static SDL_Cursor *guest_sprite;
|
||||||
static Notifier mouse_mode_notifier;
|
static Notifier mouse_mode_notifier;
|
||||||
static SDL_Window *m_window;
|
static SDL_Window *m_window;
|
||||||
static SDL_GLContext m_context;
|
static SDL_GLContext m_context;
|
||||||
int scaling_mode = 1;
|
|
||||||
struct decal_shader *blit;
|
struct decal_shader *blit;
|
||||||
|
|
||||||
static QemuSemaphore display_init_sem;
|
static QemuSemaphore display_init_sem;
|
||||||
|
@ -593,8 +592,8 @@ static void handle_windowevent(SDL_Event *ev)
|
||||||
dpy_set_ui_info(scon->dcl.con, &info);
|
dpy_set_ui_info(scon->dcl.con, &info);
|
||||||
|
|
||||||
if (!gui_fullscreen) {
|
if (!gui_fullscreen) {
|
||||||
xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_WINDOW_WIDTH, ev->window.data1);
|
g_config.display.window.last_width = ev->window.data1;
|
||||||
xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_WINDOW_HEIGHT, ev->window.data2);
|
g_config.display.window.last_height = ev->window.data2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sdl2_redraw(scon);
|
sdl2_redraw(scon);
|
||||||
|
@ -860,9 +859,8 @@ static void sdl2_display_very_early_init(DisplayOptions *o)
|
||||||
SDL_DisplayMode disp_mode;
|
SDL_DisplayMode disp_mode;
|
||||||
SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(m_window), &disp_mode);
|
SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(m_window), &disp_mode);
|
||||||
|
|
||||||
int win_w, win_h;
|
int win_w = g_config.display.window.last_width,
|
||||||
xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_WINDOW_WIDTH, &win_w);
|
win_h = g_config.display.window.last_height;
|
||||||
xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_WINDOW_HEIGHT, &win_h);
|
|
||||||
|
|
||||||
if (win_w > 0 && win_h > 0) {
|
if (win_w > 0 && win_h > 0) {
|
||||||
if (disp_mode.w >= win_w && disp_mode.h >= win_h) {
|
if (disp_mode.w >= win_w && disp_mode.h >= win_h) {
|
||||||
|
@ -938,8 +936,6 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
|
||||||
assert(o->type == DISPLAY_TYPE_XEMU);
|
assert(o->type == DISPLAY_TYPE_XEMU);
|
||||||
SDL_GL_MakeCurrent(m_window, m_context);
|
SDL_GL_MakeCurrent(m_window, m_context);
|
||||||
|
|
||||||
xemu_settings_get_enum(XEMU_SETTINGS_DISPLAY_SCALE, &scaling_mode);
|
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
SDL_VERSION(&info.version);
|
SDL_VERSION(&info.version);
|
||||||
|
|
||||||
|
@ -1177,20 +1173,20 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
|
||||||
|
|
||||||
// Calculate scaling factors
|
// Calculate scaling factors
|
||||||
float scale[2];
|
float scale[2];
|
||||||
if (scaling_mode == DISPLAY_SCALE_STRETCH) {
|
if (g_config.display.ui.fit == CONFIG_DISPLAY_UI_FIT_STRETCH) {
|
||||||
// Stretch to fit
|
// Stretch to fit
|
||||||
scale[0] = 1.0;
|
scale[0] = 1.0;
|
||||||
scale[1] = 1.0;
|
scale[1] = 1.0;
|
||||||
} else if (scaling_mode == DISPLAY_SCALE_CENTER) {
|
} else if (g_config.display.ui.fit == CONFIG_DISPLAY_UI_FIT_CENTER) {
|
||||||
// Centered
|
// Centered
|
||||||
scale[0] = (float)tw/(float)ww;
|
scale[0] = (float)tw/(float)ww;
|
||||||
scale[1] = (float)th/(float)wh;
|
scale[1] = (float)th/(float)wh;
|
||||||
} else {
|
} else {
|
||||||
float t_ratio;
|
float t_ratio;
|
||||||
if (scaling_mode == DISPLAY_SCALE_WS169) {
|
if (g_config.display.ui.fit == CONFIG_DISPLAY_UI_FIT_SCALE_16_9) {
|
||||||
// Scale to fit window using a fixed 16:9 aspect ratio
|
// Scale to fit window using a fixed 16:9 aspect ratio
|
||||||
t_ratio = 16.0f/9.0f;
|
t_ratio = 16.0f/9.0f;
|
||||||
} else if (scaling_mode == DISPLAY_SCALE_FS43) {
|
} else if (g_config.display.ui.fit == CONFIG_DISPLAY_UI_FIT_SCALE_4_3) {
|
||||||
t_ratio = 4.0f/3.0f;
|
t_ratio = 4.0f/3.0f;
|
||||||
} else {
|
} else {
|
||||||
// Scale to fit, preserving framebuffer aspect ratio
|
// Scale to fit, preserving framebuffer aspect ratio
|
||||||
|
|
Loading…
Reference in New Issue