summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/CMakeLists.txt1
-rw-r--r--src/yuzu/Info.plist2
-rw-r--r--src/yuzu/bootmanager.cpp19
-rw-r--r--src/yuzu/bootmanager.h4
-rw-r--r--src/yuzu/configuration/config.cpp61
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp10
-rw-r--r--src/yuzu/configuration/configuration_shared.h3
-rw-r--r--src/yuzu/configuration/configure_debug.cpp3
-rw-r--r--src/yuzu/configuration/configure_debug.ui15
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp1
-rw-r--r--src/yuzu/configuration/configure_graphics.ui17
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp22
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h2
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui20
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui22
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp38
-rw-r--r--src/yuzu/configuration/configure_input_player.h6
-rw-r--r--src/yuzu/configuration/configure_input_player.ui19
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp10
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp1
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp2
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp105
-rw-r--r--src/yuzu/configuration/configure_ringcon.h14
-rw-r--r--src/yuzu/configuration/configure_ringcon.ui396
-rw-r--r--src/yuzu/configuration/configure_system.cpp42
-rw-r--r--src/yuzu/configuration/configure_system.h6
-rw-r--r--src/yuzu/configuration/configure_system.ui12
-rw-r--r--src/yuzu/configuration/configure_tas.cpp1
-rw-r--r--src/yuzu/configuration/input_profiles.cpp7
-rw-r--r--src/yuzu/debugger/controller.cpp15
-rw-r--r--src/yuzu/debugger/profiler.cpp5
-rw-r--r--src/yuzu/hotkeys.cpp6
-rw-r--r--src/yuzu/hotkeys.h1
-rw-r--r--src/yuzu/install_dialog.cpp1
-rw-r--r--src/yuzu/main.cpp74
-rw-r--r--src/yuzu/main.h5
-rw-r--r--src/yuzu/multiplayer/direct_connect.cpp21
-rw-r--r--src/yuzu/multiplayer/direct_connect.ui23
-rw-r--r--src/yuzu/multiplayer/validation.h25
-rw-r--r--src/yuzu/uisettings.h1
-rw-r--r--src/yuzu/util/limitable_input_dialog.cpp2
-rw-r--r--src/yuzu/util/sequence_dialog/sequence_dialog.cpp1
43 files changed, 733 insertions, 310 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 4a7d35617..dfc675cc8 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -5,7 +5,6 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules)
# Set the RPATH for Qt Libraries
# This must be done before the `yuzu` target is created
diff --git a/src/yuzu/Info.plist b/src/yuzu/Info.plist
index 0eb377926..f05f3186c 100644
--- a/src/yuzu/Info.plist
+++ b/src/yuzu/Info.plist
@@ -34,6 +34,8 @@ SPDX-License-Identifier: GPL-2.0-or-later
<string></string>
<key>CSResourcesFileMapped</key>
<true/>
+ <key>LSApplicationCategoryType</key>
+ <string>public.app-category.games</string>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 3d560f303..d65991734 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -96,9 +96,9 @@ void EmuThread::run() {
m_is_running.store(false);
m_is_running.notify_all();
- emit DebugModeEntered();
+ EmulationPaused(lk);
Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; });
- emit DebugModeLeft();
+ EmulationResumed(lk);
}
}
@@ -111,6 +111,21 @@ void EmuThread::run() {
#endif
}
+// Unlock while emitting signals so that the main thread can
+// continue pumping events.
+
+void EmuThread::EmulationPaused(std::unique_lock<std::mutex>& lk) {
+ lk.unlock();
+ emit DebugModeEntered();
+ lk.lock();
+}
+
+void EmuThread::EmulationResumed(std::unique_lock<std::mutex>& lk) {
+ lk.unlock();
+ emit DebugModeLeft();
+ lk.lock();
+}
+
#ifdef HAS_OPENGL
class OpenGLSharedContext : public Core::Frontend::GraphicsContext {
public:
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index eca16b313..092c6206f 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -92,6 +92,10 @@ public:
}
private:
+ void EmulationPaused(std::unique_lock<std::mutex>& lk);
+ void EmulationResumed(std::unique_lock<std::mutex>& lk);
+
+private:
Core::System& m_system;
std::stop_source m_stop_source;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 2ea4f367b..35fef506a 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -70,28 +70,28 @@ const std::array<int, 2> Config::default_ringcon_analogs{{
// UISetting::values.shortcuts, which is alphabetically ordered.
// clang-format off
const std::array<UISettings::Shortcut, 22> 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}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut}},
+ {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(""), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral(""), 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 Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut, false}},
}};
// clang-format on
@@ -440,6 +440,7 @@ void Config::ReadControlValues() {
ReadBasicSetting(Settings::values.emulate_analog_keyboard);
Settings::values.mouse_panning = false;
ReadBasicSetting(Settings::values.mouse_panning_sensitivity);
+ ReadBasicSetting(Settings::values.enable_joycon_driver);
ReadBasicSetting(Settings::values.tas_enable);
ReadBasicSetting(Settings::values.tas_loop);
@@ -562,6 +563,7 @@ void Config::ReadDebuggingValues() {
ReadBasicSetting(Settings::values.reporting_services);
ReadBasicSetting(Settings::values.quest_flag);
ReadBasicSetting(Settings::values.disable_macro_jit);
+ ReadBasicSetting(Settings::values.disable_macro_hle);
ReadBasicSetting(Settings::values.extended_logging);
ReadBasicSetting(Settings::values.use_debug_asserts);
ReadBasicSetting(Settings::values.use_auto_stub);
@@ -689,6 +691,7 @@ void Config::ReadRendererValues() {
qt_config->beginGroup(QStringLiteral("Renderer"));
ReadGlobalSetting(Settings::values.renderer_backend);
+ ReadGlobalSetting(Settings::values.renderer_force_max_clock);
ReadGlobalSetting(Settings::values.vulkan_device);
ReadGlobalSetting(Settings::values.fullscreen_mode);
ReadGlobalSetting(Settings::values.aspect_ratio);
@@ -708,6 +711,7 @@ void Config::ReadRendererValues() {
ReadGlobalSetting(Settings::values.use_asynchronous_shaders);
ReadGlobalSetting(Settings::values.use_fast_gpu_time);
ReadGlobalSetting(Settings::values.use_pessimistic_flushes);
+ ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
ReadGlobalSetting(Settings::values.bg_red);
ReadGlobalSetting(Settings::values.bg_green);
ReadGlobalSetting(Settings::values.bg_blue);
@@ -744,7 +748,7 @@ void Config::ReadShortcutValues() {
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 innacurately returns a value of 1
+ // 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(
@@ -753,7 +757,7 @@ void Config::ReadShortcutValues() {
{ReadSetting(QStringLiteral("KeySeq"), shortcut.keyseq).toString(),
ReadSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq)
.toString(),
- shortcut.context}});
+ shortcut.context, ReadSetting(QStringLiteral("Repeat"), shortcut.repeat).toBool()}});
qt_config->endGroup();
qt_config->endGroup();
}
@@ -941,7 +945,6 @@ void Config::ReadValues() {
ReadRendererValues();
ReadAudioValues();
ReadSystemValues();
- ReadMultiplayerValues();
}
void Config::SavePlayerValue(std::size_t player_index) {
@@ -1099,7 +1102,6 @@ void Config::SaveValues() {
SaveRendererValues();
SaveAudioValues();
SaveSystemValues();
- SaveMultiplayerValues();
}
void Config::SaveAudioValues() {
@@ -1138,6 +1140,7 @@ void Config::SaveControlValues() {
WriteGlobalSetting(Settings::values.enable_accurate_vibrations);
WriteGlobalSetting(Settings::values.motion_enabled);
WriteBasicSetting(Settings::values.enable_raw_input);
+ WriteBasicSetting(Settings::values.enable_joycon_driver);
WriteBasicSetting(Settings::values.keyboard_enabled);
WriteBasicSetting(Settings::values.emulate_analog_keyboard);
WriteBasicSetting(Settings::values.mouse_panning_sensitivity);
@@ -1200,6 +1203,7 @@ void Config::SaveDebuggingValues() {
WriteBasicSetting(Settings::values.quest_flag);
WriteBasicSetting(Settings::values.use_debug_asserts);
WriteBasicSetting(Settings::values.disable_macro_jit);
+ WriteBasicSetting(Settings::values.disable_macro_hle);
WriteBasicSetting(Settings::values.enable_all_controllers);
WriteBasicSetting(Settings::values.create_crash_dumps);
WriteBasicSetting(Settings::values.perform_vulkan_check);
@@ -1305,6 +1309,9 @@ void Config::SaveRendererValues() {
static_cast<u32>(Settings::values.renderer_backend.GetValue(global)),
static_cast<u32>(Settings::values.renderer_backend.GetDefault()),
Settings::values.renderer_backend.UsingGlobal());
+ WriteSetting(QString::fromStdString(Settings::values.renderer_force_max_clock.GetLabel()),
+ static_cast<u32>(Settings::values.renderer_force_max_clock.GetValue(global)),
+ static_cast<u32>(Settings::values.renderer_force_max_clock.GetDefault()));
WriteGlobalSetting(Settings::values.vulkan_device);
WriteSetting(QString::fromStdString(Settings::values.fullscreen_mode.GetLabel()),
static_cast<u32>(Settings::values.fullscreen_mode.GetValue(global)),
@@ -1348,6 +1355,7 @@ void Config::SaveRendererValues() {
WriteGlobalSetting(Settings::values.use_asynchronous_shaders);
WriteGlobalSetting(Settings::values.use_fast_gpu_time);
WriteGlobalSetting(Settings::values.use_pessimistic_flushes);
+ WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
WriteGlobalSetting(Settings::values.bg_red);
WriteGlobalSetting(Settings::values.bg_green);
WriteGlobalSetting(Settings::values.bg_blue);
@@ -1387,6 +1395,7 @@ void Config::SaveShortcutValues() {
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();
}
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index 97fb664bf..ac42cc7fc 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -92,3 +92,13 @@ void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index
combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text);
combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX);
}
+
+int ConfigurationShared::GetComboboxIndex(int global_setting_index, const QComboBox* combobox) {
+ if (Settings::IsConfiguringGlobal()) {
+ return combobox->currentIndex();
+ }
+ if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
+ return global_setting_index;
+ }
+ return combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET;
+}
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index e597dcdb5..04c88758c 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -69,4 +69,7 @@ void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global);
// Adds the "Use Global Configuration" selection and separator to the beginning of a QComboBox
void InsertGlobalItem(QComboBox* combobox, int global_index);
+// Returns the correct index of a QComboBox taking into account global configuration
+int GetComboboxIndex(int global_setting_index, const QComboBox* combobox);
+
} // namespace ConfigurationShared
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index dacc75a20..cbeb8f168 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -73,6 +73,8 @@ void ConfigureDebug::SetConfiguration() {
ui->dump_macros->setChecked(Settings::values.dump_macros.GetValue());
ui->disable_macro_jit->setEnabled(runtime_lock);
ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue());
+ ui->disable_macro_hle->setEnabled(runtime_lock);
+ ui->disable_macro_hle->setChecked(Settings::values.disable_macro_hle.GetValue());
ui->disable_loop_safety_checks->setEnabled(runtime_lock);
ui->disable_loop_safety_checks->setChecked(
Settings::values.disable_shader_loop_safety_checks.GetValue());
@@ -117,6 +119,7 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.disable_shader_loop_safety_checks =
ui->disable_loop_safety_checks->isChecked();
Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
+ Settings::values.disable_macro_hle = ui->disable_macro_hle->isChecked();
Settings::values.extended_logging = ui->extended_logging->isChecked();
Settings::values.perform_vulkan_check = ui->perform_vulkan_check->isChecked();
UISettings::values.disable_web_applet = ui->disable_web_applet->isChecked();
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 102c8c66c..15acefe33 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -176,7 +176,7 @@
</property>
</widget>
</item>
- <item row="0" column="2">
+ <item row="1" column="2">
<widget class="QCheckBox" name="dump_macros">
<property name="enabled">
<bool>true</bool>
@@ -202,6 +202,19 @@
</property>
</widget>
</item>
+ <item row="0" column="2">
+ <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="1" column="0">
<widget class="QCheckBox" name="enable_shader_feedback">
<property name="toolTip">
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 4301313cf..2aaefcc05 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -66,7 +66,6 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
web_tab->SetWebServiceConfigEnabled(enable_web_config);
hotkeys_tab->Populate(registry);
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
input_tab->Initialize(input_subsystem);
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index aa02cc63c..a45ec69ec 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -366,6 +366,11 @@
</item>
<item>
<property name="text">
+ <string>1.5X (1080p/1620p) [EXPERIMENTAL]</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string>2X (1440p/2160p)</string>
</property>
</item>
@@ -389,6 +394,16 @@
<string>6X (4320p/6480p)</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>7X (5040p/7560p)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8X (5760p/8640p)</string>
+ </property>
+ </item>
</widget>
</item>
</layout>
@@ -445,7 +460,7 @@
</item>
<item>
<property name="text">
- <string>AMD FidelityFX™️ Super Resolution (Vulkan Only)</string>
+ <string>AMD FidelityFX™️ Super Resolution</string>
</property>
</item>
</widget>
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 01f074699..cc0155a2c 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -22,13 +22,17 @@ ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default;
void ConfigureGraphicsAdvanced::SetConfiguration() {
const bool runtime_lock = !system.IsPoweredOn();
ui->use_vsync->setEnabled(runtime_lock);
+ ui->renderer_force_max_clock->setEnabled(runtime_lock);
ui->use_asynchronous_shaders->setEnabled(runtime_lock);
ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
+ ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue());
ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
ui->use_pessimistic_flushes->setChecked(Settings::values.use_pessimistic_flushes.GetValue());
+ ui->use_vulkan_driver_pipeline_cache->setChecked(
+ Settings::values.use_vulkan_driver_pipeline_cache.GetValue());
if (Settings::IsConfiguringGlobal()) {
ui->gpu_accuracy->setCurrentIndex(
@@ -41,6 +45,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
&Settings::values.max_anisotropy);
ConfigurationShared::SetHighlight(ui->label_gpu_accuracy,
!Settings::values.gpu_accuracy.UsingGlobal());
+ ConfigurationShared::SetHighlight(ui->renderer_force_max_clock,
+ !Settings::values.renderer_force_max_clock.UsingGlobal());
ConfigurationShared::SetHighlight(ui->af_label,
!Settings::values.max_anisotropy.UsingGlobal());
}
@@ -48,6 +54,9 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
void ConfigureGraphicsAdvanced::ApplyConfiguration() {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.gpu_accuracy, ui->gpu_accuracy);
+ ConfigurationShared::ApplyPerGameSetting(&Settings::values.renderer_force_max_clock,
+ ui->renderer_force_max_clock,
+ renderer_force_max_clock);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
ui->anisotropic_filtering_combobox);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync);
@@ -58,6 +67,9 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
ui->use_fast_gpu_time, use_fast_gpu_time);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_pessimistic_flushes,
ui->use_pessimistic_flushes, use_pessimistic_flushes);
+ ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache,
+ ui->use_vulkan_driver_pipeline_cache,
+ use_vulkan_driver_pipeline_cache);
}
void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
@@ -76,18 +88,25 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
// Disable if not global (only happens during game)
if (Settings::IsConfiguringGlobal()) {
ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal());
+ ui->renderer_force_max_clock->setEnabled(
+ Settings::values.renderer_force_max_clock.UsingGlobal());
ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal());
ui->use_asynchronous_shaders->setEnabled(
Settings::values.use_asynchronous_shaders.UsingGlobal());
ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
ui->use_pessimistic_flushes->setEnabled(
Settings::values.use_pessimistic_flushes.UsingGlobal());
+ ui->use_vulkan_driver_pipeline_cache->setEnabled(
+ Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal());
ui->anisotropic_filtering_combobox->setEnabled(
Settings::values.max_anisotropy.UsingGlobal());
return;
}
+ ConfigurationShared::SetColoredTristate(ui->renderer_force_max_clock,
+ Settings::values.renderer_force_max_clock,
+ renderer_force_max_clock);
ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync);
ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders,
Settings::values.use_asynchronous_shaders,
@@ -97,6 +116,9 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
ConfigurationShared::SetColoredTristate(ui->use_pessimistic_flushes,
Settings::values.use_pessimistic_flushes,
use_pessimistic_flushes);
+ ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache,
+ Settings::values.use_vulkan_driver_pipeline_cache,
+ use_vulkan_driver_pipeline_cache);
ConfigurationShared::SetColoredComboBox(
ui->gpu_accuracy, ui->label_gpu_accuracy,
static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index 12e816905..df557d585 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -36,10 +36,12 @@ private:
std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui;
+ ConfigurationShared::CheckState renderer_force_max_clock;
ConfigurationShared::CheckState use_vsync;
ConfigurationShared::CheckState use_asynchronous_shaders;
ConfigurationShared::CheckState use_fast_gpu_time;
ConfigurationShared::CheckState use_pessimistic_flushes;
+ ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache;
const Core::System& system;
};
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 87a121471..061885e30 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -70,6 +70,16 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="renderer_force_max_clock">
+ <property name="toolTip">
+ <string>Runs work in the background while waiting for graphics commands to keep the GPU from lowering its clock speed.</string>
+ </property>
+ <property name="text">
+ <string>Force maximum clocks (Vulkan only)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QCheckBox" name="use_vsync">
<property name="toolTip">
<string>VSync prevents the screen from tearing, but some graphics cards have lower performance with VSync enabled. Keep it enabled if you don't notice a performance difference.</string>
@@ -110,6 +120,16 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache">
+ <property name="toolTip">
+ <string>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.</string>
+ </property>
+ <property name="text">
+ <string>Use Vulkan pipeline cache</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QWidget" name="af_layout" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_1">
<property name="leftMargin">
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index 235b813d9..77b976e74 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -138,6 +138,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
Settings::values.controller_navigation = ui->controller_navigation->isChecked();
Settings::values.enable_ring_controller = ui->enable_ring_controller->isChecked();
Settings::values.enable_ir_sensor = ui->enable_ir_sensor->isChecked();
+ Settings::values.enable_joycon_driver = ui->enable_joycon_driver->isChecked();
}
void ConfigureInputAdvanced::LoadConfiguration() {
@@ -172,6 +173,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
ui->controller_navigation->setChecked(Settings::values.controller_navigation.GetValue());
ui->enable_ring_controller->setChecked(Settings::values.enable_ring_controller.GetValue());
ui->enable_ir_sensor->setChecked(Settings::values.enable_ir_sensor.GetValue());
+ ui->enable_joycon_driver->setChecked(Settings::values.enable_joycon_driver.GetValue());
UpdateUIEnabled();
}
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index fac8cf827..75d96d3ab 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2696,6 +2696,22 @@
</widget>
</item>
<item row="5" column="0">
+ <widget class="QCheckBox" name="enable_joycon_driver">
+ <property name="toolTip">
+ <string>Requires restarting yuzu</string>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Enable direct JoyCon driver</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
<widget class="QCheckBox" name="mouse_panning">
<property name="minimumSize">
<size>
@@ -2708,7 +2724,7 @@
</property>
</widget>
</item>
- <item row="5" column="2">
+ <item row="6" column="2">
<widget class="QSpinBox" name="mouse_panning_sensitivity">
<property name="toolTip">
<string>Mouse sensitivity</string>
@@ -2730,14 +2746,14 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="motion_touch">
<property name="text">
<string>Motion / Touch</string>
</property>
</widget>
</item>
- <item row="6" column="2">
+ <item row="7" column="2">
<widget class="QPushButton" name="buttonMotionTouch">
<property name="text">
<string>Configure</string>
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index b1575b0d3..4b7e3b01b 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -66,6 +66,18 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
return QObject::tr("R");
case Common::Input::ButtonNames::TriggerL:
return QObject::tr("L");
+ case Common::Input::ButtonNames::TriggerZR:
+ return QObject::tr("ZR");
+ case Common::Input::ButtonNames::TriggerZL:
+ return QObject::tr("ZL");
+ case Common::Input::ButtonNames::TriggerSR:
+ return QObject::tr("SR");
+ case Common::Input::ButtonNames::TriggerSL:
+ return QObject::tr("SL");
+ case Common::Input::ButtonNames::ButtonStickL:
+ return QObject::tr("Stick L");
+ case Common::Input::ButtonNames::ButtonStickR:
+ return QObject::tr("Stick R");
case Common::Input::ButtonNames::ButtonA:
return QObject::tr("A");
case Common::Input::ButtonNames::ButtonB:
@@ -76,6 +88,14 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
return QObject::tr("Y");
case Common::Input::ButtonNames::ButtonStart:
return QObject::tr("Start");
+ case Common::Input::ButtonNames::ButtonPlus:
+ return QObject::tr("Plus");
+ case Common::Input::ButtonNames::ButtonMinus:
+ return QObject::tr("Minus");
+ case Common::Input::ButtonNames::ButtonHome:
+ return QObject::tr("Home");
+ case Common::Input::ButtonNames::ButtonCapture:
+ return QObject::tr("Capture");
case Common::Input::ButtonNames::L1:
return QObject::tr("L1");
case Common::Input::ButtonNames::L2:
@@ -738,13 +758,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
&ConfigureInputPlayer::UpdateMappingWithDefaults);
+ ui->comboDevices->installEventFilter(this);
ui->comboDevices->setCurrentIndex(-1);
- ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
- connect(ui->buttonRefreshDevices, &QPushButton::clicked,
- [this] { emit RefreshInputDevices(); });
-
timeout_timer->setSingleShot(true);
connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
@@ -1469,6 +1486,12 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
}
+void ConfigureInputPlayer::wheelEvent(QWheelEvent* event) {
+ const int x = event->angleDelta().x();
+ const int y = event->angleDelta().y();
+ input_subsystem->GetMouse()->MouseWheelChange(x, y);
+}
+
void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
if (!input_setter || !event) {
return;
@@ -1479,6 +1502,13 @@ void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
}
}
+bool ConfigureInputPlayer::eventFilter(QObject* object, QEvent* event) {
+ if (object == ui->comboDevices && event->type() == QEvent::MouseButtonPress) {
+ RefreshInputDevices();
+ }
+ return object->eventFilter(object, event);
+}
+
void ConfigureInputPlayer::CreateProfile() {
const auto profile_name =
LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 30,
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 26f60d121..99a9c875d 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -116,9 +116,15 @@ private:
/// Handle mouse button press events.
void mousePressEvent(QMouseEvent* event) override;
+ /// Handle mouse wheel move events.
+ void wheelEvent(QWheelEvent* event) override;
+
/// Handle key press events.
void keyPressEvent(QKeyEvent* event) override;
+ /// Handle combobox list refresh
+ bool eventFilter(QObject* object, QEvent* event) override;
+
/// Update UI to reflect current configuration.
void UpdateUI();
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index a62b57501..a9567c6ee 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -122,25 +122,6 @@
</property>
</widget>
</item>
- <item>
- <widget class="QPushButton" name="buttonRefreshDevices">
- <property name="minimumSize">
- <size>
- <width>21</width>
- <height>21</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>21</width>
- <height>21</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- </widget>
- </item>
</layout>
</widget>
</item>
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 11390fec0..68af6c20c 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -103,9 +103,13 @@ void PlayerControlPreview::UpdateColors() {
colors.left = colors.primary;
colors.right = colors.primary;
- // Possible alternative to set colors from settings
- // colors.left = QColor(controller->GetColors().left.body);
- // colors.right = QColor(controller->GetColors().right.body);
+
+ const auto color_left = controller->GetColorsValues()[0].body;
+ const auto color_right = controller->GetColorsValues()[1].body;
+ if (color_left != 0 && color_right != 0) {
+ colors.left = QColor(color_left);
+ colors.right = QColor(color_right);
+ }
}
void PlayerControlPreview::ResetInputs() {
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index d1b870c72..fb1292f07 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -89,7 +89,6 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent,
"using-a-controller-or-android-phone-for-motion-or-touch-input'><span "
"style=\"text-decoration: underline; color:#039be5;\">Learn More</span></a>"));
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
SetConfiguration();
UpdateUiDisplay();
ConnectEvents();
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 93db47cfd..7e757eafd 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -66,8 +66,6 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
setFocusPolicy(Qt::ClickFocus);
setWindowTitle(tr("Properties"));
- // remove Help question mark button from the title bar
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
addons_tab->SetTitleId(title_id);
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp
index 688c2dd38..1275f10c8 100644
--- a/src/yuzu/configuration/configure_ringcon.cpp
+++ b/src/yuzu/configuration/configure_ringcon.cpp
@@ -4,9 +4,11 @@
#include <memory>
#include <QKeyEvent>
#include <QMenu>
+#include <QMessageBox>
#include <QTimer>
+#include <fmt/format.h>
-#include "core/hid/emulated_devices.h"
+#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
@@ -126,9 +128,16 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
ui->buttonRingAnalogPush,
};
- emulated_device = hid_core_.GetEmulatedDevices();
- emulated_device->SaveCurrentConfig();
- emulated_device->EnableConfiguration();
+ emulated_controller = hid_core_.GetEmulatedController(Core::HID::NpadIdType::Player1);
+ emulated_controller->SaveCurrentConfig();
+ emulated_controller->EnableConfiguration();
+
+ Core::HID::ControllerUpdateCallback engine_callback{
+ .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
+ .is_npad_service = false,
+ };
+ callback_key = emulated_controller->SetCallback(engine_callback);
+ is_controller_set = true;
LoadConfiguration();
@@ -143,9 +152,9 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
HandleClick(
analog_map_buttons[sub_button_id],
[=, this](const Common::ParamPackage& params) {
- Common::ParamPackage param = emulated_device->GetRingParam();
+ Common::ParamPackage param = emulated_controller->GetRingParam();
SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
- emulated_device->SetRingParam(param);
+ emulated_controller->SetRingParam(param);
},
InputCommon::Polling::InputType::Stick);
});
@@ -155,16 +164,16 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
connect(analog_button, &QPushButton::customContextMenuRequested,
[=, this](const QPoint& menu_location) {
QMenu context_menu;
- Common::ParamPackage param = emulated_device->GetRingParam();
+ Common::ParamPackage param = emulated_controller->GetRingParam();
context_menu.addAction(tr("Clear"), [&] {
- emulated_device->SetRingParam({});
+ emulated_controller->SetRingParam(param);
analog_map_buttons[sub_button_id]->setText(tr("[not set]"));
});
context_menu.addAction(tr("Invert axis"), [&] {
const bool invert_value = param.Get("invert_x", "+") == "-";
const std::string invert_str = invert_value ? "+" : "-";
param.Set("invert_x", invert_str);
- emulated_device->SetRingParam(param);
+ emulated_controller->SetRingParam(param);
for (int sub_button_id2 = 0; sub_button_id2 < ANALOG_SUB_BUTTONS_NUM;
++sub_button_id2) {
analog_map_buttons[sub_button_id2]->setText(
@@ -177,16 +186,19 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
}
connect(ui->sliderRingAnalogDeadzone, &QSlider::valueChanged, [=, this] {
- Common::ParamPackage param = emulated_device->GetRingParam();
+ Common::ParamPackage param = emulated_controller->GetRingParam();
const auto slider_value = ui->sliderRingAnalogDeadzone->value();
ui->labelRingAnalogDeadzone->setText(tr("Deadzone: %1%").arg(slider_value));
param.Set("deadzone", slider_value / 100.0f);
- emulated_device->SetRingParam(param);
+ emulated_controller->SetRingParam(param);
});
connect(ui->restore_defaults_button, &QPushButton::clicked, this,
&ConfigureRingController::RestoreDefaults);
+ connect(ui->enable_ring_controller_button, &QPushButton::clicked, this,
+ &ConfigureRingController::EnableRingController);
+
timeout_timer->setSingleShot(true);
connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
@@ -202,7 +214,14 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
}
ConfigureRingController::~ConfigureRingController() {
- emulated_device->DisableConfiguration();
+ emulated_controller->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
+ Common::Input::PollingMode::Active);
+ emulated_controller->DisableConfiguration();
+
+ if (is_controller_set) {
+ emulated_controller->DeleteCallback(callback_key);
+ is_controller_set = false;
+ }
};
void ConfigureRingController::changeEvent(QEvent* event) {
@@ -219,7 +238,7 @@ void ConfigureRingController::RetranslateUI() {
void ConfigureRingController::UpdateUI() {
RetranslateUI();
- const Common::ParamPackage param = emulated_device->GetRingParam();
+ const Common::ParamPackage param = emulated_controller->GetRingParam();
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
auto* const analog_button = analog_map_buttons[sub_button_id];
@@ -240,9 +259,9 @@ void ConfigureRingController::UpdateUI() {
}
void ConfigureRingController::ApplyConfiguration() {
- emulated_device->DisableConfiguration();
- emulated_device->SaveCurrentConfig();
- emulated_device->EnableConfiguration();
+ emulated_controller->DisableConfiguration();
+ emulated_controller->SaveCurrentConfig();
+ emulated_controller->EnableConfiguration();
}
void ConfigureRingController::LoadConfiguration() {
@@ -252,10 +271,62 @@ 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);
- emulated_device->SetRingParam(Common::ParamPackage(default_ring_string));
+ emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string));
UpdateUI();
}
+void ConfigureRingController::EnableRingController() {
+ const auto dialog_title = tr("Error enabling ring input");
+
+ is_ring_enabled = false;
+ ui->ring_controller_sensor_value->setText(tr("Not connected"));
+
+ if (!Settings::values.enable_joycon_driver) {
+ QMessageBox::warning(this, dialog_title, tr("Direct Joycon driver is not enabled"));
+ return;
+ }
+
+ ui->enable_ring_controller_button->setEnabled(false);
+ ui->enable_ring_controller_button->setText(tr("Configuring"));
+ // SetPollingMode is blocking. Allow to update the button status before calling the command
+ repaint();
+
+ const auto result = emulated_controller->SetPollingMode(
+ Core::HID::EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Ring);
+ switch (result) {
+ case Common::Input::DriverResult::Success:
+ is_ring_enabled = true;
+ break;
+ case Common::Input::DriverResult::NotSupported:
+ QMessageBox::warning(this, dialog_title,
+ tr("The current mapped device doesn't support the ring controller"));
+ break;
+ case Common::Input::DriverResult::NoDeviceDetected:
+ QMessageBox::warning(this, dialog_title,
+ tr("The current mapped device doesn't have a ring attached"));
+ break;
+ default:
+ QMessageBox::warning(this, dialog_title,
+ tr("Unexpected driver result %1").arg(static_cast<int>(result)));
+ break;
+ }
+ ui->enable_ring_controller_button->setEnabled(true);
+ ui->enable_ring_controller_button->setText(tr("Enable"));
+}
+
+void ConfigureRingController::ControllerUpdate(Core::HID::ControllerTriggerType type) {
+ if (!is_ring_enabled) {
+ return;
+ }
+ if (type != Core::HID::ControllerTriggerType::RingController) {
+ return;
+ }
+
+ const auto value = emulated_controller->GetRingSensorValues();
+ const auto tex_value = QString::fromStdString(fmt::format("{:.3f}", value.raw_value));
+ ui->ring_controller_sensor_value->setText(tex_value);
+}
+
void ConfigureRingController::HandleClick(
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
InputCommon::Polling::InputType type) {
diff --git a/src/yuzu/configuration/configure_ringcon.h b/src/yuzu/configuration/configure_ringcon.h
index 38a9cb716..b23c27906 100644
--- a/src/yuzu/configuration/configure_ringcon.h
+++ b/src/yuzu/configuration/configure_ringcon.h
@@ -13,7 +13,7 @@ class InputSubsystem;
namespace Core::HID {
class HIDCore;
-class EmulatedDevices;
+class EmulatedController;
} // namespace Core::HID
namespace Ui {
@@ -42,6 +42,12 @@ private:
/// Restore all buttons to their default values.
void RestoreDefaults();
+ /// Sets current polling mode to ring input
+ void EnableRingController();
+
+ // Handles emulated controller events
+ void ControllerUpdate(Core::HID::ControllerTriggerType type);
+
/// Called when the button was pressed.
void HandleClick(QPushButton* button,
std::function<void(const Common::ParamPackage&)> new_input_setter,
@@ -78,7 +84,11 @@ private:
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
InputCommon::InputSubsystem* input_subsystem;
- Core::HID::EmulatedDevices* emulated_device;
+ Core::HID::EmulatedController* emulated_controller;
+
+ bool is_ring_enabled{};
+ bool is_controller_set{};
+ int callback_key;
std::unique_ptr<Ui::ConfigureRingController> ui;
};
diff --git a/src/yuzu/configuration/configure_ringcon.ui b/src/yuzu/configuration/configure_ringcon.ui
index 9ec634dd4..514dff372 100644
--- a/src/yuzu/configuration/configure_ringcon.ui
+++ b/src/yuzu/configuration/configure_ringcon.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>298</width>
- <height>339</height>
+ <width>315</width>
+ <height>400</height>
</rect>
</property>
<property name="windowTitle">
@@ -46,187 +46,283 @@
</property>
</spacer>
</item>
- <item>
- <widget class="QGroupBox" name="RingAnalog">
- <property name="title">
- <string>Ring Sensor Parameters</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="rightMargin">
- <number>3</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <layout class="QHBoxLayout" name="buttonRingAnalogPullHorizontaLayout">
+ <item>
+ <widget class="QGroupBox" name="RingAnalog">
+ <property name="title">
+ <string>Virtual Ring Sensor Parameters</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_1">
<property name="spacing">
- <number>3</number>
+ <number>0</number>
</property>
- <item alignment="Qt::AlignHCenter">
- <widget class="QGroupBox" name="buttonRingAnalogPullGroup">
- <property name="title">
- <string>Pull</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="buttonRingAnalogPullHorizontaLayout">
+ <property name="spacing">
+ <number>3</number>
</property>
- <layout class="QVBoxLayout" name="buttonRingAnalogPullVerticalLayout">
- <property name="spacing">
- <number>3</number>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonRingAnalogPullGroup">
+ <property name="title">
+ <string>Pull</string>
</property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>3</number>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
</property>
- <property name="rightMargin">
- <number>3</number>
+ <layout class="QVBoxLayout" name="buttonRingAnalogPullVerticalLayout">
+ <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="buttonRingAnalogPull">
+ <property name="minimumSize">
+ <size>
+ <width>70</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>Pull</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonRingAnalogPushGroup">
+ <property name="title">
+ <string>Push</string>
</property>
- <property name="bottomMargin">
- <number>3</number>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
</property>
- <item>
- <widget class="QPushButton" name="buttonRingAnalogPull">
- <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>Pull</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
+ <layout class="QVBoxLayout" name="buttonRingAnalogPushVerticalLayout">
+ <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="buttonRingAnalogPush">
+ <property name="minimumSize">
+ <size>
+ <width>70</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>Push</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
</item>
- <item alignment="Qt::AlignHCenter">
- <widget class="QGroupBox" name="buttonRingAnalogPushGroup">
- <property name="title">
- <string>Push</string>
+ <item>
+ <layout class="QVBoxLayout" name="sliderRingAnalogDeadzoneVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
</property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
</property>
- <layout class="QVBoxLayout" name="buttonRingAnalogPushVerticalLayout">
- <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>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>10</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="sliderRingAnalogDeadzoneHorizontalLayout">
<item>
- <widget class="QPushButton" name="buttonRingAnalogPush">
- <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>
+ <widget class="QLabel" name="labelRingAnalogDeadzone">
<property name="text">
- <string>Push</string>
+ <string>Deadzone: 0%</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter</set>
</property>
- </widget>
+ </widget>
</item>
- </layout>
- </widget>
+ </layout>
+ </item>
+ <item>
+ <widget class="QSlider" name="sliderRingAnalogDeadzone">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="sliderRingAnalogDeadzoneVerticalLayout">
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="RingDriver">
+ <property name="title">
+ <string>Direct Joycon Driver</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
- <number>3</number>
+ <number>0</number>
</property>
<property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
+ <enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
- <number>0</number>
+ <number>3</number>
</property>
<property name="topMargin">
- <number>10</number>
+ <number>6</number>
</property>
<property name="rightMargin">
- <number>0</number>
+ <number>3</number>
</property>
<property name="bottomMargin">
- <number>3</number>
+ <number>10</number>
</property>
<item>
- <layout class="QHBoxLayout" name="sliderRingAnalogDeadzoneHorizontalLayout">
- <item>
- <widget class="QLabel" name="labelRingAnalogDeadzone">
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>10</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>10</number>
+ </property>
+ <property name="bottomMargin">
+ <number>10</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>10</number>
+ </property>
+ <item row="0" column="1">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>76</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="enable_ring_controller_label">
+ <property name="text">
+ <string>Enable Ring Input</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="enable_ring_controller_button">
<property name="text">
- <string>Deadzone: 0%</string>
+ <string>Enable</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="ring_controller_sensor_label">
+ <property name="text">
+ <string>Ring Sensor Value</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="ring_controller_sensor_value">
+ <property name="text">
+ <string>Not connected</string>
</property>
<property name="alignment">
- <set>Qt::AlignHCenter</set>
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
- </widget>
+ </widget>
</item>
- </layout>
- </item>
- <item>
- <widget class="QSlider" name="sliderRingAnalogDeadzone">
- <property name="maximum">
- <number>100</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
+ </layout>
</item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
+ </layout>
+ </widget>
+ </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@@ -273,6 +369,6 @@
<signal>rejected()</signal>
<receiver>ConfigureRingController</receiver>
<slot>reject()</slot>
- </connection>
+ </connection>
</connections>
</ui>
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 9b14e5903..9ea4c02da 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -14,6 +14,29 @@
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_system.h"
+constexpr std::array<u32, 7> LOCALE_BLOCKLIST{
+ // pzzefezrpnkzeidfej
+ // thhsrnhutlohsternp
+ // BHH4CG U
+ // Raa1AB S
+ // nn9
+ // ts
+ 0b0100011100001100000, // Japan
+ 0b0000001101001100100, // Americas
+ 0b0100110100001000010, // Europe
+ 0b0100110100001000010, // Australia
+ 0b0000000000000000000, // China
+ 0b0100111100001000000, // Korea
+ 0b0100111100001000000, // Taiwan
+};
+
+static bool IsValidLocale(u32 region_index, u32 language_index) {
+ if (region_index >= LOCALE_BLOCKLIST.size()) {
+ return false;
+ }
+ return ((LOCALE_BLOCKLIST.at(region_index) >> language_index) & 1) == 0;
+}
+
ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
: QWidget(parent), ui{std::make_unique<Ui::ConfigureSystem>()}, system{system_} {
ui->setupUi(this);
@@ -34,6 +57,25 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
}
});
+ const auto locale_check = [this](int index) {
+ const auto region_index = ConfigurationShared::GetComboboxIndex(
+ Settings::values.region_index.GetValue(true), ui->combo_region);
+ const auto language_index = ConfigurationShared::GetComboboxIndex(
+ Settings::values.language_index.GetValue(true), ui->combo_language);
+ const bool valid_locale = IsValidLocale(region_index, language_index);
+ ui->label_warn_invalid_locale->setVisible(!valid_locale);
+ if (!valid_locale) {
+ ui->label_warn_invalid_locale->setText(
+ tr("Warning: \"%1\" is not a valid language for region \"%2\"")
+ .arg(ui->combo_language->currentText())
+ .arg(ui->combo_region->currentText()));
+ }
+ };
+
+ connect(ui->combo_language, qOverload<int>(&QComboBox::currentIndexChanged), this,
+ locale_check);
+ connect(ui->combo_region, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check);
+
ui->label_console_id->setVisible(Settings::IsConfiguringGlobal());
ui->button_regenerate_console_id->setVisible(Settings::IsConfiguringGlobal());
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index 8f02880a7..a7f086258 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -42,13 +42,7 @@ private:
std::unique_ptr<Ui::ConfigureSystem> ui;
bool enabled = false;
- int language_index = 0;
- int region_index = 0;
- int time_zone_index = 0;
- int sound_index = 0;
-
ConfigurationShared::CheckState use_rng_seed;
- ConfigurationShared::CheckState use_custom_rtc;
Core::System& system;
};
diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui
index 46892f5c1..0459cd924 100644
--- a/src/yuzu/configuration/configure_system.ui
+++ b/src/yuzu/configuration/configure_system.ui
@@ -326,7 +326,7 @@
</item>
<item>
<property name="text">
- <string>English</string>
+ <string>American English</string>
</property>
</item>
<item>
@@ -546,6 +546,16 @@
</spacer>
</item>
<item>
+ <widget class="QLabel" name="label_warn_invalid_locale">
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="label_disable_info">
<property name="text">
<string>System settings are available only when game is not running.</string>
diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp
index 1edc5f1f3..5a545aa70 100644
--- a/src/yuzu/configuration/configure_tas.cpp
+++ b/src/yuzu/configuration/configure_tas.cpp
@@ -17,7 +17,6 @@ ConfigureTasDialog::ConfigureTasDialog(QWidget* parent)
setFocusPolicy(Qt::ClickFocus);
setWindowTitle(tr("TAS Configuration"));
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(ui->tas_path_button, &QToolButton::pressed, this,
[this] { SetDirectory(DirectoryTarget::TAS, ui->tas_path_edit); });
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp
index 9bb69cab1..41ef4250a 100644
--- a/src/yuzu/configuration/input_profiles.cpp
+++ b/src/yuzu/configuration/input_profiles.cpp
@@ -58,13 +58,16 @@ std::vector<std::string> InputProfiles::GetInputProfileNames() {
std::vector<std::string> profile_names;
profile_names.reserve(map_profiles.size());
- for (const auto& [profile_name, config] : map_profiles) {
+ auto it = map_profiles.cbegin();
+ while (it != map_profiles.cend()) {
+ const auto& [profile_name, config] = *it;
if (!ProfileExistsInFilesystem(profile_name)) {
- DeleteProfile(profile_name);
+ it = map_profiles.erase(it);
continue;
}
profile_names.push_back(profile_name);
+ ++it;
}
std::stable_sort(profile_names.begin(), profile_names.end());
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index e4bf16a04..e2f55ebae 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -20,9 +20,8 @@ ControllerDialog::ControllerDialog(Core::HID::HIDCore& hid_core_,
setWindowTitle(tr("Controller P1"));
resize(500, 350);
setMinimumSize(500, 350);
- // Remove the "?" button from the titlebar and enable the maximize button
- setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) |
- Qt::WindowMaximizeButtonHint);
+ // Enable the maximize button
+ setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
widget = new PlayerControlPreview(this);
refreshConfiguration();
@@ -93,7 +92,7 @@ void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) {
case Core::HID::ControllerTriggerType::Button:
case Core::HID::ControllerTriggerType::Stick: {
const auto buttons_values = controller->GetButtonsValues();
- const auto stick_values = controller->GetSticksValues();
+ const auto stick_values = controller->GetSticks();
u64 buttons = 0;
std::size_t index = 0;
for (const auto& button : buttons_values) {
@@ -101,12 +100,12 @@ void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) {
index++;
}
const InputCommon::TasInput::TasAnalog left_axis = {
- .x = stick_values[Settings::NativeAnalog::LStick].x.value,
- .y = stick_values[Settings::NativeAnalog::LStick].y.value,
+ .x = stick_values.left.x / 32767.f,
+ .y = stick_values.left.y / 32767.f,
};
const InputCommon::TasInput::TasAnalog right_axis = {
- .x = stick_values[Settings::NativeAnalog::RStick].x.value,
- .y = stick_values[Settings::NativeAnalog::RStick].y.value,
+ .x = stick_values.right.x / 32767.f,
+ .y = stick_values.right.y / 32767.f,
};
input_subsystem->GetTas()->RecordInput(buttons, left_axis, right_axis);
break;
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp
index d3e2d3c12..493ee0b17 100644
--- a/src/yuzu/debugger/profiler.cpp
+++ b/src/yuzu/debugger/profiler.cpp
@@ -49,9 +49,8 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Di
setObjectName(QStringLiteral("MicroProfile"));
setWindowTitle(tr("&MicroProfile"));
resize(1000, 600);
- // Remove the "?" button from the titlebar and enable the maximize button
- setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) |
- Qt::WindowMaximizeButtonHint);
+ // Enable the maximize button
+ setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
#if MICROPROFILE_ENABLED
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp
index 13723f6e5..6530186c1 100644
--- a/src/yuzu/hotkeys.cpp
+++ b/src/yuzu/hotkeys.cpp
@@ -21,7 +21,7 @@ void HotkeyRegistry::SaveHotkeys() {
{hotkey.first, group.first,
UISettings::ContextualShortcut({hotkey.second.keyseq.toString(),
hotkey.second.controller_keyseq,
- hotkey.second.context})});
+ hotkey.second.context, hotkey.second.repeat})});
}
}
}
@@ -47,6 +47,7 @@ void HotkeyRegistry::LoadHotkeys() {
hk.controller_shortcut->disconnect();
hk.controller_shortcut->SetKey(hk.controller_keyseq);
}
+ hk.repeat = shortcut.shortcut.repeat;
}
}
@@ -57,8 +58,7 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action
hk.shortcut = new QShortcut(hk.keyseq, widget, nullptr, nullptr, hk.context);
}
- hk.shortcut->setAutoRepeat(false);
-
+ hk.shortcut->setAutoRepeat(hk.repeat);
return hk.shortcut;
}
diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h
index dc5b7f628..848239c35 100644
--- a/src/yuzu/hotkeys.h
+++ b/src/yuzu/hotkeys.h
@@ -115,6 +115,7 @@ private:
QShortcut* shortcut = nullptr;
ControllerShortcut* controller_shortcut = nullptr;
Qt::ShortcutContext context = Qt::WindowShortcut;
+ bool repeat;
};
using HotkeyMap = std::map<QString, Hotkey>;
diff --git a/src/yuzu/install_dialog.cpp b/src/yuzu/install_dialog.cpp
index 84ec4fe13..673bbaa83 100644
--- a/src/yuzu/install_dialog.cpp
+++ b/src/yuzu/install_dialog.cpp
@@ -46,7 +46,6 @@ InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialo
vbox_layout->addLayout(hbox_layout);
setLayout(vbox_layout);
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setWindowTitle(tr("Install Files to NAND"));
}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 524650144..42b7b64c8 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -983,11 +983,6 @@ void GMainWindow::InitializeWidgets() {
filter_status_button->setFocusPolicy(Qt::NoFocus);
connect(filter_status_button, &QPushButton::clicked, this,
&GMainWindow::OnToggleAdaptingFilter);
- auto filter = Settings::values.scaling_filter.GetValue();
- if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
- filter == Settings::ScalingFilter::Fsr) {
- Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor);
- }
UpdateFilterText();
filter_status_button->setCheckable(true);
filter_status_button->setChecked(true);
@@ -1839,9 +1834,11 @@ void GMainWindow::OnEmulationStopTimeExpired() {
void GMainWindow::OnEmulationStopped() {
shutdown_timer.stop();
- emu_thread->disconnect();
- emu_thread->wait();
- emu_thread = nullptr;
+ if (emu_thread) {
+ emu_thread->disconnect();
+ emu_thread->wait();
+ emu_thread.reset();
+ }
if (shutdown_dialog) {
shutdown_dialog->deleteLater();
@@ -2229,8 +2226,10 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ
}
switch (target) {
- case GameListRemoveTarget::GlShaderCache:
case GameListRemoveTarget::VkShaderCache:
+ RemoveVulkanDriverPipelineCache(program_id);
+ [[fallthrough]];
+ case GameListRemoveTarget::GlShaderCache:
RemoveTransferableShaderCache(program_id, target);
break;
case GameListRemoveTarget::AllShaderCache:
@@ -2271,6 +2270,22 @@ void GMainWindow::RemoveTransferableShaderCache(u64 program_id, GameListRemoveTa
}
}
+void GMainWindow::RemoveVulkanDriverPipelineCache(u64 program_id) {
+ static constexpr std::string_view target_file_name = "vulkan_pipelines.bin";
+
+ const auto shader_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir);
+ const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
+ const auto target_file = shader_cache_folder_path / target_file_name;
+
+ if (!Common::FS::Exists(target_file)) {
+ return;
+ }
+ if (!Common::FS::RemoveFile(target_file)) {
+ QMessageBox::warning(this, tr("Error Removing Vulkan Driver Pipeline Cache"),
+ tr("Failed to remove the driver pipeline cache."));
+ }
+}
+
void GMainWindow::RemoveAllTransferableShaderCaches(u64 program_id) {
const auto shader_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir);
const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id);
@@ -2738,8 +2753,7 @@ void GMainWindow::OnMenuInstallToNAND() {
ui->action_Install_File_NAND->setEnabled(false);
install_progress = new QProgressDialog(QString{}, tr("Cancel"), 0, total_size, this);
- install_progress->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint &
- ~Qt::WindowMaximizeButtonHint);
+ install_progress->setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint);
install_progress->setAttribute(Qt::WA_DeleteOnClose, true);
install_progress->setFixedWidth(installDialog.GetMinimumWidth() + 40);
install_progress->show();
@@ -3011,6 +3025,8 @@ void GMainWindow::OnStopGame() {
if (OnShutdownBegin()) {
OnShutdownBeginDialog();
+ } else {
+ OnEmulationStopped();
}
}
@@ -3447,10 +3463,6 @@ void GMainWindow::OnToggleAdaptingFilter() {
} else {
filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1);
}
- if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
- filter == Settings::ScalingFilter::Fsr) {
- filter = Settings::ScalingFilter::NearestNeighbor;
- }
Settings::values.scaling_filter.SetValue(filter);
filter_status_button->setChecked(true);
UpdateFilterText();
@@ -3708,15 +3720,36 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie
}
}
+std::string GMainWindow::CreateTASFramesString(
+ std::array<size_t, InputCommon::TasInput::PLAYER_NUMBER> frames) const {
+ std::string string = "";
+ size_t maxPlayerIndex = 0;
+ for (size_t i = 0; i < frames.size(); i++) {
+ if (frames[i] != 0) {
+ if (maxPlayerIndex != 0)
+ string += ", ";
+ while (maxPlayerIndex++ != i)
+ string += "0, ";
+ string += std::to_string(frames[i]);
+ }
+ }
+ return string;
+}
+
QString GMainWindow::GetTasStateDescription() const {
auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus();
+ std::string tas_frames_string = CreateTASFramesString(total_tas_frames);
switch (tas_status) {
case InputCommon::TasInput::TasState::Running:
- return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames);
+ return tr("TAS state: Running %1/%2")
+ .arg(current_tas_frame)
+ .arg(QString::fromStdString(tas_frames_string));
case InputCommon::TasInput::TasState::Recording:
- return tr("TAS state: Recording %1").arg(total_tas_frames);
+ return tr("TAS state: Recording %1").arg(total_tas_frames[0]);
case InputCommon::TasInput::TasState::Stopped:
- return tr("TAS state: Idle %1/%2").arg(current_tas_frame).arg(total_tas_frames);
+ return tr("TAS state: Idle %1/%2")
+ .arg(current_tas_frame)
+ .arg(QString::fromStdString(tas_frames_string));
default:
return tr("TAS State: Invalid");
}
@@ -4413,6 +4446,11 @@ int main(int argc, char* argv[]) {
}
#endif
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ // Disables the "?" button on all dialogs. Disabled by default on Qt6.
+ QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
+#endif
+
// Enables the core to make the qt created contexts current on std::threads
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
QApplication app(argc, argv);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index db318485d..0f61abc7a 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -12,6 +12,7 @@
#include "common/announce_multiplayer_room.h"
#include "common/common_types.h"
+#include "input_common/drivers/tas_input.h"
#include "yuzu/compatibility_list.h"
#include "yuzu/hotkeys.h"
@@ -266,6 +267,9 @@ private:
void changeEvent(QEvent* event) override;
void closeEvent(QCloseEvent* event) override;
+ std::string CreateTASFramesString(
+ std::array<size_t, InputCommon::TasInput::PLAYER_NUMBER> frames) const;
+
#ifdef __unix__
void SetupSigInterrupts();
static void HandleSigInterrupt(int);
@@ -347,6 +351,7 @@ private:
void RemoveUpdateContent(u64 program_id, InstalledEntryType type);
void RemoveAddOnContent(u64 program_id, InstalledEntryType type);
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target);
+ void RemoveVulkanDriverPipelineCache(u64 program_id);
void RemoveAllTransferableShaderCaches(u64 program_id);
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path);
std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp
index cbd52da85..d71cc23a7 100644
--- a/src/yuzu/multiplayer/direct_connect.cpp
+++ b/src/yuzu/multiplayer/direct_connect.cpp
@@ -81,20 +81,13 @@ void DirectConnectWindow::Connect() {
}
}
}
- switch (static_cast<ConnectionType>(ui->connection_type->currentIndex())) {
- case ConnectionType::TraversalServer:
- break;
- case ConnectionType::IP:
- if (!ui->ip->hasAcceptableInput()) {
- NetworkMessage::ErrorManager::ShowError(
- NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID);
- return;
- }
- if (!ui->port->hasAcceptableInput()) {
- NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::PORT_NOT_VALID);
- return;
- }
- break;
+ if (!ui->ip->hasAcceptableInput()) {
+ NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID);
+ return;
+ }
+ if (!ui->port->hasAcceptableInput()) {
+ NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::PORT_NOT_VALID);
+ return;
}
// Store settings
diff --git a/src/yuzu/multiplayer/direct_connect.ui b/src/yuzu/multiplayer/direct_connect.ui
index 57d6ec25a..0dd4e6829 100644
--- a/src/yuzu/multiplayer/direct_connect.ui
+++ b/src/yuzu/multiplayer/direct_connect.ui
@@ -27,19 +27,10 @@
<number>0</number>
</property>
<item>
- <widget class="QComboBox" name="connection_type">
- <item>
- <property name="text">
- <string>IP Address</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
<widget class="QWidget" name="ip_container" native="true">
<layout class="QHBoxLayout" name="ip_layout">
<property name="leftMargin">
- <number>5</number>
+ <number>0</number>
</property>
<property name="topMargin">
<number>0</number>
@@ -53,17 +44,17 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
- <string>IP</string>
+ <string>Server Address</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="ip">
<property name="toolTip">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;IPv4 address of the host&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Server address of the host&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maxLength">
- <number>16</number>
+ <number>253</number>
</property>
</widget>
</item>
@@ -85,6 +76,12 @@
<property name="placeholderText">
<string notr="true" extracomment="placeholder string that tells user default port">24872</string>
</property>
+ <property name="maximumSize">
+ <size>
+ <width>65</width>
+ <height>50</height>
+ </size>
+ </property>
</widget>
</item>
</layout>
diff --git a/src/yuzu/multiplayer/validation.h b/src/yuzu/multiplayer/validation.h
index dd25af280..cbbe6757b 100644
--- a/src/yuzu/multiplayer/validation.h
+++ b/src/yuzu/multiplayer/validation.h
@@ -38,11 +38,28 @@ private:
QRegularExpression(QStringLiteral("^[a-zA-Z0-9._ -]{4,20}"));
QRegularExpressionValidator nickname;
- /// ipv4 address only
- // TODO remove this when we support hostnames in direct connect
+ /// ipv4 / ipv6 / hostnames
QRegularExpression ip_regex = QRegularExpression(QStringLiteral(
- "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|"
- "2[0-4][0-9]|25[0-5])"));
+ // IPv4 regex
+ "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|"
+ // IPv6 regex
+ "^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|"
+ "(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-"
+ "5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|"
+ "(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)"
+ "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|"
+ "(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]"
+ "\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2["
+ "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2["
+ "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2["
+ "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?"
+ "\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?$|"
+ // Hostname regex
+ "^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}$"));
QRegularExpressionValidator ip;
/// port must be between 0 and 65535
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 2006b883e..db43b7033 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -22,6 +22,7 @@ struct ContextualShortcut {
QString keyseq;
QString controller_keyseq;
int context;
+ bool repeat;
};
struct Shortcut {
diff --git a/src/yuzu/util/limitable_input_dialog.cpp b/src/yuzu/util/limitable_input_dialog.cpp
index bbb370595..5f6a9c193 100644
--- a/src/yuzu/util/limitable_input_dialog.cpp
+++ b/src/yuzu/util/limitable_input_dialog.cpp
@@ -16,8 +16,6 @@ LimitableInputDialog::LimitableInputDialog(QWidget* parent) : QDialog{parent} {
LimitableInputDialog::~LimitableInputDialog() = default;
void LimitableInputDialog::CreateUI() {
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
-
text_label = new QLabel(this);
text_entry = new QLineEdit(this);
text_label_invalid = new QLabel(this);
diff --git a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
index 4b10fa517..1670aa596 100644
--- a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
+++ b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
@@ -8,7 +8,6 @@
SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) {
setWindowTitle(tr("Enter a hotkey"));
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
key_sequence = new QKeySequenceEdit;