mirror of
https://github.com/yuzu-mirror/yuzu.git
synced 2024-11-16 15:57:33 +01:00
config: Unify config handling under frontend_common
Replaces every way of handling config for each frontend with SimpleIni. frontend_common's Config class is at the center where it saves and loads all of the cross-platform settings and provides a set of pure virtual functions for platform specific settings. As a result of making config handling platform specific, several parts had to be moved to each platform's own config class or to other parts. Default keys were put in platform specific config classes and translatable strings for Qt were moved to shared_translation. Default hotkeys, default_theme, window geometry, and qt metatypes were moved to uisettings. Additionally, to reduce dependence on Qt, QStrings were converted to std::strings where applicable.
This commit is contained in:
parent
8da5bd27e9
commit
da14c7b8e4
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -4,9 +4,6 @@
|
||||
[submodule "enet"]
|
||||
path = externals/enet
|
||||
url = https://github.com/lsalzman/enet.git
|
||||
[submodule "inih"]
|
||||
path = externals/inih/inih
|
||||
url = https://github.com/benhoyt/inih.git
|
||||
[submodule "cubeb"]
|
||||
path = externals/cubeb
|
||||
url = https://github.com/mozilla/cubeb.git
|
||||
@ -61,3 +58,6 @@
|
||||
[submodule "breakpad"]
|
||||
path = externals/breakpad
|
||||
url = https://github.com/yuzu-emu/breakpad.git
|
||||
[submodule "simpleini"]
|
||||
path = externals/simpleini
|
||||
url = https://github.com/brofield/simpleini.git
|
||||
|
@ -285,7 +285,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
find_package(Boost 1.79.0 REQUIRED context)
|
||||
find_package(enet 1.3 MODULE)
|
||||
find_package(fmt 9 REQUIRED)
|
||||
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
||||
find_package(lz4 REQUIRED)
|
||||
find_package(nlohmann_json 3.8 REQUIRED)
|
||||
|
3
externals/CMakeLists.txt
vendored
3
externals/CMakeLists.txt
vendored
@ -295,3 +295,6 @@ if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client)
|
||||
target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# SimpleIni
|
||||
add_subdirectory(simpleini)
|
||||
|
1
externals/simpleini
vendored
Submodule
1
externals/simpleini
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 382ddbb4b92c0b26aa1b32cefba2002119a5b1f2
|
@ -187,6 +187,7 @@ add_subdirectory(audio_core)
|
||||
add_subdirectory(video_core)
|
||||
add_subdirectory(network)
|
||||
add_subdirectory(input_common)
|
||||
add_subdirectory(frontend_common)
|
||||
add_subdirectory(shader_recompiler)
|
||||
|
||||
if (YUZU_ROOM)
|
||||
|
@ -6,9 +6,6 @@ add_library(yuzu-android SHARED
|
||||
android_common/android_common.h
|
||||
applets/software_keyboard.cpp
|
||||
applets/software_keyboard.h
|
||||
config.cpp
|
||||
config.h
|
||||
default_ini.h
|
||||
emu_window/emu_window.cpp
|
||||
emu_window/emu_window.h
|
||||
id_cache.cpp
|
||||
@ -16,15 +13,17 @@ add_library(yuzu-android SHARED
|
||||
native.cpp
|
||||
native.h
|
||||
native_config.cpp
|
||||
uisettings.cpp
|
||||
android_settings.cpp
|
||||
game_metadata.cpp
|
||||
native_log.cpp
|
||||
android_config.cpp
|
||||
android_config.h
|
||||
)
|
||||
|
||||
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
|
||||
|
||||
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common)
|
||||
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log)
|
||||
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
|
||||
if (ARCHITECTURE_arm64)
|
||||
target_link_libraries(yuzu-android PRIVATE adrenotools)
|
||||
endif()
|
||||
|
70
src/android/app/src/main/jni/android_config.cpp
Normal file
70
src/android/app/src/main/jni/android_config.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "android_config.h"
|
||||
#include "android_settings.h"
|
||||
#include "common/settings_setting.h"
|
||||
|
||||
AndroidConfig::AndroidConfig(const std::string& config_name, ConfigType config_type)
|
||||
: Config(config_type) {
|
||||
Initialize(config_name);
|
||||
if (config_type != ConfigType::InputProfile) {
|
||||
ReadAndroidValues();
|
||||
SaveAndroidValues();
|
||||
}
|
||||
}
|
||||
|
||||
AndroidConfig::~AndroidConfig() {
|
||||
if (global) {
|
||||
AndroidConfig::SaveAllValues();
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidConfig::ReloadAllValues() {
|
||||
Reload();
|
||||
ReadAndroidValues();
|
||||
SaveAndroidValues();
|
||||
}
|
||||
|
||||
void AndroidConfig::SaveAllValues() {
|
||||
Save();
|
||||
SaveAndroidValues();
|
||||
}
|
||||
|
||||
void AndroidConfig::ReadAndroidValues() {
|
||||
if (global) {
|
||||
ReadAndroidUIValues();
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidConfig::ReadAndroidUIValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
|
||||
|
||||
ReadCategory(Settings::Category::Android);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void AndroidConfig::SaveAndroidValues() {
|
||||
if (global) {
|
||||
SaveAndroidUIValues();
|
||||
}
|
||||
|
||||
WriteToIni();
|
||||
}
|
||||
|
||||
void AndroidConfig::SaveAndroidUIValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Android));
|
||||
|
||||
WriteCategory(Settings::Category::Android);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) {
|
||||
auto& map = Settings::values.linkage.by_category;
|
||||
if (map.contains(category)) {
|
||||
return Settings::values.linkage.by_category[category];
|
||||
}
|
||||
return AndroidSettings::values.linkage.by_category[category];
|
||||
}
|
41
src/android/app/src/main/jni/android_config.h
Normal file
41
src/android/app/src/main/jni/android_config.h
Normal file
@ -0,0 +1,41 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "frontend_common/config.h"
|
||||
|
||||
class AndroidConfig final : public Config {
|
||||
public:
|
||||
explicit AndroidConfig(const std::string& config_name = "config",
|
||||
ConfigType config_type = ConfigType::GlobalConfig);
|
||||
~AndroidConfig() override;
|
||||
|
||||
void ReloadAllValues() override;
|
||||
void SaveAllValues() override;
|
||||
|
||||
protected:
|
||||
void ReadAndroidValues();
|
||||
void ReadAndroidUIValues();
|
||||
void ReadHidbusValues() override {}
|
||||
void ReadDebugControlValues() override {}
|
||||
void ReadPathValues() override {}
|
||||
void ReadShortcutValues() override {}
|
||||
void ReadUIValues() override {}
|
||||
void ReadUIGamelistValues() override {}
|
||||
void ReadUILayoutValues() override {}
|
||||
void ReadMultiplayerValues() override {}
|
||||
|
||||
void SaveAndroidValues();
|
||||
void SaveAndroidUIValues();
|
||||
void SaveHidbusValues() override {}
|
||||
void SaveDebugControlValues() override {}
|
||||
void SavePathValues() override {}
|
||||
void SaveShortcutValues() override {}
|
||||
void SaveUIValues() override {}
|
||||
void SaveUIGamelistValues() override {}
|
||||
void SaveUILayoutValues() override {}
|
||||
void SaveMultiplayerValues() override {}
|
||||
|
||||
std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override;
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "uisettings.h"
|
||||
#include "android_settings.h"
|
||||
|
||||
namespace AndroidSettings {
|
||||
|
@ -1,330 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
|
||||
#include <INIReader.h>
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_enums.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "input_common/main.h"
|
||||
#include "jni/config.h"
|
||||
#include "jni/default_ini.h"
|
||||
#include "uisettings.h"
|
||||
|
||||
namespace FS = Common::FS;
|
||||
|
||||
Config::Config(const std::string& config_name, ConfigType config_type)
|
||||
: type(config_type), global{config_type == ConfigType::GlobalConfig} {
|
||||
Initialize(config_name);
|
||||
}
|
||||
|
||||
Config::~Config() = default;
|
||||
|
||||
bool Config::LoadINI(const std::string& default_contents, bool retry) {
|
||||
void(FS::CreateParentDir(config_loc));
|
||||
config = std::make_unique<INIReader>(FS::PathToUTF8String(config_loc));
|
||||
const auto config_loc_str = FS::PathToUTF8String(config_loc);
|
||||
if (config->ParseError() < 0) {
|
||||
if (retry) {
|
||||
LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...",
|
||||
config_loc_str);
|
||||
|
||||
void(FS::CreateParentDir(config_loc));
|
||||
void(FS::WriteStringToFile(config_loc, FS::FileType::TextFile, default_contents));
|
||||
|
||||
config = std::make_unique<INIReader>(config_loc_str);
|
||||
|
||||
return LoadINI(default_contents, false);
|
||||
}
|
||||
LOG_ERROR(Config, "Failed.");
|
||||
return false;
|
||||
}
|
||||
LOG_INFO(Config, "Successfully loaded {}", config_loc_str);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) {
|
||||
std::string setting_value = config->Get(group, setting.GetLabel(), setting.GetDefault());
|
||||
if (setting_value.empty()) {
|
||||
setting_value = setting.GetDefault();
|
||||
}
|
||||
setting = std::move(setting_value);
|
||||
}
|
||||
|
||||
template <>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
|
||||
setting = config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
|
||||
}
|
||||
|
||||
template <typename Type, bool ranged>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
|
||||
setting = static_cast<Type>(
|
||||
config->GetInteger(group, setting.GetLabel(), static_cast<long>(setting.GetDefault())));
|
||||
}
|
||||
|
||||
void Config::ReadValues() {
|
||||
ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);
|
||||
ReadSetting("ControlsGeneral", Settings::values.touch_device);
|
||||
ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled);
|
||||
ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled);
|
||||
ReadSetting("ControlsGeneral", Settings::values.vibration_enabled);
|
||||
ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations);
|
||||
ReadSetting("ControlsGeneral", Settings::values.motion_enabled);
|
||||
Settings::values.touchscreen.enabled =
|
||||
config->GetBoolean("ControlsGeneral", "touch_enabled", true);
|
||||
Settings::values.touchscreen.rotation_angle =
|
||||
config->GetInteger("ControlsGeneral", "touch_angle", 0);
|
||||
Settings::values.touchscreen.diameter_x =
|
||||
config->GetInteger("ControlsGeneral", "touch_diameter_x", 15);
|
||||
Settings::values.touchscreen.diameter_y =
|
||||
config->GetInteger("ControlsGeneral", "touch_diameter_y", 15);
|
||||
|
||||
int num_touch_from_button_maps =
|
||||
config->GetInteger("ControlsGeneral", "touch_from_button_map", 0);
|
||||
if (num_touch_from_button_maps > 0) {
|
||||
for (int i = 0; i < num_touch_from_button_maps; ++i) {
|
||||
Settings::TouchFromButtonMap map;
|
||||
map.name = config->Get("ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||
std::string("_name"),
|
||||
"default");
|
||||
const int num_touch_maps = config->GetInteger(
|
||||
"ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"),
|
||||
0);
|
||||
map.buttons.reserve(num_touch_maps);
|
||||
|
||||
for (int j = 0; j < num_touch_maps; ++j) {
|
||||
std::string touch_mapping =
|
||||
config->Get("ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||
std::string("_bind_") + std::to_string(j),
|
||||
"");
|
||||
map.buttons.emplace_back(std::move(touch_mapping));
|
||||
}
|
||||
|
||||
Settings::values.touch_from_button_maps.emplace_back(std::move(map));
|
||||
}
|
||||
} else {
|
||||
Settings::values.touch_from_button_maps.emplace_back(
|
||||
Settings::TouchFromButtonMap{"default", {}});
|
||||
num_touch_from_button_maps = 1;
|
||||
}
|
||||
Settings::values.touch_from_button_map_index = std::clamp(
|
||||
Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
|
||||
|
||||
ReadSetting("ControlsGeneral", Settings::values.udp_input_servers);
|
||||
|
||||
// Data Storage
|
||||
ReadSetting("Data Storage", Settings::values.use_virtual_sd);
|
||||
FS::SetYuzuPath(FS::YuzuPath::NANDDir,
|
||||
config->Get("Data Storage", "nand_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
|
||||
FS::SetYuzuPath(FS::YuzuPath::SDMCDir,
|
||||
config->Get("Data Storage", "sdmc_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
|
||||
FS::SetYuzuPath(FS::YuzuPath::LoadDir,
|
||||
config->Get("Data Storage", "load_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
|
||||
FS::SetYuzuPath(FS::YuzuPath::DumpDir,
|
||||
config->Get("Data Storage", "dump_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
|
||||
ReadSetting("Data Storage", Settings::values.gamecard_inserted);
|
||||
ReadSetting("Data Storage", Settings::values.gamecard_current_game);
|
||||
ReadSetting("Data Storage", Settings::values.gamecard_path);
|
||||
|
||||
// System
|
||||
ReadSetting("System", Settings::values.current_user);
|
||||
Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0,
|
||||
Service::Account::MAX_USERS - 1);
|
||||
|
||||
// Disable docked mode by default on Android
|
||||
Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false)
|
||||
? Settings::ConsoleMode::Docked
|
||||
: Settings::ConsoleMode::Handheld);
|
||||
|
||||
const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false);
|
||||
if (rng_seed_enabled) {
|
||||
Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0));
|
||||
} else {
|
||||
Settings::values.rng_seed.SetValue(0);
|
||||
}
|
||||
Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled);
|
||||
|
||||
const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false);
|
||||
if (custom_rtc_enabled) {
|
||||
Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0);
|
||||
} else {
|
||||
Settings::values.custom_rtc = 0;
|
||||
}
|
||||
Settings::values.custom_rtc_enabled = custom_rtc_enabled;
|
||||
|
||||
ReadSetting("System", Settings::values.language_index);
|
||||
ReadSetting("System", Settings::values.region_index);
|
||||
ReadSetting("System", Settings::values.time_zone_index);
|
||||
ReadSetting("System", Settings::values.sound_index);
|
||||
|
||||
// Core
|
||||
ReadSetting("Core", Settings::values.use_multi_core);
|
||||
ReadSetting("Core", Settings::values.memory_layout_mode);
|
||||
|
||||
// Cpu
|
||||
ReadSetting("Cpu", Settings::values.cpu_accuracy);
|
||||
ReadSetting("Cpu", Settings::values.cpu_debug_mode);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_page_tables);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_block_linking);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_context_elimination);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_const_prop);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_misc_ir);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check);
|
||||
ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor);
|
||||
|
||||
// Renderer
|
||||
ReadSetting("Renderer", Settings::values.renderer_backend);
|
||||
ReadSetting("Renderer", Settings::values.renderer_debug);
|
||||
ReadSetting("Renderer", Settings::values.renderer_shader_feedback);
|
||||
ReadSetting("Renderer", Settings::values.enable_nsight_aftermath);
|
||||
ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks);
|
||||
ReadSetting("Renderer", Settings::values.vulkan_device);
|
||||
|
||||
ReadSetting("Renderer", Settings::values.resolution_setup);
|
||||
ReadSetting("Renderer", Settings::values.scaling_filter);
|
||||
ReadSetting("Renderer", Settings::values.fsr_sharpening_slider);
|
||||
ReadSetting("Renderer", Settings::values.anti_aliasing);
|
||||
ReadSetting("Renderer", Settings::values.fullscreen_mode);
|
||||
ReadSetting("Renderer", Settings::values.aspect_ratio);
|
||||
ReadSetting("Renderer", Settings::values.max_anisotropy);
|
||||
ReadSetting("Renderer", Settings::values.use_speed_limit);
|
||||
ReadSetting("Renderer", Settings::values.speed_limit);
|
||||
ReadSetting("Renderer", Settings::values.use_disk_shader_cache);
|
||||
ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation);
|
||||
ReadSetting("Renderer", Settings::values.vsync_mode);
|
||||
ReadSetting("Renderer", Settings::values.shader_backend);
|
||||
ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
|
||||
ReadSetting("Renderer", Settings::values.nvdec_emulation);
|
||||
ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
|
||||
ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
|
||||
|
||||
ReadSetting("Renderer", Settings::values.bg_red);
|
||||
ReadSetting("Renderer", Settings::values.bg_green);
|
||||
ReadSetting("Renderer", Settings::values.bg_blue);
|
||||
|
||||
// Use GPU accuracy normal by default on Android
|
||||
Settings::values.gpu_accuracy = static_cast<Settings::GpuAccuracy>(config->GetInteger(
|
||||
"Renderer", "gpu_accuracy", static_cast<u32>(Settings::GpuAccuracy::Normal)));
|
||||
|
||||
// Use GPU default anisotropic filtering on Android
|
||||
Settings::values.max_anisotropy =
|
||||
static_cast<Settings::AnisotropyMode>(config->GetInteger("Renderer", "max_anisotropy", 1));
|
||||
|
||||
// Disable ASTC compute by default on Android
|
||||
Settings::values.accelerate_astc.SetValue(
|
||||
config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu
|
||||
: Settings::AstcDecodeMode::Cpu);
|
||||
|
||||
// Enable asynchronous presentation by default on Android
|
||||
Settings::values.async_presentation =
|
||||
config->GetBoolean("Renderer", "async_presentation", true);
|
||||
|
||||
// Disable force_max_clock by default on Android
|
||||
Settings::values.renderer_force_max_clock =
|
||||
config->GetBoolean("Renderer", "force_max_clock", false);
|
||||
|
||||
// Disable use_reactive_flushing by default on Android
|
||||
Settings::values.use_reactive_flushing =
|
||||
config->GetBoolean("Renderer", "use_reactive_flushing", false);
|
||||
|
||||
// Audio
|
||||
ReadSetting("Audio", Settings::values.sink_id);
|
||||
ReadSetting("Audio", Settings::values.audio_output_device_id);
|
||||
ReadSetting("Audio", Settings::values.volume);
|
||||
|
||||
// Miscellaneous
|
||||
// log_filter has a different default here than from common
|
||||
Settings::values.log_filter = "*:Info";
|
||||
ReadSetting("Miscellaneous", Settings::values.use_dev_keys);
|
||||
|
||||
// Debugging
|
||||
Settings::values.record_frame_times =
|
||||
config->GetBoolean("Debugging", "record_frame_times", false);
|
||||
ReadSetting("Debugging", Settings::values.dump_exefs);
|
||||
ReadSetting("Debugging", Settings::values.dump_nso);
|
||||
ReadSetting("Debugging", Settings::values.enable_fs_access_log);
|
||||
ReadSetting("Debugging", Settings::values.reporting_services);
|
||||
ReadSetting("Debugging", Settings::values.quest_flag);
|
||||
ReadSetting("Debugging", Settings::values.use_debug_asserts);
|
||||
ReadSetting("Debugging", Settings::values.use_auto_stub);
|
||||
ReadSetting("Debugging", Settings::values.disable_macro_jit);
|
||||
ReadSetting("Debugging", Settings::values.disable_macro_hle);
|
||||
ReadSetting("Debugging", Settings::values.use_gdbstub);
|
||||
ReadSetting("Debugging", Settings::values.gdbstub_port);
|
||||
|
||||
const auto title_list = config->Get("AddOns", "title_ids", "");
|
||||
std::stringstream ss(title_list);
|
||||
std::string line;
|
||||
while (std::getline(ss, line, '|')) {
|
||||
const auto title_id = std::strtoul(line.c_str(), nullptr, 16);
|
||||
const auto disabled_list = config->Get("AddOns", "disabled_" + line, "");
|
||||
|
||||
std::stringstream inner_ss(disabled_list);
|
||||
std::string inner_line;
|
||||
std::vector<std::string> out;
|
||||
while (std::getline(inner_ss, inner_line, '|')) {
|
||||
out.push_back(inner_line);
|
||||
}
|
||||
|
||||
Settings::values.disabled_addons.insert_or_assign(title_id, out);
|
||||
}
|
||||
|
||||
// Web Service
|
||||
ReadSetting("WebService", Settings::values.enable_telemetry);
|
||||
ReadSetting("WebService", Settings::values.web_api_url);
|
||||
ReadSetting("WebService", Settings::values.yuzu_username);
|
||||
ReadSetting("WebService", Settings::values.yuzu_token);
|
||||
|
||||
// Network
|
||||
ReadSetting("Network", Settings::values.network_interface);
|
||||
|
||||
// Android
|
||||
ReadSetting("Android", AndroidSettings::values.picture_in_picture);
|
||||
ReadSetting("Android", AndroidSettings::values.screen_layout);
|
||||
}
|
||||
|
||||
void Config::Initialize(const std::string& config_name) {
|
||||
const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
|
||||
const auto config_file = fmt::format("{}.ini", config_name);
|
||||
|
||||
switch (type) {
|
||||
case ConfigType::GlobalConfig:
|
||||
config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
|
||||
break;
|
||||
case ConfigType::PerGameConfig:
|
||||
config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
|
||||
break;
|
||||
case ConfigType::InputProfile:
|
||||
config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
|
||||
LoadINI(DefaultINI::android_config_file);
|
||||
return;
|
||||
}
|
||||
LoadINI(DefaultINI::android_config_file);
|
||||
ReadValues();
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "common/settings.h"
|
||||
|
||||
class INIReader;
|
||||
|
||||
class Config {
|
||||
bool LoadINI(const std::string& default_contents = "", bool retry = true);
|
||||
|
||||
public:
|
||||
enum class ConfigType {
|
||||
GlobalConfig,
|
||||
PerGameConfig,
|
||||
InputProfile,
|
||||
};
|
||||
|
||||
explicit Config(const std::string& config_name = "config",
|
||||
ConfigType config_type = ConfigType::GlobalConfig);
|
||||
~Config();
|
||||
|
||||
void Initialize(const std::string& config_name);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Applies a value read from the config to a Setting.
|
||||
*
|
||||
* @param group The name of the INI group
|
||||
* @param setting The yuzu setting to modify
|
||||
*/
|
||||
template <typename Type, bool ranged>
|
||||
void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
|
||||
|
||||
void ReadValues();
|
||||
|
||||
const ConfigType type;
|
||||
std::unique_ptr<INIReader> config;
|
||||
std::string config_loc;
|
||||
const bool global;
|
||||
};
|
@ -1,511 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace DefaultINI {
|
||||
|
||||
const char* android_config_file = R"(
|
||||
|
||||
[ControlsP0]
|
||||
# The input devices and parameters for each Switch native input
|
||||
# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ...
|
||||
# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
|
||||
# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
|
||||
|
||||
# Indicates if this player should be connected at boot
|
||||
connected=
|
||||
|
||||
# for button input, the following devices are available:
|
||||
# - "keyboard" (default) for keyboard input. Required parameters:
|
||||
# - "code": the code of the key to bind
|
||||
# - "sdl" for joystick input using SDL. Required parameters:
|
||||
# - "guid": SDL identification GUID of the joystick
|
||||
# - "port": the index of the joystick to bind
|
||||
# - "button"(optional): the index of the button to bind
|
||||
# - "hat"(optional): the index of the hat to bind as direction buttons
|
||||
# - "axis"(optional): the index of the axis to bind
|
||||
# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right"
|
||||
# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
|
||||
# triggered if the axis value crosses
|
||||
# - "direction"(only used for axis): "+" means the button is triggered when the axis value
|
||||
# is greater than the threshold; "-" means the button is triggered when the axis value
|
||||
# is smaller than the threshold
|
||||
button_a=
|
||||
button_b=
|
||||
button_x=
|
||||
button_y=
|
||||
button_lstick=
|
||||
button_rstick=
|
||||
button_l=
|
||||
button_r=
|
||||
button_zl=
|
||||
button_zr=
|
||||
button_plus=
|
||||
button_minus=
|
||||
button_dleft=
|
||||
button_dup=
|
||||
button_dright=
|
||||
button_ddown=
|
||||
button_lstick_left=
|
||||
button_lstick_up=
|
||||
button_lstick_right=
|
||||
button_lstick_down=
|
||||
button_sl=
|
||||
button_sr=
|
||||
button_home=
|
||||
button_screenshot=
|
||||
|
||||
# for analog input, the following devices are available:
|
||||
# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
|
||||
# - "up", "down", "left", "right": sub-devices for each direction.
|
||||
# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00"
|
||||
# - "modifier": sub-devices as a modifier.
|
||||
# - "modifier_scale": a float number representing the applied modifier scale to the analog input.
|
||||
# Must be in range of 0.0-1.0. Defaults to 0.5
|
||||
# - "sdl" for joystick input using SDL. Required parameters:
|
||||
# - "guid": SDL identification GUID of the joystick
|
||||
# - "port": the index of the joystick to bind
|
||||
# - "axis_x": the index of the axis to bind as x-axis (default to 0)
|
||||
# - "axis_y": the index of the axis to bind as y-axis (default to 1)
|
||||
lstick=
|
||||
rstick=
|
||||
|
||||
# for motion input, the following devices are available:
|
||||
# - "keyboard" (default) for emulating random motion input from buttons. Required parameters:
|
||||
# - "code": the code of the key to bind
|
||||
# - "sdl" for motion input using SDL. Required parameters:
|
||||
# - "guid": SDL identification GUID of the joystick
|
||||
# - "port": the index of the joystick to bind
|
||||
# - "motion": the index of the motion sensor to bind
|
||||
# - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters:
|
||||
# - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001"
|
||||
# - "port": the port of the cemu hook server
|
||||
# - "pad": the index of the joystick
|
||||
# - "motion": the index of the motion sensor of the joystick to bind
|
||||
motionleft=
|
||||
motionright=
|
||||
|
||||
[ControlsGeneral]
|
||||
# To use the debug_pad, prepend `debug_pad_` before each button setting above.
|
||||
# i.e. debug_pad_button_a=
|
||||
|
||||
# Enable debug pad inputs to the guest
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
debug_pad_enabled =
|
||||
|
||||
# Whether to enable or disable vibration
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
vibration_enabled=
|
||||
|
||||
# Whether to enable or disable accurate vibrations
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
enable_accurate_vibrations=
|
||||
|
||||
# Enables controller motion inputs
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
motion_enabled =
|
||||
|
||||
# Defines the udp device's touch screen coordinate system for cemuhookudp devices
|
||||
# - "min_x", "min_y", "max_x", "max_y"
|
||||
touch_device=
|
||||
|
||||
# for mapping buttons to touch inputs.
|
||||
#touch_from_button_map=1
|
||||
#touch_from_button_maps_0_name=default
|
||||
#touch_from_button_maps_0_count=2
|
||||
#touch_from_button_maps_0_bind_0=foo
|
||||
#touch_from_button_maps_0_bind_1=bar
|
||||
# etc.
|
||||
|
||||
# List of Cemuhook UDP servers, delimited by ','.
|
||||
# Default: 127.0.0.1:26760
|
||||
# Example: 127.0.0.1:26760,123.4.5.67:26761
|
||||
udp_input_servers =
|
||||
|
||||
# Enable controlling an axis via a mouse input.
|
||||
# 0 (default): Off, 1: On
|
||||
mouse_panning =
|
||||
|
||||
# Set mouse sensitivity.
|
||||
# Default: 1.0
|
||||
mouse_panning_sensitivity =
|
||||
|
||||
# Emulate an analog control stick from keyboard inputs.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
emulate_analog_keyboard =
|
||||
|
||||
# Enable mouse inputs to the guest
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
mouse_enabled =
|
||||
|
||||
# Enable keyboard inputs to the guest
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
keyboard_enabled =
|
||||
|
||||
[Core]
|
||||
# Whether to use multi-core for CPU emulation
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
use_multi_core =
|
||||
|
||||
# Enable unsafe extended guest system memory layout (8GB DRAM)
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
use_unsafe_extended_memory_layout =
|
||||
|
||||
[Cpu]
|
||||
# Adjusts various optimizations.
|
||||
# Auto-select mode enables choice unsafe optimizations.
|
||||
# Accurate enables only safe optimizations.
|
||||
# Unsafe allows any unsafe optimizations.
|
||||
# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations
|
||||
cpu_accuracy =
|
||||
|
||||
# Allow disabling safe optimizations.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
cpu_debug_mode =
|
||||
|
||||
# Enable inline page tables optimization (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_page_tables =
|
||||
|
||||
# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_block_linking =
|
||||
|
||||
# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_return_stack_buffer =
|
||||
|
||||
# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_fast_dispatcher =
|
||||
|
||||
# Enable context elimination CPU Optimization (reduce host memory use for guest context)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_context_elimination =
|
||||
|
||||
# Enable constant propagation CPU optimization (basic IR optimization)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_const_prop =
|
||||
|
||||
# Enable miscellaneous CPU optimizations (basic IR optimization)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_misc_ir =
|
||||
|
||||
# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_reduce_misalign_checks =
|
||||
|
||||
# Enable Host MMU Emulation (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_fastmem =
|
||||
|
||||
# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_fastmem_exclusives =
|
||||
|
||||
# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_recompile_exclusives =
|
||||
|
||||
# Enable optimization to ignore invalid memory accesses (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_ignore_memory_aborts =
|
||||
|
||||
# Enable unfuse FMA (improve performance on CPUs without FMA)
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_unfuse_fma =
|
||||
|
||||
# Enable faster FRSQRTE and FRECPE
|
||||
# Only enabled if cpu_accuracy is set to Unsafe.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_reduce_fp_error =
|
||||
|
||||
# Enable faster ASIMD instructions (32 bits only)
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_ignore_standard_fpcr =
|
||||
|
||||
# Enable inaccurate NaN handling
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_inaccurate_nan =
|
||||
|
||||
# Disable address space checks (64 bits only)
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_fastmem_check =
|
||||
|
||||
# Enable faster exclusive instructions
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_ignore_global_monitor =
|
||||
|
||||
[Renderer]
|
||||
# Which backend API to use.
|
||||
# 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null
|
||||
backend =
|
||||
|
||||
# Whether to enable asynchronous presentation (Vulkan only)
|
||||
# 0: Off, 1 (default): On
|
||||
async_presentation =
|
||||
|
||||
# Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied).
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
force_max_clock =
|
||||
|
||||
# Enable graphics API debugging mode.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
debug =
|
||||
|
||||
# Enable shader feedback.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
renderer_shader_feedback =
|
||||
|
||||
# Enable Nsight Aftermath crash dumps
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
nsight_aftermath =
|
||||
|
||||
# Disable shader loop safety checks, executing the shader without loop logic changes
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
disable_shader_loop_safety_checks =
|
||||
|
||||
# Which Vulkan physical device to use (defaults to 0)
|
||||
vulkan_device =
|
||||
|
||||
# 0: 0.5x (360p/540p) [EXPERIMENTAL]
|
||||
# 1: 0.75x (540p/810p) [EXPERIMENTAL]
|
||||
# 2 (default): 1x (720p/1080p)
|
||||
# 3: 2x (1440p/2160p)
|
||||
# 4: 3x (2160p/3240p)
|
||||
# 5: 4x (2880p/4320p)
|
||||
# 6: 5x (3600p/5400p)
|
||||
# 7: 6x (4320p/6480p)
|
||||
resolution_setup =
|
||||
|
||||
# Pixel filter to use when up- or down-sampling rendered frames.
|
||||
# 0: Nearest Neighbor
|
||||
# 1 (default): Bilinear
|
||||
# 2: Bicubic
|
||||
# 3: Gaussian
|
||||
# 4: ScaleForce
|
||||
# 5: AMD FidelityFX™️ Super Resolution [Vulkan Only]
|
||||
scaling_filter =
|
||||
|
||||
# Anti-Aliasing (AA)
|
||||
# 0 (default): None, 1: FXAA
|
||||
anti_aliasing =
|
||||
|
||||
# Whether to use fullscreen or borderless window mode
|
||||
# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
|
||||
fullscreen_mode =
|
||||
|
||||
# Aspect ratio
|
||||
# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window
|
||||
aspect_ratio =
|
||||
|
||||
# Anisotropic filtering
|
||||
# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
|
||||
max_anisotropy =
|
||||
|
||||
# Whether to enable VSync or not.
|
||||
# OpenGL: Values other than 0 enable VSync
|
||||
# Vulkan: FIFO is selected if the requested mode is not supported by the driver.
|
||||
# FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate.
|
||||
# FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down.
|
||||
# Mailbox can have lower latency than FIFO and does not tear but may drop frames.
|
||||
# Immediate (no synchronization) just presents whatever is available and can exhibit tearing.
|
||||
# 0: Immediate (Off), 1 (Default): Mailbox (On), 2: FIFO, 3: FIFO Relaxed
|
||||
use_vsync =
|
||||
|
||||
# Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is
|
||||
# not available and GLASM is selected, GLSL will be used.
|
||||
# 0: GLSL, 1 (default): GLASM, 2: SPIR-V
|
||||
shader_backend =
|
||||
|
||||
# Whether to allow asynchronous shader building.
|
||||
# 0 (default): Off, 1: On
|
||||
use_asynchronous_shaders =
|
||||
|
||||
# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
|
||||
# 0 (default): Off, 1: On
|
||||
use_reactive_flushing =
|
||||
|
||||
# NVDEC emulation.
|
||||
# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
|
||||
nvdec_emulation =
|
||||
|
||||
# Accelerate ASTC texture decoding.
|
||||
# 0 (default): Off, 1: On
|
||||
accelerate_astc =
|
||||
|
||||
# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value
|
||||
# 0: Off, 1: On (default)
|
||||
use_speed_limit =
|
||||
|
||||
# Limits the speed of the game to run no faster than this value as a percentage of target speed
|
||||
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
|
||||
speed_limit =
|
||||
|
||||
# Whether to use disk based shader cache
|
||||
# 0: Off, 1 (default): On
|
||||
use_disk_shader_cache =
|
||||
|
||||
# Which gpu accuracy level to use
|
||||
# 0 (default): Normal, 1: High, 2: Extreme (Very slow)
|
||||
gpu_accuracy =
|
||||
|
||||
# Whether to use asynchronous GPU emulation
|
||||
# 0 : Off (slow), 1 (default): On (fast)
|
||||
use_asynchronous_gpu_emulation =
|
||||
|
||||
# Inform the guest that GPU operations completed more quickly than they did.
|
||||
# 0: Off, 1 (default): On
|
||||
use_fast_gpu_time =
|
||||
|
||||
# Force unmodified buffers to be flushed, which can cost performance.
|
||||
# 0: Off (default), 1: On
|
||||
use_pessimistic_flushes =
|
||||
|
||||
# Whether to use garbage collection or not for GPU caches.
|
||||
# 0 (default): Off, 1: On
|
||||
use_caches_gc =
|
||||
|
||||
# The clear color for the renderer. What shows up on the sides of the bottom screen.
|
||||
# Must be in range of 0-255. Defaults to 0 for all.
|
||||
bg_red =
|
||||
bg_blue =
|
||||
bg_green =
|
||||
|
||||
[Audio]
|
||||
# Which audio output engine to use.
|
||||
# auto (default): Auto-select
|
||||
# cubeb: Cubeb audio engine (if available)
|
||||
# sdl2: SDL2 audio engine (if available)
|
||||
# null: No audio output
|
||||
output_engine =
|
||||
|
||||
# Which audio device to use.
|
||||
# auto (default): Auto-select
|
||||
output_device =
|
||||
|
||||
# Output volume.
|
||||
# 100 (default): 100%, 0; mute
|
||||
volume =
|
||||
|
||||
[Data Storage]
|
||||
# Whether to create a virtual SD card.
|
||||
# 1: Yes, 0 (default): No
|
||||
use_virtual_sd =
|
||||
|
||||
# Whether or not to enable gamecard emulation
|
||||
# 1: Yes, 0 (default): No
|
||||
gamecard_inserted =
|
||||
|
||||
# Whether or not the gamecard should be emulated as the current game
|
||||
# If 'gamecard_inserted' is 0 this setting is irrelevant
|
||||
# 1: Yes, 0 (default): No
|
||||
gamecard_current_game =
|
||||
|
||||
# Path to an XCI file to use as the gamecard
|
||||
# If 'gamecard_inserted' is 0 this setting is irrelevant
|
||||
# If 'gamecard_current_game' is 1 this setting is irrelevant
|
||||
gamecard_path =
|
||||
|
||||
[System]
|
||||
# Whether the system is docked
|
||||
# 1 (default): Yes, 0: No
|
||||
use_docked_mode =
|
||||
|
||||
# Sets the seed for the RNG generator built into the switch
|
||||
# rng_seed will be ignored and randomly generated if rng_seed_enabled is false
|
||||
rng_seed_enabled =
|
||||
rng_seed =
|
||||
|
||||
# Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service
|
||||
# This will auto-increment, with the time set being the time the game is started
|
||||
# This override will only occur if custom_rtc_enabled is true, otherwise the current time is used
|
||||
custom_rtc_enabled =
|
||||
custom_rtc =
|
||||
|
||||
# Sets the systems language index
|
||||
# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,
|
||||
# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French,
|
||||
# 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese
|
||||
language_index =
|
||||
|
||||
# The system region that yuzu will use during emulation
|
||||
# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
|
||||
region_index =
|
||||
|
||||
# The system time zone that yuzu will use during emulation
|
||||
# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone
|
||||
time_zone_index =
|
||||
|
||||
# Sets the sound output mode.
|
||||
# 0: Mono, 1 (default): Stereo, 2: Surround
|
||||
sound_index =
|
||||
|
||||
[Miscellaneous]
|
||||
# A filter which removes logs below a certain logging level.
|
||||
# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
|
||||
log_filter = *:Trace
|
||||
|
||||
# Use developer keys
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
use_dev_keys =
|
||||
|
||||
[Debugging]
|
||||
# Record frame time data, can be found in the log directory. Boolean value
|
||||
record_frame_times =
|
||||
# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them
|
||||
dump_exefs=false
|
||||
# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
|
||||
dump_nso=false
|
||||
# Determines whether or not yuzu will save the filesystem access log.
|
||||
enable_fs_access_log=false
|
||||
# Enables verbose reporting services
|
||||
reporting_services =
|
||||
# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
|
||||
# false: Retail/Normal Mode (default), true: Kiosk Mode
|
||||
quest_flag =
|
||||
# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
|
||||
# false: Disabled (default), true: Enabled
|
||||
use_debug_asserts =
|
||||
# Determines whether unimplemented HLE service calls should be automatically stubbed.
|
||||
# false: Disabled (default), true: Enabled
|
||||
use_auto_stub =
|
||||
# Enables/Disables the macro JIT compiler
|
||||
disable_macro_jit=false
|
||||
# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
|
||||
# false: Disabled (default), true: Enabled
|
||||
use_gdbstub=false
|
||||
# The port to use for the GDB server, if it is enabled.
|
||||
gdbstub_port=6543
|
||||
|
||||
[WebService]
|
||||
# Whether or not to enable telemetry
|
||||
# 0: No, 1 (default): Yes
|
||||
enable_telemetry =
|
||||
# URL for Web API
|
||||
web_api_url = https://api.yuzu-emu.org
|
||||
# Username and token for yuzu Web Service
|
||||
# See https://profile.yuzu-emu.org/ for more info
|
||||
yuzu_username =
|
||||
yuzu_token =
|
||||
|
||||
[Network]
|
||||
# Name of the network interface device to use with yuzu LAN play.
|
||||
# e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo'
|
||||
# e.g. On Windows: 'Ethernet', 'Wi-Fi'
|
||||
network_interface =
|
||||
|
||||
[AddOns]
|
||||
# Used to disable add-ons
|
||||
# List of title IDs of games that will have add-ons disabled (separated by '|'):
|
||||
title_ids =
|
||||
# For each title ID, have a key/value pair called `disabled_<title_id>` equal to the names of the add-ons to disable (sep. by '|')
|
||||
# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey
|
||||
)";
|
||||
} // namespace DefaultINI
|
@ -52,8 +52,8 @@
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "jni/android_common/android_common.h"
|
||||
#include "jni/config.h"
|
||||
#include "jni/id_cache.h"
|
||||
#include "jni/native.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
@ -664,8 +664,6 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased(JNIEnv* env, jclass c
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz,
|
||||
jboolean reload) {
|
||||
// Create the default config.ini.
|
||||
Config{};
|
||||
// Initialize the emulated system.
|
||||
if (!reload) {
|
||||
EmulationSession::GetInstance().System().Initialize();
|
||||
@ -680,17 +678,6 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass cl
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z(
|
||||
JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate) {}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings(JNIEnv* env, jclass clazz) {
|
||||
Config{};
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initGameIni(JNIEnv* env, jclass clazz,
|
||||
jstring j_game_id) {
|
||||
std::string_view game_id = env->GetStringUTFChars(j_game_id, 0);
|
||||
|
||||
env->ReleaseStringUTFChars(j_game_id, game_id.data());
|
||||
}
|
||||
|
||||
jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) {
|
||||
jdoubleArray j_stats = env->NewDoubleArray(4);
|
||||
|
||||
|
@ -5,11 +5,14 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "android_config.h"
|
||||
#include "android_settings.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "jni/android_common/android_common.h"
|
||||
#include "jni/config.h"
|
||||
#include "uisettings.h"
|
||||
|
||||
std::unique_ptr<AndroidConfig> config;
|
||||
|
||||
template <typename T>
|
||||
Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
|
||||
@ -28,6 +31,22 @@ Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
|
||||
|
||||
extern "C" {
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializeConfig(JNIEnv* env, jobject obj) {
|
||||
config = std::make_unique<AndroidConfig>();
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_unloadConfig(JNIEnv* env, jobject obj) {
|
||||
config.reset();
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_reloadSettings(JNIEnv* env, jobject obj) {
|
||||
config->AndroidConfig::ReloadAllValues();
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_saveSettings(JNIEnv* env, jobject obj) {
|
||||
config->AndroidConfig::SaveAllValues();
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getBoolean(JNIEnv* env, jobject obj,
|
||||
jstring jkey, jboolean getDefault) {
|
||||
auto setting = getSetting<bool>(env, jkey);
|
||||
|
@ -206,9 +206,9 @@ const char* TranslateCategory(Category category) {
|
||||
case Category::UiAudio:
|
||||
return "UiAudio";
|
||||
case Category::UiLayout:
|
||||
return "UiLayout";
|
||||
return "UILayout";
|
||||
case Category::UiGameList:
|
||||
return "UiGameList";
|
||||
return "UIGameList";
|
||||
case Category::Screenshots:
|
||||
return "Screenshots";
|
||||
case Category::Shortcuts:
|
||||
|
10
src/frontend_common/CMakeLists.txt
Normal file
10
src/frontend_common/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
add_library(frontend_common STATIC
|
||||
config.cpp
|
||||
config.h
|
||||
)
|
||||
|
||||
create_target_directory_groups(frontend_common)
|
||||
target_link_libraries(frontend_common PUBLIC core SimpleIni PRIVATE common Boost::headers)
|
931
src/frontend_common/config.cpp
Normal file
931
src/frontend_common/config.cpp
Normal file
@ -0,0 +1,931 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_common.h"
|
||||
#include "common/settings_enums.h"
|
||||
#include "config.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
#include "network/network.h"
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
namespace FS = Common::FS;
|
||||
|
||||
Config::Config(const ConfigType config_type)
|
||||
: type(config_type), global{config_type == ConfigType::GlobalConfig} {}
|
||||
|
||||
void Config::Initialize(const std::string& config_name) {
|
||||
const std::filesystem::path fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
|
||||
const auto config_file = fmt::format("{}.ini", config_name);
|
||||
|
||||
switch (type) {
|
||||
case ConfigType::GlobalConfig:
|
||||
config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
|
||||
void(FS::CreateParentDir(config_loc));
|
||||
SetUpIni();
|
||||
Reload();
|
||||
break;
|
||||
case ConfigType::PerGameConfig:
|
||||
config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
|
||||
void(FS::CreateParentDir(config_loc));
|
||||
SetUpIni();
|
||||
Reload();
|
||||
break;
|
||||
case ConfigType::InputProfile:
|
||||
config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
|
||||
void(FS::CreateParentDir(config_loc));
|
||||
SetUpIni();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Config::Initialize(const std::optional<std::string> config_path) {
|
||||
const std::filesystem::path default_sdl_config_path =
|
||||
FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
|
||||
config_loc = config_path.value_or(FS::PathToUTF8String(default_sdl_config_path));
|
||||
void(FS::CreateParentDir(config_loc));
|
||||
SetUpIni();
|
||||
Reload();
|
||||
}
|
||||
|
||||
void Config::WriteToIni() const {
|
||||
if (const SI_Error rc = config->SaveFile(config_loc.c_str()); rc < 0) {
|
||||
LOG_ERROR(Frontend, "Config file could not be saved!");
|
||||
}
|
||||
}
|
||||
|
||||
void Config::SetUpIni() {
|
||||
config = std::make_unique<CSimpleIniA>();
|
||||
config->SetUnicode(true);
|
||||
config->SetSpaces(false);
|
||||
config->LoadFile(config_loc.c_str());
|
||||
}
|
||||
|
||||
bool Config::IsCustomConfig() const {
|
||||
return type == ConfigType::PerGameConfig;
|
||||
}
|
||||
|
||||
void Config::ReadPlayerValues(const std::size_t player_index) {
|
||||
std::string player_prefix;
|
||||
if (type != ConfigType::InputProfile) {
|
||||
player_prefix.append("player_").append(ToString(player_index)).append("_");
|
||||
}
|
||||
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (IsCustomConfig()) {
|
||||
const auto profile_name =
|
||||
ReadStringSetting(std::string(player_prefix).append("profile_name"));
|
||||
if (profile_name.empty()) {
|
||||
// Use the global input config
|
||||
player = Settings::values.players.GetValue(true)[player_index];
|
||||
return;
|
||||
}
|
||||
player.profile_name = profile_name;
|
||||
}
|
||||
|
||||
if (player_prefix.empty() && Settings::IsConfiguringGlobal()) {
|
||||
const auto controller = static_cast<Settings::ControllerType>(
|
||||
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
||||
static_cast<u8>(Settings::ControllerType::ProController)));
|
||||
|
||||
if (controller == Settings::ControllerType::LeftJoycon ||
|
||||
controller == Settings::ControllerType::RightJoycon) {
|
||||
player.controller_type = controller;
|
||||
}
|
||||
} else {
|
||||
std::string connected_key = player_prefix;
|
||||
player.connected = ReadBooleanSetting(connected_key.append("connected"),
|
||||
std::make_optional(player_index == 0));
|
||||
|
||||
player.controller_type = static_cast<Settings::ControllerType>(
|
||||
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
||||
static_cast<u8>(Settings::ControllerType::ProController)));
|
||||
|
||||
player.vibration_enabled = ReadBooleanSetting(
|
||||
std::string(player_prefix).append("vibration_enabled"), std::make_optional(true));
|
||||
|
||||
player.vibration_strength = static_cast<int>(
|
||||
ReadIntegerSetting(std::string(player_prefix).append("vibration_strength"), 100));
|
||||
|
||||
player.body_color_left = static_cast<u32>(ReadIntegerSetting(
|
||||
std::string(player_prefix).append("body_color_left"), Settings::JOYCON_BODY_NEON_BLUE));
|
||||
player.body_color_right = static_cast<u32>(ReadIntegerSetting(
|
||||
std::string(player_prefix).append("body_color_right"), Settings::JOYCON_BODY_NEON_RED));
|
||||
player.button_color_left = static_cast<u32>(
|
||||
ReadIntegerSetting(std::string(player_prefix).append("button_color_left"),
|
||||
Settings::JOYCON_BUTTONS_NEON_BLUE));
|
||||
player.button_color_right = static_cast<u32>(
|
||||
ReadIntegerSetting(std::string(player_prefix).append("button_color_right"),
|
||||
Settings::JOYCON_BUTTONS_NEON_RED));
|
||||
}
|
||||
}
|
||||
|
||||
void Config::ReadTouchscreenValues() {
|
||||
Settings::values.touchscreen.enabled =
|
||||
ReadBooleanSetting(std::string("touchscreen_enabled"), std::make_optional(true));
|
||||
Settings::values.touchscreen.rotation_angle =
|
||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_angle"), 0));
|
||||
Settings::values.touchscreen.diameter_x =
|
||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 15));
|
||||
Settings::values.touchscreen.diameter_y =
|
||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 15));
|
||||
}
|
||||
|
||||
void Config::ReadAudioValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Audio));
|
||||
|
||||
ReadCategory(Settings::Category::Audio);
|
||||
ReadCategory(Settings::Category::UiAudio);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadControlValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
ReadCategory(Settings::Category::Controls);
|
||||
|
||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
ReadPlayerValues(p);
|
||||
}
|
||||
|
||||
// Disable docked mode if handheld is selected
|
||||
const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
|
||||
if (controller_type == Settings::ControllerType::Handheld) {
|
||||
Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
|
||||
Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
|
||||
}
|
||||
|
||||
if (IsCustomConfig()) {
|
||||
EndGroup();
|
||||
return;
|
||||
}
|
||||
ReadTouchscreenValues();
|
||||
ReadMotionTouchValues();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadMotionTouchValues() {
|
||||
int num_touch_from_button_maps = BeginArray(std::string("touch_from_button_maps"));
|
||||
|
||||
if (num_touch_from_button_maps > 0) {
|
||||
for (int i = 0; i < num_touch_from_button_maps; ++i) {
|
||||
SetArrayIndex(i);
|
||||
|
||||
Settings::TouchFromButtonMap map;
|
||||
map.name = ReadStringSetting(std::string("name"), std::string("default"));
|
||||
|
||||
const int num_touch_maps = BeginArray(std::string("entries"));
|
||||
map.buttons.reserve(num_touch_maps);
|
||||
for (int j = 0; j < num_touch_maps; j++) {
|
||||
SetArrayIndex(j);
|
||||
std::string touch_mapping = ReadStringSetting(std::string("bind"));
|
||||
map.buttons.emplace_back(std::move(touch_mapping));
|
||||
}
|
||||
EndArray(); // entries
|
||||
Settings::values.touch_from_button_maps.emplace_back(std::move(map));
|
||||
}
|
||||
} else {
|
||||
Settings::values.touch_from_button_maps.emplace_back(
|
||||
Settings::TouchFromButtonMap{"default", {}});
|
||||
num_touch_from_button_maps = 1;
|
||||
}
|
||||
EndArray(); // touch_from_button_maps
|
||||
|
||||
Settings::values.touch_from_button_map_index = std::clamp(
|
||||
Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
|
||||
}
|
||||
|
||||
void Config::ReadCoreValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
|
||||
|
||||
ReadCategory(Settings::Category::Core);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadDataStorageValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||
|
||||
FS::SetYuzuPath(FS::YuzuPath::NANDDir, ReadStringSetting(std::string("nand_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::SDMCDir, ReadStringSetting(std::string("sdmc_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::LoadDir, ReadStringSetting(std::string("load_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::DumpDir, ReadStringSetting(std::string("dump_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::TASDir, ReadStringSetting(std::string("tas_directory")));
|
||||
|
||||
ReadCategory(Settings::Category::DataStorage);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadDebuggingValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
||||
|
||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||
Settings::values.record_frame_times =
|
||||
ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false));
|
||||
|
||||
ReadCategory(Settings::Category::Debugging);
|
||||
ReadCategory(Settings::Category::DebuggingGraphics);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadServiceValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
||||
|
||||
ReadCategory(Settings::Category::Services);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadDisabledAddOnValues() {
|
||||
// Custom config section
|
||||
BeginGroup(std::string("DisabledAddOns"));
|
||||
|
||||
const int size = BeginArray(std::string(""));
|
||||
for (int i = 0; i < size; ++i) {
|
||||
SetArrayIndex(i);
|
||||
const auto title_id = ReadIntegerSetting(std::string("title_id"), 0);
|
||||
std::vector<std::string> out;
|
||||
const int d_size = BeginArray("disabled");
|
||||
for (int j = 0; j < d_size; ++j) {
|
||||
SetArrayIndex(j);
|
||||
out.push_back(ReadStringSetting(std::string("d"), std::string("")));
|
||||
}
|
||||
EndArray(); // d
|
||||
Settings::values.disabled_addons.insert_or_assign(title_id, out);
|
||||
}
|
||||
EndArray(); // Base disabled addons array - Has no base key
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadMiscellaneousValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
|
||||
|
||||
ReadCategory(Settings::Category::Miscellaneous);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadCpuValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu));
|
||||
|
||||
ReadCategory(Settings::Category::Cpu);
|
||||
ReadCategory(Settings::Category::CpuDebug);
|
||||
ReadCategory(Settings::Category::CpuUnsafe);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadRendererValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer));
|
||||
|
||||
ReadCategory(Settings::Category::Renderer);
|
||||
ReadCategory(Settings::Category::RendererAdvanced);
|
||||
ReadCategory(Settings::Category::RendererDebug);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadScreenshotValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
|
||||
|
||||
ReadCategory(Settings::Category::Screenshots);
|
||||
FS::SetYuzuPath(FS::YuzuPath::ScreenshotsDir,
|
||||
ReadStringSetting(std::string("screenshot_path"),
|
||||
FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)));
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadSystemValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::System));
|
||||
|
||||
ReadCategory(Settings::Category::System);
|
||||
ReadCategory(Settings::Category::SystemAudio);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadWebServiceValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
|
||||
|
||||
ReadCategory(Settings::Category::WebService);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadNetworkValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
||||
|
||||
ReadCategory(Settings::Category::Network);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::ReadValues() {
|
||||
if (global) {
|
||||
ReadDataStorageValues();
|
||||
ReadDebuggingValues();
|
||||
ReadDisabledAddOnValues();
|
||||
ReadNetworkValues();
|
||||
ReadServiceValues();
|
||||
ReadWebServiceValues();
|
||||
ReadMiscellaneousValues();
|
||||
}
|
||||
ReadControlValues();
|
||||
ReadCoreValues();
|
||||
ReadCpuValues();
|
||||
ReadRendererValues();
|
||||
ReadAudioValues();
|
||||
ReadSystemValues();
|
||||
}
|
||||
|
||||
void Config::SavePlayerValues(const std::size_t player_index) {
|
||||
std::string player_prefix;
|
||||
if (type != ConfigType::InputProfile) {
|
||||
player_prefix = std::string("player_").append(ToString(player_index)).append("_");
|
||||
}
|
||||
|
||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (IsCustomConfig()) {
|
||||
if (player.profile_name.empty()) {
|
||||
// No custom profile selected
|
||||
return;
|
||||
}
|
||||
WriteSetting(std::string(player_prefix).append("profile_name"), player.profile_name,
|
||||
std::make_optional(std::string("")));
|
||||
}
|
||||
|
||||
WriteSetting(std::string(player_prefix).append("type"), static_cast<u8>(player.controller_type),
|
||||
std::make_optional(static_cast<u8>(Settings::ControllerType::ProController)));
|
||||
|
||||
if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) {
|
||||
WriteSetting(std::string(player_prefix).append("connected"), player.connected,
|
||||
std::make_optional(player_index == 0));
|
||||
WriteSetting(std::string(player_prefix).append("vibration_enabled"),
|
||||
player.vibration_enabled, std::make_optional(true));
|
||||
WriteSetting(std::string(player_prefix).append("vibration_strength"),
|
||||
player.vibration_strength, std::make_optional(100));
|
||||
WriteSetting(std::string(player_prefix).append("body_color_left"), player.body_color_left,
|
||||
std::make_optional(Settings::JOYCON_BODY_NEON_BLUE));
|
||||
WriteSetting(std::string(player_prefix).append("body_color_right"), player.body_color_right,
|
||||
std::make_optional(Settings::JOYCON_BODY_NEON_RED));
|
||||
WriteSetting(std::string(player_prefix).append("button_color_left"),
|
||||
player.button_color_left,
|
||||
std::make_optional(Settings::JOYCON_BUTTONS_NEON_BLUE));
|
||||
WriteSetting(std::string(player_prefix).append("button_color_right"),
|
||||
player.button_color_right,
|
||||
std::make_optional(Settings::JOYCON_BUTTONS_NEON_RED));
|
||||
}
|
||||
}
|
||||
|
||||
void Config::SaveTouchscreenValues() {
|
||||
const auto& touchscreen = Settings::values.touchscreen;
|
||||
|
||||
WriteSetting(std::string("touchscreen_enabled"), touchscreen.enabled, std::make_optional(true));
|
||||
|
||||
WriteSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle,
|
||||
std::make_optional(static_cast<u32>(0)));
|
||||
WriteSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x,
|
||||
std::make_optional(static_cast<u32>(15)));
|
||||
WriteSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y,
|
||||
std::make_optional(static_cast<u32>(15)));
|
||||
}
|
||||
|
||||
void Config::SaveMotionTouchValues() {
|
||||
BeginArray(std::string("touch_from_button_maps"));
|
||||
for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
|
||||
SetArrayIndex(static_cast<int>(p));
|
||||
WriteSetting(std::string("name"), Settings::values.touch_from_button_maps[p].name,
|
||||
std::make_optional(std::string("default")));
|
||||
|
||||
BeginArray(std::string("entries"));
|
||||
for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size();
|
||||
++q) {
|
||||
SetArrayIndex(static_cast<int>(q));
|
||||
WriteSetting(std::string("bind"),
|
||||
Settings::values.touch_from_button_maps[p].buttons[q]);
|
||||
}
|
||||
EndArray(); // entries
|
||||
}
|
||||
EndArray(); // touch_from_button_maps
|
||||
}
|
||||
|
||||
void Config::SaveValues() {
|
||||
if (global) {
|
||||
SaveDataStorageValues();
|
||||
SaveDebuggingValues();
|
||||
SaveDisabledAddOnValues();
|
||||
SaveNetworkValues();
|
||||
SaveWebServiceValues();
|
||||
SaveMiscellaneousValues();
|
||||
}
|
||||
SaveControlValues();
|
||||
SaveCoreValues();
|
||||
SaveCpuValues();
|
||||
SaveRendererValues();
|
||||
SaveAudioValues();
|
||||
SaveSystemValues();
|
||||
|
||||
WriteToIni();
|
||||
}
|
||||
|
||||
void Config::SaveAudioValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Audio));
|
||||
|
||||
WriteCategory(Settings::Category::Audio);
|
||||
WriteCategory(Settings::Category::UiAudio);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveControlValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
WriteCategory(Settings::Category::Controls);
|
||||
|
||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
SavePlayerValues(p);
|
||||
}
|
||||
if (IsCustomConfig()) {
|
||||
EndGroup();
|
||||
return;
|
||||
}
|
||||
SaveTouchscreenValues();
|
||||
SaveMotionTouchValues();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveCoreValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Core));
|
||||
|
||||
WriteCategory(Settings::Category::Core);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveDataStorageValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||
|
||||
WriteSetting(std::string("nand_directory"), FS::GetYuzuPathString(FS::YuzuPath::NANDDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
|
||||
WriteSetting(std::string("sdmc_directory"), FS::GetYuzuPathString(FS::YuzuPath::SDMCDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
|
||||
WriteSetting(std::string("load_directory"), FS::GetYuzuPathString(FS::YuzuPath::LoadDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
|
||||
WriteSetting(std::string("dump_directory"), FS::GetYuzuPathString(FS::YuzuPath::DumpDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
|
||||
WriteSetting(std::string("tas_directory"), FS::GetYuzuPathString(FS::YuzuPath::TASDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
|
||||
|
||||
WriteCategory(Settings::Category::DataStorage);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveDebuggingValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
||||
|
||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||
WriteSetting(std::string("record_frame_times"), Settings::values.record_frame_times);
|
||||
|
||||
WriteCategory(Settings::Category::Debugging);
|
||||
WriteCategory(Settings::Category::DebuggingGraphics);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveNetworkValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
|
||||
|
||||
WriteCategory(Settings::Category::Network);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveDisabledAddOnValues() {
|
||||
// Custom config section
|
||||
BeginGroup(std::string("DisabledAddOns"));
|
||||
|
||||
int i = 0;
|
||||
BeginArray(std::string(""));
|
||||
for (const auto& elem : Settings::values.disabled_addons) {
|
||||
SetArrayIndex(i);
|
||||
WriteSetting(std::string("title_id"), elem.first, std::make_optional(static_cast<u64>(0)));
|
||||
BeginArray(std::string("disabled"));
|
||||
for (std::size_t j = 0; j < elem.second.size(); ++j) {
|
||||
SetArrayIndex(static_cast<int>(j));
|
||||
WriteSetting(std::string("d"), elem.second[j], std::make_optional(std::string("")));
|
||||
}
|
||||
EndArray(); // disabled
|
||||
++i;
|
||||
}
|
||||
EndArray(); // Base disabled addons array - Has no base key
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveMiscellaneousValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Miscellaneous));
|
||||
|
||||
WriteCategory(Settings::Category::Miscellaneous);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveCpuValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Cpu));
|
||||
|
||||
WriteCategory(Settings::Category::Cpu);
|
||||
WriteCategory(Settings::Category::CpuDebug);
|
||||
WriteCategory(Settings::Category::CpuUnsafe);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveRendererValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Renderer));
|
||||
|
||||
WriteCategory(Settings::Category::Renderer);
|
||||
WriteCategory(Settings::Category::RendererAdvanced);
|
||||
WriteCategory(Settings::Category::RendererDebug);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveScreenshotValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
|
||||
|
||||
WriteSetting(std::string("screenshot_path"),
|
||||
FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir));
|
||||
WriteCategory(Settings::Category::Screenshots);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveSystemValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::System));
|
||||
|
||||
WriteCategory(Settings::Category::System);
|
||||
WriteCategory(Settings::Category::SystemAudio);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void Config::SaveWebServiceValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::WebService));
|
||||
|
||||
WriteCategory(Settings::Category::WebService);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
bool Config::ReadBooleanSetting(const std::string& key, const std::optional<bool> default_value) {
|
||||
std::string full_key = GetFullKey(key, false);
|
||||
if (!default_value.has_value()) {
|
||||
return config->GetBoolValue(GetSection().c_str(), full_key.c_str(), false);
|
||||
}
|
||||
|
||||
if (config->GetBoolValue(GetSection().c_str(),
|
||||
std::string(full_key).append("\\default").c_str(), false)) {
|
||||
return static_cast<bool>(default_value.value());
|
||||
} else {
|
||||
return config->GetBoolValue(GetSection().c_str(), full_key.c_str(),
|
||||
static_cast<bool>(default_value.value()));
|
||||
}
|
||||
}
|
||||
|
||||
s64 Config::ReadIntegerSetting(const std::string& key, const std::optional<s64> default_value) {
|
||||
std::string full_key = GetFullKey(key, false);
|
||||
if (!default_value.has_value()) {
|
||||
try {
|
||||
return std::stoll(
|
||||
std::string(config->GetValue(GetSection().c_str(), full_key.c_str(), "0")));
|
||||
} catch (...) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
s64 result = 0;
|
||||
if (config->GetBoolValue(GetSection().c_str(),
|
||||
std::string(full_key).append("\\default").c_str(), true)) {
|
||||
result = default_value.value();
|
||||
} else {
|
||||
try {
|
||||
result = std::stoll(std::string(config->GetValue(
|
||||
GetSection().c_str(), full_key.c_str(), ToString(default_value.value()).c_str())));
|
||||
} catch (...) {
|
||||
result = default_value.value();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double Config::ReadDoubleSetting(const std::string& key,
|
||||
const std::optional<double> default_value) {
|
||||
std::string full_key = GetFullKey(key, false);
|
||||
if (!default_value.has_value()) {
|
||||
return config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), 0);
|
||||
}
|
||||
|
||||
double result;
|
||||
if (config->GetBoolValue(GetSection().c_str(),
|
||||
std::string(full_key).append("\\default").c_str(), true)) {
|
||||
result = default_value.value();
|
||||
} else {
|
||||
result =
|
||||
config->GetDoubleValue(GetSection().c_str(), full_key.c_str(), default_value.value());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Config::ReadStringSetting(const std::string& key,
|
||||
const std::optional<std::string> default_value) {
|
||||
std::string result;
|
||||
std::string full_key = GetFullKey(key, false);
|
||||
if (!default_value.has_value()) {
|
||||
result = config->GetValue(GetSection().c_str(), full_key.c_str(), "");
|
||||
boost::replace_all(result, "\"", "");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (config->GetBoolValue(GetSection().c_str(),
|
||||
std::string(full_key).append("\\default").c_str(), true)) {
|
||||
result = default_value.value();
|
||||
} else {
|
||||
result =
|
||||
config->GetValue(GetSection().c_str(), full_key.c_str(), default_value.value().c_str());
|
||||
}
|
||||
boost::replace_all(result, "\"", "");
|
||||
boost::replace_all(result, "//", "/");
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Config::Exists(const std::string& section, const std::string& key) const {
|
||||
const std::string value = config->GetValue(section.c_str(), key.c_str(), "");
|
||||
return !value.empty();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Config::WriteSetting(const std::string& key, const Type& value,
|
||||
const std::optional<Type>& default_value,
|
||||
const std::optional<bool>& use_global) {
|
||||
std::string full_key = GetFullKey(key, false);
|
||||
|
||||
std::string saved_value;
|
||||
std::string string_default;
|
||||
if constexpr (std::is_same_v<Type, std::string>) {
|
||||
saved_value.append(AdjustOutputString(value));
|
||||
if (default_value.has_value()) {
|
||||
string_default.append(AdjustOutputString(default_value.value()));
|
||||
}
|
||||
} else {
|
||||
saved_value.append(AdjustOutputString(ToString(value)));
|
||||
if (default_value.has_value()) {
|
||||
string_default.append(ToString(default_value.value()));
|
||||
}
|
||||
}
|
||||
|
||||
if (default_value.has_value() && use_global.has_value()) {
|
||||
if (!global) {
|
||||
WriteSettingInternal(std::string(full_key).append("\\global"),
|
||||
ToString(use_global.value()));
|
||||
}
|
||||
if (global || use_global.value() == false) {
|
||||
WriteSettingInternal(std::string(full_key).append("\\default"),
|
||||
ToString(string_default == saved_value));
|
||||
WriteSettingInternal(full_key, saved_value);
|
||||
}
|
||||
} else if (default_value.has_value() && !use_global.has_value()) {
|
||||
WriteSettingInternal(std::string(full_key).append("\\default"),
|
||||
ToString(string_default == saved_value));
|
||||
WriteSettingInternal(full_key, saved_value);
|
||||
} else {
|
||||
WriteSettingInternal(full_key, saved_value);
|
||||
}
|
||||
}
|
||||
|
||||
void Config::WriteSettingInternal(const std::string& key, const std::string& value) {
|
||||
config->SetValue(GetSection().c_str(), key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
void Config::Reload() {
|
||||
ReadValues();
|
||||
// To apply default value changes
|
||||
SaveValues();
|
||||
}
|
||||
|
||||
void Config::Save() {
|
||||
SaveValues();
|
||||
}
|
||||
|
||||
void Config::ClearControlPlayerValues() const {
|
||||
// If key is an empty string, all keys in the current group() are removed.
|
||||
const char* section = Settings::TranslateCategory(Settings::Category::Controls);
|
||||
CSimpleIniA::TNamesDepend keys;
|
||||
config->GetAllKeys(section, keys);
|
||||
for (const auto& key : keys) {
|
||||
if (std::string(config->GetValue(section, key.pItem)).empty()) {
|
||||
config->Delete(section, key.pItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& Config::GetConfigFilePath() const {
|
||||
return config_loc;
|
||||
}
|
||||
|
||||
void Config::ReadCategory(const Settings::Category category) {
|
||||
const auto& settings = FindRelevantList(category);
|
||||
std::ranges::for_each(settings, [&](const auto& setting) { ReadSettingGeneric(setting); });
|
||||
}
|
||||
|
||||
void Config::WriteCategory(const Settings::Category category) {
|
||||
const auto& settings = FindRelevantList(category);
|
||||
std::ranges::for_each(settings, [&](const auto& setting) { WriteSettingGeneric(setting); });
|
||||
}
|
||||
|
||||
void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) {
|
||||
if (!setting->Save() || (!setting->Switchable() && !global)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string key = AdjustKey(setting->GetLabel());
|
||||
const std::string default_value(setting->DefaultToString());
|
||||
|
||||
bool use_global = true;
|
||||
if (setting->Switchable() && !global) {
|
||||
use_global =
|
||||
ReadBooleanSetting(std::string(key).append("\\use_global"), std::make_optional(true));
|
||||
setting->SetGlobal(use_global);
|
||||
}
|
||||
|
||||
if (global || !use_global) {
|
||||
const bool is_default =
|
||||
ReadBooleanSetting(std::string(key).append("\\default"), std::make_optional(true));
|
||||
if (!is_default) {
|
||||
const std::string setting_string = ReadStringSetting(key, default_value);
|
||||
setting->LoadString(setting_string);
|
||||
} else {
|
||||
// Empty string resets the Setting to default
|
||||
setting->LoadString("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Config::WriteSettingGeneric(const Settings::BasicSetting* const setting) {
|
||||
if (!setting->Save()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string key = AdjustKey(setting->GetLabel());
|
||||
if (setting->Switchable()) {
|
||||
if (!global) {
|
||||
WriteSetting(std::string(key).append("\\use_global"), setting->UsingGlobal());
|
||||
}
|
||||
if (global || !setting->UsingGlobal()) {
|
||||
WriteSetting(std::string(key).append("\\default"),
|
||||
setting->ToString() == setting->DefaultToString());
|
||||
WriteSetting(key, setting->ToString());
|
||||
}
|
||||
} else if (global) {
|
||||
WriteSetting(std::string(key).append("\\default"),
|
||||
setting->ToString() == setting->DefaultToString());
|
||||
WriteSetting(key, setting->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
void Config::BeginGroup(const std::string& group) {
|
||||
// You can't begin a group while reading/writing from a config array
|
||||
ASSERT(array_stack.empty());
|
||||
|
||||
key_stack.push_back(AdjustKey(group));
|
||||
}
|
||||
|
||||
void Config::EndGroup() {
|
||||
// You can't end a group if you haven't started one yet
|
||||
ASSERT(!key_stack.empty());
|
||||
|
||||
// You can't end a group when reading/writing from a config array
|
||||
ASSERT(array_stack.empty());
|
||||
|
||||
key_stack.pop_back();
|
||||
}
|
||||
|
||||
std::string Config::GetSection() {
|
||||
if (key_stack.empty()) {
|
||||
return std::string{""};
|
||||
}
|
||||
|
||||
return key_stack.front();
|
||||
}
|
||||
|
||||
std::string Config::GetGroup() const {
|
||||
if (key_stack.size() <= 1) {
|
||||
return std::string{""};
|
||||
}
|
||||
|
||||
std::string key;
|
||||
for (size_t i = 1; i < key_stack.size(); ++i) {
|
||||
key.append(key_stack[i]).append("\\");
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
std::string Config::AdjustKey(const std::string& key) {
|
||||
std::string adjusted_key(key);
|
||||
boost::replace_all(adjusted_key, "/", "\\");
|
||||
boost::replace_all(adjusted_key, " ", "%20");
|
||||
return adjusted_key;
|
||||
}
|
||||
|
||||
std::string Config::AdjustOutputString(const std::string& string) {
|
||||
std::string adjusted_string(string);
|
||||
boost::replace_all(adjusted_string, "\\", "/");
|
||||
boost::replace_all(adjusted_string, "//", "/");
|
||||
|
||||
// Needed for backwards compatibility with QSettings deserialization
|
||||
for (const auto& special_character : special_characters) {
|
||||
if (adjusted_string.find(special_character) != std::string::npos) {
|
||||
adjusted_string.insert(0, "\"");
|
||||
adjusted_string.append("\"");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return adjusted_string;
|
||||
}
|
||||
|
||||
std::string Config::GetFullKey(const std::string& key, bool skipArrayIndex) {
|
||||
if (array_stack.empty()) {
|
||||
return std::string(GetGroup()).append(AdjustKey(key));
|
||||
}
|
||||
|
||||
std::string array_key;
|
||||
for (size_t i = 0; i < array_stack.size(); ++i) {
|
||||
if (!array_stack[i].name.empty()) {
|
||||
array_key.append(array_stack[i].name).append("\\");
|
||||
}
|
||||
|
||||
if (!skipArrayIndex || (array_stack.size() - 1 != i && array_stack.size() > 1)) {
|
||||
array_key.append(ToString(array_stack[i].index)).append("\\");
|
||||
}
|
||||
}
|
||||
std::string final_key = std::string(GetGroup()).append(array_key).append(AdjustKey(key));
|
||||
return final_key;
|
||||
}
|
||||
|
||||
int Config::BeginArray(const std::string& array) {
|
||||
array_stack.push_back(ConfigArray{AdjustKey(array), 0, 0});
|
||||
const int size = config->GetLongValue(GetSection().c_str(),
|
||||
GetFullKey(std::string("size"), true).c_str(), 0);
|
||||
array_stack.back().size = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
void Config::EndArray() {
|
||||
// You can't end a config array before starting one
|
||||
ASSERT(!array_stack.empty());
|
||||
|
||||
// Write out the size to config
|
||||
if (key_stack.size() == 1 && array_stack.back().name.empty()) {
|
||||
// Edge-case where the first array created doesn't have a name
|
||||
config->SetValue(GetSection().c_str(), std::string("size").c_str(),
|
||||
ToString(array_stack.back().size).c_str());
|
||||
} else {
|
||||
const auto key = GetFullKey(std::string("size"), true);
|
||||
config->SetValue(GetSection().c_str(), key.c_str(),
|
||||
ToString(array_stack.back().size).c_str());
|
||||
}
|
||||
|
||||
array_stack.pop_back();
|
||||
}
|
||||
|
||||
void Config::SetArrayIndex(const int index) {
|
||||
// You can't set the array index if you haven't started one yet
|
||||
ASSERT(!array_stack.empty());
|
||||
|
||||
const int array_index = index + 1;
|
||||
|
||||
// You can't exceed the known max size of the array by more than 1
|
||||
ASSERT(array_stack.front().size + 1 >= array_index);
|
||||
|
||||
// Change the config array size to the current index since you may want
|
||||
// to reduce the number of elements that you read back from the config
|
||||
// in the future.
|
||||
array_stack.back().size = array_index;
|
||||
array_stack.back().index = array_index;
|
||||
}
|
206
src/frontend_common/config.h
Normal file
206
src/frontend_common/config.h
Normal file
@ -0,0 +1,206 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "common/settings.h"
|
||||
|
||||
#include <SimpleIni.h>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
// Workaround for conflicting definition in libloaderapi.h caused by SimpleIni
|
||||
#undef LoadString
|
||||
#undef CreateFile
|
||||
#undef DeleteFile
|
||||
#undef CopyFile
|
||||
#undef CreateDirectory
|
||||
#undef MoveFile
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
class Config {
|
||||
public:
|
||||
enum class ConfigType {
|
||||
GlobalConfig,
|
||||
PerGameConfig,
|
||||
InputProfile,
|
||||
};
|
||||
|
||||
virtual ~Config() = default;
|
||||
|
||||
void ClearControlPlayerValues() const;
|
||||
|
||||
[[nodiscard]] const std::string& GetConfigFilePath() const;
|
||||
|
||||
[[nodiscard]] bool Exists(const std::string& section, const std::string& key) const;
|
||||
|
||||
protected:
|
||||
explicit Config(ConfigType config_type = ConfigType::GlobalConfig);
|
||||
|
||||
void Initialize(const std::string& config_name = "config");
|
||||
void Initialize(std::optional<std::string> config_path);
|
||||
|
||||
void WriteToIni() const;
|
||||
|
||||
void SetUpIni();
|
||||
[[nodiscard]] bool IsCustomConfig() const;
|
||||
|
||||
void Reload();
|
||||
void Save();
|
||||
|
||||
/**
|
||||
* Derived config classes must implement this so they can reload all platform-specific
|
||||
* values and global ones.
|
||||
*/
|
||||
virtual void ReloadAllValues() = 0;
|
||||
|
||||
/**
|
||||
* Derived config classes must implement this so they can save all platform-specific
|
||||
* and global values.
|
||||
*/
|
||||
virtual void SaveAllValues() = 0;
|
||||
|
||||
void ReadValues();
|
||||
void ReadPlayerValues(std::size_t player_index);
|
||||
|
||||
void ReadTouchscreenValues();
|
||||
void ReadMotionTouchValues();
|
||||
|
||||
// Read functions bases off the respective config section names.
|
||||
void ReadAudioValues();
|
||||
void ReadControlValues();
|
||||
void ReadCoreValues();
|
||||
void ReadDataStorageValues();
|
||||
void ReadDebuggingValues();
|
||||
void ReadServiceValues();
|
||||
void ReadDisabledAddOnValues();
|
||||
void ReadMiscellaneousValues();
|
||||
void ReadCpuValues();
|
||||
void ReadRendererValues();
|
||||
void ReadScreenshotValues();
|
||||
void ReadSystemValues();
|
||||
void ReadWebServiceValues();
|
||||
void ReadNetworkValues();
|
||||
|
||||
// Read platform specific sections
|
||||
virtual void ReadHidbusValues() = 0;
|
||||
virtual void ReadDebugControlValues() = 0;
|
||||
virtual void ReadPathValues() = 0;
|
||||
virtual void ReadShortcutValues() = 0;
|
||||
virtual void ReadUIValues() = 0;
|
||||
virtual void ReadUIGamelistValues() = 0;
|
||||
virtual void ReadUILayoutValues() = 0;
|
||||
virtual void ReadMultiplayerValues() = 0;
|
||||
|
||||
void SaveValues();
|
||||
void SavePlayerValues(std::size_t player_index);
|
||||
void SaveTouchscreenValues();
|
||||
void SaveMotionTouchValues();
|
||||
|
||||
// Save functions based off the respective config section names.
|
||||
void SaveAudioValues();
|
||||
void SaveControlValues();
|
||||
void SaveCoreValues();
|
||||
void SaveDataStorageValues();
|
||||
void SaveDebuggingValues();
|
||||
void SaveNetworkValues();
|
||||
void SaveDisabledAddOnValues();
|
||||
void SaveMiscellaneousValues();
|
||||
void SaveCpuValues();
|
||||
void SaveRendererValues();
|
||||
void SaveScreenshotValues();
|
||||
void SaveSystemValues();
|
||||
void SaveWebServiceValues();
|
||||
|
||||
// Save platform specific sections
|
||||
virtual void SaveHidbusValues() = 0;
|
||||
virtual void SaveDebugControlValues() = 0;
|
||||
virtual void SavePathValues() = 0;
|
||||
virtual void SaveShortcutValues() = 0;
|
||||
virtual void SaveUIValues() = 0;
|
||||
virtual void SaveUIGamelistValues() = 0;
|
||||
virtual void SaveUILayoutValues() = 0;
|
||||
virtual void SaveMultiplayerValues() = 0;
|
||||
|
||||
virtual std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) = 0;
|
||||
|
||||
/**
|
||||
* Reads a setting from the qt_config.
|
||||
*
|
||||
* @param key The setting's identifier
|
||||
* @param default_value The value to use when the setting is not already present in the config
|
||||
*/
|
||||
bool ReadBooleanSetting(const std::string& key,
|
||||
std::optional<bool> default_value = std::nullopt);
|
||||
s64 ReadIntegerSetting(const std::string& key, std::optional<s64> default_value = std::nullopt);
|
||||
double ReadDoubleSetting(const std::string& key,
|
||||
std::optional<double> default_value = std::nullopt);
|
||||
std::string ReadStringSetting(const std::string& key,
|
||||
std::optional<std::string> default_value = std::nullopt);
|
||||
|
||||
/**
|
||||
* Writes a setting to the qt_config.
|
||||
*
|
||||
* @param key The setting's idetentifier
|
||||
* @param value Value of the setting
|
||||
* @param default_value Default of the setting if not present in config
|
||||
* @param use_global Specifies if the custom or global config should be in use, for custom
|
||||
* configs
|
||||
*/
|
||||
template <typename Type = int>
|
||||
void WriteSetting(const std::string& key, const Type& value,
|
||||
const std::optional<Type>& default_value = std::nullopt,
|
||||
const std::optional<bool>& use_global = std::nullopt);
|
||||
void WriteSettingInternal(const std::string& key, const std::string& value);
|
||||
|
||||
void ReadCategory(Settings::Category category);
|
||||
void WriteCategory(Settings::Category category);
|
||||
void ReadSettingGeneric(Settings::BasicSetting* setting);
|
||||
void WriteSettingGeneric(const Settings::BasicSetting* setting);
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] std::string ToString(const T& value_) {
|
||||
if constexpr (std::is_same_v<T, std::string>) {
|
||||
return value_;
|
||||
} else if constexpr (std::is_same_v<T, std::optional<u32>>) {
|
||||
return value_.has_value() ? std::to_string(*value_) : "none";
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
return value_ ? "true" : "false";
|
||||
} else {
|
||||
return std::to_string(static_cast<s64>(value_));
|
||||
}
|
||||
}
|
||||
|
||||
void BeginGroup(const std::string& group);
|
||||
void EndGroup();
|
||||
std::string GetSection();
|
||||
[[nodiscard]] std::string GetGroup() const;
|
||||
static std::string AdjustKey(const std::string& key);
|
||||
static std::string AdjustOutputString(const std::string& string);
|
||||
std::string GetFullKey(const std::string& key, bool skipArrayIndex);
|
||||
int BeginArray(const std::string& array);
|
||||
void EndArray();
|
||||
void SetArrayIndex(int index);
|
||||
|
||||
const ConfigType type;
|
||||
std::unique_ptr<CSimpleIniA> config;
|
||||
std::string config_loc;
|
||||
const bool global;
|
||||
|
||||
private:
|
||||
inline static std::array<char, 19> special_characters = {'!', '#', '$', '%', '^', '&', '*',
|
||||
'|', ';', '\'', '\"', ',', '<', '.',
|
||||
'>', '?', '`', '~', '='};
|
||||
|
||||
struct ConfigArray {
|
||||
std::string name;
|
||||
int size;
|
||||
int index;
|
||||
};
|
||||
std::vector<ConfigArray> array_stack;
|
||||
std::vector<std::string> key_stack;
|
||||
};
|
@ -38,8 +38,6 @@ add_executable(yuzu
|
||||
compatdb.ui
|
||||
compatibility_list.cpp
|
||||
compatibility_list.h
|
||||
configuration/config.cpp
|
||||
configuration/config.h
|
||||
configuration/configuration_shared.cpp
|
||||
configuration/configuration_shared.h
|
||||
configuration/configure.ui
|
||||
@ -147,6 +145,8 @@ add_executable(yuzu
|
||||
configuration/shared_translation.h
|
||||
configuration/shared_widget.cpp
|
||||
configuration/shared_widget.h
|
||||
configuration/qt_config.cpp
|
||||
configuration/qt_config.h
|
||||
debugger/console.cpp
|
||||
debugger/console.h
|
||||
debugger/controller.cpp
|
||||
@ -344,7 +344,7 @@ endif()
|
||||
|
||||
create_target_directory_groups(yuzu)
|
||||
|
||||
target_link_libraries(yuzu PRIVATE common core input_common network video_core)
|
||||
target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
|
||||
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets)
|
||||
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,179 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <QMetaType>
|
||||
#include <QVariant>
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_enums.h"
|
||||
#include "yuzu/uisettings.h"
|
||||
|
||||
class QSettings;
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
class Config {
|
||||
public:
|
||||
enum class ConfigType {
|
||||
GlobalConfig,
|
||||
PerGameConfig,
|
||||
InputProfile,
|
||||
};
|
||||
|
||||
explicit Config(const std::string& config_name = "qt-config",
|
||||
ConfigType config_type = ConfigType::GlobalConfig);
|
||||
~Config();
|
||||
|
||||
void Reload();
|
||||
void Save();
|
||||
|
||||
void ReadControlPlayerValue(std::size_t player_index);
|
||||
void SaveControlPlayerValue(std::size_t player_index);
|
||||
void ClearControlPlayerValues();
|
||||
|
||||
const std::string& GetConfigFilePath() const;
|
||||
|
||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
|
||||
static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||
static const std::array<int, 2> default_stick_mod;
|
||||
static const std::array<int, 2> default_ringcon_analogs;
|
||||
static const std::array<int, Settings::NativeMouseButton::NumMouseButtons>
|
||||
default_mouse_buttons;
|
||||
static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
|
||||
static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
|
||||
static const std::array<UISettings::Shortcut, 23> default_hotkeys;
|
||||
|
||||
static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map;
|
||||
static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map;
|
||||
static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map;
|
||||
static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map;
|
||||
static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map;
|
||||
static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map;
|
||||
|
||||
static constexpr UISettings::Theme default_theme{
|
||||
#ifdef _WIN32
|
||||
UISettings::Theme::DarkColorful
|
||||
#else
|
||||
UISettings::Theme::DefaultColorful
|
||||
#endif
|
||||
};
|
||||
|
||||
private:
|
||||
void Initialize(const std::string& config_name);
|
||||
bool IsCustomConfig();
|
||||
|
||||
void ReadValues();
|
||||
void ReadPlayerValue(std::size_t player_index);
|
||||
void ReadDebugValues();
|
||||
void ReadKeyboardValues();
|
||||
void ReadMouseValues();
|
||||
void ReadTouchscreenValues();
|
||||
void ReadMotionTouchValues();
|
||||
void ReadHidbusValues();
|
||||
void ReadIrCameraValues();
|
||||
|
||||
// Read functions bases off the respective config section names.
|
||||
void ReadAudioValues();
|
||||
void ReadControlValues();
|
||||
void ReadCoreValues();
|
||||
void ReadDataStorageValues();
|
||||
void ReadDebuggingValues();
|
||||
void ReadServiceValues();
|
||||
void ReadDisabledAddOnValues();
|
||||
void ReadMiscellaneousValues();
|
||||
void ReadPathValues();
|
||||
void ReadCpuValues();
|
||||
void ReadRendererValues();
|
||||
void ReadScreenshotValues();
|
||||
void ReadShortcutValues();
|
||||
void ReadSystemValues();
|
||||
void ReadUIValues();
|
||||
void ReadUIGamelistValues();
|
||||
void ReadUILayoutValues();
|
||||
void ReadWebServiceValues();
|
||||
void ReadMultiplayerValues();
|
||||
void ReadNetworkValues();
|
||||
|
||||
void SaveValues();
|
||||
void SavePlayerValue(std::size_t player_index);
|
||||
void SaveDebugValues();
|
||||
void SaveMouseValues();
|
||||
void SaveTouchscreenValues();
|
||||
void SaveMotionTouchValues();
|
||||
void SaveHidbusValues();
|
||||
void SaveIrCameraValues();
|
||||
|
||||
// Save functions based off the respective config section names.
|
||||
void SaveAudioValues();
|
||||
void SaveControlValues();
|
||||
void SaveCoreValues();
|
||||
void SaveDataStorageValues();
|
||||
void SaveDebuggingValues();
|
||||
void SaveNetworkValues();
|
||||
void SaveDisabledAddOnValues();
|
||||
void SaveMiscellaneousValues();
|
||||
void SavePathValues();
|
||||
void SaveCpuValues();
|
||||
void SaveRendererValues();
|
||||
void SaveScreenshotValues();
|
||||
void SaveShortcutValues();
|
||||
void SaveSystemValues();
|
||||
void SaveUIValues();
|
||||
void SaveUIGamelistValues();
|
||||
void SaveUILayoutValues();
|
||||
void SaveWebServiceValues();
|
||||
void SaveMultiplayerValues();
|
||||
|
||||
/**
|
||||
* Reads a setting from the qt_config.
|
||||
*
|
||||
* @param name The setting's identifier
|
||||
* @param default_value The value to use when the setting is not already present in the config
|
||||
*/
|
||||
QVariant ReadSetting(const QString& name) const;
|
||||
QVariant ReadSetting(const QString& name, const QVariant& default_value) const;
|
||||
|
||||
/**
|
||||
* Writes a setting to the qt_config.
|
||||
*
|
||||
* @param name The setting's idetentifier
|
||||
* @param value Value of the setting
|
||||
* @param default_value Default of the setting if not present in qt_config
|
||||
* @param use_global Specifies if the custom or global config should be in use, for custom
|
||||
* configs
|
||||
*/
|
||||
void WriteSetting(const QString& name, const QVariant& value);
|
||||
void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value);
|
||||
void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value,
|
||||
bool use_global);
|
||||
|
||||
void ReadCategory(Settings::Category category);
|
||||
void WriteCategory(Settings::Category category);
|
||||
void ReadSettingGeneric(Settings::BasicSetting* const setting);
|
||||
void WriteSettingGeneric(Settings::BasicSetting* const setting) const;
|
||||
|
||||
const ConfigType type;
|
||||
std::unique_ptr<QSettings> qt_config;
|
||||
std::string qt_config_loc;
|
||||
const bool global;
|
||||
};
|
||||
|
||||
// These metatype declarations cannot be in common/settings.h because core is devoid of QT
|
||||
Q_DECLARE_METATYPE(Settings::CpuAccuracy);
|
||||
Q_DECLARE_METATYPE(Settings::GpuAccuracy);
|
||||
Q_DECLARE_METATYPE(Settings::FullscreenMode);
|
||||
Q_DECLARE_METATYPE(Settings::NvdecEmulation);
|
||||
Q_DECLARE_METATYPE(Settings::ResolutionSetup);
|
||||
Q_DECLARE_METATYPE(Settings::ScalingFilter);
|
||||
Q_DECLARE_METATYPE(Settings::AntiAliasing);
|
||||
Q_DECLARE_METATYPE(Settings::RendererBackend);
|
||||
Q_DECLARE_METATYPE(Settings::ShaderBackend);
|
||||
Q_DECLARE_METATYPE(Settings::AstcRecompression);
|
||||
Q_DECLARE_METATYPE(Settings::AstcDecodeMode);
|
@ -10,10 +10,10 @@
|
||||
#include <QStandardItemModel>
|
||||
#include <QTimer>
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "input_common/drivers/camera.h"
|
||||
#include "input_common/main.h"
|
||||
#include "ui_configure_camera.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_camera.h"
|
||||
|
||||
ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_)
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "core/core.h"
|
||||
#include "ui_configure.h"
|
||||
#include "vk_device_info.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_audio.h"
|
||||
#include "yuzu/configuration/configure_cpu.h"
|
||||
#include "yuzu/configuration/configure_debug_tab.h"
|
||||
|
@ -9,10 +9,11 @@
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "core/hid/hid_core.h"
|
||||
|
||||
#include "frontend_common/config.h"
|
||||
#include "ui_configure_hotkeys.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_hotkeys.h"
|
||||
#include "yuzu/hotkeys.h"
|
||||
#include "yuzu/uisettings.h"
|
||||
#include "yuzu/util/sequence_dialog/sequence_dialog.h"
|
||||
|
||||
constexpr int name_column = 0;
|
||||
@ -62,18 +63,21 @@ ConfigureHotkeys::~ConfigureHotkeys() = default;
|
||||
|
||||
void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
|
||||
for (const auto& group : registry.hotkey_groups) {
|
||||
QString parent_item_data = QString::fromStdString(group.first);
|
||||
auto* parent_item =
|
||||
new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(group.first)));
|
||||
new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(parent_item_data)));
|
||||
parent_item->setEditable(false);
|
||||
parent_item->setData(group.first);
|
||||
parent_item->setData(parent_item_data);
|
||||
for (const auto& hotkey : group.second) {
|
||||
auto* action =
|
||||
new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(hotkey.first)));
|
||||
QString hotkey_action_data = QString::fromStdString(hotkey.first);
|
||||
auto* action = new QStandardItem(
|
||||
QCoreApplication::translate("Hotkeys", qPrintable(hotkey_action_data)));
|
||||
auto* keyseq =
|
||||
new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText));
|
||||
auto* controller_keyseq = new QStandardItem(hotkey.second.controller_keyseq);
|
||||
auto* controller_keyseq =
|
||||
new QStandardItem(QString::fromStdString(hotkey.second.controller_keyseq));
|
||||
action->setEditable(false);
|
||||
action->setData(hotkey.first);
|
||||
action->setData(hotkey_action_data);
|
||||
keyseq->setEditable(false);
|
||||
controller_keyseq->setEditable(false);
|
||||
parent_item->appendRow({action, keyseq, controller_keyseq});
|
||||
@ -301,13 +305,13 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
|
||||
const QStandardItem* controller_keyseq =
|
||||
parent->child(key_column_id, controller_column);
|
||||
for (auto& [group, sub_actions] : registry.hotkey_groups) {
|
||||
if (group != parent->data())
|
||||
if (group != parent->data().toString().toStdString())
|
||||
continue;
|
||||
for (auto& [action_name, hotkey] : sub_actions) {
|
||||
if (action_name != action->data())
|
||||
if (action_name != action->data().toString().toStdString())
|
||||
continue;
|
||||
hotkey.keyseq = QKeySequence(keyseq->text());
|
||||
hotkey.controller_keyseq = controller_keyseq->text();
|
||||
hotkey.controller_keyseq = controller_keyseq->text().toStdString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -319,7 +323,7 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
|
||||
void ConfigureHotkeys::RestoreDefaults() {
|
||||
for (int r = 0; r < model->rowCount(); ++r) {
|
||||
const QStandardItem* parent = model->item(r, 0);
|
||||
const int hotkey_size = static_cast<int>(Config::default_hotkeys.size());
|
||||
const int hotkey_size = static_cast<int>(UISettings::default_hotkeys.size());
|
||||
|
||||
if (hotkey_size != parent->rowCount()) {
|
||||
QMessageBox::warning(this, tr("Invalid hotkey settings"),
|
||||
@ -330,10 +334,11 @@ void ConfigureHotkeys::RestoreDefaults() {
|
||||
for (int r2 = 0; r2 < parent->rowCount(); ++r2) {
|
||||
model->item(r, 0)
|
||||
->child(r2, hotkey_column)
|
||||
->setText(Config::default_hotkeys[r2].shortcut.keyseq);
|
||||
->setText(QString::fromStdString(UISettings::default_hotkeys[r2].shortcut.keyseq));
|
||||
model->item(r, 0)
|
||||
->child(r2, controller_column)
|
||||
->setText(Config::default_hotkeys[r2].shortcut.controller_keyseq);
|
||||
->setText(QString::fromStdString(
|
||||
UISettings::default_hotkeys[r2].shortcut.controller_keyseq));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,7 +384,7 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) {
|
||||
|
||||
void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) {
|
||||
const QString& default_key_sequence =
|
||||
Config::default_hotkeys[index.row()].shortcut.controller_keyseq;
|
||||
QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.controller_keyseq);
|
||||
const auto [key_sequence_used, used_action] = IsUsedControllerKey(default_key_sequence);
|
||||
|
||||
if (key_sequence_used && default_key_sequence != model->data(index).toString()) {
|
||||
@ -393,7 +398,8 @@ void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) {
|
||||
|
||||
void ConfigureHotkeys::RestoreHotkey(QModelIndex index) {
|
||||
const QKeySequence& default_key_sequence = QKeySequence::fromString(
|
||||
Config::default_hotkeys[index.row()].shortcut.keyseq, QKeySequence::NativeText);
|
||||
QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.keyseq),
|
||||
QKeySequence::NativeText);
|
||||
const auto [key_sequence_used, used_action] = IsUsedKey(default_key_sequence);
|
||||
|
||||
if (key_sequence_used && default_key_sequence != QKeySequence(model->data(index).toString())) {
|
||||
|
@ -5,12 +5,12 @@
|
||||
#include "core/core.h"
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "core/hid/hid_core.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "ui_configure_input_per_game.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_input_per_game.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
|
||||
ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_,
|
||||
ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, QtConfig* config_,
|
||||
QWidget* parent)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPerGame>()),
|
||||
profiles(std::make_unique<InputProfiles>()), system{system_}, config{config_} {
|
||||
@ -110,6 +110,6 @@ void ConfigureInputPerGame::SaveConfiguration() {
|
||||
// Clear all controls from the config in case the user reverted back to globals
|
||||
config->ClearControlPlayerValues();
|
||||
for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) {
|
||||
config->SaveControlPlayerValue(index);
|
||||
config->SaveQtControlPlayerValues(index);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "ui_configure_input_per_game.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
#include "yuzu/configuration/qt_config.h"
|
||||
|
||||
class QComboBox;
|
||||
|
||||
@ -22,7 +23,7 @@ class ConfigureInputPerGame : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureInputPerGame(Core::System& system_, Config* config_,
|
||||
explicit ConfigureInputPerGame(Core::System& system_, QtConfig* config_,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
/// Load and Save configurations to settings file.
|
||||
@ -41,5 +42,5 @@ private:
|
||||
std::array<QComboBox*, 8> profile_comboboxes;
|
||||
|
||||
Core::System& system;
|
||||
Config* config;
|
||||
QtConfig* config;
|
||||
};
|
||||
|
@ -12,15 +12,16 @@
|
||||
#include <QTimer>
|
||||
#include "common/assert.h"
|
||||
#include "common/param_package.h"
|
||||
#include "configuration/qt_config.h"
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "core/hid/hid_core.h"
|
||||
#include "core/hid/hid_types.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "input_common/drivers/keyboard.h"
|
||||
#include "input_common/drivers/mouse.h"
|
||||
#include "input_common/main.h"
|
||||
#include "ui_configure_input_player.h"
|
||||
#include "yuzu/bootmanager.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
#include "yuzu/configuration/configure_input_player_widget.h"
|
||||
#include "yuzu/configuration/configure_mouse_panning.h"
|
||||
@ -1397,25 +1398,25 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
||||
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
|
||||
emulated_controller->SetButtonParam(
|
||||
button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
|
||||
Config::default_buttons[button_id])});
|
||||
QtConfig::default_buttons[button_id])});
|
||||
}
|
||||
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
||||
Common::ParamPackage analog_param{};
|
||||
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
|
||||
Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
|
||||
Config::default_analogs[analog_id][sub_button_id])};
|
||||
QtConfig::default_analogs[analog_id][sub_button_id])};
|
||||
SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]);
|
||||
}
|
||||
|
||||
analog_param.Set("modifier", InputCommon::GenerateKeyboardParam(
|
||||
Config::default_stick_mod[analog_id]));
|
||||
QtConfig::default_stick_mod[analog_id]));
|
||||
emulated_controller->SetStickParam(analog_id, analog_param);
|
||||
}
|
||||
|
||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||
emulated_controller->SetMotionParam(
|
||||
motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
|
||||
Config::default_motions[motion_id])});
|
||||
QtConfig::default_motions[motion_id])});
|
||||
}
|
||||
|
||||
// If mouse is selected we want to override with mappings from the driver
|
||||
|
@ -25,8 +25,8 @@
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/xts_archive.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "ui_configure_per_game.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configuration_shared.h"
|
||||
#include "yuzu/configuration/configure_audio.h"
|
||||
#include "yuzu/configuration/configure_cpu.h"
|
||||
@ -50,8 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
|
||||
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
|
||||
const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
|
||||
: fmt::format("{:016X}", title_id);
|
||||
game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
|
||||
|
||||
game_config = std::make_unique<QtConfig>(config_file_name, Config::ConfigType::PerGameConfig);
|
||||
addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this);
|
||||
audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this);
|
||||
cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this);
|
||||
@ -108,7 +107,7 @@ void ConfigurePerGame::ApplyConfiguration() {
|
||||
system.ApplySettings();
|
||||
Settings::LogSettings();
|
||||
|
||||
game_config->Save();
|
||||
game_config->SaveAllValues();
|
||||
}
|
||||
|
||||
void ConfigurePerGame::changeEvent(QEvent* event) {
|
||||
|
@ -12,9 +12,10 @@
|
||||
|
||||
#include "configuration/shared_widget.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "vk_device_info.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configuration_shared.h"
|
||||
#include "yuzu/configuration/qt_config.h"
|
||||
#include "yuzu/configuration/shared_translation.h"
|
||||
|
||||
namespace Core {
|
||||
@ -72,7 +73,7 @@ private:
|
||||
|
||||
QGraphicsScene* scene;
|
||||
|
||||
std::unique_ptr<Config> game_config;
|
||||
std::unique_ptr<QtConfig> game_config;
|
||||
|
||||
Core::System& system;
|
||||
std::unique_ptr<ConfigurationShared::Builder> builder;
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "core/file_sys/xts_archive.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "ui_configure_per_game_addons.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_input.h"
|
||||
#include "yuzu/configuration/configure_per_game_addons.h"
|
||||
#include "yuzu/uisettings.h"
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <QTimer>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "configuration/qt_config.h"
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "core/hid/hid_core.h"
|
||||
#include "input_common/drivers/keyboard.h"
|
||||
@ -15,7 +16,6 @@
|
||||
#include "input_common/main.h"
|
||||
#include "ui_configure_ringcon.h"
|
||||
#include "yuzu/bootmanager.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_ringcon.h"
|
||||
|
||||
const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM>
|
||||
@ -270,7 +270,7 @@ void ConfigureRingController::LoadConfiguration() {
|
||||
|
||||
void ConfigureRingController::RestoreDefaults() {
|
||||
const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys(
|
||||
0, 0, Config::default_ringcon_analogs[0], Config::default_ringcon_analogs[1], 0, 0.05f);
|
||||
0, 0, QtConfig::default_ringcon_analogs[0], QtConfig::default_ringcon_analogs[1], 0, 0.05f);
|
||||
emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string));
|
||||
UpdateUI();
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/time/time_manager.h"
|
||||
#include "ui_configure_system.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configuration_shared.h"
|
||||
#include "yuzu/configuration/configure_system.h"
|
||||
#include "yuzu/configuration/shared_widget.h"
|
||||
|
@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <memory>
|
||||
#include "common/settings.h"
|
||||
#include "ui_configure_touchscreen_advanced.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_touchscreen_advanced.h"
|
||||
|
||||
ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent)
|
||||
|
@ -164,7 +164,7 @@ ConfigureUi::~ConfigureUi() = default;
|
||||
|
||||
void ConfigureUi::ApplyConfiguration() {
|
||||
UISettings::values.theme =
|
||||
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
|
||||
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString();
|
||||
UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
|
||||
UISettings::values.show_compat = ui->show_compat->isChecked();
|
||||
UISettings::values.show_size = ui->show_size->isChecked();
|
||||
@ -191,9 +191,10 @@ void ConfigureUi::RequestGameListUpdate() {
|
||||
}
|
||||
|
||||
void ConfigureUi::SetConfiguration() {
|
||||
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
|
||||
ui->theme_combobox->setCurrentIndex(
|
||||
ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme)));
|
||||
ui->language_combobox->setCurrentIndex(
|
||||
ui->language_combobox->findData(UISettings::values.language));
|
||||
ui->language_combobox->findData(QString::fromStdString(UISettings::values.language)));
|
||||
ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue());
|
||||
ui->show_compat->setChecked(UISettings::values.show_compat.GetValue());
|
||||
ui->show_size->setChecked(UISettings::values.show_size.GetValue());
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
|
||||
namespace FS = Common::FS;
|
||||
@ -44,7 +44,7 @@ InputProfiles::InputProfiles() {
|
||||
if (IsINI(filename) && IsProfileNameValid(name_without_ext)) {
|
||||
map_profiles.insert_or_assign(
|
||||
name_without_ext,
|
||||
std::make_unique<Config>(name_without_ext, Config::ConfigType::InputProfile));
|
||||
std::make_unique<QtConfig>(name_without_ext, Config::ConfigType::InputProfile));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -85,7 +85,7 @@ bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t p
|
||||
}
|
||||
|
||||
map_profiles.insert_or_assign(
|
||||
profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile));
|
||||
profile_name, std::make_unique<QtConfig>(profile_name, Config::ConfigType::InputProfile));
|
||||
|
||||
return SaveProfile(profile_name, player_index);
|
||||
}
|
||||
@ -113,7 +113,7 @@ bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t pla
|
||||
return false;
|
||||
}
|
||||
|
||||
map_profiles[profile_name]->ReadControlPlayerValue(player_index);
|
||||
map_profiles[profile_name]->ReadQtControlPlayerValues(player_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t pla
|
||||
return false;
|
||||
}
|
||||
|
||||
map_profiles[profile_name]->SaveControlPlayerValue(player_index);
|
||||
map_profiles[profile_name]->SaveQtControlPlayerValues(player_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "configuration/qt_config.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
@ -30,5 +32,5 @@ public:
|
||||
private:
|
||||
bool ProfileExistsInMap(const std::string& profile_name) const;
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles;
|
||||
std::unordered_map<std::string, std::unique_ptr<QtConfig>> map_profiles;
|
||||
};
|
||||
|
548
src/yuzu/configuration/qt_config.cpp
Normal file
548
src/yuzu/configuration/qt_config.cpp
Normal file
@ -0,0 +1,548 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "input_common/main.h"
|
||||
#include "qt_config.h"
|
||||
#include "uisettings.h"
|
||||
|
||||
const std::array<int, Settings::NativeButton::NumButtons> QtConfig::default_buttons = {
|
||||
Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F,
|
||||
Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T,
|
||||
Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right,
|
||||
Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0,
|
||||
Qt::Key_Q, Qt::Key_E,
|
||||
};
|
||||
|
||||
const std::array<int, Settings::NativeMotion::NumMotions> QtConfig::default_motions = {
|
||||
Qt::Key_7,
|
||||
Qt::Key_8,
|
||||
};
|
||||
|
||||
const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> QtConfig::default_analogs{{
|
||||
{
|
||||
Qt::Key_W,
|
||||
Qt::Key_S,
|
||||
Qt::Key_A,
|
||||
Qt::Key_D,
|
||||
},
|
||||
{
|
||||
Qt::Key_I,
|
||||
Qt::Key_K,
|
||||
Qt::Key_J,
|
||||
Qt::Key_L,
|
||||
},
|
||||
}};
|
||||
|
||||
const std::array<int, 2> QtConfig::default_stick_mod = {
|
||||
Qt::Key_Shift,
|
||||
0,
|
||||
};
|
||||
|
||||
const std::array<int, 2> QtConfig::default_ringcon_analogs{{
|
||||
Qt::Key_A,
|
||||
Qt::Key_D,
|
||||
}};
|
||||
|
||||
QtConfig::QtConfig(const std::string& config_name, const ConfigType config_type)
|
||||
: Config(config_type) {
|
||||
Initialize(config_name);
|
||||
if (config_type != ConfigType::InputProfile) {
|
||||
ReadQtValues();
|
||||
SaveQtValues();
|
||||
}
|
||||
}
|
||||
|
||||
QtConfig::~QtConfig() {
|
||||
if (global) {
|
||||
QtConfig::SaveAllValues();
|
||||
}
|
||||
}
|
||||
|
||||
void QtConfig::ReloadAllValues() {
|
||||
Reload();
|
||||
ReadQtValues();
|
||||
SaveQtValues();
|
||||
}
|
||||
|
||||
void QtConfig::SaveAllValues() {
|
||||
Save();
|
||||
SaveQtValues();
|
||||
}
|
||||
|
||||
void QtConfig::ReadQtValues() {
|
||||
if (global) {
|
||||
ReadUIValues();
|
||||
}
|
||||
ReadQtControlValues();
|
||||
}
|
||||
|
||||
void QtConfig::ReadQtPlayerValues(const std::size_t player_index) {
|
||||
std::string player_prefix;
|
||||
if (type != ConfigType::InputProfile) {
|
||||
player_prefix.append("player_").append(ToString(player_index)).append("_");
|
||||
}
|
||||
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (IsCustomConfig()) {
|
||||
const auto profile_name =
|
||||
ReadStringSetting(std::string(player_prefix).append("profile_name"));
|
||||
if (profile_name.empty()) {
|
||||
// Use the global input config
|
||||
player = Settings::values.players.GetValue(true)[player_index];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
auto& player_buttons = player.buttons[i];
|
||||
|
||||
player_buttons = ReadStringSetting(
|
||||
std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param);
|
||||
if (player_buttons.empty()) {
|
||||
player_buttons = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
auto& player_analogs = player.analogs[i];
|
||||
|
||||
player_analogs = ReadStringSetting(
|
||||
std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param);
|
||||
if (player_analogs.empty()) {
|
||||
player_analogs = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
auto& player_motions = player.motions[i];
|
||||
|
||||
player_motions = ReadStringSetting(
|
||||
std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param);
|
||||
if (player_motions.empty()) {
|
||||
player_motions = default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QtConfig::ReadHidbusValues() {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
|
||||
auto& ringcon_analogs = Settings::values.ringcon_analogs;
|
||||
|
||||
ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param);
|
||||
if (ringcon_analogs.empty()) {
|
||||
ringcon_analogs = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
void QtConfig::ReadDebugControlValues() {
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
|
||||
|
||||
debug_pad_buttons = ReadStringSetting(
|
||||
std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param);
|
||||
if (debug_pad_buttons.empty()) {
|
||||
debug_pad_buttons = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i];
|
||||
|
||||
debug_pad_analogs = ReadStringSetting(
|
||||
std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param);
|
||||
if (debug_pad_analogs.empty()) {
|
||||
debug_pad_analogs = default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QtConfig::ReadQtControlValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
ReadQtPlayerValues(p);
|
||||
}
|
||||
if (IsCustomConfig()) {
|
||||
EndGroup();
|
||||
return;
|
||||
}
|
||||
ReadDebugControlValues();
|
||||
ReadHidbusValues();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::ReadPathValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
|
||||
|
||||
UISettings::values.roms_path = ReadStringSetting(std::string("romsPath"));
|
||||
UISettings::values.symbols_path = ReadStringSetting(std::string("symbolsPath"));
|
||||
UISettings::values.game_dir_deprecated =
|
||||
ReadStringSetting(std::string("gameListRootDir"), std::string("."));
|
||||
UISettings::values.game_dir_deprecated_deepscan =
|
||||
ReadBooleanSetting(std::string("gameListDeepScan"), std::make_optional(false));
|
||||
|
||||
const int gamedirs_size = BeginArray(std::string("gamedirs"));
|
||||
for (int i = 0; i < gamedirs_size; ++i) {
|
||||
SetArrayIndex(i);
|
||||
UISettings::GameDir game_dir;
|
||||
game_dir.path = ReadStringSetting(std::string("path"));
|
||||
game_dir.deep_scan =
|
||||
ReadBooleanSetting(std::string("deep_scan"), std::make_optional(false));
|
||||
game_dir.expanded = ReadBooleanSetting(std::string("expanded"), std::make_optional(true));
|
||||
UISettings::values.game_dirs.append(game_dir);
|
||||
}
|
||||
EndArray();
|
||||
|
||||
// Create NAND and SD card directories if empty, these are not removable through the UI,
|
||||
// also carries over old game list settings if present
|
||||
if (UISettings::values.game_dirs.empty()) {
|
||||
UISettings::GameDir game_dir;
|
||||
game_dir.path = std::string("SDMC");
|
||||
game_dir.expanded = true;
|
||||
UISettings::values.game_dirs.append(game_dir);
|
||||
game_dir.path = std::string("UserNAND");
|
||||
UISettings::values.game_dirs.append(game_dir);
|
||||
game_dir.path = std::string("SysNAND");
|
||||
UISettings::values.game_dirs.append(game_dir);
|
||||
if (UISettings::values.game_dir_deprecated != std::string(".")) {
|
||||
game_dir.path = UISettings::values.game_dir_deprecated;
|
||||
game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan;
|
||||
UISettings::values.game_dirs.append(game_dir);
|
||||
}
|
||||
}
|
||||
UISettings::values.recent_files =
|
||||
QString::fromStdString(ReadStringSetting(std::string("recentFiles")))
|
||||
.split(QStringLiteral(", "), Qt::SkipEmptyParts, Qt::CaseSensitive);
|
||||
UISettings::values.language = ReadStringSetting(std::string("language"), std::string(""));
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::ReadShortcutValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts));
|
||||
|
||||
for (const auto& [name, group, shortcut] : UISettings::default_hotkeys) {
|
||||
BeginGroup(group);
|
||||
BeginGroup(name);
|
||||
|
||||
// No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1
|
||||
// for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open
|
||||
// a file dialog in windowed mode
|
||||
UISettings::values.shortcuts.push_back(
|
||||
{name,
|
||||
group,
|
||||
{ReadStringSetting(std::string("KeySeq"), shortcut.keyseq),
|
||||
ReadStringSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq),
|
||||
shortcut.context,
|
||||
ReadBooleanSetting(std::string("Repeat"), std::optional(shortcut.repeat))}});
|
||||
|
||||
EndGroup(); // name
|
||||
EndGroup(); // group
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::ReadUIValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Ui));
|
||||
|
||||
UISettings::values.theme = ReadStringSetting(
|
||||
std::string("theme"),
|
||||
std::string(UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second));
|
||||
|
||||
ReadUIGamelistValues();
|
||||
ReadUILayoutValues();
|
||||
ReadPathValues();
|
||||
ReadScreenshotValues();
|
||||
ReadShortcutValues();
|
||||
ReadMultiplayerValues();
|
||||
|
||||
ReadCategory(Settings::Category::Ui);
|
||||
ReadCategory(Settings::Category::UiGeneral);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::ReadUIGamelistValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
|
||||
|
||||
ReadCategory(Settings::Category::UiGameList);
|
||||
|
||||
const int favorites_size = BeginArray("favorites");
|
||||
for (int i = 0; i < favorites_size; i++) {
|
||||
SetArrayIndex(i);
|
||||
UISettings::values.favorited_ids.append(ReadIntegerSetting(std::string("program_id")));
|
||||
}
|
||||
EndArray();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::ReadUILayoutValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
|
||||
|
||||
ReadCategory(Settings::Category::UiLayout);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::ReadMultiplayerValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Multiplayer));
|
||||
|
||||
ReadCategory(Settings::Category::Multiplayer);
|
||||
|
||||
// Read ban list back
|
||||
int size = BeginArray(std::string("username_ban_list"));
|
||||
UISettings::values.multiplayer_ban_list.first.resize(size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
SetArrayIndex(i);
|
||||
UISettings::values.multiplayer_ban_list.first[i] =
|
||||
ReadStringSetting(std::string("username"), std::string(""));
|
||||
}
|
||||
EndArray();
|
||||
|
||||
size = BeginArray(std::string("ip_ban_list"));
|
||||
UISettings::values.multiplayer_ban_list.second.resize(size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
UISettings::values.multiplayer_ban_list.second[i] =
|
||||
ReadStringSetting("username", std::string(""));
|
||||
}
|
||||
EndArray();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SaveQtValues() {
|
||||
if (global) {
|
||||
SaveUIValues();
|
||||
}
|
||||
SaveQtControlValues();
|
||||
|
||||
WriteToIni();
|
||||
}
|
||||
|
||||
void QtConfig::SaveQtPlayerValues(const std::size_t player_index) {
|
||||
std::string player_prefix;
|
||||
if (type != ConfigType::InputProfile) {
|
||||
player_prefix = std::string("player_").append(ToString(player_index)).append("_");
|
||||
}
|
||||
|
||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (IsCustomConfig() && player.profile_name.empty()) {
|
||||
// No custom profile selected
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]),
|
||||
player.buttons[i], std::make_optional(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]),
|
||||
player.analogs[i], std::make_optional(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]),
|
||||
player.motions[i], std::make_optional(default_param));
|
||||
}
|
||||
}
|
||||
|
||||
void QtConfig::SaveDebugControlValues() {
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]),
|
||||
Settings::values.debug_pad_buttons[i], std::make_optional(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]),
|
||||
Settings::values.debug_pad_analogs[i], std::make_optional(default_param));
|
||||
}
|
||||
}
|
||||
|
||||
void QtConfig::SaveHidbusValues() {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
|
||||
WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs,
|
||||
std::make_optional(default_param));
|
||||
}
|
||||
|
||||
void QtConfig::SaveQtControlValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
SaveQtPlayerValues(p);
|
||||
}
|
||||
if (IsCustomConfig()) {
|
||||
EndGroup();
|
||||
return;
|
||||
}
|
||||
SaveDebugControlValues();
|
||||
SaveHidbusValues();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SavePathValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
|
||||
|
||||
WriteSetting(std::string("romsPath"), UISettings::values.roms_path);
|
||||
WriteSetting(std::string("symbolsPath"), UISettings::values.symbols_path);
|
||||
BeginArray(std::string("gamedirs"));
|
||||
for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
|
||||
SetArrayIndex(i);
|
||||
const auto& game_dir = UISettings::values.game_dirs[i];
|
||||
WriteSetting(std::string("path"), game_dir.path);
|
||||
WriteSetting(std::string("deep_scan"), game_dir.deep_scan, std::make_optional(false));
|
||||
WriteSetting(std::string("expanded"), game_dir.expanded, std::make_optional(true));
|
||||
}
|
||||
EndArray();
|
||||
|
||||
WriteSetting(std::string("recentFiles"),
|
||||
UISettings::values.recent_files.join(QStringLiteral(", ")).toStdString());
|
||||
WriteSetting(std::string("language"), UISettings::values.language);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SaveShortcutValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts));
|
||||
|
||||
// Lengths of UISettings::values.shortcuts & default_hotkeys are same.
|
||||
// However, their ordering must also be the same.
|
||||
for (std::size_t i = 0; i < UISettings::default_hotkeys.size(); i++) {
|
||||
const auto& [name, group, shortcut] = UISettings::values.shortcuts[i];
|
||||
const auto& default_hotkey = UISettings::default_hotkeys[i].shortcut;
|
||||
|
||||
BeginGroup(group);
|
||||
BeginGroup(name);
|
||||
|
||||
WriteSetting(std::string("KeySeq"), shortcut.keyseq,
|
||||
std::make_optional(default_hotkey.keyseq));
|
||||
WriteSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq,
|
||||
std::make_optional(default_hotkey.controller_keyseq));
|
||||
WriteSetting(std::string("Context"), shortcut.context,
|
||||
std::make_optional(default_hotkey.context));
|
||||
WriteSetting(std::string("Repeat"), shortcut.repeat,
|
||||
std::make_optional(default_hotkey.repeat));
|
||||
|
||||
EndGroup(); // name
|
||||
EndGroup(); // group
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SaveUIValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Ui));
|
||||
|
||||
WriteCategory(Settings::Category::Ui);
|
||||
WriteCategory(Settings::Category::UiGeneral);
|
||||
|
||||
WriteSetting(std::string("theme"), UISettings::values.theme,
|
||||
std::make_optional(std::string(
|
||||
UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second)));
|
||||
|
||||
SaveUIGamelistValues();
|
||||
SaveUILayoutValues();
|
||||
SavePathValues();
|
||||
SaveScreenshotValues();
|
||||
SaveShortcutValues();
|
||||
SaveMultiplayerValues();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SaveUIGamelistValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
|
||||
|
||||
WriteCategory(Settings::Category::UiGameList);
|
||||
|
||||
BeginArray(std::string("favorites"));
|
||||
for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
|
||||
SetArrayIndex(i);
|
||||
WriteSetting(std::string("program_id"), UISettings::values.favorited_ids[i]);
|
||||
}
|
||||
EndArray(); // favorites
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SaveUILayoutValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::UiLayout));
|
||||
|
||||
WriteCategory(Settings::Category::UiLayout);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SaveMultiplayerValues() {
|
||||
BeginGroup(std::string("Multiplayer"));
|
||||
|
||||
WriteCategory(Settings::Category::Multiplayer);
|
||||
|
||||
// Write ban list
|
||||
BeginArray(std::string("username_ban_list"));
|
||||
for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) {
|
||||
SetArrayIndex(static_cast<int>(i));
|
||||
WriteSetting(std::string("username"), UISettings::values.multiplayer_ban_list.first[i]);
|
||||
}
|
||||
EndArray(); // username_ban_list
|
||||
|
||||
BeginArray(std::string("ip_ban_list"));
|
||||
for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) {
|
||||
SetArrayIndex(static_cast<int>(i));
|
||||
WriteSetting(std::string("ip"), UISettings::values.multiplayer_ban_list.second[i]);
|
||||
}
|
||||
EndArray(); // ip_ban_list
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
std::vector<Settings::BasicSetting*>& QtConfig::FindRelevantList(Settings::Category category) {
|
||||
auto& map = Settings::values.linkage.by_category;
|
||||
if (map.contains(category)) {
|
||||
return Settings::values.linkage.by_category[category];
|
||||
}
|
||||
return UISettings::values.linkage.by_category[category];
|
||||
}
|
||||
|
||||
void QtConfig::ReadQtControlPlayerValues(std::size_t player_index) {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
ReadPlayerValues(player_index);
|
||||
ReadQtPlayerValues(player_index);
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
SavePlayerValues(player_index);
|
||||
SaveQtPlayerValues(player_index);
|
||||
|
||||
EndGroup();
|
||||
|
||||
WriteToIni();
|
||||
}
|
55
src/yuzu/configuration/qt_config.h
Normal file
55
src/yuzu/configuration/qt_config.h
Normal file
@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include "frontend_common/config.h"
|
||||
|
||||
class QtConfig final : public Config {
|
||||
public:
|
||||
explicit QtConfig(const std::string& config_name = "qt-config",
|
||||
ConfigType config_type = ConfigType::GlobalConfig);
|
||||
~QtConfig() override;
|
||||
|
||||
void ReloadAllValues() override;
|
||||
void SaveAllValues() override;
|
||||
|
||||
void ReadQtControlPlayerValues(std::size_t player_index);
|
||||
void SaveQtControlPlayerValues(std::size_t player_index);
|
||||
|
||||
protected:
|
||||
void ReadQtValues();
|
||||
void ReadQtPlayerValues(std::size_t player_index);
|
||||
void ReadQtControlValues();
|
||||
void ReadHidbusValues() override;
|
||||
void ReadDebugControlValues() override;
|
||||
void ReadPathValues() override;
|
||||
void ReadShortcutValues() override;
|
||||
void ReadUIValues() override;
|
||||
void ReadUIGamelistValues() override;
|
||||
void ReadUILayoutValues() override;
|
||||
void ReadMultiplayerValues() override;
|
||||
|
||||
void SaveQtValues();
|
||||
void SaveQtPlayerValues(std::size_t player_index);
|
||||
void SaveQtControlValues();
|
||||
void SaveHidbusValues() override;
|
||||
void SaveDebugControlValues() override;
|
||||
void SavePathValues() override;
|
||||
void SaveShortcutValues() override;
|
||||
void SaveUIValues() override;
|
||||
void SaveUIGamelistValues() override;
|
||||
void SaveUILayoutValues() override;
|
||||
void SaveMultiplayerValues() override;
|
||||
|
||||
std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override;
|
||||
|
||||
public:
|
||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
|
||||
static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||
static const std::array<int, 2> default_stick_mod;
|
||||
static const std::array<int, 2> default_ringcon_analogs;
|
||||
};
|
@ -10,6 +10,7 @@
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings.h"
|
||||
|
||||
class QWidget;
|
||||
|
||||
@ -22,4 +23,46 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent);
|
||||
|
||||
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent);
|
||||
|
||||
static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map = {
|
||||
{Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))},
|
||||
{Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))},
|
||||
{Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map = {
|
||||
{Settings::ScalingFilter::NearestNeighbor,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))},
|
||||
{Settings::ScalingFilter::Bilinear,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))},
|
||||
{Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))},
|
||||
{Settings::ScalingFilter::Gaussian,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))},
|
||||
{Settings::ScalingFilter::ScaleForce,
|
||||
QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))},
|
||||
{Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map = {
|
||||
{Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
|
||||
{Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map = {
|
||||
{Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))},
|
||||
{Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))},
|
||||
{Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map = {
|
||||
{Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))},
|
||||
{Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))},
|
||||
{Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
|
||||
};
|
||||
|
||||
static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map = {
|
||||
{Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))},
|
||||
{Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))},
|
||||
{Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))},
|
||||
};
|
||||
|
||||
} // namespace ConfigurationShared
|
||||
|
@ -36,10 +36,8 @@ constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{
|
||||
|
||||
bool IsDarkTheme() {
|
||||
const auto& theme = UISettings::values.theme;
|
||||
return theme == QStringLiteral("qdarkstyle") ||
|
||||
theme == QStringLiteral("qdarkstyle_midnight_blue") ||
|
||||
theme == QStringLiteral("colorful_dark") ||
|
||||
theme == QStringLiteral("colorful_midnight_blue");
|
||||
return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
|
||||
theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -278,7 +278,7 @@ void GameList::OnUpdateThemedIcons() {
|
||||
case GameListItemType::CustomDir: {
|
||||
const UISettings::GameDir& game_dir =
|
||||
UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()];
|
||||
const QString icon_name = QFileInfo::exists(game_dir.path)
|
||||
const QString icon_name = QFileInfo::exists(QString::fromStdString(game_dir.path))
|
||||
? QStringLiteral("folder")
|
||||
: QStringLiteral("bad_folder");
|
||||
child->setData(
|
||||
@ -727,7 +727,8 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) {
|
||||
});
|
||||
|
||||
connect(open_directory_location, &QAction::triggered, [this, game_dir_index] {
|
||||
emit OpenDirectory(UISettings::values.game_dirs[game_dir_index].path);
|
||||
emit OpenDirectory(
|
||||
QString::fromStdString(UISettings::values.game_dirs[game_dir_index].path));
|
||||
});
|
||||
}
|
||||
|
||||
@ -869,7 +870,7 @@ const QStringList GameList::supported_file_extensions = {
|
||||
QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")};
|
||||
|
||||
void GameList::RefreshGameDirectory() {
|
||||
if (!UISettings::values.game_dirs.isEmpty() && current_worker != nullptr) {
|
||||
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
|
||||
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
|
||||
PopulateAsync(UISettings::values.game_dirs);
|
||||
}
|
||||
|
@ -286,13 +286,13 @@ public:
|
||||
setData(QObject::tr("System Titles"), Qt::DisplayRole);
|
||||
break;
|
||||
case GameListItemType::CustomDir: {
|
||||
const QString icon_name = QFileInfo::exists(game_dir->path)
|
||||
? QStringLiteral("folder")
|
||||
: QStringLiteral("bad_folder");
|
||||
const QString path = QString::fromStdString(game_dir->path);
|
||||
const QString icon_name =
|
||||
QFileInfo::exists(path) ? QStringLiteral("folder") : QStringLiteral("bad_folder");
|
||||
setData(QIcon::fromTheme(icon_name).pixmap(icon_size).scaled(
|
||||
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||
Qt::DecorationRole);
|
||||
setData(game_dir->path, Qt::DisplayRole);
|
||||
setData(path, Qt::DisplayRole);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -456,26 +456,26 @@ void GameListWorker::run() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (game_dir.path == QStringLiteral("SDMC")) {
|
||||
if (game_dir.path == std::string("SDMC")) {
|
||||
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
|
||||
DirEntryReady(game_list_dir);
|
||||
AddTitlesToGameList(game_list_dir);
|
||||
} else if (game_dir.path == QStringLiteral("UserNAND")) {
|
||||
} else if (game_dir.path == std::string("UserNAND")) {
|
||||
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
|
||||
DirEntryReady(game_list_dir);
|
||||
AddTitlesToGameList(game_list_dir);
|
||||
} else if (game_dir.path == QStringLiteral("SysNAND")) {
|
||||
} else if (game_dir.path == std::string("SysNAND")) {
|
||||
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
|
||||
DirEntryReady(game_list_dir);
|
||||
AddTitlesToGameList(game_list_dir);
|
||||
} else {
|
||||
watch_list.append(game_dir.path);
|
||||
watch_list.append(QString::fromStdString(game_dir.path));
|
||||
auto* const game_list_dir = new GameListDir(game_dir);
|
||||
DirEntryReady(game_list_dir);
|
||||
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(),
|
||||
game_dir.deep_scan, game_list_dir);
|
||||
ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(),
|
||||
game_dir.deep_scan, game_list_dir);
|
||||
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan,
|
||||
game_list_dir);
|
||||
ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan,
|
||||
game_list_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ void HotkeyRegistry::SaveHotkeys() {
|
||||
for (const auto& hotkey : group.second) {
|
||||
UISettings::values.shortcuts.push_back(
|
||||
{hotkey.first, group.first,
|
||||
UISettings::ContextualShortcut({hotkey.second.keyseq.toString(),
|
||||
UISettings::ContextualShortcut({hotkey.second.keyseq.toString().toStdString(),
|
||||
hotkey.second.controller_keyseq,
|
||||
hotkey.second.context, hotkey.second.repeat})});
|
||||
}
|
||||
@ -31,12 +31,12 @@ void HotkeyRegistry::LoadHotkeys() {
|
||||
// beginGroup()
|
||||
for (auto shortcut : UISettings::values.shortcuts) {
|
||||
Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name];
|
||||
if (!shortcut.shortcut.keyseq.isEmpty()) {
|
||||
hk.keyseq =
|
||||
QKeySequence::fromString(shortcut.shortcut.keyseq, QKeySequence::NativeText);
|
||||
if (!shortcut.shortcut.keyseq.empty()) {
|
||||
hk.keyseq = QKeySequence::fromString(QString::fromStdString(shortcut.shortcut.keyseq),
|
||||
QKeySequence::NativeText);
|
||||
hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.context);
|
||||
}
|
||||
if (!shortcut.shortcut.controller_keyseq.isEmpty()) {
|
||||
if (!shortcut.shortcut.controller_keyseq.empty()) {
|
||||
hk.controller_keyseq = shortcut.shortcut.controller_keyseq;
|
||||
}
|
||||
if (hk.shortcut) {
|
||||
@ -51,7 +51,8 @@ void HotkeyRegistry::LoadHotkeys() {
|
||||
}
|
||||
}
|
||||
|
||||
QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) {
|
||||
QShortcut* HotkeyRegistry::GetHotkey(const std::string& group, const std::string& action,
|
||||
QWidget* widget) {
|
||||
Hotkey& hk = hotkey_groups[group][action];
|
||||
|
||||
if (!hk.shortcut) {
|
||||
@ -62,7 +63,8 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action
|
||||
return hk.shortcut;
|
||||
}
|
||||
|
||||
ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, const QString& action,
|
||||
ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const std::string& group,
|
||||
const std::string& action,
|
||||
Core::HID::EmulatedController* controller) {
|
||||
Hotkey& hk = hotkey_groups[group][action];
|
||||
|
||||
@ -74,12 +76,12 @@ ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, co
|
||||
return hk.controller_shortcut;
|
||||
}
|
||||
|
||||
QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) {
|
||||
QKeySequence HotkeyRegistry::GetKeySequence(const std::string& group, const std::string& action) {
|
||||
return hotkey_groups[group][action].keyseq;
|
||||
}
|
||||
|
||||
Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group,
|
||||
const QString& action) {
|
||||
Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const std::string& group,
|
||||
const std::string& action) {
|
||||
return hotkey_groups[group][action].context;
|
||||
}
|
||||
|
||||
@ -101,10 +103,10 @@ void ControllerShortcut::SetKey(const ControllerButtonSequence& buttons) {
|
||||
button_sequence = buttons;
|
||||
}
|
||||
|
||||
void ControllerShortcut::SetKey(const QString& buttons_shortcut) {
|
||||
void ControllerShortcut::SetKey(const std::string& buttons_shortcut) {
|
||||
ControllerButtonSequence sequence{};
|
||||
name = buttons_shortcut.toStdString();
|
||||
std::istringstream command_line(buttons_shortcut.toStdString());
|
||||
name = buttons_shortcut;
|
||||
std::istringstream command_line(buttons_shortcut);
|
||||
std::string line;
|
||||
while (std::getline(command_line, line, '+')) {
|
||||
if (line.empty()) {
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
~ControllerShortcut();
|
||||
|
||||
void SetKey(const ControllerButtonSequence& buttons);
|
||||
void SetKey(const QString& buttons_shortcut);
|
||||
void SetKey(const std::string& buttons_shortcut);
|
||||
|
||||
ControllerButtonSequence ButtonSequence() const;
|
||||
|
||||
@ -88,8 +88,8 @@ public:
|
||||
* will be the same. Thus, you shouldn't rely on the caller really being the
|
||||
* QShortcut's parent.
|
||||
*/
|
||||
QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget);
|
||||
ControllerShortcut* GetControllerHotkey(const QString& group, const QString& action,
|
||||
QShortcut* GetHotkey(const std::string& group, const std::string& action, QWidget* widget);
|
||||
ControllerShortcut* GetControllerHotkey(const std::string& group, const std::string& action,
|
||||
Core::HID::EmulatedController* controller);
|
||||
|
||||
/**
|
||||
@ -98,7 +98,7 @@ public:
|
||||
* @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger").
|
||||
* @param action Name of the action (e.g. "Start Emulation", "Load Image").
|
||||
*/
|
||||
QKeySequence GetKeySequence(const QString& group, const QString& action);
|
||||
QKeySequence GetKeySequence(const std::string& group, const std::string& action);
|
||||
|
||||
/**
|
||||
* Returns a Qt::ShortcutContext object who can be connected to other
|
||||
@ -108,20 +108,20 @@ public:
|
||||
* "Debugger").
|
||||
* @param action Name of the action (e.g. "Start Emulation", "Load Image").
|
||||
*/
|
||||
Qt::ShortcutContext GetShortcutContext(const QString& group, const QString& action);
|
||||
Qt::ShortcutContext GetShortcutContext(const std::string& group, const std::string& action);
|
||||
|
||||
private:
|
||||
struct Hotkey {
|
||||
QKeySequence keyseq;
|
||||
QString controller_keyseq;
|
||||
std::string controller_keyseq;
|
||||
QShortcut* shortcut = nullptr;
|
||||
ControllerShortcut* controller_shortcut = nullptr;
|
||||
Qt::ShortcutContext context = Qt::WindowShortcut;
|
||||
bool repeat;
|
||||
};
|
||||
|
||||
using HotkeyMap = std::map<QString, Hotkey>;
|
||||
using HotkeyGroupMap = std::map<QString, HotkeyMap>;
|
||||
using HotkeyMap = std::map<std::string, Hotkey>;
|
||||
using HotkeyGroupMap = std::map<std::string, HotkeyMap>;
|
||||
|
||||
HotkeyGroupMap hotkey_groups;
|
||||
};
|
||||
|
@ -128,6 +128,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
||||
#include "core/loader/loader.h"
|
||||
#include "core/perf_stats.h"
|
||||
#include "core/telemetry_session.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "input_common/drivers/tas_input.h"
|
||||
#include "input_common/drivers/virtual_amiibo.h"
|
||||
#include "input_common/main.h"
|
||||
@ -140,9 +141,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
||||
#include "yuzu/bootmanager.h"
|
||||
#include "yuzu/compatdb.h"
|
||||
#include "yuzu/compatibility_list.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_dialog.h"
|
||||
#include "yuzu/configuration/configure_input_per_game.h"
|
||||
#include "yuzu/configuration/qt_config.h"
|
||||
#include "yuzu/debugger/console.h"
|
||||
#include "yuzu/debugger/controller.h"
|
||||
#include "yuzu/debugger/profiler.h"
|
||||
@ -311,7 +312,7 @@ bool GMainWindow::CheckDarkMode() {
|
||||
#endif // __unix__
|
||||
}
|
||||
|
||||
GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan)
|
||||
GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan)
|
||||
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
|
||||
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)},
|
||||
vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
|
||||
@ -676,7 +677,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers(
|
||||
// Don't forget to apply settings.
|
||||
system->HIDCore().DisableAllControllerConfiguration();
|
||||
system->ApplySettings();
|
||||
config->Save();
|
||||
config->SaveAllValues();
|
||||
|
||||
UpdateStatusButtons();
|
||||
|
||||
@ -1129,7 +1130,7 @@ void GMainWindow::InitializeWidgets() {
|
||||
connect(aa_status_button, &QPushButton::customContextMenuRequested,
|
||||
[this](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
for (auto const& aa_text_pair : Config::anti_aliasing_texts_map) {
|
||||
for (auto const& aa_text_pair : ConfigurationShared::anti_aliasing_texts_map) {
|
||||
context_menu.addAction(aa_text_pair.second, [this, aa_text_pair] {
|
||||
Settings::values.anti_aliasing.SetValue(aa_text_pair.first);
|
||||
UpdateAAText();
|
||||
@ -1153,7 +1154,7 @@ void GMainWindow::InitializeWidgets() {
|
||||
connect(filter_status_button, &QPushButton::customContextMenuRequested,
|
||||
[this](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
for (auto const& filter_text_pair : Config::scaling_filter_texts_map) {
|
||||
for (auto const& filter_text_pair : ConfigurationShared::scaling_filter_texts_map) {
|
||||
context_menu.addAction(filter_text_pair.second, [this, filter_text_pair] {
|
||||
Settings::values.scaling_filter.SetValue(filter_text_pair.first);
|
||||
UpdateFilterText();
|
||||
@ -1176,7 +1177,7 @@ void GMainWindow::InitializeWidgets() {
|
||||
[this](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
|
||||
for (auto const& pair : Config::use_docked_mode_texts_map) {
|
||||
for (auto const& pair : ConfigurationShared::use_docked_mode_texts_map) {
|
||||
context_menu.addAction(pair.second, [this, &pair] {
|
||||
if (pair.first != Settings::values.use_docked_mode.GetValue()) {
|
||||
OnToggleDockedMode();
|
||||
@ -1200,7 +1201,7 @@ void GMainWindow::InitializeWidgets() {
|
||||
[this](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
|
||||
for (auto const& gpu_accuracy_pair : Config::gpu_accuracy_texts_map) {
|
||||
for (auto const& gpu_accuracy_pair : ConfigurationShared::gpu_accuracy_texts_map) {
|
||||
if (gpu_accuracy_pair.first == Settings::GpuAccuracy::Extreme) {
|
||||
continue;
|
||||
}
|
||||
@ -1229,7 +1230,8 @@ void GMainWindow::InitializeWidgets() {
|
||||
[this](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
|
||||
for (auto const& renderer_backend_pair : Config::renderer_backend_texts_map) {
|
||||
for (auto const& renderer_backend_pair :
|
||||
ConfigurationShared::renderer_backend_texts_map) {
|
||||
if (renderer_backend_pair.first == Settings::RendererBackend::Null) {
|
||||
continue;
|
||||
}
|
||||
@ -1294,16 +1296,17 @@ void GMainWindow::InitializeRecentFileMenuActions() {
|
||||
|
||||
void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name,
|
||||
const bool tas_allowed) {
|
||||
static const QString main_window = QStringLiteral("Main Window");
|
||||
action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name));
|
||||
action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name));
|
||||
static const auto main_window = std::string("Main Window");
|
||||
action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name.toStdString()));
|
||||
action->setShortcutContext(
|
||||
hotkey_registry.GetShortcutContext(main_window, action_name.toStdString()));
|
||||
action->setAutoRepeat(false);
|
||||
|
||||
this->addAction(action);
|
||||
|
||||
auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
const auto* controller_hotkey =
|
||||
hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
|
||||
hotkey_registry.GetControllerHotkey(main_window, action_name.toStdString(), controller);
|
||||
connect(
|
||||
controller_hotkey, &ControllerShortcut::Activated, this,
|
||||
[action, tas_allowed, this] {
|
||||
@ -1335,10 +1338,11 @@ void GMainWindow::InitializeHotkeys() {
|
||||
|
||||
static const QString main_window = QStringLiteral("Main Window");
|
||||
const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) {
|
||||
const auto* hotkey = hotkey_registry.GetHotkey(main_window, action_name, this);
|
||||
const auto* hotkey =
|
||||
hotkey_registry.GetHotkey(main_window.toStdString(), action_name.toStdString(), this);
|
||||
auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
const auto* controller_hotkey =
|
||||
hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
|
||||
const auto* controller_hotkey = hotkey_registry.GetControllerHotkey(
|
||||
main_window.toStdString(), action_name.toStdString(), controller);
|
||||
connect(hotkey, &QShortcut::activated, this, function);
|
||||
connect(controller_hotkey, &ControllerShortcut::Activated, this, function,
|
||||
Qt::QueuedConnection);
|
||||
@ -1918,7 +1922,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
||||
// Save configurations
|
||||
UpdateUISettings();
|
||||
game_list->SaveInterfaceLayout();
|
||||
config->Save();
|
||||
config->SaveAllValues();
|
||||
|
||||
u64 title_id{0};
|
||||
|
||||
@ -1936,7 +1940,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
||||
const auto config_file_name = title_id == 0
|
||||
? Common::FS::PathToUTF8String(file_path.filename())
|
||||
: fmt::format("{:016X}", title_id);
|
||||
Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
|
||||
QtConfig per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
|
||||
system->HIDCore().ReloadInputDevices();
|
||||
system->ApplySettings();
|
||||
}
|
||||
@ -3135,7 +3139,7 @@ void GMainWindow::OnGameListAddDirectory() {
|
||||
return;
|
||||
}
|
||||
|
||||
UISettings::GameDir game_dir{dir_path, false, true};
|
||||
UISettings::GameDir game_dir{dir_path.toStdString(), false, true};
|
||||
if (!UISettings::values.game_dirs.contains(game_dir)) {
|
||||
UISettings::values.game_dirs.append(game_dir);
|
||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||
@ -3181,14 +3185,14 @@ void GMainWindow::OnMenuLoadFile() {
|
||||
"%1 is an identifier for the Switch executable file extensions.")
|
||||
.arg(extensions);
|
||||
const QString filename = QFileDialog::getOpenFileName(
|
||||
this, tr("Load File"), UISettings::values.roms_path, file_filter);
|
||||
this, tr("Load File"), QString::fromStdString(UISettings::values.roms_path), file_filter);
|
||||
is_load_file_select_active = false;
|
||||
|
||||
if (filename.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename);
|
||||
}
|
||||
|
||||
@ -3221,7 +3225,8 @@ void GMainWindow::OnMenuInstallToNAND() {
|
||||
"Image (*.xci)");
|
||||
|
||||
QStringList filenames = QFileDialog::getOpenFileNames(
|
||||
this, tr("Install Files"), UISettings::values.roms_path, file_filter);
|
||||
this, tr("Install Files"), QString::fromStdString(UISettings::values.roms_path),
|
||||
file_filter);
|
||||
|
||||
if (filenames.isEmpty()) {
|
||||
return;
|
||||
@ -3239,7 +3244,7 @@ void GMainWindow::OnMenuInstallToNAND() {
|
||||
}
|
||||
|
||||
// Save folder location of the first selected file
|
||||
UISettings::values.roms_path = QFileInfo(filenames[0]).path();
|
||||
UISettings::values.roms_path = QFileInfo(filenames[0]).path().toStdString();
|
||||
|
||||
int remaining = filenames.size();
|
||||
|
||||
@ -3584,7 +3589,7 @@ void GMainWindow::OnExit() {
|
||||
|
||||
void GMainWindow::OnSaveConfig() {
|
||||
system->ApplySettings();
|
||||
config->Save();
|
||||
config->SaveAllValues();
|
||||
}
|
||||
|
||||
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
|
||||
@ -3840,7 +3845,7 @@ void GMainWindow::OnConfigure() {
|
||||
|
||||
Settings::values.disabled_addons.clear();
|
||||
|
||||
config = std::make_unique<Config>();
|
||||
config = std::make_unique<QtConfig>();
|
||||
UISettings::values.reset_to_defaults = false;
|
||||
|
||||
UISettings::values.game_dirs = std::move(old_game_dirs);
|
||||
@ -3875,7 +3880,7 @@ void GMainWindow::OnConfigure() {
|
||||
|
||||
UISettings::values.configuration_applied = false;
|
||||
|
||||
config->Save();
|
||||
config->SaveAllValues();
|
||||
|
||||
if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) {
|
||||
render_window->installEventFilter(render_window);
|
||||
@ -4091,7 +4096,7 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file
|
||||
UISettings::values.configuration_applied = false;
|
||||
|
||||
if (!is_powered_on) {
|
||||
config->Save();
|
||||
config->SaveAllValues();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4324,7 +4329,7 @@ void GMainWindow::OnAlbum() {
|
||||
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::PhotoViewer);
|
||||
|
||||
const auto filename = QString::fromStdString(album_nca->GetFullPath());
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, AlbumId);
|
||||
}
|
||||
|
||||
@ -4348,7 +4353,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
|
||||
system->GetAppletManager().SetCabinetMode(mode);
|
||||
|
||||
const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, CabinetId);
|
||||
}
|
||||
|
||||
@ -4371,7 +4376,7 @@ void GMainWindow::OnMiiEdit() {
|
||||
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit);
|
||||
|
||||
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, MiiEditId);
|
||||
}
|
||||
|
||||
@ -4396,7 +4401,7 @@ void GMainWindow::OnOpenControllerMenu() {
|
||||
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller);
|
||||
|
||||
const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
|
||||
BootGame(filename, ControllerAppletId);
|
||||
}
|
||||
|
||||
@ -4590,7 +4595,8 @@ void GMainWindow::UpdateStatusBar() {
|
||||
|
||||
void GMainWindow::UpdateGPUAccuracyButton() {
|
||||
const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue();
|
||||
const auto gpu_accuracy_text = Config::gpu_accuracy_texts_map.find(gpu_accuracy)->second;
|
||||
const auto gpu_accuracy_text =
|
||||
ConfigurationShared::gpu_accuracy_texts_map.find(gpu_accuracy)->second;
|
||||
gpu_accuracy_button->setText(gpu_accuracy_text.toUpper());
|
||||
gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GpuAccuracy::Normal);
|
||||
}
|
||||
@ -4599,31 +4605,32 @@ void GMainWindow::UpdateDockedButton() {
|
||||
const auto console_mode = Settings::values.use_docked_mode.GetValue();
|
||||
dock_status_button->setChecked(Settings::IsDockedMode());
|
||||
dock_status_button->setText(
|
||||
Config::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
|
||||
ConfigurationShared::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateAPIText() {
|
||||
const auto api = Settings::values.renderer_backend.GetValue();
|
||||
const auto renderer_status_text = Config::renderer_backend_texts_map.find(api)->second;
|
||||
const auto renderer_status_text =
|
||||
ConfigurationShared::renderer_backend_texts_map.find(api)->second;
|
||||
renderer_status_button->setText(
|
||||
api == Settings::RendererBackend::OpenGL
|
||||
? tr("%1 %2").arg(
|
||||
renderer_status_text.toUpper(),
|
||||
Config::shader_backend_texts_map.find(Settings::values.shader_backend.GetValue())
|
||||
? tr("%1 %2").arg(renderer_status_text.toUpper(),
|
||||
ConfigurationShared::shader_backend_texts_map
|
||||
.find(Settings::values.shader_backend.GetValue())
|
||||
->second)
|
||||
: renderer_status_text.toUpper());
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateFilterText() {
|
||||
const auto filter = Settings::values.scaling_filter.GetValue();
|
||||
const auto filter_text = Config::scaling_filter_texts_map.find(filter)->second;
|
||||
const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second;
|
||||
filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR")
|
||||
: filter_text.toUpper());
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateAAText() {
|
||||
const auto aa_mode = Settings::values.anti_aliasing.GetValue();
|
||||
const auto aa_text = Config::anti_aliasing_texts_map.find(aa_mode)->second;
|
||||
const auto aa_text = ConfigurationShared::anti_aliasing_texts_map.find(aa_mode)->second;
|
||||
aa_status_button->setText(aa_mode == Settings::AntiAliasing::None
|
||||
? QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "NO AA"))
|
||||
: aa_text.toUpper());
|
||||
@ -4926,6 +4933,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
|
||||
|
||||
UpdateUISettings();
|
||||
game_list->SaveInterfaceLayout();
|
||||
UISettings::SaveWindowState();
|
||||
hotkey_registry.SaveHotkeys();
|
||||
|
||||
// Unload controllers early
|
||||
@ -5080,9 +5088,9 @@ static void AdjustLinkColor() {
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateUITheme() {
|
||||
const QString default_theme =
|
||||
QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);
|
||||
QString current_theme = UISettings::values.theme;
|
||||
const QString default_theme = QString::fromUtf8(
|
||||
UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second);
|
||||
QString current_theme = QString::fromStdString(UISettings::values.theme);
|
||||
|
||||
if (current_theme.isEmpty()) {
|
||||
current_theme = default_theme;
|
||||
@ -5110,7 +5118,7 @@ void GMainWindow::UpdateUITheme() {
|
||||
QFile f(theme_uri);
|
||||
if (!f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
|
||||
UISettings::values.theme.toStdString());
|
||||
UISettings::values.theme);
|
||||
current_theme = default_theme;
|
||||
}
|
||||
}
|
||||
@ -5123,7 +5131,7 @@ void GMainWindow::UpdateUITheme() {
|
||||
setStyleSheet(ts.readAll());
|
||||
} else {
|
||||
LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found",
|
||||
UISettings::values.theme.toStdString());
|
||||
UISettings::values.theme);
|
||||
qApp->setStyleSheet({});
|
||||
setStyleSheet({});
|
||||
}
|
||||
@ -5132,27 +5140,28 @@ void GMainWindow::UpdateUITheme() {
|
||||
void GMainWindow::LoadTranslation() {
|
||||
bool loaded;
|
||||
|
||||
if (UISettings::values.language.isEmpty()) {
|
||||
if (UISettings::values.language.empty()) {
|
||||
// If the selected language is empty, use system locale
|
||||
loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
|
||||
} else {
|
||||
// Otherwise load from the specified file
|
||||
loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
|
||||
loaded = translator.load(QString::fromStdString(UISettings::values.language),
|
||||
QStringLiteral(":/languages/"));
|
||||
}
|
||||
|
||||
if (loaded) {
|
||||
qApp->installTranslator(&translator);
|
||||
} else {
|
||||
UISettings::values.language = QStringLiteral("en");
|
||||
UISettings::values.language = std::string("en");
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnLanguageChanged(const QString& locale) {
|
||||
if (UISettings::values.language != QStringLiteral("en")) {
|
||||
if (UISettings::values.language != std::string("en")) {
|
||||
qApp->removeTranslator(&translator);
|
||||
}
|
||||
|
||||
UISettings::values.language = locale;
|
||||
UISettings::values.language = locale.toStdString();
|
||||
LoadTranslation();
|
||||
ui->retranslateUi(this);
|
||||
multiplayer_state->retranslateUi();
|
||||
@ -5178,7 +5187,7 @@ void GMainWindow::changeEvent(QEvent* event) {
|
||||
// UpdateUITheme is a decent work around
|
||||
if (event->type() == QEvent::PaletteChange) {
|
||||
const QPalette test_palette(qApp->palette());
|
||||
const QString current_theme = UISettings::values.theme;
|
||||
const QString current_theme = QString::fromStdString(UISettings::values.theme);
|
||||
// Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
|
||||
static QColor last_window_color;
|
||||
const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
|
||||
@ -5272,7 +5281,8 @@ static void SetHighDPIAttributes() {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::unique_ptr<Config> config = std::make_unique<Config>();
|
||||
std::unique_ptr<QtConfig> config = std::make_unique<QtConfig>();
|
||||
UISettings::RestoreWindowState(config);
|
||||
bool has_broken_vulkan = false;
|
||||
bool is_child = false;
|
||||
if (CheckEnvVars(&is_child)) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "common/announce_multiplayer_room.h"
|
||||
#include "common/common_types.h"
|
||||
#include "configuration/qt_config.h"
|
||||
#include "input_common/drivers/tas_input.h"
|
||||
#include "yuzu/compatibility_list.h"
|
||||
#include "yuzu/hotkeys.h"
|
||||
@ -26,7 +27,7 @@
|
||||
#include <QtDBus/QtDBus>
|
||||
#endif
|
||||
|
||||
class Config;
|
||||
class QtConfig;
|
||||
class ClickableLabel;
|
||||
class EmuThread;
|
||||
class GameList;
|
||||
@ -185,7 +186,7 @@ class GMainWindow : public QMainWindow {
|
||||
public:
|
||||
void filterBarSetChecked(bool state);
|
||||
void UpdateUITheme();
|
||||
explicit GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan);
|
||||
explicit GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan);
|
||||
~GMainWindow() override;
|
||||
|
||||
bool DropAction(QDropEvent* event);
|
||||
@ -521,7 +522,7 @@ private:
|
||||
QSlider* volume_slider = nullptr;
|
||||
QTimer status_bar_update_timer;
|
||||
|
||||
std::unique_ptr<Config> config;
|
||||
std::unique_ptr<QtConfig> config;
|
||||
|
||||
// Whether emulation is currently running in yuzu.
|
||||
bool emulation_running = false;
|
||||
|
@ -1,6 +1,9 @@
|
||||
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <QSettings>
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "yuzu/uisettings.h"
|
||||
|
||||
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
|
||||
@ -15,6 +18,8 @@ template class Setting<unsigned long long>;
|
||||
} // namespace Settings
|
||||
#endif
|
||||
|
||||
namespace FS = Common::FS;
|
||||
|
||||
namespace UISettings {
|
||||
|
||||
const Themes themes{{
|
||||
@ -28,10 +33,8 @@ const Themes themes{{
|
||||
|
||||
bool IsDarkTheme() {
|
||||
const auto& theme = UISettings::values.theme;
|
||||
return theme == QStringLiteral("qdarkstyle") ||
|
||||
theme == QStringLiteral("qdarkstyle_midnight_blue") ||
|
||||
theme == QStringLiteral("colorful_dark") ||
|
||||
theme == QStringLiteral("colorful_midnight_blue");
|
||||
return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
|
||||
theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
|
||||
}
|
||||
|
||||
Values values = {};
|
||||
@ -52,4 +55,58 @@ u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) {
|
||||
return height * 16 / 9;
|
||||
}
|
||||
|
||||
void SaveWindowState() {
|
||||
const auto window_state_config_loc =
|
||||
FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini");
|
||||
|
||||
void(FS::CreateParentDir(window_state_config_loc));
|
||||
QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat);
|
||||
|
||||
config.setValue(QStringLiteral("geometry"), values.geometry);
|
||||
config.setValue(QStringLiteral("state"), values.state);
|
||||
config.setValue(QStringLiteral("geometryRenderWindow"), values.renderwindow_geometry);
|
||||
config.setValue(QStringLiteral("gameListHeaderState"), values.gamelist_header_state);
|
||||
config.setValue(QStringLiteral("microProfileDialogGeometry"), values.microprofile_geometry);
|
||||
|
||||
config.sync();
|
||||
}
|
||||
|
||||
void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig) {
|
||||
const auto window_state_config_loc =
|
||||
FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini");
|
||||
|
||||
// Migrate window state from old location
|
||||
if (!FS::Exists(window_state_config_loc) && qtConfig->Exists("UI", "UILayout\\geometry")) {
|
||||
const auto config_loc =
|
||||
FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "qt-config.ini");
|
||||
QSettings config(QString::fromStdString(config_loc), QSettings::IniFormat);
|
||||
|
||||
config.beginGroup(QStringLiteral("UI"));
|
||||
config.beginGroup(QStringLiteral("UILayout"));
|
||||
values.geometry = config.value(QStringLiteral("geometry")).toByteArray();
|
||||
values.state = config.value(QStringLiteral("state")).toByteArray();
|
||||
values.renderwindow_geometry =
|
||||
config.value(QStringLiteral("geometryRenderWindow")).toByteArray();
|
||||
values.gamelist_header_state =
|
||||
config.value(QStringLiteral("gameListHeaderState")).toByteArray();
|
||||
values.microprofile_geometry =
|
||||
config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray();
|
||||
config.endGroup();
|
||||
config.endGroup();
|
||||
return;
|
||||
}
|
||||
|
||||
void(FS::CreateParentDir(window_state_config_loc));
|
||||
const QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat);
|
||||
|
||||
values.geometry = config.value(QStringLiteral("geometry")).toByteArray();
|
||||
values.state = config.value(QStringLiteral("state")).toByteArray();
|
||||
values.renderwindow_geometry =
|
||||
config.value(QStringLiteral("geometryRenderWindow")).toByteArray();
|
||||
values.gamelist_header_state =
|
||||
config.value(QStringLiteral("gameListHeaderState")).toByteArray();
|
||||
values.microprofile_geometry =
|
||||
config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray();
|
||||
}
|
||||
|
||||
} // namespace UISettings
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_enums.h"
|
||||
#include "configuration/qt_config.h"
|
||||
|
||||
using Settings::Category;
|
||||
using Settings::ConfirmStop;
|
||||
@ -37,15 +38,15 @@ namespace UISettings {
|
||||
bool IsDarkTheme();
|
||||
|
||||
struct ContextualShortcut {
|
||||
QString keyseq;
|
||||
QString controller_keyseq;
|
||||
std::string keyseq;
|
||||
std::string controller_keyseq;
|
||||
int context;
|
||||
bool repeat;
|
||||
};
|
||||
|
||||
struct Shortcut {
|
||||
QString name;
|
||||
QString group;
|
||||
std::string name;
|
||||
std::string group;
|
||||
ContextualShortcut shortcut;
|
||||
};
|
||||
|
||||
@ -58,11 +59,19 @@ enum class Theme {
|
||||
MidnightBlueColorful,
|
||||
};
|
||||
|
||||
static constexpr Theme default_theme{
|
||||
#ifdef _WIN32
|
||||
Theme::DarkColorful
|
||||
#else
|
||||
Theme::DefaultColorful
|
||||
#endif
|
||||
};
|
||||
|
||||
using Themes = std::array<std::pair<const char*, const char*>, 6>;
|
||||
extern const Themes themes;
|
||||
|
||||
struct GameDir {
|
||||
QString path;
|
||||
std::string path;
|
||||
bool deep_scan = false;
|
||||
bool expanded = false;
|
||||
bool operator==(const GameDir& rhs) const {
|
||||
@ -144,15 +153,15 @@ struct Values {
|
||||
Category::Screenshots};
|
||||
Setting<u32> screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots};
|
||||
|
||||
QString roms_path;
|
||||
QString symbols_path;
|
||||
QString game_dir_deprecated;
|
||||
std::string roms_path;
|
||||
std::string symbols_path;
|
||||
std::string game_dir_deprecated;
|
||||
bool game_dir_deprecated_deepscan;
|
||||
QVector<UISettings::GameDir> game_dirs;
|
||||
QVector<GameDir> game_dirs;
|
||||
QStringList recent_files;
|
||||
QString language;
|
||||
std::string language;
|
||||
|
||||
QString theme;
|
||||
std::string theme;
|
||||
|
||||
// Shortcut name <Shortcut, context>
|
||||
std::vector<Shortcut> shortcuts;
|
||||
@ -206,6 +215,54 @@ extern Values values;
|
||||
|
||||
u32 CalculateWidth(u32 height, Settings::AspectRatio ratio);
|
||||
|
||||
void SaveWindowState();
|
||||
void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig);
|
||||
|
||||
// This shouldn't have anything except static initializers (no functions). So
|
||||
// QKeySequence(...).toString() is NOT ALLOWED HERE.
|
||||
// This must be in alphabetical order according to action name as it must have the same order as
|
||||
// UISetting::values.shortcuts, which is alphabetically ordered.
|
||||
// clang-format off
|
||||
const std::array<Shortcut, 23> default_hotkeys{{
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+P"), std::string("Screenshot"), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F8"), std::string("Home+L"), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F10"), std::string("Home+X"), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F9"), std::string("Home+R"), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F4"), std::string("Home+Plus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F6"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F5"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F"), std::string(""), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+U"), std::string("Home+Y"), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F9"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string(""), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+S"), std::string(""), Qt::WindowShortcut, false}},
|
||||
}};
|
||||
// clang-format on
|
||||
|
||||
} // namespace UISettings
|
||||
|
||||
Q_DECLARE_METATYPE(UISettings::GameDir*);
|
||||
|
||||
// These metatype declarations cannot be in common/settings.h because core is devoid of QT
|
||||
Q_DECLARE_METATYPE(Settings::CpuAccuracy);
|
||||
Q_DECLARE_METATYPE(Settings::GpuAccuracy);
|
||||
Q_DECLARE_METATYPE(Settings::FullscreenMode);
|
||||
Q_DECLARE_METATYPE(Settings::NvdecEmulation);
|
||||
Q_DECLARE_METATYPE(Settings::ResolutionSetup);
|
||||
Q_DECLARE_METATYPE(Settings::ScalingFilter);
|
||||
Q_DECLARE_METATYPE(Settings::AntiAliasing);
|
||||
Q_DECLARE_METATYPE(Settings::RendererBackend);
|
||||
Q_DECLARE_METATYPE(Settings::ShaderBackend);
|
||||
Q_DECLARE_METATYPE(Settings::AstcRecompression);
|
||||
Q_DECLARE_METATYPE(Settings::AstcDecodeMode);
|
||||
|
@ -13,9 +13,6 @@ function(create_resource file output filename)
|
||||
endfunction()
|
||||
|
||||
add_executable(yuzu-cmd
|
||||
config.cpp
|
||||
config.h
|
||||
default_ini.h
|
||||
emu_window/emu_window_sdl2.cpp
|
||||
emu_window/emu_window_sdl2.h
|
||||
emu_window/emu_window_sdl2_gl.cpp
|
||||
@ -25,14 +22,16 @@ add_executable(yuzu-cmd
|
||||
emu_window/emu_window_sdl2_vk.cpp
|
||||
emu_window/emu_window_sdl2_vk.h
|
||||
precompiled_headers.h
|
||||
sdl_config.cpp
|
||||
sdl_config.h
|
||||
yuzu.cpp
|
||||
yuzu.rc
|
||||
)
|
||||
|
||||
create_target_directory_groups(yuzu-cmd)
|
||||
|
||||
target_link_libraries(yuzu-cmd PRIVATE common core input_common)
|
||||
target_link_libraries(yuzu-cmd PRIVATE inih::INIReader glad)
|
||||
target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common)
|
||||
if (MSVC)
|
||||
target_link_libraries(yuzu-cmd PRIVATE getopt)
|
||||
endif()
|
||||
|
@ -1,279 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <INIReader.h>
|
||||
#include <SDL.h>
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "input_common/main.h"
|
||||
#include "yuzu_cmd/config.h"
|
||||
#include "yuzu_cmd/default_ini.h"
|
||||
|
||||
namespace FS = Common::FS;
|
||||
|
||||
const std::filesystem::path default_config_path =
|
||||
FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
|
||||
|
||||
Config::Config(std::optional<std::filesystem::path> config_path)
|
||||
: sdl2_config_loc{config_path.value_or(default_config_path)},
|
||||
sdl2_config{std::make_unique<INIReader>(FS::PathToUTF8String(sdl2_config_loc))} {
|
||||
Reload();
|
||||
}
|
||||
|
||||
Config::~Config() = default;
|
||||
|
||||
bool Config::LoadINI(const std::string& default_contents, bool retry) {
|
||||
const auto config_loc_str = FS::PathToUTF8String(sdl2_config_loc);
|
||||
if (sdl2_config->ParseError() < 0) {
|
||||
if (retry) {
|
||||
LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...",
|
||||
config_loc_str);
|
||||
|
||||
void(FS::CreateParentDir(sdl2_config_loc));
|
||||
void(FS::WriteStringToFile(sdl2_config_loc, FS::FileType::TextFile, default_contents));
|
||||
|
||||
sdl2_config = std::make_unique<INIReader>(config_loc_str);
|
||||
|
||||
return LoadINI(default_contents, false);
|
||||
}
|
||||
LOG_ERROR(Config, "Failed.");
|
||||
return false;
|
||||
}
|
||||
LOG_INFO(Config, "Successfully loaded {}", config_loc_str);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons = {
|
||||
SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T,
|
||||
SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W,
|
||||
SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
|
||||
};
|
||||
|
||||
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions = {
|
||||
SDL_SCANCODE_7,
|
||||
SDL_SCANCODE_8,
|
||||
};
|
||||
|
||||
static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{
|
||||
{
|
||||
SDL_SCANCODE_UP,
|
||||
SDL_SCANCODE_DOWN,
|
||||
SDL_SCANCODE_LEFT,
|
||||
SDL_SCANCODE_RIGHT,
|
||||
SDL_SCANCODE_D,
|
||||
},
|
||||
{
|
||||
SDL_SCANCODE_I,
|
||||
SDL_SCANCODE_K,
|
||||
SDL_SCANCODE_J,
|
||||
SDL_SCANCODE_L,
|
||||
SDL_SCANCODE_D,
|
||||
},
|
||||
}};
|
||||
|
||||
template <>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) {
|
||||
std::string setting_value = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault());
|
||||
if (setting_value.empty()) {
|
||||
setting_value = setting.GetDefault();
|
||||
}
|
||||
setting = std::move(setting_value);
|
||||
}
|
||||
|
||||
template <>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
|
||||
setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
|
||||
}
|
||||
|
||||
template <typename Type, bool ranged>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
|
||||
setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(),
|
||||
static_cast<long>(setting.GetDefault())));
|
||||
}
|
||||
|
||||
void Config::ReadCategory(Settings::Category category) {
|
||||
for (const auto setting : Settings::values.linkage.by_category[category]) {
|
||||
const char* category_name = [&]() {
|
||||
if (category == Settings::Category::Controls) {
|
||||
// For compatibility with older configs
|
||||
return "ControlsGeneral";
|
||||
} else {
|
||||
return Settings::TranslateCategory(category);
|
||||
}
|
||||
}();
|
||||
std::string setting_value =
|
||||
sdl2_config->Get(category_name, setting->GetLabel(), setting->DefaultToString());
|
||||
setting->LoadString(setting_value);
|
||||
}
|
||||
}
|
||||
|
||||
void Config::ReadValues() {
|
||||
// Controls
|
||||
ReadCategory(Settings::Category::Controls);
|
||||
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
auto& player = Settings::values.players.GetValue()[p];
|
||||
|
||||
const auto group = fmt::format("ControlsP{}", p);
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
player.buttons[i] =
|
||||
sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
|
||||
if (player.buttons[i].empty()) {
|
||||
player.buttons[i] = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_analogs[i][4], 0.5f);
|
||||
player.analogs[i] =
|
||||
sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
|
||||
if (player.analogs[i].empty()) {
|
||||
player.analogs[i] = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param =
|
||||
InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
auto& player_motions = player.motions[i];
|
||||
|
||||
player_motions =
|
||||
sdl2_config->Get(group, Settings::NativeMotion::mapping[i], default_param);
|
||||
if (player_motions.empty()) {
|
||||
player_motions = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
player.connected = sdl2_config->GetBoolean(group, "connected", false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
Settings::values.debug_pad_buttons[i] = sdl2_config->Get(
|
||||
"ControlsGeneral", std::string("debug_pad_") + Settings::NativeButton::mapping[i],
|
||||
default_param);
|
||||
if (Settings::values.debug_pad_buttons[i].empty())
|
||||
Settings::values.debug_pad_buttons[i] = default_param;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_analogs[i][4], 0.5f);
|
||||
Settings::values.debug_pad_analogs[i] = sdl2_config->Get(
|
||||
"ControlsGeneral", std::string("debug_pad_") + Settings::NativeAnalog::mapping[i],
|
||||
default_param);
|
||||
if (Settings::values.debug_pad_analogs[i].empty())
|
||||
Settings::values.debug_pad_analogs[i] = default_param;
|
||||
}
|
||||
|
||||
Settings::values.touchscreen.enabled =
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true);
|
||||
Settings::values.touchscreen.rotation_angle =
|
||||
sdl2_config->GetInteger("ControlsGeneral", "touch_angle", 0);
|
||||
Settings::values.touchscreen.diameter_x =
|
||||
sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_x", 15);
|
||||
Settings::values.touchscreen.diameter_y =
|
||||
sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_y", 15);
|
||||
|
||||
int num_touch_from_button_maps =
|
||||
sdl2_config->GetInteger("ControlsGeneral", "touch_from_button_map", 0);
|
||||
if (num_touch_from_button_maps > 0) {
|
||||
for (int i = 0; i < num_touch_from_button_maps; ++i) {
|
||||
Settings::TouchFromButtonMap map;
|
||||
map.name = sdl2_config->Get("ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||
std::string("_name"),
|
||||
"default");
|
||||
const int num_touch_maps = sdl2_config->GetInteger(
|
||||
"ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"),
|
||||
0);
|
||||
map.buttons.reserve(num_touch_maps);
|
||||
|
||||
for (int j = 0; j < num_touch_maps; ++j) {
|
||||
std::string touch_mapping =
|
||||
sdl2_config->Get("ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||
std::string("_bind_") + std::to_string(j),
|
||||
"");
|
||||
map.buttons.emplace_back(std::move(touch_mapping));
|
||||
}
|
||||
|
||||
Settings::values.touch_from_button_maps.emplace_back(std::move(map));
|
||||
}
|
||||
} else {
|
||||
Settings::values.touch_from_button_maps.emplace_back(
|
||||
Settings::TouchFromButtonMap{"default", {}});
|
||||
num_touch_from_button_maps = 1;
|
||||
}
|
||||
Settings::values.touch_from_button_map_index = std::clamp(
|
||||
Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
|
||||
|
||||
ReadCategory(Settings::Category::Audio);
|
||||
ReadCategory(Settings::Category::Core);
|
||||
ReadCategory(Settings::Category::Cpu);
|
||||
ReadCategory(Settings::Category::CpuDebug);
|
||||
ReadCategory(Settings::Category::CpuUnsafe);
|
||||
ReadCategory(Settings::Category::Renderer);
|
||||
ReadCategory(Settings::Category::RendererAdvanced);
|
||||
ReadCategory(Settings::Category::RendererDebug);
|
||||
ReadCategory(Settings::Category::System);
|
||||
ReadCategory(Settings::Category::SystemAudio);
|
||||
ReadCategory(Settings::Category::DataStorage);
|
||||
ReadCategory(Settings::Category::Debugging);
|
||||
ReadCategory(Settings::Category::DebuggingGraphics);
|
||||
ReadCategory(Settings::Category::Miscellaneous);
|
||||
ReadCategory(Settings::Category::Network);
|
||||
ReadCategory(Settings::Category::WebService);
|
||||
|
||||
// Data Storage
|
||||
FS::SetYuzuPath(FS::YuzuPath::NANDDir,
|
||||
sdl2_config->Get("Data Storage", "nand_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
|
||||
FS::SetYuzuPath(FS::YuzuPath::SDMCDir,
|
||||
sdl2_config->Get("Data Storage", "sdmc_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
|
||||
FS::SetYuzuPath(FS::YuzuPath::LoadDir,
|
||||
sdl2_config->Get("Data Storage", "load_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
|
||||
FS::SetYuzuPath(FS::YuzuPath::DumpDir,
|
||||
sdl2_config->Get("Data Storage", "dump_directory",
|
||||
FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
|
||||
|
||||
// Debugging
|
||||
Settings::values.record_frame_times =
|
||||
sdl2_config->GetBoolean("Debugging", "record_frame_times", false);
|
||||
|
||||
const auto title_list = sdl2_config->Get("AddOns", "title_ids", "");
|
||||
std::stringstream ss(title_list);
|
||||
std::string line;
|
||||
while (std::getline(ss, line, '|')) {
|
||||
const auto title_id = std::strtoul(line.c_str(), nullptr, 16);
|
||||
const auto disabled_list = sdl2_config->Get("AddOns", "disabled_" + line, "");
|
||||
|
||||
std::stringstream inner_ss(disabled_list);
|
||||
std::string inner_line;
|
||||
std::vector<std::string> out;
|
||||
while (std::getline(inner_ss, inner_line, '|')) {
|
||||
out.push_back(inner_line);
|
||||
}
|
||||
|
||||
Settings::values.disabled_addons.insert_or_assign(title_id, out);
|
||||
}
|
||||
}
|
||||
|
||||
void Config::Reload() {
|
||||
LoadINI(DefaultINI::sdl2_config_file);
|
||||
ReadValues();
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "common/settings.h"
|
||||
|
||||
class INIReader;
|
||||
|
||||
class Config {
|
||||
std::filesystem::path sdl2_config_loc;
|
||||
std::unique_ptr<INIReader> sdl2_config;
|
||||
|
||||
bool LoadINI(const std::string& default_contents = "", bool retry = true);
|
||||
void ReadValues();
|
||||
|
||||
public:
|
||||
explicit Config(std::optional<std::filesystem::path> config_path);
|
||||
~Config();
|
||||
|
||||
void Reload();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Applies a value read from the sdl2_config to a Setting.
|
||||
*
|
||||
* @param group The name of the INI group
|
||||
* @param setting The yuzu setting to modify
|
||||
*/
|
||||
template <typename Type, bool ranged>
|
||||
void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
|
||||
void ReadCategory(Settings::Category category);
|
||||
};
|
@ -1,553 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace DefaultINI {
|
||||
|
||||
const char* sdl2_config_file =
|
||||
R"(
|
||||
[ControlsP0]
|
||||
# The input devices and parameters for each Switch native input
|
||||
# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ...
|
||||
# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
|
||||
# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
|
||||
|
||||
# Indicates if this player should be connected at boot
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
connected=
|
||||
|
||||
# for button input, the following devices are available:
|
||||
# - "keyboard" (default) for keyboard input. Required parameters:
|
||||
# - "code": the code of the key to bind
|
||||
# - "sdl" for joystick input using SDL. Required parameters:
|
||||
# - "guid": SDL identification GUID of the joystick
|
||||
# - "port": the index of the joystick to bind
|
||||
# - "button"(optional): the index of the button to bind
|
||||
# - "hat"(optional): the index of the hat to bind as direction buttons
|
||||
# - "axis"(optional): the index of the axis to bind
|
||||
# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right"
|
||||
# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
|
||||
# triggered if the axis value crosses
|
||||
# - "direction"(only used for axis): "+" means the button is triggered when the axis value
|
||||
# is greater than the threshold; "-" means the button is triggered when the axis value
|
||||
# is smaller than the threshold
|
||||
button_a=
|
||||
button_b=
|
||||
button_x=
|
||||
button_y=
|
||||
button_lstick=
|
||||
button_rstick=
|
||||
button_l=
|
||||
button_r=
|
||||
button_zl=
|
||||
button_zr=
|
||||
button_plus=
|
||||
button_minus=
|
||||
button_dleft=
|
||||
button_dup=
|
||||
button_dright=
|
||||
button_ddown=
|
||||
button_lstick_left=
|
||||
button_lstick_up=
|
||||
button_lstick_right=
|
||||
button_lstick_down=
|
||||
button_sl=
|
||||
button_sr=
|
||||
button_home=
|
||||
button_screenshot=
|
||||
|
||||
# for analog input, the following devices are available:
|
||||
# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
|
||||
# - "up", "down", "left", "right": sub-devices for each direction.
|
||||
# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00"
|
||||
# - "modifier": sub-devices as a modifier.
|
||||
# - "modifier_scale": a float number representing the applied modifier scale to the analog input.
|
||||
# Must be in range of 0.0-1.0. Defaults to 0.5
|
||||
# - "sdl" for joystick input using SDL. Required parameters:
|
||||
# - "guid": SDL identification GUID of the joystick
|
||||
# - "port": the index of the joystick to bind
|
||||
# - "axis_x": the index of the axis to bind as x-axis (default to 0)
|
||||
# - "axis_y": the index of the axis to bind as y-axis (default to 1)
|
||||
lstick=
|
||||
rstick=
|
||||
|
||||
# for motion input, the following devices are available:
|
||||
# - "keyboard" (default) for emulating random motion input from buttons. Required parameters:
|
||||
# - "code": the code of the key to bind
|
||||
# - "sdl" for motion input using SDL. Required parameters:
|
||||
# - "guid": SDL identification GUID of the joystick
|
||||
# - "port": the index of the joystick to bind
|
||||
# - "motion": the index of the motion sensor to bind
|
||||
# - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters:
|
||||
# - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001"
|
||||
# - "port": the port of the cemu hook server
|
||||
# - "pad": the index of the joystick
|
||||
# - "motion": the index of the motion sensor of the joystick to bind
|
||||
motionleft=
|
||||
motionright=
|
||||
|
||||
[ControlsGeneral]
|
||||
# To use the debug_pad, prepend `debug_pad_` before each button setting above.
|
||||
# i.e. debug_pad_button_a=
|
||||
|
||||
# Enable debug pad inputs to the guest
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
debug_pad_enabled =
|
||||
|
||||
# Enable sdl raw input. Allows to configure up to 8 xinput controllers.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
enable_raw_input =
|
||||
|
||||
# Enable yuzu joycon driver instead of SDL drive.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
enable_joycon_driver =
|
||||
|
||||
# Emulates an analog input from buttons. Allowing to dial any angle.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
emulate_analog_keyboard =
|
||||
|
||||
# Whether to enable or disable vibration
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
vibration_enabled=
|
||||
|
||||
# Whether to enable or disable accurate vibrations
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
enable_accurate_vibrations=
|
||||
|
||||
# Enables controller motion inputs
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
motion_enabled =
|
||||
|
||||
# Defines the udp device's touch screen coordinate system for cemuhookudp devices
|
||||
# - "min_x", "min_y", "max_x", "max_y"
|
||||
touch_device=
|
||||
|
||||
# for mapping buttons to touch inputs.
|
||||
#touch_from_button_map=1
|
||||
#touch_from_button_maps_0_name=default
|
||||
#touch_from_button_maps_0_count=2
|
||||
#touch_from_button_maps_0_bind_0=foo
|
||||
#touch_from_button_maps_0_bind_1=bar
|
||||
# etc.
|
||||
|
||||
# List of Cemuhook UDP servers, delimited by ','.
|
||||
# Default: 127.0.0.1:26760
|
||||
# Example: 127.0.0.1:26760,123.4.5.67:26761
|
||||
udp_input_servers =
|
||||
|
||||
# Enable controlling an axis via a mouse input.
|
||||
# 0 (default): Off, 1: On
|
||||
mouse_panning =
|
||||
|
||||
# Set mouse panning horizontal sensitivity.
|
||||
# Default: 50.0
|
||||
mouse_panning_x_sensitivity =
|
||||
|
||||
# Set mouse panning vertical sensitivity.
|
||||
# Default: 50.0
|
||||
mouse_panning_y_sensitivity =
|
||||
|
||||
# Set mouse panning deadzone horizontal counterweight.
|
||||
# Default: 0.0
|
||||
mouse_panning_deadzone_x_counterweight =
|
||||
|
||||
# Set mouse panning deadzone vertical counterweight.
|
||||
# Default: 0.0
|
||||
mouse_panning_deadzone_y_counterweight =
|
||||
|
||||
# Set mouse panning stick decay strength.
|
||||
# Default: 22.0
|
||||
mouse_panning_decay_strength =
|
||||
|
||||
# Set mouse panning stick minimum decay.
|
||||
# Default: 5.0
|
||||
mouse_panning_minimum_decay =
|
||||
|
||||
# Emulate an analog control stick from keyboard inputs.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
emulate_analog_keyboard =
|
||||
|
||||
# Enable mouse inputs to the guest
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
mouse_enabled =
|
||||
|
||||
# Enable keyboard inputs to the guest
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
keyboard_enabled =
|
||||
|
||||
)"
|
||||
R"(
|
||||
[Core]
|
||||
# Whether to use multi-core for CPU emulation
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
use_multi_core =
|
||||
|
||||
# Enable unsafe extended guest system memory layout (8GB DRAM)
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
use_unsafe_extended_memory_layout =
|
||||
|
||||
[Cpu]
|
||||
# Adjusts various optimizations.
|
||||
# Auto-select mode enables choice unsafe optimizations.
|
||||
# Accurate enables only safe optimizations.
|
||||
# Unsafe allows any unsafe optimizations.
|
||||
# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations
|
||||
cpu_accuracy =
|
||||
|
||||
# Allow disabling safe optimizations.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
cpu_debug_mode =
|
||||
|
||||
# Enable inline page tables optimization (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_page_tables =
|
||||
|
||||
# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_block_linking =
|
||||
|
||||
# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_return_stack_buffer =
|
||||
|
||||
# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_fast_dispatcher =
|
||||
|
||||
# Enable context elimination CPU Optimization (reduce host memory use for guest context)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_context_elimination =
|
||||
|
||||
# Enable constant propagation CPU optimization (basic IR optimization)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_const_prop =
|
||||
|
||||
# Enable miscellaneous CPU optimizations (basic IR optimization)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_misc_ir =
|
||||
|
||||
# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_reduce_misalign_checks =
|
||||
|
||||
# Enable Host MMU Emulation (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_fastmem =
|
||||
|
||||
# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_fastmem_exclusives =
|
||||
|
||||
# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_recompile_exclusives =
|
||||
|
||||
# Enable optimization to ignore invalid memory accesses (faster guest memory access)
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_ignore_memory_aborts =
|
||||
|
||||
# Enable unfuse FMA (improve performance on CPUs without FMA)
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_unfuse_fma =
|
||||
|
||||
# Enable faster FRSQRTE and FRECPE
|
||||
# Only enabled if cpu_accuracy is set to Unsafe.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_reduce_fp_error =
|
||||
|
||||
# Enable faster ASIMD instructions (32 bits only)
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_ignore_standard_fpcr =
|
||||
|
||||
# Enable inaccurate NaN handling
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_inaccurate_nan =
|
||||
|
||||
# Disable address space checks (64 bits only)
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_fastmem_check =
|
||||
|
||||
# Enable faster exclusive instructions
|
||||
# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
cpuopt_unsafe_ignore_global_monitor =
|
||||
|
||||
)"
|
||||
R"(
|
||||
[Renderer]
|
||||
# Which backend API to use.
|
||||
# 0: OpenGL, 1 (default): Vulkan
|
||||
backend =
|
||||
|
||||
# Whether to enable asynchronous presentation (Vulkan only)
|
||||
# 0 (default): Off, 1: On
|
||||
async_presentation =
|
||||
|
||||
# Enable graphics API debugging mode.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
debug =
|
||||
|
||||
# Enable shader feedback.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
renderer_shader_feedback =
|
||||
|
||||
# Enable Nsight Aftermath crash dumps
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
nsight_aftermath =
|
||||
|
||||
# Disable shader loop safety checks, executing the shader without loop logic changes
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
disable_shader_loop_safety_checks =
|
||||
|
||||
# Which Vulkan physical device to use (defaults to 0)
|
||||
vulkan_device =
|
||||
|
||||
# 0: 0.5x (360p/540p) [EXPERIMENTAL]
|
||||
# 1: 0.75x (540p/810p) [EXPERIMENTAL]
|
||||
# 2 (default): 1x (720p/1080p)
|
||||
# 3: 1.5x (1080p/1620p) [EXPERIMENTAL]
|
||||
# 4: 2x (1440p/2160p)
|
||||
# 5: 3x (2160p/3240p)
|
||||
# 6: 4x (2880p/4320p)
|
||||
# 7: 5x (3600p/5400p)
|
||||
# 8: 6x (4320p/6480p)
|
||||
# 9: 7x (5040p/7560p)
|
||||
# 10: 8x (5760/8640p)
|
||||
resolution_setup =
|
||||
|
||||
# Pixel filter to use when up- or down-sampling rendered frames.
|
||||
# 0: Nearest Neighbor
|
||||
# 1 (default): Bilinear
|
||||
# 2: Bicubic
|
||||
# 3: Gaussian
|
||||
# 4: ScaleForce
|
||||
# 5: AMD FidelityFX™️ Super Resolution
|
||||
scaling_filter =
|
||||
|
||||
# Anti-Aliasing (AA)
|
||||
# 0 (default): None, 1: FXAA, 2: SMAA
|
||||
anti_aliasing =
|
||||
|
||||
# Whether to use fullscreen or borderless window mode
|
||||
# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen
|
||||
fullscreen_mode =
|
||||
|
||||
# Aspect ratio
|
||||
# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window
|
||||
aspect_ratio =
|
||||
|
||||
# Anisotropic filtering
|
||||
# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
|
||||
max_anisotropy =
|
||||
|
||||
# Whether to enable VSync or not.
|
||||
# OpenGL: Values other than 0 enable VSync
|
||||
# Vulkan: FIFO is selected if the requested mode is not supported by the driver.
|
||||
# FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate.
|
||||
# FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down.
|
||||
# Mailbox can have lower latency than FIFO and does not tear but may drop frames.
|
||||
# Immediate (no synchronization) just presents whatever is available and can exhibit tearing.
|
||||
# 0: Immediate (Off), 1: Mailbox, 2 (Default): FIFO (On), 3: FIFO Relaxed
|
||||
use_vsync =
|
||||
|
||||
# Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is
|
||||
# not available and GLASM is selected, GLSL will be used.
|
||||
# 0: GLSL, 1 (default): GLASM, 2: SPIR-V
|
||||
shader_backend =
|
||||
|
||||
# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
|
||||
# 0: Off, 1 (default): On
|
||||
use_reactive_flushing =
|
||||
|
||||
# Whether to allow asynchronous shader building.
|
||||
# 0 (default): Off, 1: On
|
||||
use_asynchronous_shaders =
|
||||
|
||||
# NVDEC emulation.
|
||||
# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
|
||||
nvdec_emulation =
|
||||
|
||||
# Accelerate ASTC texture decoding.
|
||||
# 0: Off, 1 (default): On
|
||||
accelerate_astc =
|
||||
|
||||
# Decode ASTC textures asynchronously.
|
||||
# 0 (default): Off, 1: On
|
||||
async_astc =
|
||||
|
||||
# Recompress ASTC textures to a different format.
|
||||
# 0 (default): Uncompressed, 1: BC1 (Low quality), 2: BC3: (Medium quality)
|
||||
async_astc =
|
||||
|
||||
# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value
|
||||
# 0: Off, 1: On (default)
|
||||
use_speed_limit =
|
||||
|
||||
# Limits the speed of the game to run no faster than this value as a percentage of target speed
|
||||
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
|
||||
speed_limit =
|
||||
|
||||
# Whether to use disk based shader cache
|
||||
# 0: Off, 1 (default): On
|
||||
use_disk_shader_cache =
|
||||
|
||||
# Which gpu accuracy level to use
|
||||
# 0: Normal, 1 (default): High, 2: Extreme (Very slow)
|
||||
gpu_accuracy =
|
||||
|
||||
# Whether to use asynchronous GPU emulation
|
||||
# 0 : Off (slow), 1 (default): On (fast)
|
||||
use_asynchronous_gpu_emulation =
|
||||
|
||||
# Inform the guest that GPU operations completed more quickly than they did.
|
||||
# 0: Off, 1 (default): On
|
||||
use_fast_gpu_time =
|
||||
|
||||
# Whether to use garbage collection or not for GPU caches.
|
||||
# 0 (default): Off, 1: On
|
||||
use_caches_gc =
|
||||
|
||||
# The clear color for the renderer. What shows up on the sides of the bottom screen.
|
||||
# Must be in range of 0-255. Defaults to 0 for all.
|
||||
bg_red =
|
||||
bg_blue =
|
||||
bg_green =
|
||||
|
||||
)"
|
||||
R"(
|
||||
[Audio]
|
||||
# Which audio output engine to use.
|
||||
# auto (default): Auto-select
|
||||
# cubeb: Cubeb audio engine (if available)
|
||||
# sdl2: SDL2 audio engine (if available)
|
||||
# null: No audio output
|
||||
output_engine =
|
||||
|
||||
# Which audio device to use.
|
||||
# auto (default): Auto-select
|
||||
output_device =
|
||||
|
||||
# Output volume.
|
||||
# 100 (default): 100%, 0; mute
|
||||
volume =
|
||||
|
||||
[Data Storage]
|
||||
# Whether to create a virtual SD card.
|
||||
# 1 (default): Yes, 0: No
|
||||
use_virtual_sd =
|
||||
|
||||
# Whether or not to enable gamecard emulation
|
||||
# 1: Yes, 0 (default): No
|
||||
gamecard_inserted =
|
||||
|
||||
# Whether or not the gamecard should be emulated as the current game
|
||||
# If 'gamecard_inserted' is 0 this setting is irrelevant
|
||||
# 1: Yes, 0 (default): No
|
||||
gamecard_current_game =
|
||||
|
||||
# Path to an XCI file to use as the gamecard
|
||||
# If 'gamecard_inserted' is 0 this setting is irrelevant
|
||||
# If 'gamecard_current_game' is 1 this setting is irrelevant
|
||||
gamecard_path =
|
||||
|
||||
[System]
|
||||
# Whether the system is docked
|
||||
# 1 (default): Yes, 0: No
|
||||
use_docked_mode =
|
||||
|
||||
# Sets the seed for the RNG generator built into the switch
|
||||
# rng_seed will be ignored and randomly generated if rng_seed_enabled is false
|
||||
rng_seed_enabled =
|
||||
rng_seed =
|
||||
|
||||
# Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service
|
||||
# This will auto-increment, with the time set being the time the game is started
|
||||
# This override will only occur if custom_rtc_enabled is true, otherwise the current time is used
|
||||
custom_rtc_enabled =
|
||||
custom_rtc =
|
||||
|
||||
# Sets the systems language index
|
||||
# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese,
|
||||
# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French,
|
||||
# 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese
|
||||
language_index =
|
||||
|
||||
# The system region that yuzu will use during emulation
|
||||
# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
|
||||
region_index =
|
||||
|
||||
# The system time zone that yuzu will use during emulation
|
||||
# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone
|
||||
time_zone_index =
|
||||
|
||||
# Sets the sound output mode.
|
||||
# 0: Mono, 1 (default): Stereo, 2: Surround
|
||||
sound_index =
|
||||
|
||||
[Miscellaneous]
|
||||
# A filter which removes logs below a certain logging level.
|
||||
# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
|
||||
log_filter = *:Trace
|
||||
|
||||
# Use developer keys
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
use_dev_keys =
|
||||
|
||||
[Debugging]
|
||||
# Record frame time data, can be found in the log directory. Boolean value
|
||||
record_frame_times =
|
||||
# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them
|
||||
dump_exefs=false
|
||||
# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
|
||||
dump_nso=false
|
||||
# Determines whether or not yuzu will save the filesystem access log.
|
||||
enable_fs_access_log=false
|
||||
# Enables verbose reporting services
|
||||
reporting_services =
|
||||
# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
|
||||
# false: Retail/Normal Mode (default), true: Kiosk Mode
|
||||
quest_flag =
|
||||
# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
|
||||
# false: Disabled (default), true: Enabled
|
||||
use_debug_asserts =
|
||||
# Determines whether unimplemented HLE service calls should be automatically stubbed.
|
||||
# false: Disabled (default), true: Enabled
|
||||
use_auto_stub =
|
||||
# Enables/Disables the macro JIT compiler
|
||||
disable_macro_jit=false
|
||||
# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
|
||||
# false: Disabled (default), true: Enabled
|
||||
use_gdbstub=false
|
||||
# The port to use for the GDB server, if it is enabled.
|
||||
gdbstub_port=6543
|
||||
|
||||
[WebService]
|
||||
# Whether or not to enable telemetry
|
||||
# 0: No, 1 (default): Yes
|
||||
enable_telemetry =
|
||||
# URL for Web API
|
||||
web_api_url = https://api.yuzu-emu.org
|
||||
# Username and token for yuzu Web Service
|
||||
# See https://profile.yuzu-emu.org/ for more info
|
||||
yuzu_username =
|
||||
yuzu_token =
|
||||
|
||||
[Network]
|
||||
# Name of the network interface device to use with yuzu LAN play.
|
||||
# e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo'
|
||||
# e.g. On Windows: 'Ethernet', 'Wi-Fi'
|
||||
network_interface =
|
||||
|
||||
[AddOns]
|
||||
# Used to disable add-ons
|
||||
# List of title IDs of games that will have add-ons disabled (separated by '|'):
|
||||
title_ids =
|
||||
# For each title ID, have a key/value pair called `disabled_<title_id>` equal to the names of the add-ons to disable (sep. by '|')
|
||||
# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey
|
||||
)";
|
||||
} // namespace DefaultINI
|
257
src/yuzu_cmd/sdl_config.cpp
Normal file
257
src/yuzu_cmd/sdl_config.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SDL will break our main function in yuzu-cmd if we don't define this before adding SDL.h
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include <SDL.h>
|
||||
|
||||
#include "input_common/main.h"
|
||||
#include "sdl_config.h"
|
||||
|
||||
const std::array<int, Settings::NativeButton::NumButtons> SdlConfig::default_buttons = {
|
||||
SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T,
|
||||
SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W,
|
||||
SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
|
||||
};
|
||||
|
||||
const std::array<int, Settings::NativeMotion::NumMotions> SdlConfig::default_motions = {
|
||||
SDL_SCANCODE_7,
|
||||
SDL_SCANCODE_8,
|
||||
};
|
||||
|
||||
const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> SdlConfig::default_analogs{
|
||||
{
|
||||
{
|
||||
SDL_SCANCODE_UP,
|
||||
SDL_SCANCODE_DOWN,
|
||||
SDL_SCANCODE_LEFT,
|
||||
SDL_SCANCODE_RIGHT,
|
||||
},
|
||||
{
|
||||
SDL_SCANCODE_I,
|
||||
SDL_SCANCODE_K,
|
||||
SDL_SCANCODE_J,
|
||||
SDL_SCANCODE_L,
|
||||
},
|
||||
}};
|
||||
|
||||
const std::array<int, 2> SdlConfig::default_stick_mod = {
|
||||
SDL_SCANCODE_D,
|
||||
0,
|
||||
};
|
||||
|
||||
const std::array<int, 2> SdlConfig::default_ringcon_analogs{{
|
||||
0,
|
||||
0,
|
||||
}};
|
||||
|
||||
SdlConfig::SdlConfig(const std::optional<std::string> config_path) {
|
||||
Initialize(config_path);
|
||||
ReadSdlValues();
|
||||
SaveSdlValues();
|
||||
}
|
||||
|
||||
SdlConfig::~SdlConfig() {
|
||||
if (global) {
|
||||
SdlConfig::SaveAllValues();
|
||||
}
|
||||
}
|
||||
|
||||
void SdlConfig::ReloadAllValues() {
|
||||
Reload();
|
||||
ReadSdlValues();
|
||||
SaveSdlValues();
|
||||
}
|
||||
|
||||
void SdlConfig::SaveAllValues() {
|
||||
Save();
|
||||
SaveSdlValues();
|
||||
}
|
||||
|
||||
void SdlConfig::ReadSdlValues() {
|
||||
ReadSdlControlValues();
|
||||
}
|
||||
|
||||
void SdlConfig::ReadSdlControlValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
ReadSdlPlayerValues(p);
|
||||
}
|
||||
if (IsCustomConfig()) {
|
||||
EndGroup();
|
||||
return;
|
||||
}
|
||||
ReadDebugControlValues();
|
||||
ReadHidbusValues();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void SdlConfig::ReadSdlPlayerValues(const std::size_t player_index) {
|
||||
std::string player_prefix;
|
||||
if (type != ConfigType::InputProfile) {
|
||||
player_prefix.append("player_").append(ToString(player_index)).append("_");
|
||||
}
|
||||
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (IsCustomConfig()) {
|
||||
const auto profile_name =
|
||||
ReadStringSetting(std::string(player_prefix).append("profile_name"));
|
||||
if (profile_name.empty()) {
|
||||
// Use the global input config
|
||||
player = Settings::values.players.GetValue(true)[player_index];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
auto& player_buttons = player.buttons[i];
|
||||
|
||||
player_buttons = ReadStringSetting(
|
||||
std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param);
|
||||
if (player_buttons.empty()) {
|
||||
player_buttons = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
auto& player_analogs = player.analogs[i];
|
||||
|
||||
player_analogs = ReadStringSetting(
|
||||
std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param);
|
||||
if (player_analogs.empty()) {
|
||||
player_analogs = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
auto& player_motions = player.motions[i];
|
||||
|
||||
player_motions = ReadStringSetting(
|
||||
std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param);
|
||||
if (player_motions.empty()) {
|
||||
player_motions = default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SdlConfig::ReadDebugControlValues() {
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i];
|
||||
debug_pad_buttons = ReadStringSetting(
|
||||
std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param);
|
||||
if (debug_pad_buttons.empty()) {
|
||||
debug_pad_buttons = default_param;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i];
|
||||
debug_pad_analogs = ReadStringSetting(
|
||||
std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param);
|
||||
if (debug_pad_analogs.empty()) {
|
||||
debug_pad_analogs = default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SdlConfig::ReadHidbusValues() {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
|
||||
auto& ringcon_analogs = Settings::values.ringcon_analogs;
|
||||
|
||||
ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param);
|
||||
if (ringcon_analogs.empty()) {
|
||||
ringcon_analogs = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
void SdlConfig::SaveSdlValues() {
|
||||
SaveSdlControlValues();
|
||||
|
||||
WriteToIni();
|
||||
}
|
||||
|
||||
void SdlConfig::SaveSdlControlValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
Settings::values.players.SetGlobal(!IsCustomConfig());
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
SaveSdlPlayerValues(p);
|
||||
}
|
||||
if (IsCustomConfig()) {
|
||||
EndGroup();
|
||||
return;
|
||||
}
|
||||
SaveDebugControlValues();
|
||||
SaveHidbusValues();
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
void SdlConfig::SaveSdlPlayerValues(const std::size_t player_index) {
|
||||
std::string player_prefix;
|
||||
if (type != ConfigType::InputProfile) {
|
||||
player_prefix = std::string("player_").append(ToString(player_index)).append("_");
|
||||
}
|
||||
|
||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (IsCustomConfig() && player.profile_name.empty()) {
|
||||
// No custom profile selected
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]),
|
||||
player.buttons[i], std::make_optional(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]),
|
||||
player.analogs[i], std::make_optional(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]),
|
||||
player.motions[i], std::make_optional(default_param));
|
||||
}
|
||||
}
|
||||
|
||||
void SdlConfig::SaveDebugControlValues() {
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]),
|
||||
Settings::values.debug_pad_buttons[i], std::make_optional(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]),
|
||||
Settings::values.debug_pad_analogs[i], std::make_optional(default_param));
|
||||
}
|
||||
}
|
||||
|
||||
void SdlConfig::SaveHidbusValues() {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
|
||||
WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs,
|
||||
std::make_optional(default_param));
|
||||
}
|
||||
|
||||
std::vector<Settings::BasicSetting*>& SdlConfig::FindRelevantList(Settings::Category category) {
|
||||
return Settings::values.linkage.by_category[category];
|
||||
}
|
49
src/yuzu_cmd/sdl_config.h
Normal file
49
src/yuzu_cmd/sdl_config.h
Normal file
@ -0,0 +1,49 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "frontend_common/config.h"
|
||||
|
||||
class SdlConfig final : public Config {
|
||||
public:
|
||||
explicit SdlConfig(std::optional<std::string> config_path);
|
||||
~SdlConfig() override;
|
||||
|
||||
void ReloadAllValues() override;
|
||||
void SaveAllValues() override;
|
||||
|
||||
protected:
|
||||
void ReadSdlValues();
|
||||
void ReadSdlPlayerValues(std::size_t player_index);
|
||||
void ReadSdlControlValues();
|
||||
void ReadHidbusValues() override;
|
||||
void ReadDebugControlValues() override;
|
||||
void ReadPathValues() override {}
|
||||
void ReadShortcutValues() override {}
|
||||
void ReadUIValues() override {}
|
||||
void ReadUIGamelistValues() override {}
|
||||
void ReadUILayoutValues() override {}
|
||||
void ReadMultiplayerValues() override {}
|
||||
|
||||
void SaveSdlValues();
|
||||
void SaveSdlPlayerValues(std::size_t player_index);
|
||||
void SaveSdlControlValues();
|
||||
void SaveHidbusValues() override;
|
||||
void SaveDebugControlValues() override;
|
||||
void SavePathValues() override {}
|
||||
void SaveShortcutValues() override {}
|
||||
void SaveUIValues() override {}
|
||||
void SaveUIGamelistValues() override {}
|
||||
void SaveUILayoutValues() override {}
|
||||
void SaveMultiplayerValues() override {}
|
||||
|
||||
std::vector<Settings::BasicSetting*>& FindRelevantList(Settings::Category category) override;
|
||||
|
||||
public:
|
||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
|
||||
static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||
static const std::array<int, 2> default_stick_mod;
|
||||
static const std::array<int, 2> default_ringcon_analogs;
|
||||
};
|
@ -29,10 +29,11 @@
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "core/telemetry_session.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "input_common/main.h"
|
||||
#include "network/network.h"
|
||||
#include "sdl_config.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "yuzu_cmd/config.h"
|
||||
#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
|
||||
#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h"
|
||||
#include "yuzu_cmd/emu_window/emu_window_sdl2_null.h"
|
||||
@ -300,7 +301,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
Config config{config_path};
|
||||
SdlConfig config{config_path};
|
||||
|
||||
// apply the log_filter setting
|
||||
// the logger was initialized before and doesn't pick up the filter on its own
|
||||
|
Loading…
Reference in New Issue
Block a user