Merge pull request #11889 from t895/ini-lib
configuration: Unify config handling across frontendsmaster
commit
5a182f4e7c
@ -1,27 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
pkg_search_module(INIH QUIET IMPORTED_TARGET inih)
|
|
||||||
if (INIReader IN_LIST inih_FIND_COMPONENTS)
|
|
||||||
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
|
|
||||||
if (INIREADER_FOUND)
|
|
||||||
set(inih_INIReader_FOUND TRUE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(inih
|
|
||||||
REQUIRED_VARS INIH_LINK_LIBRARIES
|
|
||||||
VERSION_VAR INIH_VERSION
|
|
||||||
HANDLE_COMPONENTS
|
|
||||||
)
|
|
||||||
|
|
||||||
if (inih_FOUND AND NOT TARGET inih::inih)
|
|
||||||
add_library(inih::inih ALIAS PkgConfig::INIH)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (inih_FOUND AND inih_INIReader_FOUND AND NOT TARGET inih::INIReader)
|
|
||||||
add_library(inih::INIReader ALIAS PkgConfig::INIREADER)
|
|
||||||
endif()
|
|
@ -1,13 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2014 Gui Andrade <admin@archshift.com>
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
add_library(inih
|
|
||||||
inih/ini.c
|
|
||||||
inih/ini.h
|
|
||||||
inih/cpp/INIReader.cpp
|
|
||||||
inih/cpp/INIReader.h
|
|
||||||
)
|
|
||||||
|
|
||||||
create_target_directory_groups(inih)
|
|
||||||
target_include_directories(inih INTERFACE inih/cpp)
|
|
||||||
add_library(inih::INIReader ALIAS inih)
|
|
@ -1 +0,0 @@
|
|||||||
Subproject commit 9cecf0643da0846e77f64d10a126d9f48b9e05e8
|
|
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 382ddbb4b92c0b26aa1b32cefba2002119a5b1f2
|
@ -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];
|
||||||
|
}
|
@ -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-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "uisettings.h"
|
#include "android_settings.h"
|
||||||
|
|
||||||
namespace AndroidSettings {
|
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;
|
|
||||||
};
|
|
@ -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)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,210 @@
|
|||||||
|
// 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);
|
||||||
|
u64 ReadUnsignedIntegerSetting(const std::string& key,
|
||||||
|
std::optional<u64> 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 if constexpr (std::is_same_v<T, u64>) {
|
||||||
|
return std::to_string(static_cast<u64>(value_));
|
||||||
|
} 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;
|
||||||
|
};
|
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);
|
|
@ -0,0 +1,549 @@
|
|||||||
|
// 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(
|
||||||
|
ReadUnsignedIntegerSetting(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();
|
||||||
|
}
|
@ -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;
|
||||||
|
};
|
@ -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);
|
|
||||||
};
|
|
@ -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];
|
||||||
|
}
|
@ -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;
|
||||||
|
};
|
Loading…
Reference in New Issue