From d14cdbc7bacde909bc3c862c06f41512442ea805 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Fri, 22 Apr 2022 01:32:28 -0700 Subject: [PATCH] config: Migrate to genconfig system --- config_spec.yml | 68 ++++++ genconfig | 2 +- hw/xbox/mcpx/apu.c | 4 +- hw/xbox/nv2a/pgraph.c | 7 +- meson.build | 18 ++ softmmu/vl.c | 37 +-- target/i386/tcg/translate.c | 2 +- ui/meson.build | 2 +- ui/xemu-hud.cc | 199 ++++------------ ui/xemu-input.c | 15 +- ui/xemu-net.c | 26 +-- ui/xemu-settings.c | 441 ------------------------------------ ui/xemu-settings.cc | 152 +++++++++++++ ui/xemu-settings.h | 68 +----- ui/xemu.c | 20 +- 15 files changed, 330 insertions(+), 731 deletions(-) create mode 100644 config_spec.yml delete mode 100644 ui/xemu-settings.c create mode 100644 ui/xemu-settings.cc diff --git a/config_spec.yml b/config_spec.yml new file mode 100644 index 0000000000..c5e5960ce8 --- /dev/null +++ b/config_spec.yml @@ -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 diff --git a/genconfig b/genconfig index 218d283f65..8220e87489 160000 --- a/genconfig +++ b/genconfig @@ -1 +1 @@ -Subproject commit 218d283f65b96232518c252c792a9ff197aca995 +Subproject commit 8220e8748922ddd9bba4cbacd608601586c9a4bb diff --git a/hw/xbox/mcpx/apu.c b/hw/xbox/mcpx/apu.c index b936f57296..1344793337 100644 --- a/hw/xbox/mcpx/apu.c +++ b/hw/xbox/mcpx/apu.c @@ -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 * use the full audio pipeline or not. */ - int use_dsp; - xemu_settings_get_bool(XEMU_SETTINGS_AUDIO_USE_DSP, &use_dsp); - if (use_dsp) { + if (g_config.audio.use_dsp) { d->mon = MCPX_APU_DEBUG_MON_GP_OR_EP; d->gp.realtime = true; d->ep.realtime = true; diff --git a/hw/xbox/nv2a/pgraph.c b/hw/xbox/nv2a/pgraph.c index b69baad186..94de42a5fb 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -3707,9 +3707,7 @@ void nv2a_set_surface_scale_factor(unsigned int scale) { NV2AState *d = g_nv2a; - xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_RENDER_SCALE, - scale < 1 ? 1 : scale); - xemu_settings_save(); + g_config.display.quality.surface_scale = scale < 1 ? 1 : scale; 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) { - int factor; - xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_RENDER_SCALE, &factor); + int factor = g_config.display.quality.surface_scale; d->pgraph.surface_scale_factor = factor < 1 ? 1 : factor; } diff --git a/meson.build b/meson.build index 73d294cb6b..a32910ca92 100644 --- a/meson.build +++ b/meson.build @@ -837,6 +837,9 @@ if 'CONFIG_OPENGL' in config_host link_args: config_host['OPENGL_LIBS'].split()) 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(), link_args: config_host['XEMU_GTK_LIBS'].split()) @@ -2056,8 +2059,20 @@ qemu_version = custom_target('qemu-version.h', build_by_default: 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 += xemu_version +genh += xemu_config hxdep = [] 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(tomlpp) +common_ss.add(genconfig) + subdir('softmmu') common_ss.add(capstone) diff --git a/softmmu/vl.c b/softmmu/vl.c index 64b0330d57..053e9418e6 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1970,9 +1970,7 @@ static void qemu_create_late_backends(void) net_init_clients(&error_fatal); #ifdef XBOX - int xemu_net_enabled; - xemu_settings_get_bool(XEMU_SETTINGS_NETWORK_ENABLED, &xemu_net_enabled); - if (xemu_net_enabled) { + if (g_config.net.enable) { xemu_net_enable(); } #endif @@ -2801,8 +2799,7 @@ void qemu_init(int argc, char **argv, char **envp) fake_argv[fake_argc++] = strdup("-machine"); char *bootrom_arg = NULL; - const char *bootrom_path; - xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_BOOTROM_PATH, &bootrom_path); + const char *bootrom_path = g_config.sys.files.bootrom_path; if (strlen(bootrom_path) > 0) { 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", (bootrom_arg != NULL) ? bootrom_arg : "", - short_animation ? ",short-animation=on" : "", + g_config.general.misc.skip_boot_anim ? ",short-animation=on" : "", ",kernel-irqchip=off" ); @@ -2841,8 +2835,7 @@ void qemu_init(int argc, char **argv, char **envp) g_free(bootrom_arg); } - const char *eeprom_path; - xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_EEPROM_PATH, &eeprom_path); + const char *eeprom_path = g_config.sys.files.eeprom_path; // Sanity check EEPROM file if (strlen(eeprom_path) > 0) { @@ -2875,8 +2868,7 @@ void qemu_init(int argc, char **argv, char **envp) if (strlen(eeprom_path) == 0) { eeprom_path = xemu_settings_get_default_eeprom_path(); if (xbox_eeprom_generate(eeprom_path, XBOX_EEPROM_VERSION_R1)) { - xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_EEPROM_PATH, eeprom_path); - xemu_settings_save(); + xemu_settings_set_string(&g_config.sys.files.eeprom_path, eeprom_path); fake_argv[fake_argc++] = strdup("-device"); char *escaped_eeprom_path = strdup_double_commas(eeprom_path); 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; - xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_FLASH_PATH, &flash_path); + const char *flashrom_path = g_config.sys.files.flashrom_path; autostart = 0; // Do not auto-start the machine without a valid BIOS file if (first_boot) { // Don't display an error if this is the first boot. Give user a chance // to configure the path. - } else if (xemu_check_file(flash_path)) { - char *msg = g_strdup_printf("Failed to open flash file '%s'. Please check machine settings.", flash_path); + } else if (xemu_check_file(flashrom_path)) { + char *msg = g_strdup_printf("Failed to open flash file '%s'. Please check machine settings.", flashrom_path); xemu_queue_error_message(msg); g_free(msg); } else { fake_argv[fake_argc++] = strdup("-bios"); - fake_argv[fake_argc++] = strdup(flash_path); + fake_argv[fake_argc++] = strdup(flashrom_path); autostart = 1; } - int mem; - xemu_settings_get_int(XEMU_SETTINGS_SYSTEM_MEMORY, &mem); + int mem = ((int)g_config.sys.mem_limit + 1) * 64; fake_argv[fake_argc++] = strdup("-m"); fake_argv[fake_argc++] = g_strdup_printf("%d", mem); - const char *hdd_path; - xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_HDD_PATH, &hdd_path); + const char *hdd_path = g_config.sys.files.hdd_path; if (strlen(hdd_path) > 0) { 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); @@ -2927,9 +2916,7 @@ void qemu_init(int argc, char **argv, char **envp) } } - const char *dvd_path = ""; - xemu_settings_get_string(XEMU_SETTINGS_SYSTEM_DVD_PATH, &dvd_path); - + const char *dvd_path = g_config.sys.files.dvd_path; // Allow overriding the dvd path from command line for (int i = 1; i < argc; i++) { if (argv[i] && strcmp(argv[i], "-dvd_path") == 0) { diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 20fb88a564..2359936e74 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -9046,7 +9046,7 @@ void tcg_x86_init(void) offsetof(CPUX86State, fpstt), "fpstt"); #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 } diff --git a/ui/meson.build b/ui/meson.build index ce0153939d..d73512360f 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -47,7 +47,7 @@ xemu_ss.add(files( 'xemu-input.c', 'xemu-monitor.c', 'xemu-net.c', - 'xemu-settings.c', + 'xemu-settings.cc', 'xemu-shaders.c', 'xemu-hud.cc', 'xemu-reporting.cc', diff --git a/ui/xemu-hud.cc b/ui/xemu-hud.cc index 1660cf76e3..18e93b8def 100644 --- a/ui/xemu-hud.cc +++ b/ui/xemu-hud.cc @@ -632,15 +632,10 @@ private: bool dirty; bool pending_restart; - char flash_path[MAX_STRING_LEN]; + char flashrom_path[MAX_STRING_LEN]; char bootrom_path[MAX_STRING_LEN]; char hdd_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: SettingsWindow() @@ -649,12 +644,10 @@ public: dirty = false; pending_restart = false; - flash_path[0] = '\0'; + flashrom_path[0] = '\0'; bootrom_path[0] = '\0'; hdd_path[0] = '\0'; eeprom_path[0] = '\0'; - memory_idx = 0; - short_animation = false; } ~SettingsWindow() @@ -663,57 +656,20 @@ public: void Load() { - const char *tmp; - int tmp_int; - size_t len; - - 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 - + strncpy(flashrom_path, g_config.sys.files.flashrom_path, sizeof(flashrom_path)-1); + strncpy(bootrom_path, g_config.sys.files.bootrom_path, sizeof(bootrom_path)-1); + 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); dirty = false; } void Save() { - xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_FLASH_PATH, flash_path); - xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_BOOTROM_PATH, bootrom_path); - xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_HDD_PATH, hdd_path); - xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_EEPROM_PATH, eeprom_path); - xemu_settings_set_int(XEMU_SETTINGS_SYSTEM_MEMORY, 64+memory_idx*64); - 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."); + xemu_settings_set_string(&g_config.sys.files.flashrom_path, flashrom_path); + xemu_settings_set_string(&g_config.sys.files.bootrom_path, bootrom_path); + xemu_settings_set_string(&g_config.sys.files.hdd_path, hdd_path); + xemu_settings_set_string(&g_config.sys.files.eeprom_path, eeprom_path); + xemu_queue_notification("Settings saved. Restart to apply updates."); pending_restart = true; } @@ -759,7 +715,7 @@ public: ImGui::NextColumn(); float picker_width = ImGui::GetColumnWidth()-120*g_ui_scale; 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::Text("MCPX Boot ROM File"); @@ -783,24 +739,18 @@ public: ImGui::Text("System Memory"); ImGui::NextColumn(); ImGui::SetNextItemWidth(ImGui::GetColumnWidth()*0.5); - if (ImGui::Combo("###mem", &memory_idx, "64 MiB\0" "128 MiB\0")) { - dirty = true; - } + ImGui::Combo("###mem", &g_config.sys.mem_limit, "64 MiB\0" "128 MiB\0"); ImGui::NextColumn(); ImGui::Dummy(ImVec2(0,0)); ImGui::NextColumn(); - if (ImGui::Checkbox("Skip startup animation", &short_animation)) { - dirty = true; - } + ImGui::Checkbox("Skip startup animation", &g_config.general.misc.skip_boot_anim); ImGui::NextColumn(); #if defined(_WIN32) ImGui::Dummy(ImVec2(0,0)); ImGui::NextColumn(); - if (ImGui::Checkbox("Check for updates on startup", &check_for_update)) { - dirty = true; - } + ImGui::Checkbox("Check for updates on startup", &g_config.general.updates.check); ImGui::NextColumn(); #endif @@ -943,14 +893,11 @@ class NetworkInterfaceManager public: std::vector> ifaces; NetworkInterface *current_iface; - const char *current_iface_name; bool failed_to_load_lib; NetworkInterfaceManager() { current_iface = NULL; - xemu_settings_get_string(XEMU_SETTINGS_NETWORK_PCAP_INTERFACE, - ¤t_iface_name); failed_to_load_lib = false; } @@ -987,7 +934,7 @@ public: #else ifaces.emplace_back(new NetworkInterface(iter)); #endif - if (!strcmp(current_iface_name, iter->name)) { + if (!strcmp(g_config.net.pcap.netif, iter->name)) { current_iface = ifaces.back().get(); } } @@ -998,10 +945,8 @@ public: void select(NetworkInterface &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()); - xemu_settings_get_string(XEMU_SETTINGS_NETWORK_PCAP_INTERFACE, - ¤t_iface_name); } bool is_current(NetworkInterface &iface) @@ -1015,7 +960,6 @@ class NetworkWindow { public: bool is_open; - int backend; char remote_addr[64]; char local_addr[64]; std::unique_ptr iface_mgr; @@ -1040,12 +984,8 @@ public: } if (ImGui::IsWindowAppearing()) { - const char *tmp; - xemu_settings_get_string(XEMU_SETTINGS_NETWORK_REMOTE_ADDR, &tmp); - 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); + strncpy(remote_addr, g_config.net.udp.remote_addr, sizeof(remote_addr)-1); + strncpy(local_addr, g_config.net.udp.bind_addr, sizeof(local_addr)-1); } ImGuiInputTextFlags flg = 0; @@ -1061,23 +1001,20 @@ public: ImGui::SameLine(); HelpMarker("The network backend which the emulated NIC interacts with"); ImGui::NextColumn(); 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) - if (ImGui::Combo("##backend", is_enabled ? &temp_backend : &backend, "NAT\0UDP Tunnel\0Bridged Adapter\0") && !is_enabled) { - xemu_settings_set_enum(XEMU_SETTINGS_NETWORK_BACKEND, backend); - xemu_settings_save(); - } + int temp_backend = g_config.net.backend; // Temporary to make backend combo read-only (FIXME: surely there's a nicer way) + ImGui::Combo("##backend", is_enabled ? &temp_backend : &g_config.net.backend, "NAT\0UDP Tunnel\0Bridged Adapter\0"); if (is_enabled) ImGui::PopStyleVar(); 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"); - } 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"); - } else if (backend == XEMU_NET_BACKEND_PCAP) { + } else if (g_config.net.backend == CONFIG_NET_BACKEND_PCAP) { HelpMarker("Bridges with a host network interface"); } ImGui::NextColumn(); - if (backend == XEMU_NET_BACKEND_SOCKET_UDP) { + if (g_config.net.backend == CONFIG_NET_BACKEND_UDP) { ImGui::Text("Remote Host"); ImGui::SameLine(); HelpMarker("The remote : to forward packets to (e.g. 1.2.3.4:9368)"); ImGui::NextColumn(); @@ -1096,7 +1033,7 @@ public: ImGui::InputText("###local_host", local_addr, sizeof(local_addr), flg); if (is_enabled) ImGui::PopStyleVar(); ImGui::NextColumn(); - } else if (backend == XEMU_NET_BACKEND_PCAP) { + } else if (g_config.net.backend == CONFIG_NET_BACKEND_PCAP) { static bool should_refresh = true; if (iface_mgr.get() == nullptr) { iface_mgr.reset(new NetworkInterfaceManager()); @@ -1128,7 +1065,7 @@ public: const char *selected_display_name = ( iface_mgr->current_iface ? 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 (ImGui::BeginCombo("###network_iface", selected_display_name)) { @@ -1169,14 +1106,12 @@ public: ImGui::SetItemDefaultFocus(); if (ImGui::Button(is_enabled ? "Disable" : "Enable", ImVec2(120*g_ui_scale, 0))) { if (!is_enabled) { - xemu_settings_set_string(XEMU_SETTINGS_NETWORK_REMOTE_ADDR, remote_addr); - xemu_settings_set_string(XEMU_SETTINGS_NETWORK_LOCAL_ADDR, local_addr); + xemu_settings_set_string(&g_config.net.udp.remote_addr, remote_addr); + xemu_settings_set_string(&g_config.net.udp.bind_addr, local_addr); xemu_net_enable(); } else { xemu_net_disable(); } - xemu_settings_set_bool(XEMU_SETTINGS_NETWORK_ENABLED, xemu_net_is_enabled()); - xemu_settings_save(); } ImGui::End(); @@ -1290,10 +1225,7 @@ public: description[0] = '\x00'; report.compat_comments = description; - const char *tmp; - xemu_settings_get_string(XEMU_SETTINGS_MISC_USER_TOKEN, &tmp); - assert(strlen(tmp) < sizeof(token_buf)); - strncpy(token_buf, tmp, sizeof(token_buf)); + strncpy(token_buf, g_config.general.user_token, sizeof(token_buf)-1); report.token = token_buf; dirty = true; @@ -1411,12 +1343,8 @@ public: did_send = true; send_result = report.Send(); if (send_result) { - // Close window on success is_open = false; - - // Save user token if it was used - xemu_settings_set_string(XEMU_SETTINGS_MISC_USER_TOKEN, token_buf); - xemu_settings_save(); + xemu_settings_set_string(&g_config.general.user_token, token_buf); } } @@ -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() { updater.check_for_update([this](){ @@ -1819,12 +1716,6 @@ public: return; } - if (should_prompt_auto_update_selection) { - prompt_auto_update_selection(); - ImGui::End(); - return; - } - if (ImGui::IsWindowAppearing() && !updater.is_update_available()) { updater.check_for_update(); } @@ -1993,23 +1884,19 @@ static bool is_shortcut_key_pressed(int scancode) static void action_eject_disc(void) { - xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_DVD_PATH, ""); - xemu_settings_save(); + xemu_settings_set_string(&g_config.sys.files.dvd_path, ""); xemu_eject_disc(); } static void action_load_disc(void) { const char *iso_file_filters = ".iso Files\0*.iso\0All Files\0*.*\0"; - const char *current_disc_path; - 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); + const char *new_disc_path = paused_file_open(NOC_FILE_DIALOG_OPEN, iso_file_filters, g_config.sys.files.dvd_path, NULL); if (new_disc_path == NULL) { /* Cancelled */ return; } - xemu_settings_set_string(XEMU_SETTINGS_SYSTEM_DVD_PATH, new_disc_path); - xemu_settings_save(); + xemu_settings_set_string(&g_config.sys.files.dvd_path, 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 (ImGui::Combo("UI Scale", &ui_scale_combo, "1x\0" "2x\0")) { g_ui_scale = ui_scale_combo + 1; - xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_UI_SCALE, g_ui_scale); - xemu_settings_save(); + g_config.display.ui.scale = g_ui_scale; g_trigger_style_update = true; } @@ -2131,9 +2017,7 @@ static void ShowMainMenu() } if (ImGui::Combo( - "Scaling Mode", &scaling_mode, "Center\0Scale\0Scale (Widescreen 16:9)\0Scale (4:3)\0Stretch\0")) { - xemu_settings_set_enum(XEMU_SETTINGS_DISPLAY_SCALE, scaling_mode); - xemu_settings_save(); + "Scaling Mode", &g_config.display.ui.fit, "Center\0Scale\0Scale (Widescreen 16:9)\0Scale (4:3)\0Stretch\0")) { } 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)) { @@ -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(); - int ui_scale_int = 1; - xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_UI_SCALE, &ui_scale_int); + int ui_scale_int = g_config.display.ui.scale; if (ui_scale_int < 1) ui_scale_int = 1; g_ui_scale = ui_scale_int; @@ -2299,13 +2182,7 @@ void xemu_hud_init(SDL_Window* window, void* sdl_gl_context) ImPlot::CreateContext(); #if defined(_WIN32) - int should_check_for_update; - 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) { + if (g_config.general.updates.check) { update_window.check_for_updates_and_prompt_if_available(); } #endif diff --git a/ui/xemu-input.c b/ui/xemu-input.c index 1549c7ccc1..e5060c3ac4 100644 --- a/ui/xemu-input.c +++ b/ui/xemu-input.c @@ -87,11 +87,11 @@ ControllerStateList available_controllers = ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL }; int test_mode; -static const enum xemu_settings_keys port_index_to_settings_key_map[] = { - XEMU_SETTINGS_INPUT_CONTROLLER_1_GUID, - XEMU_SETTINGS_INPUT_CONTROLLER_2_GUID, - XEMU_SETTINGS_INPUT_CONTROLLER_3_GUID, - XEMU_SETTINGS_INPUT_CONTROLLER_4_GUID, +static const char **port_index_to_settings_key_map[] = { + &g_config.input.bindings.port1, + &g_config.input.bindings.port2, + &g_config.input.bindings.port3, + &g_config.input.bindings.port4, }; 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++) { - const char *this_port; - xemu_settings_get_string(port_index_to_settings_key_map[i], &this_port); - if (strcmp(guid, this_port) == 0) { + if (strcmp(guid, *port_index_to_settings_key_map[i]) == 0) { 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_save(); } // Bind new controller diff --git a/ui/xemu-net.c b/ui/xemu-net.c index 8d11cbd841..a6cd9efb22 100644 --- a/ui/xemu-net.c +++ b/ui/xemu-net.c @@ -50,36 +50,28 @@ void xemu_net_enable(void) 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 QDict *qdict; - if (backend == XEMU_NET_BACKEND_USER) { + if (g_config.net.backend == CONFIG_NET_BACKEND_NAT) { qdict = qdict_new(); qdict_put_str(qdict, "id", id); 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_put_str(qdict, "id", id); qdict_put_str(qdict, "type", "socket"); - qdict_put_str(qdict, "udp", remote_addr); - qdict_put_str(qdict, "localaddr", local_addr); - } else if (backend == XEMU_NET_BACKEND_PCAP) { + qdict_put_str(qdict, "udp", g_config.net.udp.remote_addr); + qdict_put_str(qdict, "localaddr", g_config.net.udp.bind_addr); + } else if (g_config.net.backend == CONFIG_NET_BACKEND_PCAP) { #if defined(_WIN32) if (pcap_load_library()) { return; } #endif - const char *iface; - xemu_settings_get_string(XEMU_SETTINGS_NETWORK_PCAP_INTERFACE, &iface); qdict = qdict_new(); qdict_put_str(qdict, "id", id); qdict_put_str(qdict, "type", "pcap"); - qdict_put_str(qdict, "ifname", iface); + qdict_put_str(qdict, "ifname", g_config.net.pcap.netif); } else { // Unsupported backend type return; @@ -111,6 +103,8 @@ void xemu_net_enable(void) xemu_queue_error_message(error_get_pretty(local_err)); error_report_err(local_err); } + + g_config.net.enable = true; } static void remove_netdev(const char *name) @@ -139,11 +133,13 @@ void xemu_net_disable(void) { remove_netdev(id); remove_netdev(id_hubport); + g_config.net.enable = false; } int xemu_net_is_enabled(void) { NetClientState *nc; nc = qemu_find_netdev(id); - return (nc != NULL); + g_config.net.enable = (nc != NULL); + return g_config.net.enable; } diff --git a/ui/xemu-settings.c b/ui/xemu-settings.c deleted file mode 100644 index 2d5d0b6afe..0000000000 --- a/ui/xemu-settings.c +++ /dev/null @@ -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 . - */ - -#include "qemu/osdep.h" -#include -#include -#include -#include -#include -#include -#include - -#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); -} diff --git a/ui/xemu-settings.cc b/ui/xemu-settings.cc new file mode 100644 index 0000000000..49eeaa6ab3 --- /dev/null +++ b/ui/xemu-settings.cc @@ -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 . + */ + +#include "qemu/osdep.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} \ No newline at end of file diff --git a/ui/xemu-settings.h b/ui/xemu-settings.h index 85135a7cc9..32045e4189 100644 --- a/ui/xemu-settings.h +++ b/ui/xemu-settings.h @@ -28,57 +28,12 @@ extern "C" { #endif -enum xemu_settings_keys { - 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 -}; +#include "xemu-config.h" -enum DISPLAY_SCALE -{ - 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 -}; +extern struct config g_config; // 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 void xemu_settings_set_path(const char *path); @@ -95,15 +50,14 @@ void xemu_settings_load(void); // Save config file to disk void xemu_settings_save(void); -// Config item setters/getters -int xemu_settings_set_string(enum xemu_settings_keys key, const char *str); -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); -int xemu_settings_get_int(enum xemu_settings_keys key, int *val); -int xemu_settings_set_bool(enum xemu_settings_keys key, int val); -int xemu_settings_get_bool(enum xemu_settings_keys key, int *val); -int xemu_settings_set_enum(enum xemu_settings_keys key, int val); -int xemu_settings_get_enum(enum xemu_settings_keys key, int *val); +#include +#include + +static inline void xemu_settings_set_string(const char **str, const char *new_str) +{ + free((char*)*str); + *str = strdup(new_str); +} #ifdef __cplusplus } diff --git a/ui/xemu.c b/ui/xemu.c index d3fd6c7249..009c2c2be3 100644 --- a/ui/xemu.c +++ b/ui/xemu.c @@ -108,7 +108,6 @@ static SDL_Cursor *guest_sprite; static Notifier mouse_mode_notifier; static SDL_Window *m_window; static SDL_GLContext m_context; -int scaling_mode = 1; struct decal_shader *blit; static QemuSemaphore display_init_sem; @@ -593,8 +592,8 @@ static void handle_windowevent(SDL_Event *ev) dpy_set_ui_info(scon->dcl.con, &info); if (!gui_fullscreen) { - xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_WINDOW_WIDTH, ev->window.data1); - xemu_settings_set_int(XEMU_SETTINGS_DISPLAY_WINDOW_HEIGHT, ev->window.data2); + g_config.display.window.last_width = ev->window.data1; + g_config.display.window.last_height = ev->window.data2; } } sdl2_redraw(scon); @@ -860,9 +859,8 @@ static void sdl2_display_very_early_init(DisplayOptions *o) SDL_DisplayMode disp_mode; SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(m_window), &disp_mode); - int win_w, win_h; - xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_WINDOW_WIDTH, &win_w); - xemu_settings_get_int(XEMU_SETTINGS_DISPLAY_WINDOW_HEIGHT, &win_h); + int win_w = g_config.display.window.last_width, + win_h = g_config.display.window.last_height; if (win_w > 0 && win_h > 0) { 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); SDL_GL_MakeCurrent(m_window, m_context); - xemu_settings_get_enum(XEMU_SETTINGS_DISPLAY_SCALE, &scaling_mode); - memset(&info, 0, sizeof(info)); SDL_VERSION(&info.version); @@ -1177,20 +1173,20 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl) // Calculate scaling factors float scale[2]; - if (scaling_mode == DISPLAY_SCALE_STRETCH) { + if (g_config.display.ui.fit == CONFIG_DISPLAY_UI_FIT_STRETCH) { // Stretch to fit scale[0] = 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 scale[0] = (float)tw/(float)ww; scale[1] = (float)th/(float)wh; } else { 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 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; } else { // Scale to fit, preserving framebuffer aspect ratio