summaryrefslogtreecommitdiffstats
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/CMakeLists.txt57
-rw-r--r--src/yuzu/applets/qt_controller.cpp1
-rw-r--r--src/yuzu/configuration/config.cpp1306
-rw-r--r--src/yuzu/configuration/config.h179
-rw-r--r--src/yuzu/configuration/configure_audio.cpp10
-rw-r--r--src/yuzu/configuration/configure_camera.cpp2
-rw-r--r--src/yuzu/configuration/configure_camera.h2
-rw-r--r--src/yuzu/configuration/configure_debug.cpp3
-rw-r--r--src/yuzu/configuration/configure_debug.ui86
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp1
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp36
-rw-r--r--src/yuzu/configuration/configure_input.cpp2
-rw-r--r--src/yuzu/configuration/configure_input.h2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp8
-rw-r--r--src/yuzu/configuration/configure_input_advanced.h8
-rw-r--r--src/yuzu/configuration/configure_input_per_game.cpp6
-rw-r--r--src/yuzu/configuration/configure_input_per_game.h5
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp47
-rw-r--r--src/yuzu/configuration/configure_input_player.h2
-rw-r--r--src/yuzu/configuration/configure_input_player.ui389
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp45
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp7
-rw-r--r--src/yuzu/configuration/configure_per_game.h7
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp1
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp6
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp4
-rw-r--r--src/yuzu/configuration/configure_ringcon.h2
-rw-r--r--src/yuzu/configuration/configure_system.cpp1
-rw-r--r--src/yuzu/configuration/configure_tas.h2
-rw-r--r--src/yuzu/configuration/configure_touchscreen_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_touchscreen_advanced.h2
-rw-r--r--src/yuzu/configuration/configure_ui.cpp7
-rw-r--r--src/yuzu/configuration/input_profiles.cpp10
-rw-r--r--src/yuzu/configuration/input_profiles.h4
-rw-r--r--src/yuzu/configuration/qt_config.cpp549
-rw-r--r--src/yuzu/configuration/qt_config.h55
-rw-r--r--src/yuzu/configuration/shared_translation.cpp518
-rw-r--r--src/yuzu/configuration/shared_translation.h43
-rw-r--r--src/yuzu/configuration/shared_widget.cpp4
-rw-r--r--src/yuzu/debugger/wait_tree.cpp6
-rw-r--r--src/yuzu/game_list.cpp13
-rw-r--r--src/yuzu/game_list_p.h8
-rw-r--r--src/yuzu/game_list_worker.cpp18
-rw-r--r--src/yuzu/hotkeys.cpp28
-rw-r--r--src/yuzu/hotkeys.h16
-rw-r--r--src/yuzu/main.cpp659
-rw-r--r--src/yuzu/main.h31
-rw-r--r--src/yuzu/main.ui22
-rw-r--r--src/yuzu/uisettings.cpp65
-rw-r--r--src/yuzu/uisettings.h93
-rw-r--r--src/yuzu/util/util.cpp15
-rw-r--r--src/yuzu/util/util.h3
-rw-r--r--src/yuzu/vk_device_info.cpp1
53 files changed, 2038 insertions, 2361 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 33e1fb663..90278052a 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -38,8 +38,6 @@ add_executable(yuzu
compatdb.ui
compatibility_list.cpp
compatibility_list.h
- configuration/config.cpp
- configuration/config.h
configuration/configuration_shared.cpp
configuration/configuration_shared.h
configuration/configure.ui
@@ -147,6 +145,8 @@ add_executable(yuzu
configuration/shared_translation.h
configuration/shared_widget.cpp
configuration/shared_widget.h
+ configuration/qt_config.cpp
+ configuration/qt_config.h
debugger/console.cpp
debugger/console.h
debugger/controller.cpp
@@ -252,6 +252,7 @@ file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*)
if (ENABLE_QT_TRANSLATION)
set(YUZU_QT_LANGUAGES "${PROJECT_SOURCE_DIR}/dist/languages" CACHE PATH "Path to the translation bundle for the Qt frontend")
option(GENERATE_QT_TRANSLATION "Generate en.ts as the translation source file" OFF)
+ option(WORKAROUND_BROKEN_LUPDATE "Run lupdate directly through CMake if Qt's convenience wrappers don't work" OFF)
# Update source TS file if enabled
if (GENERATE_QT_TRANSLATION)
@@ -259,19 +260,51 @@ if (ENABLE_QT_TRANSLATION)
# these calls to qt_create_translation also creates a rule to generate en.qm which conflicts with providing english plurals
# so we have to set a OUTPUT_LOCATION so that we don't have multiple rules to generate en.qm
set_source_files_properties(${YUZU_QT_LANGUAGES}/en.ts PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
- qt_create_translation(QM_FILES
- ${SRCS}
- ${UIS}
- ${YUZU_QT_LANGUAGES}/en.ts
- OPTIONS
- -source-language en_US
- -target-language en_US
- )
+ if (WORKAROUND_BROKEN_LUPDATE)
+ add_custom_command(OUTPUT ${YUZU_QT_LANGUAGES}/en.ts
+ COMMAND lupdate
+ -source-language en_US
+ -target-language en_US
+ ${SRCS}
+ ${UIS}
+ -ts ${YUZU_QT_LANGUAGES}/en.ts
+ DEPENDS
+ ${SRCS}
+ ${UIS}
+ WORKING_DIRECTORY
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+ else()
+ qt_create_translation(QM_FILES
+ ${SRCS}
+ ${UIS}
+ ${YUZU_QT_LANGUAGES}/en.ts
+ OPTIONS
+ -source-language en_US
+ -target-language en_US
+ )
+ endif()
# Generate plurals into dist/english_plurals/generated_en.ts so it can be used to revise dist/english_plurals/en.ts
set(GENERATED_PLURALS_FILE ${PROJECT_SOURCE_DIR}/dist/english_plurals/generated_en.ts)
set_source_files_properties(${GENERATED_PLURALS_FILE} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/plurals")
- qt_create_translation(QM_FILES ${SRCS} ${UIS} ${GENERATED_PLURALS_FILE} OPTIONS -pluralonly -source-language en_US -target-language en_US)
+ if (WORKAROUND_BROKEN_LUPDATE)
+ add_custom_command(OUTPUT ${GENERATED_PLURALS_FILE}
+ COMMAND lupdate
+ -source-language en_US
+ -target-language en_US
+ ${SRCS}
+ ${UIS}
+ -ts ${GENERATED_PLURALS_FILE}
+ DEPENDS
+ ${SRCS}
+ ${UIS}
+ WORKING_DIRECTORY
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+ else()
+ qt_create_translation(QM_FILES ${SRCS} ${UIS} ${GENERATED_PLURALS_FILE} OPTIONS -pluralonly -source-language en_US -target-language en_US)
+ endif()
add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts ${GENERATED_PLURALS_FILE})
endif()
@@ -344,7 +377,7 @@ endif()
create_target_directory_groups(yuzu)
-target_link_libraries(yuzu PRIVATE common core input_common network video_core)
+target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets)
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 515cb7ce6..9e5319716 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -13,7 +13,6 @@
#include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/npad.h"
-#include "core/hle/service/hid/hid.h"
#include "core/hle/service/sm/sm.h"
#include "ui_qt_controller.h"
#include "yuzu/applets/qt_controller.h"
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
deleted file mode 100644
index baa3e55f3..000000000
--- a/src/yuzu/configuration/config.cpp
+++ /dev/null
@@ -1,1306 +0,0 @@
-// SPDX-FileCopyrightText: 2014 Citra Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <algorithm>
-#include <array>
-#include <QKeySequence>
-#include <QSettings>
-#include "common/fs/fs.h"
-#include "common/fs/path_util.h"
-#include "common/settings.h"
-#include "common/settings_common.h"
-#include "common/settings_enums.h"
-#include "core/core.h"
-#include "core/hle/service/acc/profile_manager.h"
-#include "core/hle/service/hid/controllers/npad.h"
-#include "input_common/main.h"
-#include "network/network.h"
-#include "yuzu/configuration/config.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() {
- if (global) {
- Save();
- }
-}
-
-const std::array<int, Settings::NativeButton::NumButtons> Config::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,
-};
-
-const std::array<int, Settings::NativeMotion::NumMotions> Config::default_motions = {
- Qt::Key_7,
- Qt::Key_8,
-};
-
-const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config::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> Config::default_stick_mod = {
- Qt::Key_Shift,
- 0,
-};
-
-const std::array<int, 2> Config::default_ringcon_analogs{{
- Qt::Key_A,
- Qt::Key_D,
-}};
-
-const std::map<Settings::AntiAliasing, QString> Config::anti_aliasing_texts_map = {
- {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))},
- {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))},
- {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))},
-};
-
-const std::map<Settings::ScalingFilter, QString> Config::scaling_filter_texts_map = {
- {Settings::ScalingFilter::NearestNeighbor,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))},
- {Settings::ScalingFilter::Bilinear,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))},
- {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))},
- {Settings::ScalingFilter::Gaussian,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))},
- {Settings::ScalingFilter::ScaleForce,
- QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))},
- {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
-};
-
-const std::map<Settings::ConsoleMode, QString> Config::use_docked_mode_texts_map = {
- {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
- {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
-};
-
-const std::map<Settings::GpuAccuracy, QString> Config::gpu_accuracy_texts_map = {
- {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))},
- {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))},
- {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))},
-};
-
-const std::map<Settings::RendererBackend, QString> Config::renderer_backend_texts_map = {
- {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))},
- {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))},
- {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
-};
-
-const std::map<Settings::ShaderBackend, QString> Config::shader_backend_texts_map = {
- {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))},
- {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))},
- {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))},
-};
-
-// This shouldn't have anything except static initializers (no functions). So
-// QKeySequence(...).toString() is NOT ALLOWED HERE.
-// This must be in alphabetical order according to action name as it must have the same order as
-// UISetting::values.shortcuts, which is alphabetically ordered.
-// clang-format off
-const std::array<UISettings::Shortcut, 23> Config::default_hotkeys{{
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral("R+Plus+Minus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral("L+Plus+Minus"), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral(""), QStringLiteral(""), Qt::ApplicationShortcut, false}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut, false}},
-}};
-// clang-format on
-
-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:
- qt_config_loc = FS::PathToUTF8String(fs_config_loc / config_file);
- void(FS::CreateParentDir(qt_config_loc));
- qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
- QSettings::IniFormat);
- Reload();
- break;
- case ConfigType::PerGameConfig:
- qt_config_loc =
- FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file));
- void(FS::CreateParentDir(qt_config_loc));
- qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
- QSettings::IniFormat);
- Reload();
- break;
- case ConfigType::InputProfile:
- qt_config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file);
- void(FS::CreateParentDir(qt_config_loc));
- qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
- QSettings::IniFormat);
- break;
- }
-}
-
-bool Config::IsCustomConfig() {
- return type == ConfigType::PerGameConfig;
-}
-
-void Config::ReadPlayerValue(std::size_t player_index) {
- const QString player_prefix = [this, player_index] {
- if (type == ConfigType::InputProfile) {
- return QString{};
- } else {
- return QStringLiteral("player_%1_").arg(player_index);
- }
- }();
-
- auto& player = Settings::values.players.GetValue()[player_index];
- if (IsCustomConfig()) {
- const auto profile_name =
- qt_config->value(QStringLiteral("%1profile_name").arg(player_prefix), QString{})
- .toString()
- .toStdString();
- if (profile_name.empty()) {
- // Use the global input config
- player = Settings::values.players.GetValue(true)[player_index];
- return;
- }
- player.profile_name = profile_name;
- }
-
- if (player_prefix.isEmpty() && Settings::IsConfiguringGlobal()) {
- const auto controller = static_cast<Settings::ControllerType>(
- qt_config
- ->value(QStringLiteral("%1type").arg(player_prefix),
- static_cast<u8>(Settings::ControllerType::ProController))
- .toUInt());
-
- if (controller == Settings::ControllerType::LeftJoycon ||
- controller == Settings::ControllerType::RightJoycon) {
- player.controller_type = controller;
- }
- } else {
- player.connected =
- ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0)
- .toBool();
-
- player.controller_type = static_cast<Settings::ControllerType>(
- qt_config
- ->value(QStringLiteral("%1type").arg(player_prefix),
- static_cast<u8>(Settings::ControllerType::ProController))
- .toUInt());
-
- player.vibration_enabled =
- qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true)
- .toBool();
-
- player.vibration_strength =
- qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100)
- .toInt();
-
- player.body_color_left = qt_config
- ->value(QStringLiteral("%1body_color_left").arg(player_prefix),
- Settings::JOYCON_BODY_NEON_BLUE)
- .toUInt();
- player.body_color_right =
- qt_config
- ->value(QStringLiteral("%1body_color_right").arg(player_prefix),
- Settings::JOYCON_BODY_NEON_RED)
- .toUInt();
- player.button_color_left =
- qt_config
- ->value(QStringLiteral("%1button_color_left").arg(player_prefix),
- Settings::JOYCON_BUTTONS_NEON_BLUE)
- .toUInt();
- player.button_color_right =
- qt_config
- ->value(QStringLiteral("%1button_color_right").arg(player_prefix),
- Settings::JOYCON_BUTTONS_NEON_RED)
- .toUInt();
- }
-
- 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 = qt_config
- ->value(QStringLiteral("%1").arg(player_prefix) +
- QString::fromUtf8(Settings::NativeButton::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- 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 = qt_config
- ->value(QStringLiteral("%1").arg(player_prefix) +
- QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- 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 = qt_config
- ->value(QStringLiteral("%1").arg(player_prefix) +
- QString::fromUtf8(Settings::NativeMotion::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (player_motions.empty()) {
- player_motions = default_param;
- }
- }
-}
-
-void Config::ReadDebugValues() {
- 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 = qt_config
- ->value(QStringLiteral("debug_pad_") +
- QString::fromUtf8(Settings::NativeButton::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- 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 = qt_config
- ->value(QStringLiteral("debug_pad_") +
- QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (debug_pad_analogs.empty()) {
- debug_pad_analogs = default_param;
- }
- }
-}
-
-void Config::ReadTouchscreenValues() {
- Settings::values.touchscreen.enabled =
- ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool();
-
- Settings::values.touchscreen.rotation_angle =
- ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt();
- Settings::values.touchscreen.diameter_x =
- ReadSetting(QStringLiteral("touchscreen_diameter_x"), 15).toUInt();
- Settings::values.touchscreen.diameter_y =
- ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt();
-}
-
-void Config::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 =
- qt_config->value(QStringLiteral("ring_controller"), QString::fromStdString(default_param))
- .toString()
- .toStdString();
- if (ringcon_analogs.empty()) {
- ringcon_analogs = default_param;
- }
-}
-
-void Config::ReadAudioValues() {
- qt_config->beginGroup(QStringLiteral("Audio"));
-
- ReadCategory(Settings::Category::Audio);
-
- qt_config->endGroup();
-}
-
-void Config::ReadControlValues() {
- qt_config->beginGroup(QStringLiteral("Controls"));
-
- ReadCategory(Settings::Category::Controls);
-
- Settings::values.players.SetGlobal(!IsCustomConfig());
- for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
- ReadPlayerValue(p);
- }
-
- // Disable docked mode if handheld is selected
- const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
- if (controller_type == Settings::ControllerType::Handheld) {
- Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
- Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
- }
-
- if (IsCustomConfig()) {
- qt_config->endGroup();
- return;
- }
- ReadDebugValues();
- ReadTouchscreenValues();
- ReadMotionTouchValues();
- ReadHidbusValues();
-
- qt_config->endGroup();
-}
-
-void Config::ReadMotionTouchValues() {
- int num_touch_from_button_maps =
- qt_config->beginReadArray(QStringLiteral("touch_from_button_maps"));
-
- if (num_touch_from_button_maps > 0) {
- const auto append_touch_from_button_map = [this] {
- Settings::TouchFromButtonMap map;
- map.name = ReadSetting(QStringLiteral("name"), QStringLiteral("default"))
- .toString()
- .toStdString();
- const int num_touch_maps = qt_config->beginReadArray(QStringLiteral("entries"));
- map.buttons.reserve(num_touch_maps);
- for (int i = 0; i < num_touch_maps; i++) {
- qt_config->setArrayIndex(i);
- std::string touch_mapping =
- ReadSetting(QStringLiteral("bind")).toString().toStdString();
- map.buttons.emplace_back(std::move(touch_mapping));
- }
- qt_config->endArray(); // entries
- Settings::values.touch_from_button_maps.emplace_back(std::move(map));
- };
-
- for (int i = 0; i < num_touch_from_button_maps; ++i) {
- qt_config->setArrayIndex(i);
- append_touch_from_button_map();
- }
- } else {
- Settings::values.touch_from_button_maps.emplace_back(
- Settings::TouchFromButtonMap{"default", {}});
- num_touch_from_button_maps = 1;
- }
- qt_config->endArray();
-
- Settings::values.touch_from_button_map_index = std::clamp(
- Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
-}
-
-void Config::ReadCoreValues() {
- qt_config->beginGroup(QStringLiteral("Core"));
-
- ReadCategory(Settings::Category::Core);
-
- qt_config->endGroup();
-}
-
-void Config::ReadDataStorageValues() {
- qt_config->beginGroup(QStringLiteral("Data Storage"));
-
- FS::SetYuzuPath(
- FS::YuzuPath::NANDDir,
- qt_config
- ->value(QStringLiteral("nand_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(
- FS::YuzuPath::SDMCDir,
- qt_config
- ->value(QStringLiteral("sdmc_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(
- FS::YuzuPath::LoadDir,
- qt_config
- ->value(QStringLiteral("load_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(
- FS::YuzuPath::DumpDir,
- qt_config
- ->value(QStringLiteral("dump_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)))
- .toString()
- .toStdString());
- FS::SetYuzuPath(FS::YuzuPath::TASDir,
- qt_config
- ->value(QStringLiteral("tas_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)))
- .toString()
- .toStdString());
-
- ReadCategory(Settings::Category::DataStorage);
-
- qt_config->endGroup();
-}
-
-void Config::ReadDebuggingValues() {
- qt_config->beginGroup(QStringLiteral("Debugging"));
-
- // Intentionally not using the QT default setting as this is intended to be changed in the ini
- Settings::values.record_frame_times =
- qt_config->value(QStringLiteral("record_frame_times"), false).toBool();
-
- ReadCategory(Settings::Category::Debugging);
- ReadCategory(Settings::Category::DebuggingGraphics);
-
- qt_config->endGroup();
-}
-
-void Config::ReadServiceValues() {
- qt_config->beginGroup(QStringLiteral("Services"));
-
- ReadCategory(Settings::Category::Services);
-
- qt_config->endGroup();
-}
-
-void Config::ReadDisabledAddOnValues() {
- const auto size = qt_config->beginReadArray(QStringLiteral("DisabledAddOns"));
-
- for (int i = 0; i < size; ++i) {
- qt_config->setArrayIndex(i);
- const auto title_id = ReadSetting(QStringLiteral("title_id"), 0).toULongLong();
- std::vector<std::string> out;
- const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled"));
- for (int j = 0; j < d_size; ++j) {
- qt_config->setArrayIndex(j);
- out.push_back(ReadSetting(QStringLiteral("d"), QString{}).toString().toStdString());
- }
- qt_config->endArray();
- Settings::values.disabled_addons.insert_or_assign(title_id, out);
- }
-
- qt_config->endArray();
-}
-
-void Config::ReadMiscellaneousValues() {
- qt_config->beginGroup(QStringLiteral("Miscellaneous"));
-
- ReadCategory(Settings::Category::Miscellaneous);
-
- qt_config->endGroup();
-}
-
-void Config::ReadPathValues() {
- qt_config->beginGroup(QStringLiteral("Paths"));
-
- UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString();
- UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString();
- UISettings::values.game_dir_deprecated =
- ReadSetting(QStringLiteral("gameListRootDir"), QStringLiteral(".")).toString();
- UISettings::values.game_dir_deprecated_deepscan =
- ReadSetting(QStringLiteral("gameListDeepScan"), false).toBool();
- const int gamedirs_size = qt_config->beginReadArray(QStringLiteral("gamedirs"));
- for (int i = 0; i < gamedirs_size; ++i) {
- qt_config->setArrayIndex(i);
- UISettings::GameDir game_dir;
- game_dir.path = ReadSetting(QStringLiteral("path")).toString();
- game_dir.deep_scan = ReadSetting(QStringLiteral("deep_scan"), false).toBool();
- game_dir.expanded = ReadSetting(QStringLiteral("expanded"), true).toBool();
- UISettings::values.game_dirs.append(game_dir);
- }
- qt_config->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.isEmpty()) {
- UISettings::GameDir game_dir;
- game_dir.path = QStringLiteral("SDMC");
- game_dir.expanded = true;
- UISettings::values.game_dirs.append(game_dir);
- game_dir.path = QStringLiteral("UserNAND");
- UISettings::values.game_dirs.append(game_dir);
- game_dir.path = QStringLiteral("SysNAND");
- UISettings::values.game_dirs.append(game_dir);
- if (UISettings::values.game_dir_deprecated != QStringLiteral(".")) {
- 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 = ReadSetting(QStringLiteral("recentFiles")).toStringList();
- UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString();
-
- qt_config->endGroup();
-}
-
-void Config::ReadCpuValues() {
- qt_config->beginGroup(QStringLiteral("Cpu"));
-
- ReadCategory(Settings::Category::Cpu);
- ReadCategory(Settings::Category::CpuDebug);
- ReadCategory(Settings::Category::CpuUnsafe);
-
- qt_config->endGroup();
-}
-
-void Config::ReadRendererValues() {
- qt_config->beginGroup(QStringLiteral("Renderer"));
-
- ReadCategory(Settings::Category::Renderer);
- ReadCategory(Settings::Category::RendererAdvanced);
- ReadCategory(Settings::Category::RendererDebug);
-
- qt_config->endGroup();
-}
-
-void Config::ReadScreenshotValues() {
- qt_config->beginGroup(QStringLiteral("Screenshots"));
-
- ReadCategory(Settings::Category::Screenshots);
- FS::SetYuzuPath(
- FS::YuzuPath::ScreenshotsDir,
- qt_config
- ->value(QStringLiteral("screenshot_path"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)))
- .toString()
- .toStdString());
-
- qt_config->endGroup();
-}
-
-void Config::ReadShortcutValues() {
- qt_config->beginGroup(QStringLiteral("Shortcuts"));
-
- for (const auto& [name, group, shortcut] : default_hotkeys) {
- qt_config->beginGroup(group);
- qt_config->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,
- {ReadSetting(QStringLiteral("KeySeq"), shortcut.keyseq).toString(),
- ReadSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq)
- .toString(),
- shortcut.context, ReadSetting(QStringLiteral("Repeat"), shortcut.repeat).toBool()}});
- qt_config->endGroup();
- qt_config->endGroup();
- }
-
- qt_config->endGroup();
-}
-
-void Config::ReadSystemValues() {
- qt_config->beginGroup(QStringLiteral("System"));
-
- ReadCategory(Settings::Category::System);
- ReadCategory(Settings::Category::SystemAudio);
-
- qt_config->endGroup();
-}
-
-void Config::ReadUIValues() {
- qt_config->beginGroup(QStringLiteral("UI"));
-
- UISettings::values.theme =
- ReadSetting(
- QStringLiteral("theme"),
- QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second))
- .toString();
-
- ReadUIGamelistValues();
- ReadUILayoutValues();
- ReadPathValues();
- ReadScreenshotValues();
- ReadShortcutValues();
- ReadMultiplayerValues();
-
- ReadCategory(Settings::Category::Ui);
- ReadCategory(Settings::Category::UiGeneral);
-
- qt_config->endGroup();
-}
-
-void Config::ReadUIGamelistValues() {
- qt_config->beginGroup(QStringLiteral("UIGameList"));
-
- ReadCategory(Settings::Category::UiGameList);
-
- const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites"));
- for (int i = 0; i < favorites_size; i++) {
- qt_config->setArrayIndex(i);
- UISettings::values.favorited_ids.append(
- ReadSetting(QStringLiteral("program_id")).toULongLong());
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-void Config::ReadUILayoutValues() {
- qt_config->beginGroup(QStringLiteral("UILayout"));
-
- UISettings::values.geometry = ReadSetting(QStringLiteral("geometry")).toByteArray();
- UISettings::values.state = ReadSetting(QStringLiteral("state")).toByteArray();
- UISettings::values.renderwindow_geometry =
- ReadSetting(QStringLiteral("geometryRenderWindow")).toByteArray();
- UISettings::values.gamelist_header_state =
- ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray();
- UISettings::values.microprofile_geometry =
- ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray();
-
- ReadCategory(Settings::Category::UiLayout);
-
- qt_config->endGroup();
-}
-
-void Config::ReadWebServiceValues() {
- qt_config->beginGroup(QStringLiteral("WebService"));
-
- ReadCategory(Settings::Category::WebService);
-
- qt_config->endGroup();
-}
-
-void Config::ReadMultiplayerValues() {
- qt_config->beginGroup(QStringLiteral("Multiplayer"));
-
- ReadCategory(Settings::Category::Multiplayer);
-
- // Read ban list back
- int size = qt_config->beginReadArray(QStringLiteral("username_ban_list"));
- UISettings::values.multiplayer_ban_list.first.resize(size);
- for (int i = 0; i < size; ++i) {
- qt_config->setArrayIndex(i);
- UISettings::values.multiplayer_ban_list.first[i] =
- ReadSetting(QStringLiteral("username")).toString().toStdString();
- }
- qt_config->endArray();
- size = qt_config->beginReadArray(QStringLiteral("ip_ban_list"));
- UISettings::values.multiplayer_ban_list.second.resize(size);
- for (int i = 0; i < size; ++i) {
- qt_config->setArrayIndex(i);
- UISettings::values.multiplayer_ban_list.second[i] =
- ReadSetting(QStringLiteral("ip")).toString().toStdString();
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-void Config::ReadNetworkValues() {
- qt_config->beginGroup(QString::fromStdString("Services"));
-
- ReadCategory(Settings::Category::Network);
-
- qt_config->endGroup();
-}
-
-void Config::ReadValues() {
- if (global) {
- ReadDataStorageValues();
- ReadDebuggingValues();
- ReadDisabledAddOnValues();
- ReadNetworkValues();
- ReadServiceValues();
- ReadUIValues();
- ReadWebServiceValues();
- ReadMiscellaneousValues();
- }
- ReadControlValues();
- ReadCoreValues();
- ReadCpuValues();
- ReadRendererValues();
- ReadAudioValues();
- ReadSystemValues();
-}
-
-void Config::SavePlayerValue(std::size_t player_index) {
- const QString player_prefix = [this, player_index] {
- if (type == ConfigType::InputProfile) {
- return QString{};
- } else {
- return QStringLiteral("player_%1_").arg(player_index);
- }
- }();
-
- const auto& player = Settings::values.players.GetValue()[player_index];
- if (IsCustomConfig()) {
- if (player.profile_name.empty()) {
- // No custom profile selected
- return;
- }
- WriteSetting(QStringLiteral("%1profile_name").arg(player_prefix),
- QString::fromStdString(player.profile_name), QString{});
- }
-
- WriteSetting(QStringLiteral("%1type").arg(player_prefix),
- static_cast<u8>(player.controller_type),
- static_cast<u8>(Settings::ControllerType::ProController));
-
- if (!player_prefix.isEmpty() || !Settings::IsConfiguringGlobal()) {
- WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected,
- player_index == 0);
- WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix),
- player.vibration_enabled, true);
- WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix),
- player.vibration_strength, 100);
- WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left,
- Settings::JOYCON_BODY_NEON_BLUE);
- WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix),
- player.body_color_right, Settings::JOYCON_BODY_NEON_RED);
- WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix),
- player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE);
- WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix),
- player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED);
- }
-
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- WriteSetting(QStringLiteral("%1").arg(player_prefix) +
- QString::fromStdString(Settings::NativeButton::mapping[i]),
- QString::fromStdString(player.buttons[i]),
- QString::fromStdString(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(QStringLiteral("%1").arg(player_prefix) +
- QString::fromStdString(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(player.analogs[i]),
- QString::fromStdString(default_param));
- }
- for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
- WriteSetting(QStringLiteral("%1").arg(player_prefix) +
- QString::fromStdString(Settings::NativeMotion::mapping[i]),
- QString::fromStdString(player.motions[i]),
- QString::fromStdString(default_param));
- }
-}
-
-void Config::SaveDebugValues() {
- for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
- WriteSetting(QStringLiteral("debug_pad_") +
- QString::fromStdString(Settings::NativeButton::mapping[i]),
- QString::fromStdString(Settings::values.debug_pad_buttons[i]),
- QString::fromStdString(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(QStringLiteral("debug_pad_") +
- QString::fromStdString(Settings::NativeAnalog::mapping[i]),
- QString::fromStdString(Settings::values.debug_pad_analogs[i]),
- QString::fromStdString(default_param));
- }
-}
-
-void Config::SaveTouchscreenValues() {
- const auto& touchscreen = Settings::values.touchscreen;
-
- WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true);
-
- WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0);
- WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15);
- WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15);
-}
-
-void Config::SaveMotionTouchValues() {
- qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps"));
- for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
- qt_config->setArrayIndex(static_cast<int>(p));
- WriteSetting(QStringLiteral("name"),
- QString::fromStdString(Settings::values.touch_from_button_maps[p].name),
- QStringLiteral("default"));
- qt_config->beginWriteArray(QStringLiteral("entries"));
- for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size();
- ++q) {
- qt_config->setArrayIndex(static_cast<int>(q));
- WriteSetting(
- QStringLiteral("bind"),
- QString::fromStdString(Settings::values.touch_from_button_maps[p].buttons[q]));
- }
- qt_config->endArray();
- }
- qt_config->endArray();
-}
-
-void Config::SaveHidbusValues() {
- const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
- 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
- WriteSetting(QStringLiteral("ring_controller"),
- QString::fromStdString(Settings::values.ringcon_analogs),
- QString::fromStdString(default_param));
-}
-
-void Config::SaveValues() {
- if (global) {
- SaveDataStorageValues();
- SaveDebuggingValues();
- SaveDisabledAddOnValues();
- SaveNetworkValues();
- SaveUIValues();
- SaveWebServiceValues();
- SaveMiscellaneousValues();
- }
- SaveControlValues();
- SaveCoreValues();
- SaveCpuValues();
- SaveRendererValues();
- SaveAudioValues();
- SaveSystemValues();
-
- qt_config->sync();
-}
-
-void Config::SaveAudioValues() {
- qt_config->beginGroup(QStringLiteral("Audio"));
-
- WriteCategory(Settings::Category::Audio);
-
- qt_config->endGroup();
-}
-
-void Config::SaveControlValues() {
- qt_config->beginGroup(QStringLiteral("Controls"));
-
- WriteCategory(Settings::Category::Controls);
-
- Settings::values.players.SetGlobal(!IsCustomConfig());
- for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
- SavePlayerValue(p);
- }
- if (IsCustomConfig()) {
- qt_config->endGroup();
- return;
- }
- SaveDebugValues();
- SaveTouchscreenValues();
- SaveMotionTouchValues();
- SaveHidbusValues();
-
- qt_config->endGroup();
-}
-
-void Config::SaveCoreValues() {
- qt_config->beginGroup(QStringLiteral("Core"));
-
- WriteCategory(Settings::Category::Core);
-
- qt_config->endGroup();
-}
-
-void Config::SaveDataStorageValues() {
- qt_config->beginGroup(QStringLiteral("Data Storage"));
-
- WriteSetting(QStringLiteral("nand_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
- WriteSetting(QStringLiteral("sdmc_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
- WriteSetting(QStringLiteral("load_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
- WriteSetting(QStringLiteral("dump_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
- WriteSetting(QStringLiteral("tas_directory"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
-
- WriteCategory(Settings::Category::DataStorage);
-
- qt_config->endGroup();
-}
-
-void Config::SaveDebuggingValues() {
- qt_config->beginGroup(QStringLiteral("Debugging"));
-
- // Intentionally not using the QT default setting as this is intended to be changed in the ini
- qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times);
-
- WriteCategory(Settings::Category::Debugging);
- WriteCategory(Settings::Category::DebuggingGraphics);
-
- qt_config->endGroup();
-}
-
-void Config::SaveNetworkValues() {
- qt_config->beginGroup(QStringLiteral("Services"));
-
- WriteCategory(Settings::Category::Network);
-
- qt_config->endGroup();
-}
-
-void Config::SaveDisabledAddOnValues() {
- qt_config->beginWriteArray(QStringLiteral("DisabledAddOns"));
-
- int i = 0;
- for (const auto& elem : Settings::values.disabled_addons) {
- qt_config->setArrayIndex(i);
- WriteSetting(QStringLiteral("title_id"), QVariant::fromValue<u64>(elem.first), 0);
- qt_config->beginWriteArray(QStringLiteral("disabled"));
- for (std::size_t j = 0; j < elem.second.size(); ++j) {
- qt_config->setArrayIndex(static_cast<int>(j));
- WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), QString{});
- }
- qt_config->endArray();
- ++i;
- }
-
- qt_config->endArray();
-}
-
-void Config::SaveMiscellaneousValues() {
- qt_config->beginGroup(QStringLiteral("Miscellaneous"));
-
- WriteCategory(Settings::Category::Miscellaneous);
-
- qt_config->endGroup();
-}
-
-void Config::SavePathValues() {
- qt_config->beginGroup(QStringLiteral("Paths"));
-
- WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path);
- WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path);
- qt_config->beginWriteArray(QStringLiteral("gamedirs"));
- for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
- qt_config->setArrayIndex(i);
- const auto& game_dir = UISettings::values.game_dirs[i];
- WriteSetting(QStringLiteral("path"), game_dir.path);
- WriteSetting(QStringLiteral("deep_scan"), game_dir.deep_scan, false);
- WriteSetting(QStringLiteral("expanded"), game_dir.expanded, true);
- }
- qt_config->endArray();
- WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files);
- WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{});
-
- qt_config->endGroup();
-}
-
-void Config::SaveCpuValues() {
- qt_config->beginGroup(QStringLiteral("Cpu"));
-
- WriteCategory(Settings::Category::Cpu);
- WriteCategory(Settings::Category::CpuDebug);
- WriteCategory(Settings::Category::CpuUnsafe);
-
- qt_config->endGroup();
-}
-
-void Config::SaveRendererValues() {
- qt_config->beginGroup(QStringLiteral("Renderer"));
-
- WriteCategory(Settings::Category::Renderer);
- WriteCategory(Settings::Category::RendererAdvanced);
- WriteCategory(Settings::Category::RendererDebug);
-
- qt_config->endGroup();
-}
-
-void Config::SaveScreenshotValues() {
- qt_config->beginGroup(QStringLiteral("Screenshots"));
-
- WriteSetting(QStringLiteral("screenshot_path"),
- QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir)));
- WriteCategory(Settings::Category::Screenshots);
-
- qt_config->endGroup();
-}
-
-void Config::SaveShortcutValues() {
- qt_config->beginGroup(QStringLiteral("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 < default_hotkeys.size(); i++) {
- const auto& [name, group, shortcut] = UISettings::values.shortcuts[i];
- const auto& default_hotkey = default_hotkeys[i].shortcut;
-
- qt_config->beginGroup(group);
- qt_config->beginGroup(name);
- WriteSetting(QStringLiteral("KeySeq"), shortcut.keyseq, default_hotkey.keyseq);
- WriteSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq,
- default_hotkey.controller_keyseq);
- WriteSetting(QStringLiteral("Context"), shortcut.context, default_hotkey.context);
- WriteSetting(QStringLiteral("Repeat"), shortcut.repeat, default_hotkey.repeat);
- qt_config->endGroup();
- qt_config->endGroup();
- }
-
- qt_config->endGroup();
-}
-
-void Config::SaveSystemValues() {
- qt_config->beginGroup(QStringLiteral("System"));
-
- WriteCategory(Settings::Category::System);
- WriteCategory(Settings::Category::SystemAudio);
-
- qt_config->endGroup();
-}
-
-void Config::SaveUIValues() {
- qt_config->beginGroup(QStringLiteral("UI"));
-
- WriteCategory(Settings::Category::Ui);
- WriteCategory(Settings::Category::UiGeneral);
-
- WriteSetting(QStringLiteral("theme"), UISettings::values.theme,
- QString::fromUtf8(UISettings::themes[static_cast<size_t>(default_theme)].second));
-
- SaveUIGamelistValues();
- SaveUILayoutValues();
- SavePathValues();
- SaveScreenshotValues();
- SaveShortcutValues();
- SaveMultiplayerValues();
-
- qt_config->endGroup();
-}
-
-void Config::SaveUIGamelistValues() {
- qt_config->beginGroup(QStringLiteral("UIGameList"));
-
- WriteCategory(Settings::Category::UiGameList);
-
- qt_config->beginWriteArray(QStringLiteral("favorites"));
- for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
- qt_config->setArrayIndex(i);
- WriteSetting(QStringLiteral("program_id"),
- QVariant::fromValue(UISettings::values.favorited_ids[i]));
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-void Config::SaveUILayoutValues() {
- qt_config->beginGroup(QStringLiteral("UILayout"));
-
- WriteSetting(QStringLiteral("geometry"), UISettings::values.geometry);
- WriteSetting(QStringLiteral("state"), UISettings::values.state);
- WriteSetting(QStringLiteral("geometryRenderWindow"), UISettings::values.renderwindow_geometry);
- WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state);
- WriteSetting(QStringLiteral("microProfileDialogGeometry"),
- UISettings::values.microprofile_geometry);
-
- WriteCategory(Settings::Category::UiLayout);
-
- qt_config->endGroup();
-}
-
-void Config::SaveWebServiceValues() {
- qt_config->beginGroup(QStringLiteral("WebService"));
-
- WriteCategory(Settings::Category::WebService);
-
- qt_config->endGroup();
-}
-
-void Config::SaveMultiplayerValues() {
- qt_config->beginGroup(QStringLiteral("Multiplayer"));
-
- WriteCategory(Settings::Category::Multiplayer);
-
- // Write ban list
- qt_config->beginWriteArray(QStringLiteral("username_ban_list"));
- for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) {
- qt_config->setArrayIndex(static_cast<int>(i));
- WriteSetting(QStringLiteral("username"),
- QString::fromStdString(UISettings::values.multiplayer_ban_list.first[i]));
- }
- qt_config->endArray();
- qt_config->beginWriteArray(QStringLiteral("ip_ban_list"));
- for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) {
- qt_config->setArrayIndex(static_cast<int>(i));
- WriteSetting(QStringLiteral("ip"),
- QString::fromStdString(UISettings::values.multiplayer_ban_list.second[i]));
- }
- qt_config->endArray();
-
- qt_config->endGroup();
-}
-
-QVariant Config::ReadSetting(const QString& name) const {
- return qt_config->value(name);
-}
-
-QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) const {
- QVariant result;
- if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) {
- result = default_value;
- } else {
- result = qt_config->value(name, default_value);
- }
- return result;
-}
-
-void Config::WriteSetting(const QString& name, const QVariant& value) {
- qt_config->setValue(name, value);
-}
-
-void Config::WriteSetting(const QString& name, const QVariant& value,
- const QVariant& default_value) {
- qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(name, value);
-}
-
-void Config::WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value,
- bool use_global) {
- if (!global) {
- qt_config->setValue(name + QStringLiteral("/use_global"), use_global);
- }
- if (global || !use_global) {
- qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(name, value);
- }
-}
-
-void Config::Reload() {
- ReadValues();
- // To apply default value changes
- SaveValues();
-}
-
-void Config::Save() {
- SaveValues();
-}
-
-void Config::ReadControlPlayerValue(std::size_t player_index) {
- qt_config->beginGroup(QStringLiteral("Controls"));
- ReadPlayerValue(player_index);
- qt_config->endGroup();
-}
-
-void Config::SaveControlPlayerValue(std::size_t player_index) {
- qt_config->beginGroup(QStringLiteral("Controls"));
- SavePlayerValue(player_index);
- qt_config->endGroup();
-}
-
-void Config::ClearControlPlayerValues() {
- qt_config->beginGroup(QStringLiteral("Controls"));
- // If key is an empty string, all keys in the current group() are removed.
- qt_config->remove(QString{});
- qt_config->endGroup();
-}
-
-const std::string& Config::GetConfigFilePath() const {
- return qt_config_loc;
-}
-
-static auto 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 Config::ReadCategory(Settings::Category category) {
- const auto& settings = FindRelevantList(category);
- std::for_each(settings.begin(), settings.end(),
- [&](const auto& setting) { ReadSettingGeneric(setting); });
-}
-
-void Config::WriteCategory(Settings::Category category) {
- const auto& settings = FindRelevantList(category);
- std::for_each(settings.begin(), settings.end(),
- [&](const auto& setting) { WriteSettingGeneric(setting); });
-}
-
-void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) {
- if (!setting->Save() || (!setting->Switchable() && !global)) {
- return;
- }
- const QString name = QString::fromStdString(setting->GetLabel());
- const auto default_value =
- QVariant::fromValue<QString>(QString::fromStdString(setting->DefaultToString()));
-
- bool use_global = true;
- if (setting->Switchable() && !global) {
- use_global = qt_config->value(name + QStringLiteral("/use_global"), true).value<bool>();
- setting->SetGlobal(use_global);
- }
-
- if (global || !use_global) {
- const bool is_default =
- qt_config->value(name + QStringLiteral("/default"), true).value<bool>();
- if (!is_default) {
- setting->LoadString(
- qt_config->value(name, default_value).value<QString>().toStdString());
- } else {
- // Empty string resets the Setting to default
- setting->LoadString("");
- }
- }
-}
-
-void Config::WriteSettingGeneric(Settings::BasicSetting* const setting) const {
- if (!setting->Save()) {
- return;
- }
- const QVariant value = QVariant::fromValue(QString::fromStdString(setting->ToString()));
- const QVariant default_value =
- QVariant::fromValue(QString::fromStdString(setting->DefaultToString()));
- const QString label = QString::fromStdString(setting->GetLabel());
- if (setting->Switchable()) {
- if (!global) {
- qt_config->setValue(label + QStringLiteral("/use_global"), setting->UsingGlobal());
- }
- if (global || !setting->UsingGlobal()) {
- qt_config->setValue(label + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(label, value);
- }
- } else if (global) {
- qt_config->setValue(label + QStringLiteral("/default"), value == default_value);
- qt_config->setValue(label, value);
- }
-}
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
deleted file mode 100644
index 74ec4f771..000000000
--- a/src/yuzu/configuration/config.h
+++ /dev/null
@@ -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);
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 81dd51ad3..9b6ef47a7 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -38,17 +38,21 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
std::map<u32, QWidget*> hold;
- auto push = [&](Settings::Category category) {
+ auto push_settings = [&](Settings::Category category) {
for (auto* setting : Settings::values.linkage.by_category[category]) {
settings.push_back(setting);
}
+ };
+
+ auto push_ui_settings = [&](Settings::Category category) {
for (auto* setting : UISettings::values.linkage.by_category[category]) {
settings.push_back(setting);
}
};
- push(Settings::Category::Audio);
- push(Settings::Category::SystemAudio);
+ push_settings(Settings::Category::Audio);
+ push_settings(Settings::Category::SystemAudio);
+ push_ui_settings(Settings::Category::UiAudio);
for (auto* setting : settings) {
auto* widget = builder.BuildWidget(setting, apply_funcs);
diff --git a/src/yuzu/configuration/configure_camera.cpp b/src/yuzu/configuration/configure_camera.cpp
index d95e96696..3368f53f3 100644
--- a/src/yuzu/configuration/configure_camera.cpp
+++ b/src/yuzu/configuration/configure_camera.cpp
@@ -10,10 +10,10 @@
#include <QStandardItemModel>
#include <QTimer>
+#include "common/settings.h"
#include "input_common/drivers/camera.h"
#include "input_common/main.h"
#include "ui_configure_camera.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_camera.h"
ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_)
diff --git a/src/yuzu/configuration/configure_camera.h b/src/yuzu/configuration/configure_camera.h
index 9a90512b3..3d822da7b 100644
--- a/src/yuzu/configuration/configure_camera.h
+++ b/src/yuzu/configuration/configure_camera.h
@@ -1,4 +1,4 @@
-// Text : Copyright 2022 yuzu Emulator Project
+// Text : Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index ef421c754..1010038b7 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -51,6 +51,8 @@ void ConfigureDebug::SetConfiguration() {
ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue());
ui->enable_renderdoc_hotkey->setEnabled(runtime_lock);
ui->enable_renderdoc_hotkey->setChecked(Settings::values.enable_renderdoc_hotkey.GetValue());
+ ui->disable_buffer_reorder->setEnabled(runtime_lock);
+ ui->disable_buffer_reorder->setChecked(Settings::values.disable_buffer_reorder.GetValue());
ui->enable_graphics_debugging->setEnabled(runtime_lock);
ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue());
ui->enable_shader_feedback->setEnabled(runtime_lock);
@@ -96,6 +98,7 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked();
Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
Settings::values.enable_renderdoc_hotkey = ui->enable_renderdoc_hotkey->isChecked();
+ Settings::values.disable_buffer_reorder = ui->disable_buffer_reorder->isChecked();
Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked();
Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked();
Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked();
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 76fe98924..22b51f39c 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -271,19 +271,6 @@
</widget>
</item>
<item row="8" column="0">
- <widget class="QCheckBox" name="disable_macro_hle">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="toolTip">
- <string>When checked, it disables the macro HLE functions. Enabling this makes games run slower</string>
- </property>
- <property name="text">
- <string>Disable Macro HLE</string>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
<widget class="QCheckBox" name="dump_macros">
<property name="enabled">
<bool>true</bool>
@@ -306,17 +293,27 @@
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QCheckBox" name="enable_shader_feedback">
+ <item row="6" column="0">
+ <widget class="QCheckBox" name="dump_shaders">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
<property name="toolTip">
- <string>When checked, yuzu will log statistics about the compiled pipeline cache</string>
+ <string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string>
</property>
<property name="text">
- <string>Enable Shader Feedback</string>
+ <string>Dump Game Shaders</string>
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="enable_renderdoc_hotkey">
+ <property name="text">
+ <string>Enable Renderdoc Hotkey</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
<widget class="QCheckBox" name="disable_macro_jit">
<property name="enabled">
<bool>true</bool>
@@ -330,20 +327,17 @@
</widget>
</item>
<item row="9" column="0">
- <spacer name="verticalSpacer_5">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <widget class="QCheckBox" name="disable_macro_hle">
+ <property name="enabled">
+ <bool>true</bool>
</property>
- <property name="sizeType">
- <enum>QSizePolicy::Preferred</enum>
+ <property name="toolTip">
+ <string>When checked, it disables the macro HLE functions. Enabling this makes games run slower</string>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>0</height>
- </size>
+ <property name="text">
+ <string>Disable Macro HLE</string>
</property>
- </spacer>
+ </widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="enable_graphics_debugging">
@@ -358,23 +352,39 @@
</property>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QCheckBox" name="dump_shaders">
- <property name="enabled">
- <bool>true</bool>
+ <item row="10" column="0">
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Preferred</enum>
</property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="enable_shader_feedback">
<property name="toolTip">
- <string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string>
+ <string>When checked, yuzu will log statistics about the compiled pipeline cache</string>
</property>
<property name="text">
- <string>Dump Game Shaders</string>
+ <string>Enable Shader Feedback</string>
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="enable_renderdoc_hotkey">
+ <item row="5" column="0">
+ <widget class="QCheckBox" name="disable_buffer_reorder">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When checked, disables reording of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
<property name="text">
- <string>Enable Renderdoc Hotkey</string>
+ <string>Disable Buffer Reorder</string>
</property>
</widget>
</item>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 0ad95cc02..aab54a1cc 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -8,7 +8,6 @@
#include "core/core.h"
#include "ui_configure.h"
#include "vk_device_info.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/configure_cpu.h"
#include "yuzu/configuration/configure_debug_tab.h"
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
index 68e21cd84..76fc33e49 100644
--- a/src/yuzu/configuration/configure_hotkeys.cpp
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -9,10 +9,11 @@
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
+#include "frontend_common/config.h"
#include "ui_configure_hotkeys.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_hotkeys.h"
#include "yuzu/hotkeys.h"
+#include "yuzu/uisettings.h"
#include "yuzu/util/sequence_dialog/sequence_dialog.h"
constexpr int name_column = 0;
@@ -62,18 +63,21 @@ ConfigureHotkeys::~ConfigureHotkeys() = default;
void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
for (const auto& group : registry.hotkey_groups) {
+ QString parent_item_data = QString::fromStdString(group.first);
auto* parent_item =
- new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(group.first)));
+ new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(parent_item_data)));
parent_item->setEditable(false);
- parent_item->setData(group.first);
+ parent_item->setData(parent_item_data);
for (const auto& hotkey : group.second) {
- auto* action =
- new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(hotkey.first)));
+ QString hotkey_action_data = QString::fromStdString(hotkey.first);
+ auto* action = new QStandardItem(
+ QCoreApplication::translate("Hotkeys", qPrintable(hotkey_action_data)));
auto* keyseq =
new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText));
- auto* controller_keyseq = new QStandardItem(hotkey.second.controller_keyseq);
+ auto* controller_keyseq =
+ new QStandardItem(QString::fromStdString(hotkey.second.controller_keyseq));
action->setEditable(false);
- action->setData(hotkey.first);
+ action->setData(hotkey_action_data);
keyseq->setEditable(false);
controller_keyseq->setEditable(false);
parent_item->appendRow({action, keyseq, controller_keyseq});
@@ -301,13 +305,13 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
const QStandardItem* controller_keyseq =
parent->child(key_column_id, controller_column);
for (auto& [group, sub_actions] : registry.hotkey_groups) {
- if (group != parent->data())
+ if (group != parent->data().toString().toStdString())
continue;
for (auto& [action_name, hotkey] : sub_actions) {
- if (action_name != action->data())
+ if (action_name != action->data().toString().toStdString())
continue;
hotkey.keyseq = QKeySequence(keyseq->text());
- hotkey.controller_keyseq = controller_keyseq->text();
+ hotkey.controller_keyseq = controller_keyseq->text().toStdString();
}
}
}
@@ -319,7 +323,7 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
void ConfigureHotkeys::RestoreDefaults() {
for (int r = 0; r < model->rowCount(); ++r) {
const QStandardItem* parent = model->item(r, 0);
- const int hotkey_size = static_cast<int>(Config::default_hotkeys.size());
+ const int hotkey_size = static_cast<int>(UISettings::default_hotkeys.size());
if (hotkey_size != parent->rowCount()) {
QMessageBox::warning(this, tr("Invalid hotkey settings"),
@@ -330,10 +334,11 @@ void ConfigureHotkeys::RestoreDefaults() {
for (int r2 = 0; r2 < parent->rowCount(); ++r2) {
model->item(r, 0)
->child(r2, hotkey_column)
- ->setText(Config::default_hotkeys[r2].shortcut.keyseq);
+ ->setText(QString::fromStdString(UISettings::default_hotkeys[r2].shortcut.keyseq));
model->item(r, 0)
->child(r2, controller_column)
- ->setText(Config::default_hotkeys[r2].shortcut.controller_keyseq);
+ ->setText(QString::fromStdString(
+ UISettings::default_hotkeys[r2].shortcut.controller_keyseq));
}
}
}
@@ -379,7 +384,7 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) {
void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) {
const QString& default_key_sequence =
- Config::default_hotkeys[index.row()].shortcut.controller_keyseq;
+ QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.controller_keyseq);
const auto [key_sequence_used, used_action] = IsUsedControllerKey(default_key_sequence);
if (key_sequence_used && default_key_sequence != model->data(index).toString()) {
@@ -393,7 +398,8 @@ void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) {
void ConfigureHotkeys::RestoreHotkey(QModelIndex index) {
const QKeySequence& default_key_sequence = QKeySequence::fromString(
- Config::default_hotkeys[index.row()].shortcut.keyseq, QKeySequence::NativeText);
+ QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.keyseq),
+ QKeySequence::NativeText);
const auto [key_sequence_used, used_action] = IsUsedKey(default_key_sequence);
if (key_sequence_used && default_key_sequence != QKeySequence(model->data(index).toString())) {
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 3dcad2701..02e23cce6 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -152,7 +152,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged,
[this](bool is_handheld) { UpdateDockedState(is_handheld); });
- advanced = new ConfigureInputAdvanced(this);
+ advanced = new ConfigureInputAdvanced(hid_core, this);
ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
ui->tabAdvanced->layout()->addWidget(advanced);
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 136cd3a0a..beb503dae 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2016 Citra Emulator Project
+// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index 3cfd5d439..441cea3f6 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -4,11 +4,13 @@
#include <QColorDialog>
#include "common/settings.h"
#include "core/core.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
#include "ui_configure_input_advanced.h"
#include "yuzu/configuration/configure_input_advanced.h"
-ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
- : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputAdvanced>()) {
+ConfigureInputAdvanced::ConfigureInputAdvanced(Core::HID::HIDCore& hid_core_, QWidget* parent)
+ : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputAdvanced>()), hid_core{hid_core_} {
ui->setupUi(this);
controllers_color_buttons = {{
@@ -123,6 +125,8 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
player.button_color_left = colors[1];
player.body_color_right = colors[2];
player.button_color_right = colors[3];
+
+ hid_core.GetEmulatedControllerByIndex(player_idx)->ReloadColorsFromSettings();
}
Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked();
diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h
index fc1230284..41f822c4a 100644
--- a/src/yuzu/configuration/configure_input_advanced.h
+++ b/src/yuzu/configuration/configure_input_advanced.h
@@ -14,11 +14,15 @@ namespace Ui {
class ConfigureInputAdvanced;
}
+namespace Core::HID {
+class HIDCore;
+} // namespace Core::HID
+
class ConfigureInputAdvanced : public QWidget {
Q_OBJECT
public:
- explicit ConfigureInputAdvanced(QWidget* parent = nullptr);
+ explicit ConfigureInputAdvanced(Core::HID::HIDCore& hid_core_, QWidget* parent = nullptr);
~ConfigureInputAdvanced() override;
void ApplyConfiguration();
@@ -44,4 +48,6 @@ private:
std::array<std::array<QColor, 4>, 8> controllers_colors;
std::array<std::array<QPushButton*, 4>, 8> controllers_color_buttons;
+
+ Core::HID::HIDCore& hid_core;
};
diff --git a/src/yuzu/configuration/configure_input_per_game.cpp b/src/yuzu/configuration/configure_input_per_game.cpp
index 78e65d468..8d9f65a05 100644
--- a/src/yuzu/configuration/configure_input_per_game.cpp
+++ b/src/yuzu/configuration/configure_input_per_game.cpp
@@ -5,12 +5,12 @@
#include "core/core.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
+#include "frontend_common/config.h"
#include "ui_configure_input_per_game.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_input_per_game.h"
#include "yuzu/configuration/input_profiles.h"
-ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_,
+ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, QtConfig* config_,
QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPerGame>()),
profiles(std::make_unique<InputProfiles>()), system{system_}, config{config_} {
@@ -110,6 +110,6 @@ void ConfigureInputPerGame::SaveConfiguration() {
// Clear all controls from the config in case the user reverted back to globals
config->ClearControlPlayerValues();
for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) {
- config->SaveControlPlayerValue(index);
+ config->SaveQtControlPlayerValues(index);
}
}
diff --git a/src/yuzu/configuration/configure_input_per_game.h b/src/yuzu/configuration/configure_input_per_game.h
index 660faf574..4420e856c 100644
--- a/src/yuzu/configuration/configure_input_per_game.h
+++ b/src/yuzu/configuration/configure_input_per_game.h
@@ -9,6 +9,7 @@
#include "ui_configure_input_per_game.h"
#include "yuzu/configuration/input_profiles.h"
+#include "yuzu/configuration/qt_config.h"
class QComboBox;
@@ -22,7 +23,7 @@ class ConfigureInputPerGame : public QWidget {
Q_OBJECT
public:
- explicit ConfigureInputPerGame(Core::System& system_, Config* config_,
+ explicit ConfigureInputPerGame(Core::System& system_, QtConfig* config_,
QWidget* parent = nullptr);
/// Load and Save configurations to settings file.
@@ -41,5 +42,5 @@ private:
std::array<QComboBox*, 8> profile_comboboxes;
Core::System& system;
- Config* config;
+ QtConfig* config;
};
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 576f5b571..0f7b3714e 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -12,15 +12,16 @@
#include <QTimer>
#include "common/assert.h"
#include "common/param_package.h"
+#include "configuration/qt_config.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
+#include "frontend_common/config.h"
#include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
#include "input_common/main.h"
#include "ui_configure_input_player.h"
#include "yuzu/bootmanager.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_input_player.h"
#include "yuzu/configuration/configure_input_player_widget.h"
#include "yuzu/configuration/configure_mouse_panning.h"
@@ -322,11 +323,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
setFocusPolicy(Qt::ClickFocus);
button_map = {
- ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY,
- ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR,
- ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus,
- ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown,
- ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot,
+ ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY,
+ ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR,
+ ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus,
+ ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown,
+ ui->buttonSLLeft, ui->buttonSRLeft, ui->buttonHome, ui->buttonScreenshot,
+ ui->buttonSLRight, ui->buttonSRRight,
};
analog_map_buttons = {{
@@ -1181,10 +1183,13 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
// List of all the widgets that will be hidden by any of the following layouts that need
// "unhidden" after the controller type changes
- const std::array<QWidget*, 11> layout_show = {
- ui->buttonShoulderButtonsSLSR,
+ const std::array<QWidget*, 14> layout_show = {
+ ui->buttonShoulderButtonsSLSRLeft,
+ ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget,
ui->horizontalSpacerShoulderButtonsWidget2,
+ ui->horizontalSpacerShoulderButtonsWidget3,
+ ui->horizontalSpacerShoulderButtonsWidget4,
ui->buttonShoulderButtonsLeft,
ui->buttonMiscButtonsMinusScreenshot,
ui->bottomLeft,
@@ -1202,16 +1207,19 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
std::vector<QWidget*> layout_hidden;
switch (layout) {
case Core::HID::NpadStyleIndex::ProController:
- case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
layout_hidden = {
- ui->buttonShoulderButtonsSLSR,
+ ui->buttonShoulderButtonsSLSRLeft,
+ ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2,
+ ui->horizontalSpacerShoulderButtonsWidget4,
};
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
layout_hidden = {
+ ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2,
+ ui->horizontalSpacerShoulderButtonsWidget3,
ui->buttonShoulderButtonsRight,
ui->buttonMiscButtonsPlusHome,
ui->bottomRight,
@@ -1219,16 +1227,17 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
break;
case Core::HID::NpadStyleIndex::JoyconRight:
layout_hidden = {
- ui->horizontalSpacerShoulderButtonsWidget,
- ui->buttonShoulderButtonsLeft,
- ui->buttonMiscButtonsMinusScreenshot,
- ui->bottomLeft,
+ ui->buttonShoulderButtonsSLSRLeft, ui->horizontalSpacerShoulderButtonsWidget,
+ ui->horizontalSpacerShoulderButtonsWidget4, ui->buttonShoulderButtonsLeft,
+ ui->buttonMiscButtonsMinusScreenshot, ui->bottomLeft,
};
break;
case Core::HID::NpadStyleIndex::GameCube:
layout_hidden = {
- ui->buttonShoulderButtonsSLSR,
+ ui->buttonShoulderButtonsSLSRLeft,
+ ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2,
+ ui->horizontalSpacerShoulderButtonsWidget4,
ui->buttonMiscButtonsMinusGroup,
ui->buttonMiscButtonsScreenshotGroup,
};
@@ -1389,25 +1398,25 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
emulated_controller->SetButtonParam(
button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
- Config::default_buttons[button_id])});
+ QtConfig::default_buttons[button_id])});
}
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
Common::ParamPackage analog_param{};
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
- Config::default_analogs[analog_id][sub_button_id])};
+ QtConfig::default_analogs[analog_id][sub_button_id])};
SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]);
}
analog_param.Set("modifier", InputCommon::GenerateKeyboardParam(
- Config::default_stick_mod[analog_id]));
+ QtConfig::default_stick_mod[analog_id]));
emulated_controller->SetStickParam(analog_id, analog_param);
}
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
emulated_controller->SetMotionParam(
motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
- Config::default_motions[motion_id])});
+ QtConfig::default_motions[motion_id])});
}
// If mouse is selected we want to override with mappings from the driver
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index d3255d2b4..fda09e925 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2016 Citra Emulator Project
+// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index 611a79477..5518cccd1 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -1208,6 +1208,159 @@
<property name="spacing">
<number>3</number>
</property>
+ <item>
+ <widget class="QWidget" name="buttonShoulderButtonsSLSRLeft" native="true">
+ <layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRLeftVerticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonShoulderButtonsSLLeftGroup">
+ <property name="title">
+ <string>SL</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QVBoxLayout" name="buttonShoulderButtonsSLLeftVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonSLLeft">
+ <property name="minimumSize">
+ <size>
+ <width>68</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>SL</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonShoulderButtonsSRLeftGroup">
+ <property name="title">
+ <string>SR</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QVBoxLayout" name="buttonShoulderButtonsSRLeftVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonSRLeft">
+ <property name="minimumSize">
+ <size>
+ <width>68</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>SR</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget4" native="true">
+ <layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidget4Layout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacerShoulderButtons5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item>
<widget class="QWidget" name="buttonShoulderButtonsLeft" native="true">
<layout class="QVBoxLayout" name="buttonShoulderButtonsLeftVerticalLayout">
@@ -1830,125 +1983,125 @@
</layout>
</widget>
</item>
- <item>
- <widget class="QWidget" name="buttonShoulderButtonsSLSR" native="true">
- <layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRVerticalLayout">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item alignment="Qt::AlignHCenter">
- <widget class="QGroupBox" name="buttonShoulderButtonsSLGroup">
- <property name="title">
- <string>SL</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <layout class="QVBoxLayout" name="buttonShoulderButtonsSLVerticalLayout">
- <property name="spacing">
- <number>3</number>
- </property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>3</number>
- </property>
- <property name="rightMargin">
- <number>3</number>
- </property>
- <property name="bottomMargin">
- <number>3</number>
- </property>
- <item>
- <widget class="QPushButton" name="buttonSL">
- <property name="minimumSize">
- <size>
- <width>68</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>68</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">min-width: 68px;</string>
- </property>
- <property name="text">
- <string>SL</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item alignment="Qt::AlignHCenter">
- <widget class="QGroupBox" name="buttonShoulderButtonsSRGroup">
- <property name="title">
- <string>SR</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <layout class="QVBoxLayout" name="buttonShoulderButtonsSRVerticalLayout">
- <property name="spacing">
- <number>3</number>
- </property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>3</number>
- </property>
- <property name="rightMargin">
- <number>3</number>
- </property>
- <property name="bottomMargin">
- <number>3</number>
- </property>
- <item>
- <widget class="QPushButton" name="buttonSR">
- <property name="minimumSize">
- <size>
- <width>68</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>68</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">min-width: 68px;</string>
- </property>
- <property name="text">
- <string>SR</string>
- </property>
- </widget>
- </item>
+ <item>
+ <widget class="QWidget" name="buttonShoulderButtonsSLSRRight" native="true">
+ <layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRRightVerticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonShoulderButtonsSLRightGroup">
+ <property name="title">
+ <string>SL</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QVBoxLayout" name="buttonShoulderButtonsSLRightVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonSLRight">
+ <property name="minimumSize">
+ <size>
+ <width>68</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>SL</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonShoulderButtonsSRRightGroup">
+ <property name="title">
+ <string>SR</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QVBoxLayout" name="buttonShoulderButtonsSRRightVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonSRRight">
+ <property name="minimumSize">
+ <size>
+ <width>68</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>SR</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
+ </widget>
+ </item>
</layout>
</item>
<item>
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index a188eef92..550cff9a0 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -297,8 +297,8 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
// Sideview SL and SR buttons
button_color = colors.slider_button;
- DrawRoundButton(p, center + QPoint(59, 52), button_values[SR], 5, 12, Direction::Left);
- DrawRoundButton(p, center + QPoint(59, -69), button_values[SL], 5, 12, Direction::Left);
+ DrawRoundButton(p, center + QPoint(59, 52), button_values[SRLeft], 5, 12, Direction::Left);
+ DrawRoundButton(p, center + QPoint(59, -69), button_values[SLLeft], 5, 12, Direction::Left);
DrawLeftBody(p, center);
@@ -353,8 +353,10 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
// SR and SL buttons
p.setPen(colors.outline);
button_color = colors.slider_button;
- DrawRoundButton(p, center + QPoint(155, 52), button_values[SR], 5.2f, 12, Direction::None, 4);
- DrawRoundButton(p, center + QPoint(155, -69), button_values[SL], 5.2f, 12, Direction::None, 4);
+ DrawRoundButton(p, center + QPoint(155, 52), button_values[SRLeft], 5.2f, 12, Direction::None,
+ 4);
+ DrawRoundButton(p, center + QPoint(155, -69), button_values[SLLeft], 5.2f, 12, Direction::None,
+ 4);
// SR and SL text
p.setPen(colors.transparent);
@@ -428,8 +430,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
// Sideview SL and SR buttons
button_color = colors.slider_button;
- DrawRoundButton(p, center + QPoint(-59, 52), button_values[SL], 5, 11, Direction::Right);
- DrawRoundButton(p, center + QPoint(-59, -69), button_values[SR], 5, 11, Direction::Right);
+ DrawRoundButton(p, center + QPoint(-59, 52), button_values[SLRight], 5, 11,
+ Direction::Right);
+ DrawRoundButton(p, center + QPoint(-59, -69), button_values[SRRight], 5, 11,
+ Direction::Right);
DrawRightBody(p, center);
@@ -484,8 +488,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
// SR and SL buttons
p.setPen(colors.outline);
button_color = colors.slider_button;
- DrawRoundButton(p, center + QPoint(-155, 52), button_values[SL], 5, 12, Direction::None, 4.0f);
- DrawRoundButton(p, center + QPoint(-155, -69), button_values[SR], 5, 12, Direction::None, 4.0f);
+ DrawRoundButton(p, center + QPoint(-155, 52), button_values[SLRight], 5, 12, Direction::None,
+ 4.0f);
+ DrawRoundButton(p, center + QPoint(-155, -69), button_values[SRRight], 5, 12, Direction::None,
+ 4.0f);
// SR and SL text
p.setPen(colors.transparent);
@@ -557,6 +563,19 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
DrawRoundButton(p, center + QPoint(-154, -72), button_values[Minus], 7, 4, Direction::Up,
1);
+ // Left SR and SL sideview buttons
+ button_color = colors.slider_button;
+ DrawRoundButton(p, center + QPoint(-20, -62), button_values[SLLeft], 4, 11,
+ Direction::Left);
+ DrawRoundButton(p, center + QPoint(-20, 47), button_values[SRLeft], 4, 11, Direction::Left);
+
+ // Right SR and SL sideview buttons
+ button_color = colors.slider_button;
+ DrawRoundButton(p, center + QPoint(20, 47), button_values[SLRight], 4, 11,
+ Direction::Right);
+ DrawRoundButton(p, center + QPoint(20, -62), button_values[SRRight], 4, 11,
+ Direction::Right);
+
DrawDualBody(p, center);
// Right trigger top view
@@ -1792,16 +1811,6 @@ void PlayerControlPreview::DrawDualBody(QPainter& p, const QPointF center) {
p.setBrush(colors.right);
DrawPolygon(p, qright_joycon_topview);
- // Right SR and SL sideview buttons
- p.setPen(colors.outline);
- p.setBrush(colors.slider_button);
- DrawRoundRectangle(p, center + QPoint(19, 47), 7, 22, 1);
- DrawRoundRectangle(p, center + QPoint(19, -62), 7, 22, 1);
-
- // Left SR and SL sideview buttons
- DrawRoundRectangle(p, center + QPoint(-19, 47), 7, 22, 1);
- DrawRoundRectangle(p, center + QPoint(-19, -62), 7, 22, 1);
-
// Right Sideview body
p.setBrush(colors.slider);
DrawPolygon(p, qright_joycon_slider);
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index b91d6ad4a..b274a3321 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -25,8 +25,8 @@
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/xts_archive.h"
#include "core/loader/loader.h"
+#include "frontend_common/config.h"
#include "ui_configure_per_game.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/configure_cpu.h"
@@ -50,8 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
: fmt::format("{:016X}", title_id);
- game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
-
+ game_config = std::make_unique<QtConfig>(config_file_name, Config::ConfigType::PerGameConfig);
addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this);
audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *builder, this);
cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, *builder, this);
@@ -108,7 +107,7 @@ void ConfigurePerGame::ApplyConfiguration() {
system.ApplySettings();
Settings::LogSettings();
- game_config->Save();
+ game_config->SaveAllValues();
}
void ConfigurePerGame::changeEvent(QEvent* event) {
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index 1a727f32c..c8ee46c04 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -12,9 +12,10 @@
#include "configuration/shared_widget.h"
#include "core/file_sys/vfs_types.h"
+#include "frontend_common/config.h"
#include "vk_device_info.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configuration_shared.h"
+#include "yuzu/configuration/qt_config.h"
#include "yuzu/configuration/shared_translation.h"
namespace Core {
@@ -72,7 +73,7 @@ private:
QGraphicsScene* scene;
- std::unique_ptr<Config> game_config;
+ std::unique_ptr<QtConfig> game_config;
Core::System& system;
std::unique_ptr<ConfigurationShared::Builder> builder;
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 674a75a62..140a7fe5d 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -19,7 +19,6 @@
#include "core/file_sys/xts_archive.h"
#include "core/loader/loader.h"
#include "ui_configure_per_game_addons.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_input.h"
#include "yuzu/configuration/configure_per_game_addons.h"
#include "yuzu/uisettings.h"
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index a47089988..6d2219bf5 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -306,10 +306,10 @@ void ConfigureProfileManager::SetUserImage() {
return;
}
- // Some games crash when the profile image is too big. Resize any image bigger than 256x256
+ // Profile image must be 256x256
QImage image(image_path);
- if (image.width() > 256 || image.height() > 256) {
- image = image.scaled(256, 256, Qt::KeepAspectRatio);
+ if (image.width() != 256 || image.height() != 256) {
+ image = image.scaled(256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
if (!image.save(image_path)) {
QMessageBox::warning(this, tr("Error resizing user image"),
tr("Unable to resize image"));
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp
index f83705544..9572ff43c 100644
--- a/src/yuzu/configuration/configure_ringcon.cpp
+++ b/src/yuzu/configuration/configure_ringcon.cpp
@@ -8,6 +8,7 @@
#include <QTimer>
#include <fmt/format.h>
+#include "configuration/qt_config.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "input_common/drivers/keyboard.h"
@@ -15,7 +16,6 @@
#include "input_common/main.h"
#include "ui_configure_ringcon.h"
#include "yuzu/bootmanager.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_ringcon.h"
const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM>
@@ -270,7 +270,7 @@ void ConfigureRingController::LoadConfiguration() {
void ConfigureRingController::RestoreDefaults() {
const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys(
- 0, 0, Config::default_ringcon_analogs[0], Config::default_ringcon_analogs[1], 0, 0.05f);
+ 0, 0, QtConfig::default_ringcon_analogs[0], QtConfig::default_ringcon_analogs[1], 0, 0.05f);
emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string));
UpdateUI();
}
diff --git a/src/yuzu/configuration/configure_ringcon.h b/src/yuzu/configuration/configure_ringcon.h
index b23c27906..6fd95e2b8 100644
--- a/src/yuzu/configuration/configure_ringcon.h
+++ b/src/yuzu/configuration/configure_ringcon.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 0c8e5c8b4..7cbf43775 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -16,7 +16,6 @@
#include "core/core.h"
#include "core/hle/service/time/time_manager.h"
#include "ui_configure_system.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_system.h"
#include "yuzu/configuration/shared_widget.h"
diff --git a/src/yuzu/configuration/configure_tas.h b/src/yuzu/configuration/configure_tas.h
index 4a6b0ba4e..a91891906 100644
--- a/src/yuzu/configuration/configure_tas.h
+++ b/src/yuzu/configuration/configure_tas.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
index 5a03e48df..94df6d9d3 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
+#include "common/settings.h"
#include "ui_configure_touchscreen_advanced.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_touchscreen_advanced.h"
ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent)
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h
index 034dc0d46..b6fdffdc8 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.h
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2016 Citra Emulator Project
+// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 82f3b6e78..dd43f0a0e 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -164,7 +164,7 @@ ConfigureUi::~ConfigureUi() = default;
void ConfigureUi::ApplyConfiguration() {
UISettings::values.theme =
- ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
+ ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString();
UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
UISettings::values.show_compat = ui->show_compat->isChecked();
UISettings::values.show_size = ui->show_size->isChecked();
@@ -191,9 +191,10 @@ void ConfigureUi::RequestGameListUpdate() {
}
void ConfigureUi::SetConfiguration() {
- ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
+ ui->theme_combobox->setCurrentIndex(
+ ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme)));
ui->language_combobox->setCurrentIndex(
- ui->language_combobox->findData(UISettings::values.language));
+ ui->language_combobox->findData(QString::fromStdString(UISettings::values.language)));
ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue());
ui->show_compat->setChecked(UISettings::values.show_compat.GetValue());
ui->show_size->setChecked(UISettings::values.show_size.GetValue());
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp
index 41ef4250a..716efbccd 100644
--- a/src/yuzu/configuration/input_profiles.cpp
+++ b/src/yuzu/configuration/input_profiles.cpp
@@ -5,7 +5,7 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
-#include "yuzu/configuration/config.h"
+#include "frontend_common/config.h"
#include "yuzu/configuration/input_profiles.h"
namespace FS = Common::FS;
@@ -44,7 +44,7 @@ InputProfiles::InputProfiles() {
if (IsINI(filename) && IsProfileNameValid(name_without_ext)) {
map_profiles.insert_or_assign(
name_without_ext,
- std::make_unique<Config>(name_without_ext, Config::ConfigType::InputProfile));
+ std::make_unique<QtConfig>(name_without_ext, Config::ConfigType::InputProfile));
}
return true;
@@ -85,7 +85,7 @@ bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t p
}
map_profiles.insert_or_assign(
- profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile));
+ profile_name, std::make_unique<QtConfig>(profile_name, Config::ConfigType::InputProfile));
return SaveProfile(profile_name, player_index);
}
@@ -113,7 +113,7 @@ bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t pla
return false;
}
- map_profiles[profile_name]->ReadControlPlayerValue(player_index);
+ map_profiles[profile_name]->ReadQtControlPlayerValues(player_index);
return true;
}
@@ -122,7 +122,7 @@ bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t pla
return false;
}
- map_profiles[profile_name]->SaveControlPlayerValue(player_index);
+ map_profiles[profile_name]->SaveQtControlPlayerValues(player_index);
return true;
}
diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h
index 2bf3e4250..023ec74a6 100644
--- a/src/yuzu/configuration/input_profiles.h
+++ b/src/yuzu/configuration/input_profiles.h
@@ -6,6 +6,8 @@
#include <string>
#include <unordered_map>
+#include "configuration/qt_config.h"
+
namespace Core {
class System;
}
@@ -30,5 +32,5 @@ public:
private:
bool ProfileExistsInMap(const std::string& profile_name) const;
- std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles;
+ std::unordered_map<std::string, std::unique_ptr<QtConfig>> map_profiles;
};
diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp
new file mode 100644
index 000000000..5a8e69aa9
--- /dev/null
+++ b/src/yuzu/configuration/qt_config.cpp
@@ -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();
+}
diff --git a/src/yuzu/configuration/qt_config.h b/src/yuzu/configuration/qt_config.h
new file mode 100644
index 000000000..dc2dceb4d
--- /dev/null
+++ b/src/yuzu/configuration/qt_config.h
@@ -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;
+};
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp
index 3fe448f27..a7b5def32 100644
--- a/src/yuzu/configuration/shared_translation.cpp
+++ b/src/yuzu/configuration/shared_translation.cpp
@@ -1,17 +1,18 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "common/time_zone.h"
#include "yuzu/configuration/shared_translation.h"
#include <map>
#include <memory>
#include <tuple>
#include <utility>
+#include <QCoreApplication>
#include <QWidget>
#include "common/settings.h"
#include "common/settings_enums.h"
#include "common/settings_setting.h"
+#include "common/time_zone.h"
#include "yuzu/uisettings.h"
namespace ConfigurationShared {
@@ -21,123 +22,135 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
const auto& tr = [parent](const char* text) -> QString { return parent->tr(text); };
#define INSERT(SETTINGS, ID, NAME, TOOLTIP) \
- translations->insert(std::pair{SETTINGS::values.ID.Id(), std::pair{tr((NAME)), tr((TOOLTIP))}})
+ translations->insert(std::pair{SETTINGS::values.ID.Id(), std::pair{(NAME), (TOOLTIP)}})
// A setting can be ignored by giving it a blank name
// Audio
- INSERT(Settings, sink_id, "Output Engine:", "");
- INSERT(Settings, audio_output_device_id, "Output Device:", "");
- INSERT(Settings, audio_input_device_id, "Input Device:", "");
- INSERT(Settings, audio_muted, "Mute audio", "");
- INSERT(Settings, volume, "Volume:", "");
- INSERT(Settings, dump_audio_commands, "", "");
- INSERT(UISettings, mute_when_in_background, "Mute audio when in background", "");
+ INSERT(Settings, sink_id, tr("Output Engine:"), QStringLiteral());
+ INSERT(Settings, audio_output_device_id, tr("Output Device:"), QStringLiteral());
+ INSERT(Settings, audio_input_device_id, tr("Input Device:"), QStringLiteral());
+ INSERT(Settings, audio_muted, tr("Mute audio"), QStringLiteral());
+ INSERT(Settings, volume, tr("Volume:"), QStringLiteral());
+ INSERT(Settings, dump_audio_commands, QStringLiteral(), QStringLiteral());
+ INSERT(UISettings, mute_when_in_background, tr("Mute audio when in background"),
+ QStringLiteral());
// Core
- INSERT(Settings, use_multi_core, "Multicore CPU Emulation", "");
- INSERT(Settings, memory_layout_mode, "Memory Layout", "");
- INSERT(Settings, use_speed_limit, "", "");
- INSERT(Settings, speed_limit, "Limit Speed Percent", "");
+ INSERT(Settings, use_multi_core, tr("Multicore CPU Emulation"), QStringLiteral());
+ INSERT(Settings, memory_layout_mode, tr("Memory Layout"), QStringLiteral());
+ INSERT(Settings, use_speed_limit, QStringLiteral(), QStringLiteral());
+ INSERT(Settings, speed_limit, tr("Limit Speed Percent"), QStringLiteral());
// Cpu
- INSERT(Settings, cpu_accuracy, "Accuracy:", "");
+ INSERT(Settings, cpu_accuracy, tr("Accuracy:"), QStringLiteral());
// Cpu Debug
// Cpu Unsafe
- INSERT(Settings, cpuopt_unsafe_unfuse_fma,
- "Unfuse FMA (improve performance on CPUs without FMA)",
- "This option improves speed by reducing accuracy of fused-multiply-add instructions on "
- "CPUs without native FMA support.");
- INSERT(Settings, cpuopt_unsafe_reduce_fp_error, "Faster FRSQRTE and FRECPE",
- "This option improves the speed of some approximate floating-point functions by using "
- "less accurate native approximations.");
- INSERT(Settings, cpuopt_unsafe_ignore_standard_fpcr, "Faster ASIMD instructions (32 bits only)",
- "This option improves the speed of 32 bits ASIMD floating-point functions by running "
- "with incorrect rounding modes.");
- INSERT(Settings, cpuopt_unsafe_inaccurate_nan, "Inaccurate NaN handling",
- "This option improves speed by removing NaN checking. Please note this also reduces "
- "accuracy of certain floating-point instructions.");
INSERT(
- Settings, cpuopt_unsafe_fastmem_check, "Disable address space checks",
- "This option improves speed by eliminating a safety check before every memory read/write "
- "in guest. Disabling it may allow a game to read/write the emulator's memory.");
- INSERT(Settings, cpuopt_unsafe_ignore_global_monitor, "Ignore global monitor",
- "This option improves speed by relying only on the semantics of cmpxchg to ensure "
+ Settings, cpuopt_unsafe_unfuse_fma,
+ tr("Unfuse FMA (improve performance on CPUs without FMA)"),
+ tr("This option improves speed by reducing accuracy of fused-multiply-add instructions on "
+ "CPUs without native FMA support."));
+ INSERT(
+ Settings, cpuopt_unsafe_reduce_fp_error, tr("Faster FRSQRTE and FRECPE"),
+ tr("This option improves the speed of some approximate floating-point functions by using "
+ "less accurate native approximations."));
+ INSERT(Settings, cpuopt_unsafe_ignore_standard_fpcr,
+ tr("Faster ASIMD instructions (32 bits only)"),
+ tr("This option improves the speed of 32 bits ASIMD floating-point functions by running "
+ "with incorrect rounding modes."));
+ INSERT(Settings, cpuopt_unsafe_inaccurate_nan, tr("Inaccurate NaN handling"),
+ tr("This option improves speed by removing NaN checking. Please note this also reduces "
+ "accuracy of certain floating-point instructions."));
+ INSERT(Settings, cpuopt_unsafe_fastmem_check, tr("Disable address space checks"),
+ tr("This option improves speed by eliminating a safety check before every memory "
+ "read/write "
+ "in guest. Disabling it may allow a game to read/write the emulator's memory."));
+ INSERT(
+ Settings, cpuopt_unsafe_ignore_global_monitor, tr("Ignore global monitor"),
+ tr("This option improves speed by relying only on the semantics of cmpxchg to ensure "
"safety of exclusive access instructions. Please note this may result in deadlocks and "
- "other race conditions.");
+ "other race conditions."));
// Renderer
- INSERT(Settings, renderer_backend, "API:", "");
- INSERT(Settings, vulkan_device, "Device:", "");
- INSERT(Settings, shader_backend, "Shader Backend:", "");
- INSERT(Settings, resolution_setup, "Resolution:", "");
- INSERT(Settings, scaling_filter, "Window Adapting Filter:", "");
- INSERT(Settings, fsr_sharpening_slider, "FSR Sharpness:", "");
- INSERT(Settings, anti_aliasing, "Anti-Aliasing Method:", "");
- INSERT(Settings, fullscreen_mode, "Fullscreen Mode:", "");
- INSERT(Settings, aspect_ratio, "Aspect Ratio:", "");
- INSERT(Settings, use_disk_shader_cache, "Use disk pipeline cache", "");
- INSERT(Settings, use_asynchronous_gpu_emulation, "Use asynchronous GPU emulation", "");
- INSERT(Settings, nvdec_emulation, "NVDEC emulation:", "");
- INSERT(Settings, accelerate_astc, "ASTC Decoding Method:", "");
- INSERT(Settings, astc_recompression, "ASTC Recompression Method:", "");
- INSERT(Settings, vsync_mode, "VSync Mode:",
- "FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen "
+ INSERT(Settings, renderer_backend, tr("API:"), QStringLiteral());
+ INSERT(Settings, vulkan_device, tr("Device:"), QStringLiteral());
+ INSERT(Settings, shader_backend, tr("Shader Backend:"), QStringLiteral());
+ INSERT(Settings, resolution_setup, tr("Resolution:"), QStringLiteral());
+ INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QStringLiteral());
+ INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"), QStringLiteral());
+ INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"), QStringLiteral());
+ INSERT(Settings, fullscreen_mode, tr("Fullscreen Mode:"), QStringLiteral());
+ INSERT(Settings, aspect_ratio, tr("Aspect Ratio:"), QStringLiteral());
+ INSERT(Settings, use_disk_shader_cache, tr("Use disk pipeline cache"), QStringLiteral());
+ INSERT(Settings, use_asynchronous_gpu_emulation, tr("Use asynchronous GPU emulation"),
+ QStringLiteral());
+ INSERT(Settings, nvdec_emulation, tr("NVDEC emulation:"), QStringLiteral());
+ INSERT(Settings, accelerate_astc, tr("ASTC Decoding Method:"), QStringLiteral());
+ INSERT(Settings, astc_recompression, tr("ASTC Recompression Method:"), QStringLiteral());
+ INSERT(
+ Settings, vsync_mode, tr("VSync Mode:"),
+ tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen "
"refresh rate.\nFIFO Relaxed is similar to FIFO but allows tearing as it recovers from "
"a slow down.\nMailbox can have lower latency than FIFO and does not tear but may drop "
"frames.\nImmediate (no synchronization) just presents whatever is available and can "
- "exhibit tearing.");
- INSERT(Settings, bg_red, "", "");
- INSERT(Settings, bg_green, "", "");
- INSERT(Settings, bg_blue, "", "");
+ "exhibit tearing."));
+ INSERT(Settings, bg_red, QStringLiteral(), QStringLiteral());
+ INSERT(Settings, bg_green, QStringLiteral(), QStringLiteral());
+ INSERT(Settings, bg_blue, QStringLiteral(), QStringLiteral());
// Renderer (Advanced Graphics)
- INSERT(Settings, async_presentation, "Enable asynchronous presentation (Vulkan only)", "");
- INSERT(Settings, renderer_force_max_clock, "Force maximum clocks (Vulkan only)",
- "Runs work in the background while waiting for graphics commands to keep the GPU from "
- "lowering its clock speed.");
- INSERT(Settings, max_anisotropy, "Anisotropic Filtering:", "");
- INSERT(Settings, gpu_accuracy, "Accuracy Level:", "");
- INSERT(Settings, use_asynchronous_shaders, "Use asynchronous shader building (Hack)",
- "Enables asynchronous shader compilation, which may reduce shader stutter. This feature "
- "is experimental.");
- INSERT(Settings, use_fast_gpu_time, "Use Fast GPU Time (Hack)",
- "Enables Fast GPU Time. This option will force most games to run at their highest "
- "native resolution.");
- INSERT(Settings, use_vulkan_driver_pipeline_cache, "Use Vulkan pipeline cache",
- "Enables GPU vendor-specific pipeline cache. This option can improve shader loading "
- "time significantly in cases where the Vulkan driver does not store pipeline cache "
- "files internally.");
- INSERT(Settings, enable_compute_pipelines, "Enable Compute Pipelines (Intel Vulkan Only)",
- "Enable compute pipelines, required by some games.\nThis setting only exists for Intel "
+ INSERT(Settings, async_presentation, tr("Enable asynchronous presentation (Vulkan only)"),
+ QStringLiteral());
+ INSERT(
+ Settings, renderer_force_max_clock, tr("Force maximum clocks (Vulkan only)"),
+ tr("Runs work in the background while waiting for graphics commands to keep the GPU from "
+ "lowering its clock speed."));
+ INSERT(Settings, max_anisotropy, tr("Anisotropic Filtering:"), QStringLiteral());
+ INSERT(Settings, gpu_accuracy, tr("Accuracy Level:"), QStringLiteral());
+ INSERT(
+ Settings, use_asynchronous_shaders, tr("Use asynchronous shader building (Hack)"),
+ tr("Enables asynchronous shader compilation, which may reduce shader stutter. This feature "
+ "is experimental."));
+ INSERT(Settings, use_fast_gpu_time, tr("Use Fast GPU Time (Hack)"),
+ tr("Enables Fast GPU Time. This option will force most games to run at their highest "
+ "native resolution."));
+ INSERT(Settings, use_vulkan_driver_pipeline_cache, tr("Use Vulkan pipeline cache"),
+ tr("Enables GPU vendor-specific pipeline cache. This option can improve shader loading "
+ "time significantly in cases where the Vulkan driver does not store pipeline cache "
+ "files internally."));
+ INSERT(
+ Settings, enable_compute_pipelines, tr("Enable Compute Pipelines (Intel Vulkan Only)"),
+ tr("Enable compute pipelines, required by some games.\nThis setting only exists for Intel "
"proprietary drivers, and may crash if enabled.\nCompute pipelines are always enabled "
- "on all other drivers.");
- INSERT(Settings, use_reactive_flushing, "Enable Reactive Flushing",
- "Uses reactive flushing instead of predictive flushing, allowing more accurate memory "
- "syncing.");
- INSERT(Settings, use_video_framerate, "Sync to framerate of video playback",
- "Run the game at normal speed during video playback, even when the framerate is "
- "unlocked.");
- INSERT(Settings, barrier_feedback_loops, "Barrier feedback loops",
- "Improves rendering of transparency effects in specific games.");
+ "on all other drivers."));
+ INSERT(
+ Settings, use_reactive_flushing, tr("Enable Reactive Flushing"),
+ tr("Uses reactive flushing instead of predictive flushing, allowing more accurate memory "
+ "syncing."));
+ INSERT(Settings, use_video_framerate, tr("Sync to framerate of video playback"),
+ tr("Run the game at normal speed during video playback, even when the framerate is "
+ "unlocked."));
+ INSERT(Settings, barrier_feedback_loops, tr("Barrier feedback loops"),
+ tr("Improves rendering of transparency effects in specific games."));
// Renderer (Debug)
// System
- INSERT(Settings, rng_seed, "RNG Seed", "");
- INSERT(Settings, rng_seed_enabled, "", "");
- INSERT(Settings, device_name, "Device Name", "");
- INSERT(Settings, custom_rtc, "Custom RTC", "");
- INSERT(Settings, custom_rtc_enabled, "", "");
- INSERT(Settings, language_index,
- "Language:", "Note: this can be overridden when region setting is auto-select");
- INSERT(Settings, region_index, "Region:", "");
- INSERT(Settings, time_zone_index, "Time Zone:", "");
- INSERT(Settings, sound_index, "Sound Output Mode:", "");
- INSERT(Settings, use_docked_mode, "Console Mode:", "");
- INSERT(Settings, current_user, "", "");
+ INSERT(Settings, rng_seed, tr("RNG Seed"), QStringLiteral());
+ INSERT(Settings, rng_seed_enabled, QStringLiteral(), QStringLiteral());
+ INSERT(Settings, device_name, tr("Device Name"), QStringLiteral());
+ INSERT(Settings, custom_rtc, tr("Custom RTC"), QStringLiteral());
+ INSERT(Settings, custom_rtc_enabled, QStringLiteral(), QStringLiteral());
+ INSERT(Settings, language_index, tr("Language:"),
+ tr("Note: this can be overridden when region setting is auto-select"));
+ INSERT(Settings, region_index, tr("Region:"), QStringLiteral());
+ INSERT(Settings, time_zone_index, tr("Time Zone:"), QStringLiteral());
+ INSERT(Settings, sound_index, tr("Sound Output Mode:"), QStringLiteral());
+ INSERT(Settings, use_docked_mode, tr("Console Mode:"), QStringLiteral());
+ INSERT(Settings, current_user, QStringLiteral(), QStringLiteral());
// Controls
@@ -154,12 +167,14 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
// Ui
// Ui General
- INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", "");
- INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", "");
- INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", "");
- INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", "");
- INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", "");
- INSERT(UISettings, controller_applet_disabled, "Disable controller applet", "");
+ INSERT(UISettings, select_user_on_boot, tr("Prompt for user on game boot"), QStringLiteral());
+ INSERT(UISettings, pause_when_in_background, tr("Pause emulation when in background"),
+ QStringLiteral());
+ INSERT(UISettings, confirm_before_stopping, tr("Confirm before stopping emulation"),
+ QStringLiteral());
+ INSERT(UISettings, hide_mouse, tr("Hide mouse on inactivity"), QStringLiteral());
+ INSERT(UISettings, controller_applet_disabled, tr("Disable controller applet"),
+ QStringLiteral());
// Ui Debugging
@@ -179,140 +194,141 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
return parent->tr(text, context);
};
-#define PAIR(ENUM, VALUE, TRANSLATION) \
- { static_cast<u32>(Settings::ENUM::VALUE), tr(TRANSLATION) }
-#define CTX_PAIR(ENUM, VALUE, TRANSLATION, CONTEXT) \
- { static_cast<u32>(Settings::ENUM::VALUE), tr(TRANSLATION, CONTEXT) }
+#define PAIR(ENUM, VALUE, TRANSLATION) {static_cast<u32>(Settings::ENUM::VALUE), (TRANSLATION)}
// Intentionally skipping VSyncMode to let the UI fill that one out
translations->insert({Settings::EnumMetadata<Settings::AstcDecodeMode>::Index(),
{
- PAIR(AstcDecodeMode, Cpu, "CPU"),
- PAIR(AstcDecodeMode, Gpu, "GPU"),
- PAIR(AstcDecodeMode, CpuAsynchronous, "CPU Asynchronous"),
- }});
- translations->insert({Settings::EnumMetadata<Settings::AstcRecompression>::Index(),
- {
- PAIR(AstcRecompression, Uncompressed, "Uncompressed (Best quality)"),
- PAIR(AstcRecompression, Bc1, "BC1 (Low quality)"),
- PAIR(AstcRecompression, Bc3, "BC3 (Medium quality)"),
+ PAIR(AstcDecodeMode, Cpu, tr("CPU")),
+ PAIR(AstcDecodeMode, Gpu, tr("GPU")),
+ PAIR(AstcDecodeMode, CpuAsynchronous, tr("CPU Asynchronous")),
}});
+ translations->insert(
+ {Settings::EnumMetadata<Settings::AstcRecompression>::Index(),
+ {
+ PAIR(AstcRecompression, Uncompressed, tr("Uncompressed (Best quality)")),
+ PAIR(AstcRecompression, Bc1, tr("BC1 (Low quality)")),
+ PAIR(AstcRecompression, Bc3, tr("BC3 (Medium quality)")),
+ }});
translations->insert({Settings::EnumMetadata<Settings::RendererBackend>::Index(),
{
#ifdef HAS_OPENGL
- PAIR(RendererBackend, OpenGL, "OpenGL"),
+ PAIR(RendererBackend, OpenGL, tr("OpenGL")),
#endif
- PAIR(RendererBackend, Vulkan, "Vulkan"),
- PAIR(RendererBackend, Null, "Null"),
- }});
- translations->insert({Settings::EnumMetadata<Settings::ShaderBackend>::Index(),
- {
- PAIR(ShaderBackend, Glsl, "GLSL"),
- PAIR(ShaderBackend, Glasm, "GLASM (Assembly Shaders, NVIDIA Only)"),
- PAIR(ShaderBackend, SpirV, "SPIR-V (Experimental, Mesa Only)"),
+ PAIR(RendererBackend, Vulkan, tr("Vulkan")),
+ PAIR(RendererBackend, Null, tr("Null")),
}});
+ translations->insert(
+ {Settings::EnumMetadata<Settings::ShaderBackend>::Index(),
+ {
+ PAIR(ShaderBackend, Glsl, tr("GLSL")),
+ PAIR(ShaderBackend, Glasm, tr("GLASM (Assembly Shaders, NVIDIA Only)")),
+ PAIR(ShaderBackend, SpirV, tr("SPIR-V (Experimental, Mesa Only)")),
+ }});
translations->insert({Settings::EnumMetadata<Settings::GpuAccuracy>::Index(),
{
- PAIR(GpuAccuracy, Normal, "Normal"),
- PAIR(GpuAccuracy, High, "High"),
- PAIR(GpuAccuracy, Extreme, "Extreme"),
- }});
- translations->insert({Settings::EnumMetadata<Settings::CpuAccuracy>::Index(),
- {
- PAIR(CpuAccuracy, Auto, "Auto"),
- PAIR(CpuAccuracy, Accurate, "Accurate"),
- PAIR(CpuAccuracy, Unsafe, "Unsafe"),
- PAIR(CpuAccuracy, Paranoid, "Paranoid (disables most optimizations)"),
+ PAIR(GpuAccuracy, Normal, tr("Normal")),
+ PAIR(GpuAccuracy, High, tr("High")),
+ PAIR(GpuAccuracy, Extreme, tr("Extreme")),
}});
+ translations->insert(
+ {Settings::EnumMetadata<Settings::CpuAccuracy>::Index(),
+ {
+ PAIR(CpuAccuracy, Auto, tr("Auto")),
+ PAIR(CpuAccuracy, Accurate, tr("Accurate")),
+ PAIR(CpuAccuracy, Unsafe, tr("Unsafe")),
+ PAIR(CpuAccuracy, Paranoid, tr("Paranoid (disables most optimizations)")),
+ }});
translations->insert({Settings::EnumMetadata<Settings::FullscreenMode>::Index(),
{
- PAIR(FullscreenMode, Borderless, "Borderless Windowed"),
- PAIR(FullscreenMode, Exclusive, "Exclusive Fullscreen"),
+ PAIR(FullscreenMode, Borderless, tr("Borderless Windowed")),
+ PAIR(FullscreenMode, Exclusive, tr("Exclusive Fullscreen")),
}});
translations->insert({Settings::EnumMetadata<Settings::NvdecEmulation>::Index(),
{
- PAIR(NvdecEmulation, Off, "No Video Output"),
- PAIR(NvdecEmulation, Cpu, "CPU Video Decoding"),
- PAIR(NvdecEmulation, Gpu, "GPU Video Decoding (Default)"),
- }});
- translations->insert({Settings::EnumMetadata<Settings::ResolutionSetup>::Index(),
- {
- PAIR(ResolutionSetup, Res1_2X, "0.5X (360p/540p) [EXPERIMENTAL]"),
- PAIR(ResolutionSetup, Res3_4X, "0.75X (540p/810p) [EXPERIMENTAL]"),
- PAIR(ResolutionSetup, Res1X, "1X (720p/1080p)"),
- PAIR(ResolutionSetup, Res3_2X, "1.5X (1080p/1620p) [EXPERIMENTAL]"),
- PAIR(ResolutionSetup, Res2X, "2X (1440p/2160p)"),
- PAIR(ResolutionSetup, Res3X, "3X (2160p/3240p)"),
- PAIR(ResolutionSetup, Res4X, "4X (2880p/4320p)"),
- PAIR(ResolutionSetup, Res5X, "5X (3600p/5400p)"),
- PAIR(ResolutionSetup, Res6X, "6X (4320p/6480p)"),
- PAIR(ResolutionSetup, Res7X, "7X (5040p/7560p)"),
- PAIR(ResolutionSetup, Res8X, "8X (5760p/8640p)"),
+ PAIR(NvdecEmulation, Off, tr("No Video Output")),
+ PAIR(NvdecEmulation, Cpu, tr("CPU Video Decoding")),
+ PAIR(NvdecEmulation, Gpu, tr("GPU Video Decoding (Default)")),
}});
+ translations->insert(
+ {Settings::EnumMetadata<Settings::ResolutionSetup>::Index(),
+ {
+ PAIR(ResolutionSetup, Res1_2X, tr("0.5X (360p/540p) [EXPERIMENTAL]")),
+ PAIR(ResolutionSetup, Res3_4X, tr("0.75X (540p/810p) [EXPERIMENTAL]")),
+ PAIR(ResolutionSetup, Res1X, tr("1X (720p/1080p)")),
+ PAIR(ResolutionSetup, Res3_2X, tr("1.5X (1080p/1620p) [EXPERIMENTAL]")),
+ PAIR(ResolutionSetup, Res2X, tr("2X (1440p/2160p)")),
+ PAIR(ResolutionSetup, Res3X, tr("3X (2160p/3240p)")),
+ PAIR(ResolutionSetup, Res4X, tr("4X (2880p/4320p)")),
+ PAIR(ResolutionSetup, Res5X, tr("5X (3600p/5400p)")),
+ PAIR(ResolutionSetup, Res6X, tr("6X (4320p/6480p)")),
+ PAIR(ResolutionSetup, Res7X, tr("7X (5040p/7560p)")),
+ PAIR(ResolutionSetup, Res8X, tr("8X (5760p/8640p)")),
+ }});
translations->insert({Settings::EnumMetadata<Settings::ScalingFilter>::Index(),
{
- PAIR(ScalingFilter, NearestNeighbor, "Nearest Neighbor"),
- PAIR(ScalingFilter, Bilinear, "Bilinear"),
- PAIR(ScalingFilter, Bicubic, "Bicubic"),
- PAIR(ScalingFilter, Gaussian, "Gaussian"),
- PAIR(ScalingFilter, ScaleForce, "ScaleForce"),
- PAIR(ScalingFilter, Fsr, "AMD FidelityFX™️ Super Resolution"),
+ PAIR(ScalingFilter, NearestNeighbor, tr("Nearest Neighbor")),
+ PAIR(ScalingFilter, Bilinear, tr("Bilinear")),
+ PAIR(ScalingFilter, Bicubic, tr("Bicubic")),
+ PAIR(ScalingFilter, Gaussian, tr("Gaussian")),
+ PAIR(ScalingFilter, ScaleForce, tr("ScaleForce")),
+ PAIR(ScalingFilter, Fsr, tr("AMD FidelityFX™️ Super Resolution")),
}});
translations->insert({Settings::EnumMetadata<Settings::AntiAliasing>::Index(),
{
- PAIR(AntiAliasing, None, "None"),
- PAIR(AntiAliasing, Fxaa, "FXAA"),
- PAIR(AntiAliasing, Smaa, "SMAA"),
+ PAIR(AntiAliasing, None, tr("None")),
+ PAIR(AntiAliasing, Fxaa, tr("FXAA")),
+ PAIR(AntiAliasing, Smaa, tr("SMAA")),
}});
translations->insert({Settings::EnumMetadata<Settings::AspectRatio>::Index(),
{
- PAIR(AspectRatio, R16_9, "Default (16:9)"),
- PAIR(AspectRatio, R4_3, "Force 4:3"),
- PAIR(AspectRatio, R21_9, "Force 21:9"),
- PAIR(AspectRatio, R16_10, "Force 16:10"),
- PAIR(AspectRatio, Stretch, "Stretch to Window"),
+ PAIR(AspectRatio, R16_9, tr("Default (16:9)")),
+ PAIR(AspectRatio, R4_3, tr("Force 4:3")),
+ PAIR(AspectRatio, R21_9, tr("Force 21:9")),
+ PAIR(AspectRatio, R16_10, tr("Force 16:10")),
+ PAIR(AspectRatio, Stretch, tr("Stretch to Window")),
}});
translations->insert({Settings::EnumMetadata<Settings::AnisotropyMode>::Index(),
{
- PAIR(AnisotropyMode, Automatic, "Automatic"),
- PAIR(AnisotropyMode, Default, "Default"),
- PAIR(AnisotropyMode, X2, "2x"),
- PAIR(AnisotropyMode, X4, "4x"),
- PAIR(AnisotropyMode, X8, "8x"),
- PAIR(AnisotropyMode, X16, "16x"),
+ PAIR(AnisotropyMode, Automatic, tr("Automatic")),
+ PAIR(AnisotropyMode, Default, tr("Default")),
+ PAIR(AnisotropyMode, X2, tr("2x")),
+ PAIR(AnisotropyMode, X4, tr("4x")),
+ PAIR(AnisotropyMode, X8, tr("8x")),
+ PAIR(AnisotropyMode, X16, tr("16x")),
}});
translations->insert(
{Settings::EnumMetadata<Settings::Language>::Index(),
{
- PAIR(Language, Japanese, "Japanese (日本語)"),
- PAIR(Language, EnglishAmerican, "American English"),
- PAIR(Language, French, "French (français)"),
- PAIR(Language, German, "German (Deutsch)"),
- PAIR(Language, Italian, "Italian (italiano)"),
- PAIR(Language, Spanish, "Spanish (español)"),
- PAIR(Language, Chinese, "Chinese"),
- PAIR(Language, Korean, "Korean (한국어)"),
- PAIR(Language, Dutch, "Dutch (Nederlands)"),
- PAIR(Language, Portuguese, "Portuguese (português)"),
- PAIR(Language, Russian, "Russian (Русский)"),
- PAIR(Language, Taiwanese, "Taiwanese"),
- PAIR(Language, EnglishBritish, "British English"),
- PAIR(Language, FrenchCanadian, "Canadian French"),
- PAIR(Language, SpanishLatin, "Latin American Spanish"),
- PAIR(Language, ChineseSimplified, "Simplified Chinese"),
- PAIR(Language, ChineseTraditional, "Traditional Chinese (正體中文)"),
- PAIR(Language, PortugueseBrazilian, "Brazilian Portuguese (português do Brasil)"),
+ PAIR(Language, Japanese, tr("Japanese (日本語)")),
+ PAIR(Language, EnglishAmerican, tr("American English")),
+ PAIR(Language, French, tr("French (français)")),
+ PAIR(Language, German, tr("German (Deutsch)")),
+ PAIR(Language, Italian, tr("Italian (italiano)")),
+ PAIR(Language, Spanish, tr("Spanish (español)")),
+ PAIR(Language, Chinese, tr("Chinese")),
+ PAIR(Language, Korean, tr("Korean (한국어)")),
+ PAIR(Language, Dutch, tr("Dutch (Nederlands)")),
+ PAIR(Language, Portuguese, tr("Portuguese (português)")),
+ PAIR(Language, Russian, tr("Russian (Русский)")),
+ PAIR(Language, Taiwanese, tr("Taiwanese")),
+ PAIR(Language, EnglishBritish, tr("British English")),
+ PAIR(Language, FrenchCanadian, tr("Canadian French")),
+ PAIR(Language, SpanishLatin, tr("Latin American Spanish")),
+ PAIR(Language, ChineseSimplified, tr("Simplified Chinese")),
+ PAIR(Language, ChineseTraditional, tr("Traditional Chinese (正體中文)")),
+ PAIR(Language, PortugueseBrazilian, tr("Brazilian Portuguese (português do Brasil)")),
}});
translations->insert({Settings::EnumMetadata<Settings::Region>::Index(),
{
- PAIR(Region, Japan, "Japan"),
- PAIR(Region, Usa, "USA"),
- PAIR(Region, Europe, "Europe"),
- PAIR(Region, Australia, "Australia"),
- PAIR(Region, China, "China"),
- PAIR(Region, Korea, "Korea"),
- PAIR(Region, Taiwan, "Taiwan"),
+ PAIR(Region, Japan, tr("Japan")),
+ PAIR(Region, Usa, tr("USA")),
+ PAIR(Region, Europe, tr("Europe")),
+ PAIR(Region, Australia, tr("Australia")),
+ PAIR(Region, China, tr("China")),
+ PAIR(Region, Korea, tr("Korea")),
+ PAIR(Region, Taiwan, tr("Taiwan")),
}});
translations->insert(
{Settings::EnumMetadata<Settings::TimeZone>::Index(),
@@ -324,72 +340,74 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
{static_cast<u32>(Settings::TimeZone::Default),
tr("Default (%1)", "Default time zone")
.arg(QString::fromStdString(Common::TimeZone::GetDefaultTimeZone()))},
- PAIR(TimeZone, Cet, "CET"),
- PAIR(TimeZone, Cst6Cdt, "CST6CDT"),
- PAIR(TimeZone, Cuba, "Cuba"),
- PAIR(TimeZone, Eet, "EET"),
- PAIR(TimeZone, Egypt, "Egypt"),
- PAIR(TimeZone, Eire, "Eire"),
- PAIR(TimeZone, Est, "EST"),
- PAIR(TimeZone, Est5Edt, "EST5EDT"),
- PAIR(TimeZone, Gb, "GB"),
- PAIR(TimeZone, GbEire, "GB-Eire"),
- PAIR(TimeZone, Gmt, "GMT"),
- PAIR(TimeZone, GmtPlusZero, "GMT+0"),
- PAIR(TimeZone, GmtMinusZero, "GMT-0"),
- PAIR(TimeZone, GmtZero, "GMT0"),
- PAIR(TimeZone, Greenwich, "Greenwich"),
- PAIR(TimeZone, Hongkong, "Hongkong"),
- PAIR(TimeZone, Hst, "HST"),
- PAIR(TimeZone, Iceland, "Iceland"),
- PAIR(TimeZone, Iran, "Iran"),
- PAIR(TimeZone, Israel, "Israel"),
- PAIR(TimeZone, Jamaica, "Jamaica"),
- PAIR(TimeZone, Japan, "Japan"),
- PAIR(TimeZone, Kwajalein, "Kwajalein"),
- PAIR(TimeZone, Libya, "Libya"),
- PAIR(TimeZone, Met, "MET"),
- PAIR(TimeZone, Mst, "MST"),
- PAIR(TimeZone, Mst7Mdt, "MST7MDT"),
- PAIR(TimeZone, Navajo, "Navajo"),
- PAIR(TimeZone, Nz, "NZ"),
- PAIR(TimeZone, NzChat, "NZ-CHAT"),
- PAIR(TimeZone, Poland, "Poland"),
- PAIR(TimeZone, Portugal, "Portugal"),
- PAIR(TimeZone, Prc, "PRC"),
- PAIR(TimeZone, Pst8Pdt, "PST8PDT"),
- PAIR(TimeZone, Roc, "ROC"),
- PAIR(TimeZone, Rok, "ROK"),
- PAIR(TimeZone, Singapore, "Singapore"),
- PAIR(TimeZone, Turkey, "Turkey"),
- PAIR(TimeZone, Uct, "UCT"),
- PAIR(TimeZone, Universal, "Universal"),
- PAIR(TimeZone, Utc, "UTC"),
- PAIR(TimeZone, WSu, "W-SU"),
- PAIR(TimeZone, Wet, "WET"),
- PAIR(TimeZone, Zulu, "Zulu"),
+ PAIR(TimeZone, Cet, tr("CET")),
+ PAIR(TimeZone, Cst6Cdt, tr("CST6CDT")),
+ PAIR(TimeZone, Cuba, tr("Cuba")),
+ PAIR(TimeZone, Eet, tr("EET")),
+ PAIR(TimeZone, Egypt, tr("Egypt")),
+ PAIR(TimeZone, Eire, tr("Eire")),
+ PAIR(TimeZone, Est, tr("EST")),
+ PAIR(TimeZone, Est5Edt, tr("EST5EDT")),
+ PAIR(TimeZone, Gb, tr("GB")),
+ PAIR(TimeZone, GbEire, tr("GB-Eire")),
+ PAIR(TimeZone, Gmt, tr("GMT")),
+ PAIR(TimeZone, GmtPlusZero, tr("GMT+0")),
+ PAIR(TimeZone, GmtMinusZero, tr("GMT-0")),
+ PAIR(TimeZone, GmtZero, tr("GMT0")),
+ PAIR(TimeZone, Greenwich, tr("Greenwich")),
+ PAIR(TimeZone, Hongkong, tr("Hongkong")),
+ PAIR(TimeZone, Hst, tr("HST")),
+ PAIR(TimeZone, Iceland, tr("Iceland")),
+ PAIR(TimeZone, Iran, tr("Iran")),
+ PAIR(TimeZone, Israel, tr("Israel")),
+ PAIR(TimeZone, Jamaica, tr("Jamaica")),
+ PAIR(TimeZone, Japan, tr("Japan")),
+ PAIR(TimeZone, Kwajalein, tr("Kwajalein")),
+ PAIR(TimeZone, Libya, tr("Libya")),
+ PAIR(TimeZone, Met, tr("MET")),
+ PAIR(TimeZone, Mst, tr("MST")),
+ PAIR(TimeZone, Mst7Mdt, tr("MST7MDT")),
+ PAIR(TimeZone, Navajo, tr("Navajo")),
+ PAIR(TimeZone, Nz, tr("NZ")),
+ PAIR(TimeZone, NzChat, tr("NZ-CHAT")),
+ PAIR(TimeZone, Poland, tr("Poland")),
+ PAIR(TimeZone, Portugal, tr("Portugal")),
+ PAIR(TimeZone, Prc, tr("PRC")),
+ PAIR(TimeZone, Pst8Pdt, tr("PST8PDT")),
+ PAIR(TimeZone, Roc, tr("ROC")),
+ PAIR(TimeZone, Rok, tr("ROK")),
+ PAIR(TimeZone, Singapore, tr("Singapore")),
+ PAIR(TimeZone, Turkey, tr("Turkey")),
+ PAIR(TimeZone, Uct, tr("UCT")),
+ PAIR(TimeZone, Universal, tr("Universal")),
+ PAIR(TimeZone, Utc, tr("UTC")),
+ PAIR(TimeZone, WSu, tr("W-SU")),
+ PAIR(TimeZone, Wet, tr("WET")),
+ PAIR(TimeZone, Zulu, tr("Zulu")),
}});
translations->insert({Settings::EnumMetadata<Settings::AudioMode>::Index(),
{
- PAIR(AudioMode, Mono, "Mono"),
- PAIR(AudioMode, Stereo, "Stereo"),
- PAIR(AudioMode, Surround, "Surround"),
+ PAIR(AudioMode, Mono, tr("Mono")),
+ PAIR(AudioMode, Stereo, tr("Stereo")),
+ PAIR(AudioMode, Surround, tr("Surround")),
}});
translations->insert({Settings::EnumMetadata<Settings::MemoryLayout>::Index(),
{
- PAIR(MemoryLayout, Memory_4Gb, "4GB DRAM (Default)"),
- PAIR(MemoryLayout, Memory_6Gb, "6GB DRAM (Unsafe)"),
- PAIR(MemoryLayout, Memory_8Gb, "8GB DRAM (Unsafe)"),
+ PAIR(MemoryLayout, Memory_4Gb, tr("4GB DRAM (Default)")),
+ PAIR(MemoryLayout, Memory_6Gb, tr("6GB DRAM (Unsafe)")),
+ PAIR(MemoryLayout, Memory_8Gb, tr("8GB DRAM (Unsafe)")),
+ }});
+ translations->insert({Settings::EnumMetadata<Settings::ConsoleMode>::Index(),
+ {
+ PAIR(ConsoleMode, Docked, tr("Docked")),
+ PAIR(ConsoleMode, Handheld, tr("Handheld")),
}});
- translations->insert(
- {Settings::EnumMetadata<Settings::ConsoleMode>::Index(),
- {PAIR(ConsoleMode, Docked, "Docked"), PAIR(ConsoleMode, Handheld, "Handheld")}});
translations->insert(
{Settings::EnumMetadata<Settings::ConfirmStop>::Index(),
{
- PAIR(ConfirmStop, Ask_Always, "Always ask (Default)"),
- PAIR(ConfirmStop, Ask_Based_On_Game, "Only if game specifies not to stop"),
- PAIR(ConfirmStop, Ask_Never, "Never ask"),
+ PAIR(ConfirmStop, Ask_Always, tr("Always ask (Default)")),
+ PAIR(ConfirmStop, Ask_Based_On_Game, tr("Only if game specifies not to stop")),
+ PAIR(ConfirmStop, Ask_Never, tr("Never ask")),
}});
#undef PAIR
diff --git a/src/yuzu/configuration/shared_translation.h b/src/yuzu/configuration/shared_translation.h
index 99a0e808c..d5fc3b8de 100644
--- a/src/yuzu/configuration/shared_translation.h
+++ b/src/yuzu/configuration/shared_translation.h
@@ -10,6 +10,7 @@
#include <vector>
#include <QString>
#include "common/common_types.h"
+#include "common/settings.h"
class QWidget;
@@ -22,4 +23,46 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent);
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent);
+static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map = {
+ {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))},
+ {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))},
+ {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))},
+};
+
+static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map = {
+ {Settings::ScalingFilter::NearestNeighbor,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))},
+ {Settings::ScalingFilter::Bilinear,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))},
+ {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))},
+ {Settings::ScalingFilter::Gaussian,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))},
+ {Settings::ScalingFilter::ScaleForce,
+ QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))},
+ {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
+};
+
+static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map = {
+ {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
+ {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
+};
+
+static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map = {
+ {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))},
+ {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))},
+ {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))},
+};
+
+static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map = {
+ {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))},
+ {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))},
+ {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
+};
+
+static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map = {
+ {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))},
+ {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))},
+ {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))},
+};
+
} // namespace ConfigurationShared
diff --git a/src/yuzu/configuration/shared_widget.cpp b/src/yuzu/configuration/shared_widget.cpp
index ea8d7add4..941683a43 100644
--- a/src/yuzu/configuration/shared_widget.cpp
+++ b/src/yuzu/configuration/shared_widget.cpp
@@ -194,7 +194,7 @@ QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
return group;
}
- const auto get_selected = [=]() -> int {
+ const auto get_selected = [this]() -> int {
for (const auto& [id, button] : radio_buttons) {
if (button->isChecked()) {
return id;
@@ -203,7 +203,7 @@ QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
return -1;
};
- const auto set_index = [=](u32 value) {
+ const auto set_index = [this](u32 value) {
for (const auto& [id, button] : radio_buttons) {
button->setChecked(id == value);
}
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 7049c57b6..6d227ef8d 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -36,10 +36,8 @@ constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{
bool IsDarkTheme() {
const auto& theme = UISettings::values.theme;
- return theme == QStringLiteral("qdarkstyle") ||
- theme == QStringLiteral("qdarkstyle_midnight_blue") ||
- theme == QStringLiteral("colorful_dark") ||
- theme == QStringLiteral("colorful_midnight_blue");
+ return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
+ theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
}
} // namespace
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 7e7d8e252..59b317135 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -278,7 +278,7 @@ void GameList::OnUpdateThemedIcons() {
case GameListItemType::CustomDir: {
const UISettings::GameDir& game_dir =
UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()];
- const QString icon_name = QFileInfo::exists(game_dir.path)
+ const QString icon_name = QFileInfo::exists(QString::fromStdString(game_dir.path))
? QStringLiteral("folder")
: QStringLiteral("bad_folder");
child->setData(
@@ -567,9 +567,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
QAction* verify_integrity = context_menu.addAction(tr("Verify Integrity"));
QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard"));
QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
+// TODO: Implement shortcut creation for macOS
+#if !defined(__APPLE__)
QMenu* shortcut_menu = context_menu.addMenu(tr("Create Shortcut"));
QAction* create_desktop_shortcut = shortcut_menu->addAction(tr("Add to Desktop"));
-#ifndef WIN32
QAction* create_applications_menu_shortcut =
shortcut_menu->addAction(tr("Add to Applications Menu"));
#endif
@@ -647,10 +648,11 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() {
emit NavigateToGamedbEntryRequested(program_id, compatibility_list);
});
+// TODO: Implement shortcut creation for macOS
+#if !defined(__APPLE__)
connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() {
emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop);
});
-#ifndef WIN32
connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() {
emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications);
});
@@ -725,7 +727,8 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) {
});
connect(open_directory_location, &QAction::triggered, [this, game_dir_index] {
- emit OpenDirectory(UISettings::values.game_dirs[game_dir_index].path);
+ emit OpenDirectory(
+ QString::fromStdString(UISettings::values.game_dirs[game_dir_index].path));
});
}
@@ -867,7 +870,7 @@ const QStringList GameList::supported_file_extensions = {
QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")};
void GameList::RefreshGameDirectory() {
- if (!UISettings::values.game_dirs.isEmpty() && current_worker != nullptr) {
+ if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
PopulateAsync(UISettings::values.game_dirs);
}
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index 86a0c41d9..c330b574f 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -286,13 +286,13 @@ public:
setData(QObject::tr("System Titles"), Qt::DisplayRole);
break;
case GameListItemType::CustomDir: {
- const QString icon_name = QFileInfo::exists(game_dir->path)
- ? QStringLiteral("folder")
- : QStringLiteral("bad_folder");
+ const QString path = QString::fromStdString(game_dir->path);
+ const QString icon_name =
+ QFileInfo::exists(path) ? QStringLiteral("folder") : QStringLiteral("bad_folder");
setData(QIcon::fromTheme(icon_name).pixmap(icon_size).scaled(
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
- setData(game_dir->path, Qt::DisplayRole);
+ setData(path, Qt::DisplayRole);
break;
}
default:
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 69be21027..dc006832e 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -456,29 +456,29 @@ void GameListWorker::run() {
break;
}
- if (game_dir.path == QStringLiteral("SDMC")) {
+ if (game_dir.path == std::string("SDMC")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
- } else if (game_dir.path == QStringLiteral("UserNAND")) {
+ } else if (game_dir.path == std::string("UserNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
- } else if (game_dir.path == QStringLiteral("SysNAND")) {
+ } else if (game_dir.path == std::string("SysNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
} else {
- watch_list.append(game_dir.path);
+ watch_list.append(QString::fromStdString(game_dir.path));
auto* const game_list_dir = new GameListDir(game_dir);
DirEntryReady(game_list_dir);
- ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(),
- game_dir.deep_scan, game_list_dir);
- ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(),
- game_dir.deep_scan, game_list_dir);
+ ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan,
+ game_list_dir);
+ ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan,
+ game_list_dir);
}
}
- RecordEvent([=](GameList* game_list) { game_list->DonePopulating(watch_list); });
+ RecordEvent([this](GameList* game_list) { game_list->DonePopulating(watch_list); });
processing_completed.Set();
}
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp
index 6530186c1..eebfbf155 100644
--- a/src/yuzu/hotkeys.cpp
+++ b/src/yuzu/hotkeys.cpp
@@ -19,7 +19,7 @@ void HotkeyRegistry::SaveHotkeys() {
for (const auto& hotkey : group.second) {
UISettings::values.shortcuts.push_back(
{hotkey.first, group.first,
- UISettings::ContextualShortcut({hotkey.second.keyseq.toString(),
+ UISettings::ContextualShortcut({hotkey.second.keyseq.toString().toStdString(),
hotkey.second.controller_keyseq,
hotkey.second.context, hotkey.second.repeat})});
}
@@ -31,12 +31,12 @@ void HotkeyRegistry::LoadHotkeys() {
// beginGroup()
for (auto shortcut : UISettings::values.shortcuts) {
Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name];
- if (!shortcut.shortcut.keyseq.isEmpty()) {
- hk.keyseq =
- QKeySequence::fromString(shortcut.shortcut.keyseq, QKeySequence::NativeText);
+ if (!shortcut.shortcut.keyseq.empty()) {
+ hk.keyseq = QKeySequence::fromString(QString::fromStdString(shortcut.shortcut.keyseq),
+ QKeySequence::NativeText);
hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.context);
}
- if (!shortcut.shortcut.controller_keyseq.isEmpty()) {
+ if (!shortcut.shortcut.controller_keyseq.empty()) {
hk.controller_keyseq = shortcut.shortcut.controller_keyseq;
}
if (hk.shortcut) {
@@ -51,7 +51,8 @@ void HotkeyRegistry::LoadHotkeys() {
}
}
-QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) {
+QShortcut* HotkeyRegistry::GetHotkey(const std::string& group, const std::string& action,
+ QWidget* widget) {
Hotkey& hk = hotkey_groups[group][action];
if (!hk.shortcut) {
@@ -62,7 +63,8 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action
return hk.shortcut;
}
-ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, const QString& action,
+ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const std::string& group,
+ const std::string& action,
Core::HID::EmulatedController* controller) {
Hotkey& hk = hotkey_groups[group][action];
@@ -74,12 +76,12 @@ ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, co
return hk.controller_shortcut;
}
-QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) {
+QKeySequence HotkeyRegistry::GetKeySequence(const std::string& group, const std::string& action) {
return hotkey_groups[group][action].keyseq;
}
-Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group,
- const QString& action) {
+Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const std::string& group,
+ const std::string& action) {
return hotkey_groups[group][action].context;
}
@@ -101,10 +103,10 @@ void ControllerShortcut::SetKey(const ControllerButtonSequence& buttons) {
button_sequence = buttons;
}
-void ControllerShortcut::SetKey(const QString& buttons_shortcut) {
+void ControllerShortcut::SetKey(const std::string& buttons_shortcut) {
ControllerButtonSequence sequence{};
- name = buttons_shortcut.toStdString();
- std::istringstream command_line(buttons_shortcut.toStdString());
+ name = buttons_shortcut;
+ std::istringstream command_line(buttons_shortcut);
std::string line;
while (std::getline(command_line, line, '+')) {
if (line.empty()) {
diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h
index 56eee8d82..e11332d2e 100644
--- a/src/yuzu/hotkeys.h
+++ b/src/yuzu/hotkeys.h
@@ -33,7 +33,7 @@ public:
~ControllerShortcut();
void SetKey(const ControllerButtonSequence& buttons);
- void SetKey(const QString& buttons_shortcut);
+ void SetKey(const std::string& buttons_shortcut);
ControllerButtonSequence ButtonSequence() const;
@@ -88,8 +88,8 @@ public:
* will be the same. Thus, you shouldn't rely on the caller really being the
* QShortcut's parent.
*/
- QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget);
- ControllerShortcut* GetControllerHotkey(const QString& group, const QString& action,
+ QShortcut* GetHotkey(const std::string& group, const std::string& action, QWidget* widget);
+ ControllerShortcut* GetControllerHotkey(const std::string& group, const std::string& action,
Core::HID::EmulatedController* controller);
/**
@@ -98,7 +98,7 @@ public:
* @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger").
* @param action Name of the action (e.g. "Start Emulation", "Load Image").
*/
- QKeySequence GetKeySequence(const QString& group, const QString& action);
+ QKeySequence GetKeySequence(const std::string& group, const std::string& action);
/**
* Returns a Qt::ShortcutContext object who can be connected to other
@@ -108,20 +108,20 @@ public:
* "Debugger").
* @param action Name of the action (e.g. "Start Emulation", "Load Image").
*/
- Qt::ShortcutContext GetShortcutContext(const QString& group, const QString& action);
+ Qt::ShortcutContext GetShortcutContext(const std::string& group, const std::string& action);
private:
struct Hotkey {
QKeySequence keyseq;
- QString controller_keyseq;
+ std::string controller_keyseq;
QShortcut* shortcut = nullptr;
ControllerShortcut* controller_shortcut = nullptr;
Qt::ShortcutContext context = Qt::WindowShortcut;
bool repeat;
};
- using HotkeyMap = std::map<QString, Hotkey>;
- using HotkeyGroupMap = std::map<QString, HotkeyMap>;
+ using HotkeyMap = std::map<std::string, Hotkey>;
+ using HotkeyGroupMap = std::map<std::string, HotkeyMap>;
HotkeyGroupMap hotkey_groups;
};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 0df163029..dcf68460a 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -10,6 +10,7 @@
#include <thread>
#include "core/loader/nca.h"
#include "core/tools/renderdoc.h"
+
#ifdef __APPLE__
#include <unistd.h> // for chdir
#endif
@@ -46,6 +47,7 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/set/set_sys.h"
#include "yuzu/multiplayer/state.h"
#include "yuzu/util/controller_navigation.h"
@@ -127,6 +129,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "core/loader/loader.h"
#include "core/perf_stats.h"
#include "core/telemetry_session.h"
+#include "frontend_common/config.h"
#include "input_common/drivers/tas_input.h"
#include "input_common/drivers/virtual_amiibo.h"
#include "input_common/main.h"
@@ -139,9 +142,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "yuzu/bootmanager.h"
#include "yuzu/compatdb.h"
#include "yuzu/compatibility_list.h"
-#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_dialog.h"
#include "yuzu/configuration/configure_input_per_game.h"
+#include "yuzu/configuration/qt_config.h"
#include "yuzu/debugger/console.h"
#include "yuzu/debugger/controller.h"
#include "yuzu/debugger/profiler.h"
@@ -310,7 +313,7 @@ bool GMainWindow::CheckDarkMode() {
#endif // __unix__
}
-GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan)
+GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan)
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)},
vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
@@ -675,7 +678,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers(
// Don't forget to apply settings.
system->HIDCore().DisableAllControllerConfiguration();
system->ApplySettings();
- config->Save();
+ config->SaveAllValues();
UpdateStatusButtons();
@@ -1046,7 +1049,12 @@ void GMainWindow::InitializeWidgets() {
statusBar()->addPermanentWidget(label);
}
- // TODO (flTobi): Add the widget when multiplayer is fully implemented
+ firmware_label = new QLabel();
+ firmware_label->setObjectName(QStringLiteral("FirmwareLabel"));
+ firmware_label->setVisible(false);
+ firmware_label->setFocusPolicy(Qt::NoFocus);
+ statusBar()->addPermanentWidget(firmware_label);
+
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0);
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0);
@@ -1064,12 +1072,6 @@ void GMainWindow::InitializeWidgets() {
volume_slider->setObjectName(QStringLiteral("volume_slider"));
volume_slider->setMaximum(200);
volume_slider->setPageStep(5);
- connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) {
- Settings::values.audio_muted = false;
- const auto volume = static_cast<u8>(percentage);
- Settings::values.volume.SetValue(volume);
- UpdateVolumeUI();
- });
volume_popup->layout()->addWidget(volume_slider);
volume_button = new VolumeButton();
@@ -1077,6 +1079,12 @@ void GMainWindow::InitializeWidgets() {
volume_button->setFocusPolicy(Qt::NoFocus);
volume_button->setCheckable(true);
UpdateVolumeUI();
+ connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) {
+ Settings::values.audio_muted = false;
+ const auto volume = static_cast<u8>(percentage);
+ Settings::values.volume.SetValue(volume);
+ UpdateVolumeUI();
+ });
connect(volume_button, &QPushButton::clicked, this, [&] {
UpdateVolumeUI();
volume_popup->setVisible(!volume_popup->isVisible());
@@ -1128,7 +1136,7 @@ void GMainWindow::InitializeWidgets() {
connect(aa_status_button, &QPushButton::customContextMenuRequested,
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& aa_text_pair : Config::anti_aliasing_texts_map) {
+ for (auto const& aa_text_pair : ConfigurationShared::anti_aliasing_texts_map) {
context_menu.addAction(aa_text_pair.second, [this, aa_text_pair] {
Settings::values.anti_aliasing.SetValue(aa_text_pair.first);
UpdateAAText();
@@ -1152,7 +1160,7 @@ void GMainWindow::InitializeWidgets() {
connect(filter_status_button, &QPushButton::customContextMenuRequested,
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& filter_text_pair : Config::scaling_filter_texts_map) {
+ for (auto const& filter_text_pair : ConfigurationShared::scaling_filter_texts_map) {
context_menu.addAction(filter_text_pair.second, [this, filter_text_pair] {
Settings::values.scaling_filter.SetValue(filter_text_pair.first);
UpdateFilterText();
@@ -1175,7 +1183,7 @@ void GMainWindow::InitializeWidgets() {
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& pair : Config::use_docked_mode_texts_map) {
+ for (auto const& pair : ConfigurationShared::use_docked_mode_texts_map) {
context_menu.addAction(pair.second, [this, &pair] {
if (pair.first != Settings::values.use_docked_mode.GetValue()) {
OnToggleDockedMode();
@@ -1199,7 +1207,7 @@ void GMainWindow::InitializeWidgets() {
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& gpu_accuracy_pair : Config::gpu_accuracy_texts_map) {
+ for (auto const& gpu_accuracy_pair : ConfigurationShared::gpu_accuracy_texts_map) {
if (gpu_accuracy_pair.first == Settings::GpuAccuracy::Extreme) {
continue;
}
@@ -1228,7 +1236,8 @@ void GMainWindow::InitializeWidgets() {
[this](const QPoint& menu_location) {
QMenu context_menu;
- for (auto const& renderer_backend_pair : Config::renderer_backend_texts_map) {
+ for (auto const& renderer_backend_pair :
+ ConfigurationShared::renderer_backend_texts_map) {
if (renderer_backend_pair.first == Settings::RendererBackend::Null) {
continue;
}
@@ -1293,16 +1302,17 @@ void GMainWindow::InitializeRecentFileMenuActions() {
void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name,
const bool tas_allowed) {
- static const QString main_window = QStringLiteral("Main Window");
- action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name));
- action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name));
+ static const auto main_window = std::string("Main Window");
+ action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name.toStdString()));
+ action->setShortcutContext(
+ hotkey_registry.GetShortcutContext(main_window, action_name.toStdString()));
action->setAutoRepeat(false);
this->addAction(action);
auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
const auto* controller_hotkey =
- hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
+ hotkey_registry.GetControllerHotkey(main_window, action_name.toStdString(), controller);
connect(
controller_hotkey, &ControllerShortcut::Activated, this,
[action, tas_allowed, this] {
@@ -1334,10 +1344,11 @@ void GMainWindow::InitializeHotkeys() {
static const QString main_window = QStringLiteral("Main Window");
const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) {
- const auto* hotkey = hotkey_registry.GetHotkey(main_window, action_name, this);
+ const auto* hotkey =
+ hotkey_registry.GetHotkey(main_window.toStdString(), action_name.toStdString(), this);
auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
- const auto* controller_hotkey =
- hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
+ const auto* controller_hotkey = hotkey_registry.GetControllerHotkey(
+ main_window.toStdString(), action_name.toStdString(), controller);
connect(hotkey, &QShortcut::activated, this, function);
connect(controller_hotkey, &ControllerShortcut::Activated, this, function,
Qt::QueuedConnection);
@@ -1574,6 +1585,7 @@ void GMainWindow::ConnectMenuEvents() {
connect_menu(ui->action_Load_Cabinet_Formatter,
[this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
+ connect_menu(ui->action_Open_Controller_Menu, &GMainWindow::OnOpenControllerMenu);
connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
// TAS
@@ -1601,14 +1613,13 @@ void GMainWindow::UpdateMenuState() {
ui->action_Pause,
};
- const std::array applet_actions{
- ui->action_Load_Album,
- ui->action_Load_Cabinet_Nickname_Owner,
- ui->action_Load_Cabinet_Eraser,
- ui->action_Load_Cabinet_Restorer,
- ui->action_Load_Cabinet_Formatter,
- ui->action_Load_Mii_Edit,
- };
+ const std::array applet_actions{ui->action_Load_Album,
+ ui->action_Load_Cabinet_Nickname_Owner,
+ ui->action_Load_Cabinet_Eraser,
+ ui->action_Load_Cabinet_Restorer,
+ ui->action_Load_Cabinet_Formatter,
+ ui->action_Load_Mii_Edit,
+ ui->action_Open_Controller_Menu};
for (QAction* action : running_actions) {
action->setEnabled(emulation_running);
@@ -1908,12 +1919,16 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
StartGameType type, AmLaunchType launch_type) {
LOG_INFO(Frontend, "yuzu starting...");
- StoreRecentFile(filename); // Put the filename on top of the list
+
+ if (program_id == 0 ||
+ program_id > static_cast<u64>(Service::AM::Applets::AppletProgramId::MaxProgramId)) {
+ StoreRecentFile(filename); // Put the filename on top of the list
+ }
// Save configurations
UpdateUISettings();
game_list->SaveInterfaceLayout();
- config->Save();
+ config->SaveAllValues();
u64 title_id{0};
@@ -1931,7 +1946,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
const auto config_file_name = title_id == 0
? Common::FS::PathToUTF8String(file_path.filename())
: fmt::format("{:016X}", title_id);
- Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
+ QtConfig per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
system->HIDCore().ReloadInputDevices();
system->ApplySettings();
}
@@ -2156,6 +2171,10 @@ void GMainWindow::OnEmulationStopped() {
emu_frametime_label->setVisible(false);
renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan);
+ if (!firmware_label->text().isEmpty()) {
+ firmware_label->setVisible(true);
+ }
+
current_game_path.clear();
// When closing the game, destroy the GLWindow to clear the context after the game is closed
@@ -2174,6 +2193,7 @@ void GMainWindow::ShutdownGame() {
return;
}
+ play_time_manager->Stop();
OnShutdownBegin();
OnEmulationStopTimeExpired();
OnEmulationStopped();
@@ -2737,7 +2757,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
return;
}
- const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full);
+ const auto extracted = FileSys::ExtractRomFS(romfs);
if (extracted == nullptr) {
failed();
return;
@@ -2842,170 +2862,259 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory));
}
-void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path,
- GameListShortcutTarget target) {
- // Get path to yuzu executable
- const QStringList args = QApplication::arguments();
- std::filesystem::path yuzu_command = args[0].toStdString();
-
- // If relative path, make it an absolute path
- if (yuzu_command.c_str()[0] == '.') {
- yuzu_command = Common::FS::GetCurrentDir() / yuzu_command;
+bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
+ const std::string& comment,
+ const std::filesystem::path& icon_path,
+ const std::filesystem::path& command,
+ const std::string& arguments, const std::string& categories,
+ const std::string& keywords, const std::string& name) try {
+#if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD
+ std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop");
+ std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc);
+ if (!shortcut_stream.is_open()) {
+ LOG_ERROR(Frontend, "Failed to create shortcut");
+ return false;
}
-
-#if defined(__linux__)
- // Warn once if we are making a shortcut to a volatile AppImage
- const std::string appimage_ending =
- std::string(Common::g_scm_rev).substr(0, 9).append(".AppImage");
- if (yuzu_command.string().ends_with(appimage_ending) &&
- !UISettings::values.shortcut_already_warned) {
- if (QMessageBox::warning(this, tr("Create Shortcut"),
- tr("This will create a shortcut to the current AppImage. This may "
- "not work well if you update. Continue?"),
- QMessageBox::StandardButton::Ok |
- QMessageBox::StandardButton::Cancel) ==
- QMessageBox::StandardButton::Cancel) {
- return;
+ // TODO: Migrate fmt::print to std::print in futures STD C++ 23.
+ fmt::print(shortcut_stream, "[Desktop Entry]\n");
+ fmt::print(shortcut_stream, "Type=Application\n");
+ fmt::print(shortcut_stream, "Version=1.0\n");
+ fmt::print(shortcut_stream, "Name={}\n", name);
+ if (!comment.empty()) {
+ fmt::print(shortcut_stream, "Comment={}\n", comment);
+ }
+ if (std::filesystem::is_regular_file(icon_path)) {
+ fmt::print(shortcut_stream, "Icon={}\n", icon_path.string());
+ }
+ fmt::print(shortcut_stream, "TryExec={}\n", command.string());
+ fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments);
+ if (!categories.empty()) {
+ fmt::print(shortcut_stream, "Categories={}\n", categories);
+ }
+ if (!keywords.empty()) {
+ fmt::print(shortcut_stream, "Keywords={}\n", keywords);
+ }
+ return true;
+#elif defined(_WIN32) // Windows
+ HRESULT hr = CoInitialize(nullptr);
+ if (FAILED(hr)) {
+ LOG_ERROR(Frontend, "CoInitialize failed");
+ return false;
+ }
+ SCOPE_EXIT({ CoUninitialize(); });
+ IShellLinkW* ps1 = nullptr;
+ IPersistFile* persist_file = nullptr;
+ SCOPE_EXIT({
+ if (persist_file != nullptr) {
+ persist_file->Release();
}
- UISettings::values.shortcut_already_warned = true;
+ if (ps1 != nullptr) {
+ ps1->Release();
+ }
+ });
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
+ reinterpret_cast<void**>(&ps1));
+ if (FAILED(hres)) {
+ LOG_ERROR(Frontend, "Failed to create IShellLinkW instance");
+ return false;
}
-#endif // __linux__
-
- std::filesystem::path target_directory{};
-
- switch (target) {
- case GameListShortcutTarget::Desktop: {
- const QString desktop_path =
- QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
- target_directory = desktop_path.toUtf8().toStdString();
- break;
+ hres = ps1->SetPath(command.c_str());
+ if (FAILED(hres)) {
+ LOG_ERROR(Frontend, "Failed to set path");
+ return false;
}
- case GameListShortcutTarget::Applications: {
- const QString applications_path =
- QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
- if (applications_path.isEmpty()) {
- const char* home = std::getenv("HOME");
- if (home != nullptr) {
- target_directory = std::filesystem::path(home) / ".local/share/applications";
- }
- } else {
- target_directory = applications_path.toUtf8().toStdString();
+ if (!arguments.empty()) {
+ hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data());
+ if (FAILED(hres)) {
+ LOG_ERROR(Frontend, "Failed to set arguments");
+ return false;
}
- break;
}
- default:
- return;
+ if (!comment.empty()) {
+ hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data());
+ if (FAILED(hres)) {
+ LOG_ERROR(Frontend, "Failed to set description");
+ return false;
+ }
}
-
- const QDir dir(QString::fromStdString(target_directory.generic_string()));
- if (!dir.exists()) {
- QMessageBox::critical(this, tr("Create Shortcut"),
- tr("Cannot create shortcut. Path \"%1\" does not exist.")
- .arg(QString::fromStdString(target_directory.generic_string())),
- QMessageBox::StandardButton::Ok);
- return;
+ if (std::filesystem::is_regular_file(icon_path)) {
+ hres = ps1->SetIconLocation(icon_path.c_str(), 0);
+ if (FAILED(hres)) {
+ LOG_ERROR(Frontend, "Failed to set icon location");
+ return false;
+ }
}
+ hres = ps1->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&persist_file));
+ if (FAILED(hres)) {
+ LOG_ERROR(Frontend, "Failed to get IPersistFile interface");
+ return false;
+ }
+ hres = persist_file->Save(std::filesystem::path{shortcut_path / (name + ".lnk")}.c_str(), TRUE);
+ if (FAILED(hres)) {
+ LOG_ERROR(Frontend, "Failed to save shortcut");
+ return false;
+ }
+ return true;
+#else // Unsupported platform
+ return false;
+#endif
+} catch (const std::exception& e) {
+ LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
+ return false;
+}
+// Messages in pre-defined message boxes for less code spaghetti
+bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) {
+ int result = 0;
+ QMessageBox::StandardButtons buttons;
+ switch (imsg) {
+ case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES:
+ buttons = QMessageBox::Yes | QMessageBox::No;
+ result =
+ QMessageBox::information(parent, tr("Create Shortcut"),
+ tr("Do you want to launch the game in fullscreen?"), buttons);
+ return result == QMessageBox::Yes;
+ case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS:
+ QMessageBox::information(parent, tr("Create Shortcut"),
+ tr("Successfully created a shortcut to %1").arg(game_title));
+ return false;
+ case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING:
+ buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel;
+ result =
+ QMessageBox::warning(this, tr("Create Shortcut"),
+ tr("This will create a shortcut to the current AppImage. This may "
+ "not work well if you update. Continue?"),
+ buttons);
+ return result == QMessageBox::Ok;
+ default:
+ buttons = QMessageBox::Ok;
+ QMessageBox::critical(parent, tr("Create Shortcut"),
+ tr("Failed to create a shortcut to %1").arg(game_title), buttons);
+ return false;
+ }
+}
- const std::string game_file_name = std::filesystem::path(game_path).filename().string();
- // Determine full paths for icon and shortcut
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
- const char* home = std::getenv("HOME");
- const std::filesystem::path home_path = (home == nullptr ? "~" : home);
- const char* xdg_data_home = std::getenv("XDG_DATA_HOME");
-
- std::filesystem::path system_icons_path =
- (xdg_data_home == nullptr ? home_path / ".local/share/"
- : std::filesystem::path(xdg_data_home)) /
- "icons/hicolor/256x256";
- if (!Common::FS::CreateDirs(system_icons_path)) {
+bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
+ std::filesystem::path& out_icon_path) {
+ // Get path to Yuzu icons directory & icon extension
+ std::string ico_extension = "png";
+#if defined(_WIN32)
+ out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::IconsDir);
+ ico_extension = "ico";
+#elif defined(__linux__) || defined(__FreeBSD__)
+ out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
+#endif
+ // Create icons directory if it doesn't exist
+ if (!Common::FS::CreateDirs(out_icon_path)) {
QMessageBox::critical(
this, tr("Create Icon"),
tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.")
- .arg(QString::fromStdString(system_icons_path)),
+ .arg(QString::fromStdString(out_icon_path.string())),
QMessageBox::StandardButton::Ok);
- return;
+ out_icon_path.clear();
+ return false;
}
- std::filesystem::path icon_path =
- system_icons_path / (program_id == 0 ? fmt::format("yuzu-{}.png", game_file_name)
- : fmt::format("yuzu-{:016X}.png", program_id));
- const std::filesystem::path shortcut_path =
- target_directory / (program_id == 0 ? fmt::format("yuzu-{}.desktop", game_file_name)
- : fmt::format("yuzu-{:016X}.desktop", program_id));
-#elif defined(WIN32)
- std::filesystem::path icons_path =
- Common::FS::GetYuzuPathString(Common::FS::YuzuPath::IconsDir);
- std::filesystem::path icon_path =
- icons_path / ((program_id == 0 ? fmt::format("yuzu-{}.ico", game_file_name)
- : fmt::format("yuzu-{:016X}.ico", program_id)));
-#else
- std::string icon_extension;
-#endif
-
- // Get title from game file
- const FileSys::PatchManager pm{program_id, system->GetFileSystemController(),
- system->GetContentProvider()};
- const auto control = pm.GetControlMetadata();
- const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
- std::string title{fmt::format("{:016X}", program_id)};
-
- if (control.first != nullptr) {
- title = control.first->GetApplicationName();
- } else {
- loader->ReadTitle(title);
- }
+ // Create icon file path
+ out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension)
+ : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
+ return true;
+}
- // Get icon from game file
- std::vector<u8> icon_image_file{};
- if (control.second != nullptr) {
- icon_image_file = control.second->ReadAllBytes();
- } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) {
- LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
+void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path,
+ GameListShortcutTarget target) {
+ std::string game_title;
+ QString qt_game_title;
+ std::filesystem::path out_icon_path;
+ // Get path to yuzu executable
+ const QStringList args = QApplication::arguments();
+ std::filesystem::path yuzu_command = args[0].toStdString();
+ // If relative path, make it an absolute path
+ if (yuzu_command.c_str()[0] == '.') {
+ yuzu_command = Common::FS::GetCurrentDir() / yuzu_command;
}
-
- QImage icon_data =
- QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
- // Convert and write the icon as a PNG
- if (!icon_data.save(QString::fromStdString(icon_path.string()))) {
- LOG_ERROR(Frontend, "Could not write icon as PNG to file");
+ // Shortcut path
+ std::filesystem::path shortcut_path{};
+ if (target == GameListShortcutTarget::Desktop) {
+ shortcut_path =
+ QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
+ } else if (target == GameListShortcutTarget::Applications) {
+ shortcut_path =
+ QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString();
+ }
+ // Icon path and title
+ if (std::filesystem::exists(shortcut_path)) {
+ // Get title from game file
+ const FileSys::PatchManager pm{program_id, system->GetFileSystemController(),
+ system->GetContentProvider()};
+ const auto control = pm.GetControlMetadata();
+ const auto loader =
+ Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
+ game_title = fmt::format("{:016X}", program_id);
+ if (control.first != nullptr) {
+ game_title = control.first->GetApplicationName();
+ } else {
+ loader->ReadTitle(game_title);
+ }
+ // Delete illegal characters from title
+ const std::string illegal_chars = "<>:\"/\\|?*.";
+ for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) {
+ if (illegal_chars.find(*it) != std::string::npos) {
+ game_title.erase(it.base() - 1);
+ }
+ }
+ qt_game_title = QString::fromStdString(game_title);
+ // Get icon from game file
+ std::vector<u8> icon_image_file{};
+ if (control.second != nullptr) {
+ icon_image_file = control.second->ReadAllBytes();
+ } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) {
+ LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
+ }
+ QImage icon_data =
+ QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
+ if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
+ if (!SaveIconToFile(out_icon_path, icon_data)) {
+ LOG_ERROR(Frontend, "Could not write icon to file");
+ }
+ }
} else {
- LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string());
- }
-#elif defined(WIN32)
- if (!SaveIconToFile(icon_path.string(), icon_data)) {
- LOG_ERROR(Frontend, "Could not write icon to file");
+ GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
+ qt_game_title);
+ LOG_ERROR(Frontend, "Invalid shortcut target");
return;
}
+#if defined(__linux__)
+ // Special case for AppImages
+ // Warn once if we are making a shortcut to a volatile AppImage
+ const std::string appimage_ending =
+ std::string(Common::g_scm_rev).substr(0, 9).append(".AppImage");
+ if (yuzu_command.string().ends_with(appimage_ending) &&
+ !UISettings::values.shortcut_already_warned) {
+ if (GMainWindow::CreateShortcutMessagesGUI(
+ this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, qt_game_title)) {
+ return;
+ }
+ UISettings::values.shortcut_already_warned = true;
+ }
#endif // __linux__
-
-#ifdef _WIN32
- // Replace characters that are illegal in Windows filenames by a dash
- const std::string illegal_chars = "<>:\"/\\|?*";
- for (char c : illegal_chars) {
- std::replace(title.begin(), title.end(), c, '_');
+ // Create shortcut
+ std::string arguments = fmt::format("-g \"{:s}\"", game_path);
+ if (GMainWindow::CreateShortcutMessagesGUI(
+ this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) {
+ arguments = "-f " + arguments;
}
- const std::filesystem::path shortcut_path = target_directory / (title + ".lnk").c_str();
-#endif
-
- const std::string comment =
- tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(title)).toStdString();
- const std::string arguments = fmt::format("-g \"{:s}\"", game_path);
+ const std::string comment = fmt::format("Start {:s} with the yuzu Emulator", game_title);
const std::string categories = "Game;Emulator;Qt;";
const std::string keywords = "Switch;Nintendo;";
- if (!CreateShortcut(shortcut_path.string(), title, comment, icon_path.string(),
- yuzu_command.string(), arguments, categories, keywords)) {
- QMessageBox::critical(this, tr("Create Shortcut"),
- tr("Failed to create a shortcut at %1")
- .arg(QString::fromStdString(shortcut_path.string())));
+ if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, yuzu_command,
+ arguments, categories, keywords, game_title)) {
+ GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS,
+ qt_game_title);
return;
}
-
- LOG_INFO(Frontend, "Wrote a shortcut to {}", shortcut_path.string());
- QMessageBox::information(
- this, tr("Create Shortcut"),
- tr("Successfully created a shortcut to %1").arg(QString::fromStdString(title)));
+ GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
+ qt_game_title);
}
void GMainWindow::OnGameListOpenDirectory(const QString& directory) {
@@ -3040,7 +3149,7 @@ void GMainWindow::OnGameListAddDirectory() {
return;
}
- UISettings::GameDir game_dir{dir_path, false, true};
+ UISettings::GameDir game_dir{dir_path.toStdString(), false, true};
if (!UISettings::values.game_dirs.contains(game_dir)) {
UISettings::values.game_dirs.append(game_dir);
game_list->PopulateAsync(UISettings::values.game_dirs);
@@ -3086,14 +3195,14 @@ void GMainWindow::OnMenuLoadFile() {
"%1 is an identifier for the Switch executable file extensions.")
.arg(extensions);
const QString filename = QFileDialog::getOpenFileName(
- this, tr("Load File"), UISettings::values.roms_path, file_filter);
+ this, tr("Load File"), QString::fromStdString(UISettings::values.roms_path), file_filter);
is_load_file_select_active = false;
if (filename.isEmpty()) {
return;
}
- UISettings::values.roms_path = QFileInfo(filename).path();
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename);
}
@@ -3126,7 +3235,8 @@ void GMainWindow::OnMenuInstallToNAND() {
"Image (*.xci)");
QStringList filenames = QFileDialog::getOpenFileNames(
- this, tr("Install Files"), UISettings::values.roms_path, file_filter);
+ this, tr("Install Files"), QString::fromStdString(UISettings::values.roms_path),
+ file_filter);
if (filenames.isEmpty()) {
return;
@@ -3144,7 +3254,7 @@ void GMainWindow::OnMenuInstallToNAND() {
}
// Save folder location of the first selected file
- UISettings::values.roms_path = QFileInfo(filenames[0]).path();
+ UISettings::values.roms_path = QFileInfo(filenames[0]).path().toStdString();
int remaining = filenames.size();
@@ -3484,12 +3594,12 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
}
void GMainWindow::OnExit() {
- OnStopGame();
+ ShutdownGame();
}
void GMainWindow::OnSaveConfig() {
system->ApplySettings();
- config->Save();
+ config->SaveAllValues();
}
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
@@ -3745,7 +3855,7 @@ void GMainWindow::OnConfigure() {
Settings::values.disabled_addons.clear();
- config = std::make_unique<Config>();
+ config = std::make_unique<QtConfig>();
UISettings::values.reset_to_defaults = false;
UISettings::values.game_dirs = std::move(old_game_dirs);
@@ -3780,7 +3890,7 @@ void GMainWindow::OnConfigure() {
UISettings::values.configuration_applied = false;
- config->Save();
+ config->SaveAllValues();
if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) {
render_window->installEventFilter(render_window);
@@ -3996,68 +4106,8 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file
UISettings::values.configuration_applied = false;
if (!is_powered_on) {
- config->Save();
- }
-}
-
-bool GMainWindow::CreateShortcut(const std::string& shortcut_path, const std::string& title,
- const std::string& comment, const std::string& icon_path,
- const std::string& command, const std::string& arguments,
- const std::string& categories, const std::string& keywords) {
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
- // This desktop file template was writing referencing
- // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
- std::string shortcut_contents{};
- shortcut_contents.append("[Desktop Entry]\n");
- shortcut_contents.append("Type=Application\n");
- shortcut_contents.append("Version=1.0\n");
- shortcut_contents.append(fmt::format("Name={:s}\n", title));
- shortcut_contents.append(fmt::format("Comment={:s}\n", comment));
- shortcut_contents.append(fmt::format("Icon={:s}\n", icon_path));
- shortcut_contents.append(fmt::format("TryExec={:s}\n", command));
- shortcut_contents.append(fmt::format("Exec={:s} {:s}\n", command, arguments));
- shortcut_contents.append(fmt::format("Categories={:s}\n", categories));
- shortcut_contents.append(fmt::format("Keywords={:s}\n", keywords));
-
- std::ofstream shortcut_stream(shortcut_path);
- if (!shortcut_stream.is_open()) {
- LOG_WARNING(Common, "Failed to create file {:s}", shortcut_path);
- return false;
+ config->SaveAllValues();
}
- shortcut_stream << shortcut_contents;
- shortcut_stream.close();
-
- return true;
-#elif defined(WIN32)
- IShellLinkW* shell_link;
- auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
- (void**)&shell_link);
- if (FAILED(hres)) {
- return false;
- }
- shell_link->SetPath(
- Common::UTF8ToUTF16W(command).data()); // Path to the object we are referring to
- shell_link->SetArguments(Common::UTF8ToUTF16W(arguments).data());
- shell_link->SetDescription(Common::UTF8ToUTF16W(comment).data());
- shell_link->SetIconLocation(Common::UTF8ToUTF16W(icon_path).data(), 0);
-
- IPersistFile* persist_file;
- hres = shell_link->QueryInterface(IID_IPersistFile, (void**)&persist_file);
- if (FAILED(hres)) {
- return false;
- }
-
- hres = persist_file->Save(Common::UTF8ToUTF16W(shortcut_path).data(), TRUE);
- if (FAILED(hres)) {
- return false;
- }
-
- persist_file->Release();
- shell_link->Release();
-
- return true;
-#endif
- return false;
}
void GMainWindow::OnLoadAmiibo() {
@@ -4098,7 +4148,6 @@ void GMainWindow::OnLoadAmiibo() {
bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton defaultButton) {
-
QMessageBox* box_dialog = new QMessageBox(parent);
box_dialog->setWindowTitle(title);
box_dialog->setText(text);
@@ -4272,7 +4321,7 @@ void GMainWindow::OnToggleStatusBar() {
}
void GMainWindow::OnAlbum() {
- constexpr u64 AlbumId = 0x010000000000100Dull;
+ constexpr u64 AlbumId = static_cast<u64>(Service::AM::Applets::AppletProgramId::PhotoViewer);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
QMessageBox::warning(this, tr("No firmware available"),
@@ -4290,12 +4339,12 @@ void GMainWindow::OnAlbum() {
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::PhotoViewer);
const auto filename = QString::fromStdString(album_nca->GetFullPath());
- UISettings::values.roms_path = QFileInfo(filename).path();
- BootGame(filename);
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
+ BootGame(filename, AlbumId);
}
void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
- constexpr u64 CabinetId = 0x0100000000001002ull;
+ constexpr u64 CabinetId = static_cast<u64>(Service::AM::Applets::AppletProgramId::Cabinet);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
QMessageBox::warning(this, tr("No firmware available"),
@@ -4314,12 +4363,12 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
system->GetAppletManager().SetCabinetMode(mode);
const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
- UISettings::values.roms_path = QFileInfo(filename).path();
- BootGame(filename);
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
+ BootGame(filename, CabinetId);
}
void GMainWindow::OnMiiEdit() {
- constexpr u64 MiiEditId = 0x0100000000001009ull;
+ constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
QMessageBox::warning(this, tr("No firmware available"),
@@ -4337,8 +4386,33 @@ void GMainWindow::OnMiiEdit() {
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit);
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
- UISettings::values.roms_path = QFileInfo(filename).path();
- BootGame(filename);
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
+ BootGame(filename, MiiEditId);
+}
+
+void GMainWindow::OnOpenControllerMenu() {
+ constexpr u64 ControllerAppletId =
+ static_cast<u64>(Service::AM::Applets::AppletProgramId::Controller);
+ auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
+ if (!bis_system) {
+ QMessageBox::warning(this, tr("No firmware available"),
+ tr("Please install the firmware to use the Controller Menu."));
+ return;
+ }
+
+ auto controller_applet_nca =
+ bis_system->GetEntry(ControllerAppletId, FileSys::ContentRecordType::Program);
+ if (!controller_applet_nca) {
+ QMessageBox::warning(this, tr("Controller Applet"),
+ tr("Controller Menu is not available. Please reinstall firmware."));
+ return;
+ }
+
+ system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller);
+
+ const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath()));
+ UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
+ BootGame(filename, ControllerAppletId);
}
void GMainWindow::OnCaptureScreenshot() {
@@ -4527,11 +4601,13 @@ void GMainWindow::UpdateStatusBar() {
emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());
game_fps_label->setVisible(true);
emu_frametime_label->setVisible(true);
+ firmware_label->setVisible(false);
}
void GMainWindow::UpdateGPUAccuracyButton() {
const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue();
- const auto gpu_accuracy_text = Config::gpu_accuracy_texts_map.find(gpu_accuracy)->second;
+ const auto gpu_accuracy_text =
+ ConfigurationShared::gpu_accuracy_texts_map.find(gpu_accuracy)->second;
gpu_accuracy_button->setText(gpu_accuracy_text.toUpper());
gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GpuAccuracy::Normal);
}
@@ -4540,31 +4616,32 @@ void GMainWindow::UpdateDockedButton() {
const auto console_mode = Settings::values.use_docked_mode.GetValue();
dock_status_button->setChecked(Settings::IsDockedMode());
dock_status_button->setText(
- Config::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
+ ConfigurationShared::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
}
void GMainWindow::UpdateAPIText() {
const auto api = Settings::values.renderer_backend.GetValue();
- const auto renderer_status_text = Config::renderer_backend_texts_map.find(api)->second;
+ const auto renderer_status_text =
+ ConfigurationShared::renderer_backend_texts_map.find(api)->second;
renderer_status_button->setText(
api == Settings::RendererBackend::OpenGL
- ? tr("%1 %2").arg(
- renderer_status_text.toUpper(),
- Config::shader_backend_texts_map.find(Settings::values.shader_backend.GetValue())
- ->second)
+ ? tr("%1 %2").arg(renderer_status_text.toUpper(),
+ ConfigurationShared::shader_backend_texts_map
+ .find(Settings::values.shader_backend.GetValue())
+ ->second)
: renderer_status_text.toUpper());
}
void GMainWindow::UpdateFilterText() {
const auto filter = Settings::values.scaling_filter.GetValue();
- const auto filter_text = Config::scaling_filter_texts_map.find(filter)->second;
+ const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second;
filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR")
: filter_text.toUpper());
}
void GMainWindow::UpdateAAText() {
const auto aa_mode = Settings::values.anti_aliasing.GetValue();
- const auto aa_text = Config::anti_aliasing_texts_map.find(aa_mode)->second;
+ const auto aa_text = ConfigurationShared::anti_aliasing_texts_map.find(aa_mode)->second;
aa_status_button->setText(aa_mode == Settings::AntiAliasing::None
? QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "NO AA"))
: aa_text.toUpper());
@@ -4744,6 +4821,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
"games."));
}
+ SetFirmwareVersion();
+
if (behavior == ReinitializeKeyBehavior::Warning) {
game_list->PopulateAsync(UISettings::values.game_dirs);
}
@@ -4771,7 +4850,7 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
}
bool GMainWindow::CheckFirmwarePresence() {
- constexpr u64 MiiEditId = 0x0100000000001009ull;
+ constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
@@ -4786,6 +4865,28 @@ bool GMainWindow::CheckFirmwarePresence() {
return true;
}
+void GMainWindow::SetFirmwareVersion() {
+ Service::Set::FirmwareVersionFormat firmware_data{};
+ const auto result = Service::Set::GetFirmwareVersionImpl(
+ firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2);
+
+ if (result.IsError() || !CheckFirmwarePresence()) {
+ LOG_INFO(Frontend, "Installed firmware: No firmware available");
+ firmware_label->setVisible(false);
+ return;
+ }
+
+ firmware_label->setVisible(true);
+
+ const std::string display_version(firmware_data.display_version.data());
+ const std::string display_title(firmware_data.display_title.data());
+
+ LOG_INFO(Frontend, "Installed firmware: {}", display_title);
+
+ firmware_label->setText(QString::fromStdString(display_version));
+ firmware_label->setToolTip(QString::fromStdString(display_title));
+}
+
bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
u64* selected_title_id, u8* selected_content_record_type) {
using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>;
@@ -4847,7 +4948,12 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
}
bool GMainWindow::ConfirmClose() {
- if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) {
+ if (emu_thread == nullptr ||
+ UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Never) {
+ return true;
+ }
+ if (!system->GetExitLocked() &&
+ UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Based_On_Game) {
return true;
}
const auto text = tr("Are you sure you want to close yuzu?");
@@ -4862,6 +4968,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
UpdateUISettings();
game_list->SaveInterfaceLayout();
+ UISettings::SaveWindowState();
hotkey_registry.SaveHotkeys();
// Unload controllers early
@@ -4952,7 +5059,7 @@ bool GMainWindow::ConfirmChangeGame() {
}
bool GMainWindow::ConfirmForceLockedExit() {
- if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) {
+ if (emu_thread == nullptr) {
return true;
}
const auto text = tr("The currently running application has requested yuzu to not exit.\n\n"
@@ -5016,9 +5123,9 @@ static void AdjustLinkColor() {
}
void GMainWindow::UpdateUITheme() {
- const QString default_theme =
- QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);
- QString current_theme = UISettings::values.theme;
+ const QString default_theme = QString::fromUtf8(
+ UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second);
+ QString current_theme = QString::fromStdString(UISettings::values.theme);
if (current_theme.isEmpty()) {
current_theme = default_theme;
@@ -5046,7 +5153,7 @@ void GMainWindow::UpdateUITheme() {
QFile f(theme_uri);
if (!f.open(QFile::ReadOnly | QFile::Text)) {
LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
- UISettings::values.theme.toStdString());
+ UISettings::values.theme);
current_theme = default_theme;
}
}
@@ -5059,7 +5166,7 @@ void GMainWindow::UpdateUITheme() {
setStyleSheet(ts.readAll());
} else {
LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found",
- UISettings::values.theme.toStdString());
+ UISettings::values.theme);
qApp->setStyleSheet({});
setStyleSheet({});
}
@@ -5068,27 +5175,28 @@ void GMainWindow::UpdateUITheme() {
void GMainWindow::LoadTranslation() {
bool loaded;
- if (UISettings::values.language.isEmpty()) {
+ if (UISettings::values.language.empty()) {
// If the selected language is empty, use system locale
loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
} else {
// Otherwise load from the specified file
- loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
+ loaded = translator.load(QString::fromStdString(UISettings::values.language),
+ QStringLiteral(":/languages/"));
}
if (loaded) {
qApp->installTranslator(&translator);
} else {
- UISettings::values.language = QStringLiteral("en");
+ UISettings::values.language = std::string("en");
}
}
void GMainWindow::OnLanguageChanged(const QString& locale) {
- if (UISettings::values.language != QStringLiteral("en")) {
+ if (UISettings::values.language != std::string("en")) {
qApp->removeTranslator(&translator);
}
- UISettings::values.language = locale;
+ UISettings::values.language = locale.toStdString();
LoadTranslation();
ui->retranslateUi(this);
multiplayer_state->retranslateUi();
@@ -5114,7 +5222,7 @@ void GMainWindow::changeEvent(QEvent* event) {
// UpdateUITheme is a decent work around
if (event->type() == QEvent::PaletteChange) {
const QPalette test_palette(qApp->palette());
- const QString current_theme = UISettings::values.theme;
+ const QString current_theme = QString::fromStdString(UISettings::values.theme);
// Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
static QColor last_window_color;
const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
@@ -5208,7 +5316,8 @@ static void SetHighDPIAttributes() {
}
int main(int argc, char* argv[]) {
- std::unique_ptr<Config> config = std::make_unique<Config>();
+ std::unique_ptr<QtConfig> config = std::make_unique<QtConfig>();
+ UISettings::RestoreWindowState(config);
bool has_broken_vulkan = false;
bool is_child = false;
if (CheckEnvVars(&is_child)) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index f9c6efe4f..e99d58995 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -6,6 +6,7 @@
#include <memory>
#include <optional>
+#include <filesystem>
#include <QMainWindow>
#include <QMessageBox>
#include <QPushButton>
@@ -14,6 +15,7 @@
#include "common/announce_multiplayer_room.h"
#include "common/common_types.h"
+#include "configuration/qt_config.h"
#include "input_common/drivers/tas_input.h"
#include "yuzu/compatibility_list.h"
#include "yuzu/hotkeys.h"
@@ -25,7 +27,7 @@
#include <QtDBus/QtDBus>
#endif
-class Config;
+class QtConfig;
class ClickableLabel;
class EmuThread;
class GameList;
@@ -174,10 +176,17 @@ class GMainWindow : public QMainWindow {
UI_EMU_STOPPING,
};
+ enum {
+ CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES,
+ CREATE_SHORTCUT_MSGBOX_SUCCESS,
+ CREATE_SHORTCUT_MSGBOX_ERROR,
+ CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING,
+ };
+
public:
void filterBarSetChecked(bool state);
void UpdateUITheme();
- explicit GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan);
+ explicit GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan);
~GMainWindow() override;
bool DropAction(QDropEvent* event);
@@ -402,6 +411,7 @@ private slots:
void OnAlbum();
void OnCabinet(Service::NFP::CabinetMode mode);
void OnMiiEdit();
+ void OnOpenControllerMenu();
void OnCaptureScreenshot();
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
void OnLanguageChanged(const QString& locale);
@@ -448,6 +458,7 @@ private:
bool CheckDarkMode();
bool CheckSystemArchiveDecryption();
bool CheckFirmwarePresence();
+ void SetFirmwareVersion();
void ConfigureFilesystemProvider(const std::string& filepath);
/**
* Open (or not) the right confirm dialog based on current setting and game exit lock
@@ -456,11 +467,14 @@ private:
bool ConfirmShutdownGame();
QString GetTasStateDescription() const;
- bool CreateShortcut(const std::string& shortcut_path, const std::string& title,
- const std::string& comment, const std::string& icon_path,
- const std::string& command, const std::string& arguments,
- const std::string& categories, const std::string& keywords);
-
+ bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title);
+ bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
+ std::filesystem::path& out_icon_path);
+ bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment,
+ const std::filesystem::path& icon_path,
+ const std::filesystem::path& command, const std::string& arguments,
+ const std::string& categories, const std::string& keywords,
+ const std::string& name);
/**
* Mimic the behavior of QMessageBox::question but link controller navigation to the dialog
* The only difference is that it returns a boolean.
@@ -499,6 +513,7 @@ private:
QLabel* game_fps_label = nullptr;
QLabel* emu_frametime_label = nullptr;
QLabel* tas_label = nullptr;
+ QLabel* firmware_label = nullptr;
QPushButton* gpu_accuracy_button = nullptr;
QPushButton* renderer_status_button = nullptr;
QPushButton* dock_status_button = nullptr;
@@ -509,7 +524,7 @@ private:
QSlider* volume_slider = nullptr;
QTimer status_bar_update_timer;
- std::unique_ptr<Config> config;
+ std::unique_ptr<QtConfig> config;
// Whether emulation is currently running in yuzu.
bool emulation_running = false;
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index 88684ffb5..e53f9951e 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -25,7 +25,7 @@
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
- <property name="margin">
+ <property name="margin" stdset="0">
<number>0</number>
</property>
</layout>
@@ -36,7 +36,7 @@
<x>0</x>
<y>0</y>
<width>1280</width>
- <height>26</height>
+ <height>21</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
@@ -162,6 +162,7 @@
<addaction name="menu_cabinet_applet"/>
<addaction name="action_Load_Album"/>
<addaction name="action_Load_Mii_Edit"/>
+ <addaction name="action_Open_Controller_Menu"/>
<addaction name="separator"/>
<addaction name="action_Capture_Screenshot"/>
<addaction name="menuTAS"/>
@@ -382,9 +383,9 @@
</property>
</action>
<action name="action_Load_Album">
- <property name="text">
- <string>Open &amp;Album</string>
- </property>
+ <property name="text">
+ <string>Open &amp;Album</string>
+ </property>
</action>
<action name="action_Load_Cabinet_Nickname_Owner">
<property name="text">
@@ -407,9 +408,9 @@
</property>
</action>
<action name="action_Load_Mii_Edit">
- <property name="text">
- <string>Open &amp;Mii Editor</string>
- </property>
+ <property name="text">
+ <string>Open &amp;Mii Editor</string>
+ </property>
</action>
<action name="action_Configure_Tas">
<property name="text">
@@ -454,6 +455,11 @@
<string>R&amp;ecord</string>
</property>
</action>
+ <action name="action_Open_Controller_Menu">
+ <property name="text">
+ <string>Open &amp;Controller Menu</string>
+ </property>
+ </action>
</widget>
<resources>
<include location="yuzu.qrc"/>
diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp
index 1c833767b..7bb7e95af 100644
--- a/src/yuzu/uisettings.cpp
+++ b/src/yuzu/uisettings.cpp
@@ -1,6 +1,9 @@
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <QSettings>
+#include "common/fs/fs.h"
+#include "common/fs/path_util.h"
#include "yuzu/uisettings.h"
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
@@ -15,6 +18,8 @@ template class Setting<unsigned long long>;
} // namespace Settings
#endif
+namespace FS = Common::FS;
+
namespace UISettings {
const Themes themes{{
@@ -28,10 +33,8 @@ const Themes themes{{
bool IsDarkTheme() {
const auto& theme = UISettings::values.theme;
- return theme == QStringLiteral("qdarkstyle") ||
- theme == QStringLiteral("qdarkstyle_midnight_blue") ||
- theme == QStringLiteral("colorful_dark") ||
- theme == QStringLiteral("colorful_midnight_blue");
+ return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
+ theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
}
Values values = {};
@@ -52,4 +55,58 @@ u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) {
return height * 16 / 9;
}
+void SaveWindowState() {
+ const auto window_state_config_loc =
+ FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini");
+
+ void(FS::CreateParentDir(window_state_config_loc));
+ QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat);
+
+ config.setValue(QStringLiteral("geometry"), values.geometry);
+ config.setValue(QStringLiteral("state"), values.state);
+ config.setValue(QStringLiteral("geometryRenderWindow"), values.renderwindow_geometry);
+ config.setValue(QStringLiteral("gameListHeaderState"), values.gamelist_header_state);
+ config.setValue(QStringLiteral("microProfileDialogGeometry"), values.microprofile_geometry);
+
+ config.sync();
+}
+
+void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig) {
+ const auto window_state_config_loc =
+ FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini");
+
+ // Migrate window state from old location
+ if (!FS::Exists(window_state_config_loc) && qtConfig->Exists("UI", "UILayout\\geometry")) {
+ const auto config_loc =
+ FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "qt-config.ini");
+ QSettings config(QString::fromStdString(config_loc), QSettings::IniFormat);
+
+ config.beginGroup(QStringLiteral("UI"));
+ config.beginGroup(QStringLiteral("UILayout"));
+ values.geometry = config.value(QStringLiteral("geometry")).toByteArray();
+ values.state = config.value(QStringLiteral("state")).toByteArray();
+ values.renderwindow_geometry =
+ config.value(QStringLiteral("geometryRenderWindow")).toByteArray();
+ values.gamelist_header_state =
+ config.value(QStringLiteral("gameListHeaderState")).toByteArray();
+ values.microprofile_geometry =
+ config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray();
+ config.endGroup();
+ config.endGroup();
+ return;
+ }
+
+ void(FS::CreateParentDir(window_state_config_loc));
+ const QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat);
+
+ values.geometry = config.value(QStringLiteral("geometry")).toByteArray();
+ values.state = config.value(QStringLiteral("state")).toByteArray();
+ values.renderwindow_geometry =
+ config.value(QStringLiteral("geometryRenderWindow")).toByteArray();
+ values.gamelist_header_state =
+ config.value(QStringLiteral("gameListHeaderState")).toByteArray();
+ values.microprofile_geometry =
+ config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray();
+}
+
} // namespace UISettings
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index b62ff620c..549a39e1b 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -14,6 +14,7 @@
#include "common/common_types.h"
#include "common/settings.h"
#include "common/settings_enums.h"
+#include "configuration/qt_config.h"
using Settings::Category;
using Settings::ConfirmStop;
@@ -37,15 +38,15 @@ namespace UISettings {
bool IsDarkTheme();
struct ContextualShortcut {
- QString keyseq;
- QString controller_keyseq;
+ std::string keyseq;
+ std::string controller_keyseq;
int context;
bool repeat;
};
struct Shortcut {
- QString name;
- QString group;
+ std::string name;
+ std::string group;
ContextualShortcut shortcut;
};
@@ -58,11 +59,19 @@ enum class Theme {
MidnightBlueColorful,
};
+static constexpr Theme default_theme{
+#ifdef _WIN32
+ Theme::DarkColorful
+#else
+ Theme::DefaultColorful
+#endif
+};
+
using Themes = std::array<std::pair<const char*, const char*>, 6>;
extern const Themes themes;
struct GameDir {
- QString path;
+ std::string path;
bool deep_scan = false;
bool expanded = false;
bool operator==(const GameDir& rhs) const {
@@ -93,10 +102,6 @@ struct Values {
Setting<bool> show_filter_bar{linkage, true, "showFilterBar", Category::Ui};
Setting<bool> show_status_bar{linkage, true, "showStatusBar", Category::Ui};
- Setting<bool> confirm_before_closing{
- linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default,
- true, true};
-
SwitchableSetting<ConfirmStop> confirm_before_stopping{linkage,
ConfirmStop::Ask_Always,
"confirmStop",
@@ -113,9 +118,13 @@ struct Values {
Settings::Specialization::Default,
true,
true};
- Setting<bool> mute_when_in_background{
- linkage, false, "muteWhenInBackground", Category::Audio, Settings::Specialization::Default,
- true, true};
+ Setting<bool> mute_when_in_background{linkage,
+ false,
+ "muteWhenInBackground",
+ Category::UiAudio,
+ Settings::Specialization::Default,
+ true,
+ true};
Setting<bool> hide_mouse{
linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default,
true, true};
@@ -144,15 +153,15 @@ struct Values {
Category::Screenshots};
Setting<u32> screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots};
- QString roms_path;
- QString symbols_path;
- QString game_dir_deprecated;
+ std::string roms_path;
+ std::string symbols_path;
+ std::string game_dir_deprecated;
bool game_dir_deprecated_deepscan;
- QVector<UISettings::GameDir> game_dirs;
+ QVector<GameDir> game_dirs;
QStringList recent_files;
- QString language;
+ std::string language;
- QString theme;
+ std::string theme;
// Shortcut name <Shortcut, context>
std::vector<Shortcut> shortcuts;
@@ -206,6 +215,54 @@ extern Values values;
u32 CalculateWidth(u32 height, Settings::AspectRatio ratio);
+void SaveWindowState();
+void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig);
+
+// This shouldn't have anything except static initializers (no functions). So
+// QKeySequence(...).toString() is NOT ALLOWED HERE.
+// This must be in alphabetical order according to action name as it must have the same order as
+// UISetting::values.shortcuts, which is alphabetically ordered.
+// clang-format off
+const std::array<Shortcut, 23> default_hotkeys{{
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+P"), std::string("Screenshot"), Qt::WidgetWithChildrenShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F8"), std::string("Home+L"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F10"), std::string("Home+X"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F9"), std::string("Home+R"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F4"), std::string("Home+Plus"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F6"), std::string(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F5"), std::string(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F"), std::string(""), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+U"), std::string("Home+Y"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F9"), std::string(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string(""), std::string(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+S"), std::string(""), Qt::WindowShortcut, false}},
+}};
+// clang-format on
+
} // namespace UISettings
Q_DECLARE_METATYPE(UISettings::GameDir*);
+
+// These metatype declarations cannot be in common/settings.h because core is devoid of QT
+Q_DECLARE_METATYPE(Settings::CpuAccuracy);
+Q_DECLARE_METATYPE(Settings::GpuAccuracy);
+Q_DECLARE_METATYPE(Settings::FullscreenMode);
+Q_DECLARE_METATYPE(Settings::NvdecEmulation);
+Q_DECLARE_METATYPE(Settings::ResolutionSetup);
+Q_DECLARE_METATYPE(Settings::ScalingFilter);
+Q_DECLARE_METATYPE(Settings::AntiAliasing);
+Q_DECLARE_METATYPE(Settings::RendererBackend);
+Q_DECLARE_METATYPE(Settings::ShaderBackend);
+Q_DECLARE_METATYPE(Settings::AstcRecompression);
+Q_DECLARE_METATYPE(Settings::AstcDecodeMode);
diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp
index f2854c8ec..e22cf84bf 100644
--- a/src/yuzu/util/util.cpp
+++ b/src/yuzu/util/util.cpp
@@ -4,7 +4,10 @@
#include <array>
#include <cmath>
#include <QPainter>
+
+#include "common/logging/log.h"
#include "yuzu/util/util.h"
+
#ifdef _WIN32
#include <windows.h>
#include "common/fs/file.h"
@@ -42,7 +45,7 @@ QPixmap CreateCirclePixmapFromColor(const QColor& color) {
return circle_pixmap;
}
-bool SaveIconToFile(const std::string_view path, const QImage& image) {
+bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image) {
#if defined(WIN32)
#pragma pack(push, 2)
struct IconDir {
@@ -73,7 +76,7 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) {
.id_count = static_cast<WORD>(scale_sizes.size()),
};
- Common::FS::IOFile icon_file(path, Common::FS::FileAccessMode::Write,
+ Common::FS::IOFile icon_file(icon_path.string(), Common::FS::FileAccessMode::Write,
Common::FS::FileType::BinaryFile);
if (!icon_file.IsOpen()) {
return false;
@@ -135,6 +138,14 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) {
icon_file.Close();
return true;
+#elif defined(__linux__) || defined(__FreeBSD__)
+ // Convert and write the icon as a PNG
+ if (!image.save(QString::fromStdString(icon_path.string()))) {
+ LOG_ERROR(Frontend, "Could not write icon as PNG to file");
+ } else {
+ LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string());
+ }
+ return true;
#else
return false;
#endif
diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h
index 09c14ce3f..4094cf6c2 100644
--- a/src/yuzu/util/util.h
+++ b/src/yuzu/util/util.h
@@ -3,6 +3,7 @@
#pragma once
+#include <filesystem>
#include <QFont>
#include <QString>
@@ -25,4 +26,4 @@
* @param image The image to save
* @return bool If the operation succeeded
*/
-[[nodiscard]] bool SaveIconToFile(const std::string_view path, const QImage& image);
+[[nodiscard]] bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image);
diff --git a/src/yuzu/vk_device_info.cpp b/src/yuzu/vk_device_info.cpp
index 92f10d315..ab0d39c25 100644
--- a/src/yuzu/vk_device_info.cpp
+++ b/src/yuzu/vk_device_info.cpp
@@ -31,6 +31,7 @@ void PopulateRecords(std::vector<Record>& records, QWindow* window) try {
// Create a test window with a Vulkan surface type for checking present modes.
QWindow test_window(window);
test_window.setSurfaceType(QWindow::VulkanSurface);
+ test_window.create();
auto wsi = QtCommon::GetWindowSystemInfo(&test_window);
vk::InstanceDispatch dld;