summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/k_code_memory.cpp6
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/service/pm/pm.cpp45
-rw-r--r--src/input_common/drivers/sdl_driver.cpp6
-rw-r--r--src/input_common/input_poller.cpp2
-rw-r--r--src/yuzu/configuration/config.cpp6
-rw-r--r--src/yuzu/configuration/config.h2
-rw-r--r--src/yuzu/configuration/configure_general.cpp2
-rw-r--r--src/yuzu/configuration/configure_general.ui7
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp26
-rw-r--r--src/yuzu/main.cpp137
-rw-r--r--src/yuzu/main.h4
-rw-r--r--src/yuzu/uisettings.h1
-rw-r--r--src/yuzu_cmd/config.cpp36
14 files changed, 204 insertions, 78 deletions
diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp
index d69f7ffb7..0b225e8e0 100644
--- a/src/core/hle/kernel/k_code_memory.cpp
+++ b/src/core/hle/kernel/k_code_memory.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/alignment.h"
5#include "common/common_types.h" 6#include "common/common_types.h"
6#include "core/device_memory.h" 7#include "core/device_memory.h"
7#include "core/hle/kernel/k_auto_object.h" 8#include "core/hle/kernel/k_auto_object.h"
@@ -28,8 +29,7 @@ ResultCode KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr
28 auto& page_table = m_owner->PageTable(); 29 auto& page_table = m_owner->PageTable();
29 30
30 // Construct the page group. 31 // Construct the page group.
31 KMemoryInfo kBlockInfo = page_table.QueryInfo(addr); 32 m_page_group = KPageLinkedList(addr, Common::DivideUp(size, PageSize));
32 m_page_group = KPageLinkedList(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages());
33 33
34 // Lock the memory. 34 // Lock the memory.
35 R_TRY(page_table.LockForCodeMemory(addr, size)) 35 R_TRY(page_table.LockForCodeMemory(addr, size))
@@ -143,4 +143,4 @@ ResultCode KCodeMemory::UnmapFromOwner(VAddr address, size_t size) {
143 return ResultSuccess; 143 return ResultSuccess;
144} 144}
145 145
146} // namespace Kernel \ No newline at end of file 146} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 4f7aebf3f..9387373c1 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -396,7 +396,7 @@ static ResultCode GetProcessId(Core::System& system, u64* out_process_id, Handle
396 // Get the process id. 396 // Get the process id.
397 *out_process_id = process->GetId(); 397 *out_process_id = process->GetId();
398 398
399 return ResultInvalidHandle; 399 return ResultSuccess;
400} 400}
401 401
402static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low, 402static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low,
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp
index 277abc17a..057666021 100644
--- a/src/core/hle/service/pm/pm.cpp
+++ b/src/core/hle/service/pm/pm.cpp
@@ -91,6 +91,8 @@ public:
91 {4, &DebugMonitor::GetApplicationProcessId, "GetApplicationProcessId"}, 91 {4, &DebugMonitor::GetApplicationProcessId, "GetApplicationProcessId"},
92 {5, nullptr, "HookToCreateApplicationProgress"}, 92 {5, nullptr, "HookToCreateApplicationProgress"},
93 {6, nullptr, "ClearHook"}, 93 {6, nullptr, "ClearHook"},
94 {65000, &DebugMonitor::AtmosphereGetProcessInfo, "AtmosphereGetProcessInfo"},
95 {65001, nullptr, "AtmosphereGetCurrentLimitInfo"},
94 }; 96 };
95 // clang-format on 97 // clang-format on
96 98
@@ -125,6 +127,49 @@ private:
125 GetApplicationPidGeneric(ctx, kernel.GetProcessList()); 127 GetApplicationPidGeneric(ctx, kernel.GetProcessList());
126 } 128 }
127 129
130 void AtmosphereGetProcessInfo(Kernel::HLERequestContext& ctx) {
131 // https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/pm/source/impl/pm_process_manager.cpp#L614
132 // This implementation is incomplete; only a handle to the process is returned.
133 IPC::RequestParser rp{ctx};
134 const auto pid = rp.PopRaw<u64>();
135
136 LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid);
137
138 const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) {
139 return proc->GetProcessID() == pid;
140 });
141
142 if (!process.has_value()) {
143 IPC::ResponseBuilder rb{ctx, 2};
144 rb.Push(ResultProcessNotFound);
145 return;
146 }
147
148 struct ProgramLocation {
149 u64 program_id;
150 u8 storage_id;
151 };
152 static_assert(sizeof(ProgramLocation) == 0x10, "ProgramLocation has an invalid size");
153
154 struct OverrideStatus {
155 u64 keys_held;
156 u64 flags;
157 };
158 static_assert(sizeof(OverrideStatus) == 0x10, "OverrideStatus has an invalid size");
159
160 OverrideStatus override_status{};
161 ProgramLocation program_location{
162 .program_id = (*process)->GetProgramID(),
163 .storage_id = 0,
164 };
165
166 IPC::ResponseBuilder rb{ctx, 10, 1};
167 rb.Push(ResultSuccess);
168 rb.PushCopyObjects(*process);
169 rb.PushRaw(program_location);
170 rb.PushRaw(override_status);
171 }
172
128 const Kernel::KernelCore& kernel; 173 const Kernel::KernelCore& kernel;
129}; 174};
130 175
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 655eb5275..5cf1987ad 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -811,7 +811,7 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p
811 PreSetAxis(identifier, binding_left_x.value.axis); 811 PreSetAxis(identifier, binding_left_x.value.axis);
812 PreSetAxis(identifier, binding_left_y.value.axis); 812 PreSetAxis(identifier, binding_left_y.value.axis);
813 const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis); 813 const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis);
814 const auto left_offset_y = -GetAxis(identifier, binding_left_y.value.axis); 814 const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis);
815 mapping.insert_or_assign(Settings::NativeAnalog::LStick, 815 mapping.insert_or_assign(Settings::NativeAnalog::LStick,
816 BuildParamPackageForAnalog(identifier, binding_left_x.value.axis, 816 BuildParamPackageForAnalog(identifier, binding_left_x.value.axis,
817 binding_left_y.value.axis, 817 binding_left_y.value.axis,
@@ -822,7 +822,7 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p
822 PreSetAxis(identifier, binding_left_x.value.axis); 822 PreSetAxis(identifier, binding_left_x.value.axis);
823 PreSetAxis(identifier, binding_left_y.value.axis); 823 PreSetAxis(identifier, binding_left_y.value.axis);
824 const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis); 824 const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis);
825 const auto left_offset_y = -GetAxis(identifier, binding_left_y.value.axis); 825 const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis);
826 mapping.insert_or_assign(Settings::NativeAnalog::LStick, 826 mapping.insert_or_assign(Settings::NativeAnalog::LStick,
827 BuildParamPackageForAnalog(identifier, binding_left_x.value.axis, 827 BuildParamPackageForAnalog(identifier, binding_left_x.value.axis,
828 binding_left_y.value.axis, 828 binding_left_y.value.axis,
@@ -837,7 +837,7 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p
837 PreSetAxis(identifier, binding_right_x.value.axis); 837 PreSetAxis(identifier, binding_right_x.value.axis);
838 PreSetAxis(identifier, binding_right_y.value.axis); 838 PreSetAxis(identifier, binding_right_y.value.axis);
839 const auto right_offset_x = -GetAxis(identifier, binding_right_x.value.axis); 839 const auto right_offset_x = -GetAxis(identifier, binding_right_x.value.axis);
840 const auto right_offset_y = -GetAxis(identifier, binding_right_y.value.axis); 840 const auto right_offset_y = GetAxis(identifier, binding_right_y.value.axis);
841 mapping.insert_or_assign(Settings::NativeAnalog::RStick, 841 mapping.insert_or_assign(Settings::NativeAnalog::RStick,
842 BuildParamPackageForAnalog(identifier, binding_right_x.value.axis, 842 BuildParamPackageForAnalog(identifier, binding_right_x.value.axis,
843 binding_right_y.value.axis, right_offset_x, 843 binding_right_y.value.axis, right_offset_x,
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 2f3c0735a..7f3c08597 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -181,7 +181,7 @@ public:
181 .raw_value = input_engine->GetAxis(identifier, axis_y), 181 .raw_value = input_engine->GetAxis(identifier, axis_y),
182 .properties = properties_y, 182 .properties = properties_y,
183 }; 183 };
184 // This is a workaround too keep compatibility with old yuzu versions. Vertical axis is 184 // This is a workaround to keep compatibility with old yuzu versions. Vertical axis is
185 // inverted on SDL compared to Nintendo 185 // inverted on SDL compared to Nintendo
186 if (invert_axis_y) { 186 if (invert_axis_y) {
187 status.y.raw_value = -status.y.raw_value; 187 status.y.raw_value = -status.y.raw_value;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 2c8c10c50..9ee7992e7 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -65,12 +65,14 @@ const std::array<int, 2> Config::default_stick_mod = {
65// This must be in alphabetical order according to action name as it must have the same order as 65// This must be in alphabetical order according to action name as it must have the same order as
66// UISetting::values.shortcuts, which is alphabetically ordered. 66// UISetting::values.shortcuts, which is alphabetically ordered.
67// clang-format off 67// clang-format off
68const std::array<UISettings::Shortcut, 20> Config::default_hotkeys{{ 68const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{
69 {QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}}, 69 {QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}},
70 {QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}}, 70 {QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}},
71 {QStringLiteral("Audio Volume Up"), QStringLiteral("Main Window"), {QStringLiteral("+"), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}}, 71 {QStringLiteral("Audio Volume Up"), QStringLiteral("Main Window"), {QStringLiteral("+"), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}},
72 {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}}, 72 {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}},
73 {QStringLiteral("Change Adapting Filter"), QStringLiteral("Main Window"), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}},
73 {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}}, 74 {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}},
75 {QStringLiteral("Change GPU Accuracy"), QStringLiteral("Main Window"), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut}},
74 {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut}}, 76 {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut}},
75 {QStringLiteral("Exit Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut}}, 77 {QStringLiteral("Exit Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut}},
76 {QStringLiteral("Exit yuzu"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut}}, 78 {QStringLiteral("Exit yuzu"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut}},
@@ -767,6 +769,7 @@ void Config::ReadUIValues() {
767 ReadBasicSetting(UISettings::values.callout_flags); 769 ReadBasicSetting(UISettings::values.callout_flags);
768 ReadBasicSetting(UISettings::values.show_console); 770 ReadBasicSetting(UISettings::values.show_console);
769 ReadBasicSetting(UISettings::values.pause_when_in_background); 771 ReadBasicSetting(UISettings::values.pause_when_in_background);
772 ReadBasicSetting(UISettings::values.mute_when_in_background);
770 ReadBasicSetting(UISettings::values.hide_mouse); 773 ReadBasicSetting(UISettings::values.hide_mouse);
771 774
772 qt_config->endGroup(); 775 qt_config->endGroup();
@@ -1295,6 +1298,7 @@ void Config::SaveUIValues() {
1295 WriteBasicSetting(UISettings::values.callout_flags); 1298 WriteBasicSetting(UISettings::values.callout_flags);
1296 WriteBasicSetting(UISettings::values.show_console); 1299 WriteBasicSetting(UISettings::values.show_console);
1297 WriteBasicSetting(UISettings::values.pause_when_in_background); 1300 WriteBasicSetting(UISettings::values.pause_when_in_background);
1301 WriteBasicSetting(UISettings::values.mute_when_in_background);
1298 WriteBasicSetting(UISettings::values.hide_mouse); 1302 WriteBasicSetting(UISettings::values.hide_mouse);
1299 1303
1300 qt_config->endGroup(); 1304 qt_config->endGroup();
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 60b20a62f..ae3e36a11 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -46,7 +46,7 @@ public:
46 default_mouse_buttons; 46 default_mouse_buttons;
47 static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; 47 static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
48 static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; 48 static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
49 static const std::array<UISettings::Shortcut, 20> default_hotkeys; 49 static const std::array<UISettings::Shortcut, 22> default_hotkeys;
50 50
51 static constexpr UISettings::Theme default_theme{ 51 static constexpr UISettings::Theme default_theme{
52#ifdef _WIN32 52#ifdef _WIN32
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 566879317..978a29fe6 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -46,6 +46,7 @@ void ConfigureGeneral::SetConfiguration() {
46 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); 46 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue());
47 ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); 47 ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue());
48 ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue()); 48 ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue());
49 ui->toggle_background_mute->setChecked(UISettings::values.mute_when_in_background.GetValue());
49 ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue()); 50 ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue());
50 51
51 ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue()); 52 ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue());
@@ -95,6 +96,7 @@ void ConfigureGeneral::ApplyConfiguration() {
95 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); 96 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
96 UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); 97 UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
97 UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); 98 UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
99 UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked();
98 UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked(); 100 UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
99 101
100 Settings::values.fps_cap.SetValue(ui->fps_cap->value()); 102 Settings::values.fps_cap.SetValue(ui->fps_cap->value());
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui
index 112dc72b3..bfc771135 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -164,6 +164,13 @@
164 </widget> 164 </widget>
165 </item> 165 </item>
166 <item> 166 <item>
167 <widget class="QCheckBox" name="toggle_background_mute">
168 <property name="text">
169 <string>Mute audio when in background</string>
170 </property>
171 </widget>
172 </item>
173 <item>
167 <widget class="QCheckBox" name="toggle_hide_mouse"> 174 <widget class="QCheckBox" name="toggle_hide_mouse">
168 <property name="text"> 175 <property name="text">
169 <string>Hide mouse on inactivity</string> 176 <string>Hide mouse on inactivity</string>
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index cc0534907..9db564663 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -488,6 +488,32 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
488 emulated_controller->SetStickParam(analog_id, {}); 488 emulated_controller->SetStickParam(analog_id, {});
489 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); 489 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
490 }); 490 });
491 context_menu.addAction(tr("Center axis"), [&] {
492 const auto stick_value =
493 emulated_controller->GetSticksValues()[analog_id];
494 const float offset_x = stick_value.x.properties.offset;
495 const float offset_y = stick_value.y.properties.offset;
496 float raw_value_x = stick_value.x.raw_value;
497 float raw_value_y = stick_value.y.raw_value;
498 // See Core::HID::SanitizeStick() to obtain the original raw axis value
499 if (std::abs(offset_x) < 0.5f) {
500 if (raw_value_x > 0) {
501 raw_value_x *= 1 + offset_x;
502 } else {
503 raw_value_x *= 1 - offset_x;
504 }
505 }
506 if (std::abs(offset_x) < 0.5f) {
507 if (raw_value_y > 0) {
508 raw_value_y *= 1 + offset_y;
509 } else {
510 raw_value_y *= 1 - offset_y;
511 }
512 }
513 param.Set("offset_x", -raw_value_x + offset_x);
514 param.Set("offset_y", -raw_value_y + offset_y);
515 emulated_controller->SetStickParam(analog_id, param);
516 });
491 context_menu.addAction(tr("Invert axis"), [&] { 517 context_menu.addAction(tr("Invert axis"), [&] {
492 if (sub_button_id == 2 || sub_button_id == 3) { 518 if (sub_button_id == 2 || sub_button_id == 3) {
493 const bool invert_value = param.Get("invert_x", "+") == "-"; 519 const bool invert_value = param.Get("invert_x", "+") == "-";
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index c89909737..3c2d7d080 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -806,21 +806,8 @@ void GMainWindow::InitializeWidgets() {
806 filter_status_button = new QPushButton(); 806 filter_status_button = new QPushButton();
807 filter_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); 807 filter_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
808 filter_status_button->setFocusPolicy(Qt::NoFocus); 808 filter_status_button->setFocusPolicy(Qt::NoFocus);
809 connect(filter_status_button, &QPushButton::clicked, [&] { 809 connect(filter_status_button, &QPushButton::clicked, this,
810 auto filter = Settings::values.scaling_filter.GetValue(); 810 &GMainWindow::OnToggleAdaptingFilter);
811 if (filter == Settings::ScalingFilter::LastFilter) {
812 filter = Settings::ScalingFilter::NearestNeighbor;
813 } else {
814 filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1);
815 }
816 if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
817 filter == Settings::ScalingFilter::Fsr) {
818 filter = Settings::ScalingFilter::NearestNeighbor;
819 }
820 Settings::values.scaling_filter.SetValue(filter);
821 filter_status_button->setChecked(true);
822 UpdateFilterText();
823 });
824 auto filter = Settings::values.scaling_filter.GetValue(); 811 auto filter = Settings::values.scaling_filter.GetValue();
825 if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL && 812 if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
826 filter == Settings::ScalingFilter::Fsr) { 813 filter == Settings::ScalingFilter::Fsr) {
@@ -835,25 +822,7 @@ void GMainWindow::InitializeWidgets() {
835 dock_status_button = new QPushButton(); 822 dock_status_button = new QPushButton();
836 dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); 823 dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
837 dock_status_button->setFocusPolicy(Qt::NoFocus); 824 dock_status_button->setFocusPolicy(Qt::NoFocus);
838 connect(dock_status_button, &QPushButton::clicked, [&] { 825 connect(dock_status_button, &QPushButton::clicked, this, &GMainWindow::OnToggleDockedMode);
839 const bool is_docked = Settings::values.use_docked_mode.GetValue();
840 auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
841 auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
842
843 if (!is_docked && handheld->IsConnected()) {
844 QMessageBox::warning(this, tr("Invalid config detected"),
845 tr("Handheld controller can't be used on docked mode. Pro "
846 "controller will be selected."));
847 handheld->Disconnect();
848 player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
849 player_1->Connect();
850 controller_dialog->refreshConfiguration();
851 }
852
853 Settings::values.use_docked_mode.SetValue(!is_docked);
854 dock_status_button->setChecked(!is_docked);
855 OnDockedModeChanged(is_docked, !is_docked, *system);
856 });
857 dock_status_button->setText(tr("DOCK")); 826 dock_status_button->setText(tr("DOCK"));
858 dock_status_button->setCheckable(true); 827 dock_status_button->setCheckable(true);
859 dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); 828 dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
@@ -863,22 +832,7 @@ void GMainWindow::InitializeWidgets() {
863 gpu_accuracy_button->setObjectName(QStringLiteral("GPUStatusBarButton")); 832 gpu_accuracy_button->setObjectName(QStringLiteral("GPUStatusBarButton"));
864 gpu_accuracy_button->setCheckable(true); 833 gpu_accuracy_button->setCheckable(true);
865 gpu_accuracy_button->setFocusPolicy(Qt::NoFocus); 834 gpu_accuracy_button->setFocusPolicy(Qt::NoFocus);
866 connect(gpu_accuracy_button, &QPushButton::clicked, [this] { 835 connect(gpu_accuracy_button, &QPushButton::clicked, this, &GMainWindow::OnToggleGpuAccuracy);
867 switch (Settings::values.gpu_accuracy.GetValue()) {
868 case Settings::GPUAccuracy::High: {
869 Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::Normal);
870 break;
871 }
872 case Settings::GPUAccuracy::Normal:
873 case Settings::GPUAccuracy::Extreme:
874 default: {
875 Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High);
876 }
877 }
878
879 system->ApplySettings();
880 UpdateGPUAccuracyButton();
881 });
882 UpdateGPUAccuracyButton(); 836 UpdateGPUAccuracyButton();
883 statusBar()->insertPermanentWidget(0, gpu_accuracy_button); 837 statusBar()->insertPermanentWidget(0, gpu_accuracy_button);
884 838
@@ -1009,12 +963,10 @@ void GMainWindow::InitializeHotkeys() {
1009 ToggleFullscreen(); 963 ToggleFullscreen();
1010 } 964 }
1011 }); 965 });
1012 connect_shortcut(QStringLiteral("Change Docked Mode"), [&] { 966 connect_shortcut(QStringLiteral("Change Adapting Filter"),
1013 Settings::values.use_docked_mode.SetValue(!Settings::values.use_docked_mode.GetValue()); 967 &GMainWindow::OnToggleAdaptingFilter);
1014 OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(), 968 connect_shortcut(QStringLiteral("Change Docked Mode"), &GMainWindow::OnToggleDockedMode);
1015 Settings::values.use_docked_mode.GetValue(), *system); 969 connect_shortcut(QStringLiteral("Change GPU Accuracy"), &GMainWindow::OnToggleGpuAccuracy);
1016 dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
1017 });
1018 connect_shortcut(QStringLiteral("Audio Mute/Unmute"), 970 connect_shortcut(QStringLiteral("Audio Mute/Unmute"),
1019 [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); 971 [] { Settings::values.audio_muted = !Settings::values.audio_muted; });
1020 connect_shortcut(QStringLiteral("Audio Volume Down"), [] { 972 connect_shortcut(QStringLiteral("Audio Volume Down"), [] {
@@ -1052,8 +1004,10 @@ void GMainWindow::SetDefaultUIGeometry() {
1052} 1004}
1053 1005
1054void GMainWindow::RestoreUIState() { 1006void GMainWindow::RestoreUIState() {
1007 setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
1055 restoreGeometry(UISettings::values.geometry); 1008 restoreGeometry(UISettings::values.geometry);
1056 restoreState(UISettings::values.state); 1009 restoreState(UISettings::values.state);
1010 render_window->setWindowFlags(render_window->windowFlags() & ~Qt::FramelessWindowHint);
1057 render_window->restoreGeometry(UISettings::values.renderwindow_geometry); 1011 render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
1058#if MICROPROFILE_ENABLED 1012#if MICROPROFILE_ENABLED
1059 microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); 1013 microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);
@@ -1080,14 +1034,14 @@ void GMainWindow::RestoreUIState() {
1080} 1034}
1081 1035
1082void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) { 1036void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
1083 if (!UISettings::values.pause_when_in_background) {
1084 return;
1085 }
1086 if (state != Qt::ApplicationHidden && state != Qt::ApplicationInactive && 1037 if (state != Qt::ApplicationHidden && state != Qt::ApplicationInactive &&
1087 state != Qt::ApplicationActive) { 1038 state != Qt::ApplicationActive) {
1088 LOG_DEBUG(Frontend, "ApplicationState unusual flag: {} ", state); 1039 LOG_DEBUG(Frontend, "ApplicationState unusual flag: {} ", state);
1089 } 1040 }
1090 if (emulation_running) { 1041 if (!emulation_running) {
1042 return;
1043 }
1044 if (UISettings::values.pause_when_in_background) {
1091 if (emu_thread->IsRunning() && 1045 if (emu_thread->IsRunning() &&
1092 (state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) { 1046 (state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) {
1093 auto_paused = true; 1047 auto_paused = true;
@@ -1097,6 +1051,16 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
1097 OnStartGame(); 1051 OnStartGame();
1098 } 1052 }
1099 } 1053 }
1054 if (UISettings::values.mute_when_in_background) {
1055 if (!Settings::values.audio_muted &&
1056 (state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) {
1057 Settings::values.audio_muted = true;
1058 auto_muted = true;
1059 } else if (auto_muted && state == Qt::ApplicationActive) {
1060 Settings::values.audio_muted = false;
1061 auto_muted = false;
1062 }
1063 }
1100} 1064}
1101 1065
1102void GMainWindow::ConnectWidgetEvents() { 1066void GMainWindow::ConnectWidgetEvents() {
@@ -2866,6 +2830,59 @@ void GMainWindow::OnTasReset() {
2866 input_subsystem->GetTas()->Reset(); 2830 input_subsystem->GetTas()->Reset();
2867} 2831}
2868 2832
2833void GMainWindow::OnToggleDockedMode() {
2834 const bool is_docked = Settings::values.use_docked_mode.GetValue();
2835 auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
2836 auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
2837
2838 if (!is_docked && handheld->IsConnected()) {
2839 QMessageBox::warning(this, tr("Invalid config detected"),
2840 tr("Handheld controller can't be used on docked mode. Pro "
2841 "controller will be selected."));
2842 handheld->Disconnect();
2843 player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
2844 player_1->Connect();
2845 controller_dialog->refreshConfiguration();
2846 }
2847
2848 Settings::values.use_docked_mode.SetValue(!is_docked);
2849 dock_status_button->setChecked(!is_docked);
2850 OnDockedModeChanged(is_docked, !is_docked, *system);
2851}
2852
2853void GMainWindow::OnToggleGpuAccuracy() {
2854 switch (Settings::values.gpu_accuracy.GetValue()) {
2855 case Settings::GPUAccuracy::High: {
2856 Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::Normal);
2857 break;
2858 }
2859 case Settings::GPUAccuracy::Normal:
2860 case Settings::GPUAccuracy::Extreme:
2861 default: {
2862 Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High);
2863 }
2864 }
2865
2866 system->ApplySettings();
2867 UpdateGPUAccuracyButton();
2868}
2869
2870void GMainWindow::OnToggleAdaptingFilter() {
2871 auto filter = Settings::values.scaling_filter.GetValue();
2872 if (filter == Settings::ScalingFilter::LastFilter) {
2873 filter = Settings::ScalingFilter::NearestNeighbor;
2874 } else {
2875 filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1);
2876 }
2877 if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
2878 filter == Settings::ScalingFilter::Fsr) {
2879 filter = Settings::ScalingFilter::NearestNeighbor;
2880 }
2881 Settings::values.scaling_filter.SetValue(filter);
2882 filter_status_button->setChecked(true);
2883 UpdateFilterText();
2884}
2885
2869void GMainWindow::OnConfigurePerGame() { 2886void GMainWindow::OnConfigurePerGame() {
2870 const u64 title_id = system->GetCurrentProcessProgramID(); 2887 const u64 title_id = system->GetCurrentProcessProgramID();
2871 OpenPerGameConfiguration(title_id, game_path.toStdString()); 2888 OpenPerGameConfiguration(title_id, game_path.toStdString());
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index ca4ab9af5..6a35b9e3d 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -284,6 +284,9 @@ private slots:
284 void OnTasStartStop(); 284 void OnTasStartStop();
285 void OnTasRecord(); 285 void OnTasRecord();
286 void OnTasReset(); 286 void OnTasReset();
287 void OnToggleDockedMode();
288 void OnToggleGpuAccuracy();
289 void OnToggleAdaptingFilter();
287 void OnConfigurePerGame(); 290 void OnConfigurePerGame();
288 void OnLoadAmiibo(); 291 void OnLoadAmiibo();
289 void OnOpenYuzuFolder(); 292 void OnOpenYuzuFolder();
@@ -369,6 +372,7 @@ private:
369 QString game_path; 372 QString game_path;
370 373
371 bool auto_paused = false; 374 bool auto_paused = false;
375 bool auto_muted = false;
372 QTimer mouse_hide_timer; 376 QTimer mouse_hide_timer;
373 377
374 // FS 378 // FS
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index f7298ddad..06e8b46da 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -73,6 +73,7 @@ struct Values {
73 Settings::BasicSetting<bool> confirm_before_closing{true, "confirmClose"}; 73 Settings::BasicSetting<bool> confirm_before_closing{true, "confirmClose"};
74 Settings::BasicSetting<bool> first_start{true, "firstStart"}; 74 Settings::BasicSetting<bool> first_start{true, "firstStart"};
75 Settings::BasicSetting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; 75 Settings::BasicSetting<bool> pause_when_in_background{false, "pauseWhenInBackground"};
76 Settings::BasicSetting<bool> mute_when_in_background{false, "muteWhenInBackground"};
76 Settings::BasicSetting<bool> hide_mouse{true, "hideInactiveMouse"}; 77 Settings::BasicSetting<bool> hide_mouse{true, "hideInactiveMouse"};
77 78
78 Settings::BasicSetting<bool> select_user_on_boot{false, "select_user_on_boot"}; 79 Settings::BasicSetting<bool> select_user_on_boot{false, "select_user_on_boot"};
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 8e9c7d211..ff616da70 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -66,6 +66,11 @@ static const std::array<int, Settings::NativeButton::NumButtons> default_buttons
66 SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B, 66 SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
67}; 67};
68 68
69static const std::array<int, Settings::NativeMotion::NumMotions> default_motions = {
70 SDL_SCANCODE_7,
71 SDL_SCANCODE_8,
72};
73
69static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{ 74static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{
70 { 75 {
71 SDL_SCANCODE_UP, 76 SDL_SCANCODE_UP,
@@ -102,27 +107,42 @@ void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>&
102void Config::ReadValues() { 107void Config::ReadValues() {
103 // Controls 108 // Controls
104 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { 109 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
110 auto& player = Settings::values.players.GetValue()[p];
111
105 const auto group = fmt::format("ControlsP{}", p); 112 const auto group = fmt::format("ControlsP{}", p);
106 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { 113 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
107 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); 114 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
108 Settings::values.players.GetValue()[p].buttons[i] = 115 player.buttons[i] =
109 sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); 116 sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
110 if (Settings::values.players.GetValue()[p].buttons[i].empty()) 117 if (player.buttons[i].empty()) {
111 Settings::values.players.GetValue()[p].buttons[i] = default_param; 118 player.buttons[i] = default_param;
119 }
112 } 120 }
113 121
114 for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { 122 for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
115 std::string default_param = InputCommon::GenerateAnalogParamFromKeys( 123 std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
116 default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], 124 default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
117 default_analogs[i][3], default_analogs[i][4], 0.5f); 125 default_analogs[i][3], default_analogs[i][4], 0.5f);
118 Settings::values.players.GetValue()[p].analogs[i] = 126 player.analogs[i] =
119 sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); 127 sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
120 if (Settings::values.players.GetValue()[p].analogs[i].empty()) 128 if (player.analogs[i].empty()) {
121 Settings::values.players.GetValue()[p].analogs[i] = default_param; 129 player.analogs[i] = default_param;
130 }
131 }
132
133 for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
134 const std::string default_param =
135 InputCommon::GenerateKeyboardParam(default_motions[i]);
136 auto& player_motions = player.motions[i];
137
138 player_motions =
139 sdl2_config->Get(group, Settings::NativeMotion::mapping[i], default_param);
140 if (player_motions.empty()) {
141 player_motions = default_param;
142 }
122 } 143 }
123 144
124 Settings::values.players.GetValue()[p].connected = 145 player.connected = sdl2_config->GetBoolean(group, "connected", false);
125 sdl2_config->GetBoolean(group, "connected", false);
126 } 146 }
127 147
128 ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); 148 ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);