summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/CMakeLists.txt4
-rw-r--r--src/common/logging/backend.cpp1
-rw-r--r--src/common/logging/log.h1
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/client_port.cpp12
-rw-r--r--src/core/hle/kernel/client_port.h14
-rw-r--r--src/core/hle/kernel/server_session.cpp2
-rw-r--r--src/core/hle/service/apm/apm.cpp1
-rw-r--r--src/core/hle/service/apm/interface.cpp25
-rw-r--r--src/core/hle/service/apm/interface.h8
-rw-r--r--src/core/hle/service/hid/hid.cpp1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp6
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp2
-rw-r--r--src/core/hle/service/nvdrv/interface.h1
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp2
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.cpp2
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp5
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h8
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/core/hle/service/time/time.cpp4
-rw-r--r--src/core/hle/service/usb/usb.cpp238
-rw-r--r--src/core/hle/service/usb/usb.h15
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp2
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp5
-rw-r--r--src/yuzu/configuration/configure_dialog.h4
-rw-r--r--src/yuzu/configuration/configure_general.cpp4
-rw-r--r--src/yuzu/configuration/configure_general.h4
-rw-r--r--src/yuzu/hotkeys.cpp67
-rw-r--r--src/yuzu/hotkeys.h107
-rw-r--r--src/yuzu/main.cpp84
-rw-r--r--src/yuzu/main.h3
39 files changed, 507 insertions, 150 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index 827ab0ac7..ec71524a3 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -4,8 +4,6 @@ add_library(audio_core STATIC
4 audio_renderer.cpp 4 audio_renderer.cpp
5 audio_renderer.h 5 audio_renderer.h
6 buffer.h 6 buffer.h
7 cubeb_sink.cpp
8 cubeb_sink.h
9 codec.cpp 7 codec.cpp
10 codec.h 8 codec.h
11 null_sink.h 9 null_sink.h
@@ -15,6 +13,8 @@ add_library(audio_core STATIC
15 sink_details.cpp 13 sink_details.cpp
16 sink_details.h 14 sink_details.h
17 sink_stream.h 15 sink_stream.h
16
17 $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h>
18) 18)
19 19
20create_target_directory_groups(audio_core) 20create_target_directory_groups(audio_core)
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 816414e8d..355abd682 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -200,6 +200,7 @@ void FileBackend::Write(const Entry& entry) {
200 SUB(Service, SPL) \ 200 SUB(Service, SPL) \
201 SUB(Service, SSL) \ 201 SUB(Service, SSL) \
202 SUB(Service, Time) \ 202 SUB(Service, Time) \
203 SUB(Service, USB) \
203 SUB(Service, VI) \ 204 SUB(Service, VI) \
204 SUB(Service, WLAN) \ 205 SUB(Service, WLAN) \
205 CLS(HW) \ 206 CLS(HW) \
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 7ab5277ea..a889ebefa 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -87,6 +87,7 @@ enum class Class : ClassType {
87 Service_SPL, ///< The SPL service 87 Service_SPL, ///< The SPL service
88 Service_SSL, ///< The SSL service 88 Service_SSL, ///< The SSL service
89 Service_Time, ///< The time service 89 Service_Time, ///< The time service
90 Service_USB, ///< The USB (Universal Serial Bus) service
90 Service_VI, ///< The VI (Video interface) service 91 Service_VI, ///< The VI (Video interface) service
91 Service_WLAN, ///< The WLAN (Wireless local area network) service 92 Service_WLAN, ///< The WLAN (Wireless local area network) service
92 HW, ///< Low-level hardware emulation 93 HW, ///< Low-level hardware emulation
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c11f017da..0abf7edc1 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -315,6 +315,8 @@ add_library(core STATIC
315 hle/service/time/interface.h 315 hle/service/time/interface.h
316 hle/service/time/time.cpp 316 hle/service/time/time.cpp
317 hle/service/time/time.h 317 hle/service/time/time.h
318 hle/service/usb/usb.cpp
319 hle/service/usb/usb.h
318 hle/service/vi/vi.cpp 320 hle/service/vi/vi.cpp
319 hle/service/vi/vi.h 321 hle/service/vi/vi.h
320 hle/service/vi/vi_m.cpp 322 hle/service/vi/vi_m.cpp
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 7933c105c..134e41ebc 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -14,8 +14,8 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17ClientPort::ClientPort() {} 17ClientPort::ClientPort() = default;
18ClientPort::~ClientPort() {} 18ClientPort::~ClientPort() = default;
19 19
20ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() { 20ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
21 // Note: Threads do not wait for the server endpoint to call 21 // Note: Threads do not wait for the server endpoint to call
@@ -40,4 +40,12 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
40 return MakeResult(std::get<SharedPtr<ClientSession>>(sessions)); 40 return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
41} 41}
42 42
43void ClientPort::ConnectionClosed() {
44 if (active_sessions == 0) {
45 return;
46 }
47
48 --active_sessions;
49}
50
43} // namespace Kernel 51} // namespace Kernel
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index b42c94bde..b1269ea5c 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -37,14 +37,20 @@ public:
37 */ 37 */
38 ResultVal<SharedPtr<ClientSession>> Connect(); 38 ResultVal<SharedPtr<ClientSession>> Connect();
39 39
40 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. 40 /**
41 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have 41 * Signifies that a previously active connection has been closed,
42 u32 active_sessions; ///< Number of currently open sessions to this port 42 * decreasing the total number of active connections to this port.
43 std::string name; ///< Name of client port (optional) 43 */
44 void ConnectionClosed();
44 45
45private: 46private:
46 ClientPort(); 47 ClientPort();
47 ~ClientPort() override; 48 ~ClientPort() override;
49
50 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
51 u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have
52 u32 active_sessions = 0; ///< Number of currently open sessions to this port
53 std::string name; ///< Name of client port (optional)
48}; 54};
49 55
50} // namespace Kernel 56} // namespace Kernel
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 60370e9ec..93560152f 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -27,7 +27,7 @@ ServerSession::~ServerSession() {
27 27
28 // Decrease the port's connection count. 28 // Decrease the port's connection count.
29 if (parent->port) 29 if (parent->port)
30 parent->port->active_sessions--; 30 parent->port->ConnectionClosed();
31 31
32 // TODO(Subv): Wake up all the ClientSession's waiting threads and set 32 // TODO(Subv): Wake up all the ClientSession's waiting threads and set
33 // the SendSyncRequest result to 0xC920181A. 33 // the SendSyncRequest result to 0xC920181A.
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index 7a185c6c8..4109cb7f7 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -13,6 +13,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
13 auto module_ = std::make_shared<Module>(); 13 auto module_ = std::make_shared<Module>();
14 std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager); 14 std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager);
15 std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager); 15 std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
16 std::make_shared<APM_Sys>()->InstallAsService(service_manager);
16} 17}
17 18
18} // namespace Service::APM 19} // namespace Service::APM
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index ce943d829..4cd8132f5 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -74,6 +74,31 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
74 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 74 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
75 rb.Push(RESULT_SUCCESS); 75 rb.Push(RESULT_SUCCESS);
76 rb.PushIpcInterface<ISession>(); 76 rb.PushIpcInterface<ISession>();
77
78 LOG_DEBUG(Service_APM, "called");
79}
80
81APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
82 // clang-format off
83 static const FunctionInfo functions[] = {
84 {0, nullptr, "RequestPerformanceMode"},
85 {1, &APM_Sys::GetPerformanceEvent, "GetPerformanceEvent"},
86 {2, nullptr, "GetThrottlingState"},
87 {3, nullptr, "GetLastThrottlingState"},
88 {4, nullptr, "ClearLastThrottlingState"},
89 {5, nullptr, "LoadAndApplySettings"},
90 };
91 // clang-format on
92
93 RegisterHandlers(functions);
94}
95
96void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
97 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
98 rb.Push(RESULT_SUCCESS);
99 rb.PushIpcInterface<ISession>();
100
101 LOG_DEBUG(Service_APM, "called");
77} 102}
78 103
79} // namespace Service::APM 104} // namespace Service::APM
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index fa68c7d93..d14264ad7 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -19,4 +19,12 @@ private:
19 std::shared_ptr<Module> apm; 19 std::shared_ptr<Module> apm;
20}; 20};
21 21
22class APM_Sys final : public ServiceFramework<APM_Sys> {
23public:
24 explicit APM_Sys();
25
26private:
27 void GetPerformanceEvent(Kernel::HLERequestContext& ctx);
28};
29
22} // namespace Service::APM 30} // namespace Service::APM
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ed53f96c5..8f0262e34 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -337,6 +337,7 @@ public:
337 "AcquireNpadStyleSetUpdateEventHandle"}, 337 "AcquireNpadStyleSetUpdateEventHandle"},
338 {107, nullptr, "DisconnectNpad"}, 338 {107, nullptr, "DisconnectNpad"},
339 {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"}, 339 {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
340 {109, nullptr, "ActivateNpadWithRevision"},
340 {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, 341 {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
341 {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, 342 {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
342 {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, 343 {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 2b74e6a33..8bc49935a 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -7,8 +7,8 @@
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 8#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
9#include "core/hle/service/nvdrv/devices/nvmap.h" 9#include "core/hle/service/nvdrv/devices/nvmap.h"
10#include "video_core/gpu.h"
10#include "video_core/renderer_base.h" 11#include "video_core/renderer_base.h"
11#include "video_core/video_core.h"
12 12
13namespace Service::Nvidia::Devices { 13namespace Service::Nvidia::Devices {
14 14
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 4b601781f..be2b79256 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -2,14 +2,15 @@
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 <cinttypes> 5#include <cstring>
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" 9#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
10#include "core/hle/service/nvdrv/devices/nvmap.h" 10#include "core/hle/service/nvdrv/devices/nvmap.h"
11#include "video_core/memory_manager.h"
12#include "video_core/rasterizer_interface.h"
11#include "video_core/renderer_base.h" 13#include "video_core/renderer_base.h"
12#include "video_core/video_core.h"
13 14
14namespace Service::Nvidia::Devices { 15namespace Service::Nvidia::Devices {
15 16
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 671b092e1..5685eb2be 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -2,6 +2,9 @@
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 <cstdlib>
6#include <cstring>
7
5#include "common/assert.h" 8#include "common/assert.h"
6#include "common/logging/log.h" 9#include "common/logging/log.h"
7#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" 10#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 090261a60..6b496e9fe 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -5,8 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <cstdlib>
9#include <cstring>
10#include <vector> 8#include <vector>
11#include "common/common_types.h" 9#include "common/common_types.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 10#include "core/hle/service/nvdrv/devices/nvdevice.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 010072a5b..ae421247d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -2,7 +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 <cinttypes> 5#include <cstring>
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" 8#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 5a1123ad2..116dabedb 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -2,12 +2,14 @@
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 <cinttypes> 5#include <cstring>
6#include <map>
7#include "common/assert.h" 6#include "common/assert.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9#include "core/core.h" 8#include "core/core.h"
10#include "core/hle/service/nvdrv/devices/nvhost_gpu.h" 9#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
10#include "core/memory.h"
11#include "video_core/gpu.h"
12#include "video_core/memory_manager.h"
11 13
12namespace Service::Nvidia::Devices { 14namespace Service::Nvidia::Devices {
13 15
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index aa8df2e6e..650ed8fbc 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -6,6 +6,7 @@
6 6
7#include <memory> 7#include <memory>
8#include <vector> 8#include <vector>
9#include "common/bit_field.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "common/swap.h" 11#include "common/swap.h"
11#include "core/hle/service/nvdrv/devices/nvdevice.h" 12#include "core/hle/service/nvdrv/devices/nvdevice.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index b51c73ee8..364619e67 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -2,6 +2,8 @@
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 <cstring>
6
5#include "common/assert.h" 7#include "common/assert.h"
6#include "common/logging/log.h" 8#include "common/logging/log.h"
7#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" 9#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index 0192aecdd..6ad74421b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -4,11 +4,9 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <cstdlib>
9#include <cstring>
10#include <vector> 7#include <vector>
11#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/swap.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 10#include "core/hle/service/nvdrv/devices/nvdevice.h"
13 11
14namespace Service::Nvidia::Devices { 12namespace Service::Nvidia::Devices {
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 724eeb139..e9305bfb3 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cinttypes> 6#include <cstring>
7 7
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index 959b5ba29..1c3529bb6 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <string>
9#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
10#include "core/hle/service/nvdrv/nvdrv.h" 9#include "core/hle/service/nvdrv/nvdrv.h"
11#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 1555ea806..e8b30921a 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -54,7 +54,7 @@ u32 Module::Open(const std::string& device_name) {
54 return fd; 54 return fd;
55} 55}
56 56
57u32 Module::Ioctl(u32 fd, u32_le command, const std::vector<u8>& input, std::vector<u8>& output) { 57u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
58 auto itr = open_files.find(fd); 58 auto itr = open_files.find(fd);
59 ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); 59 ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
60 60
diff --git a/src/core/hle/service/nvdrv/nvmemp.cpp b/src/core/hle/service/nvdrv/nvmemp.cpp
index 9ca6e5512..0e8e21bad 100644
--- a/src/core/hle/service/nvdrv/nvmemp.cpp
+++ b/src/core/hle/service/nvdrv/nvmemp.cpp
@@ -4,8 +4,6 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/hle/ipc_helpers.h"
8#include "core/hle/service/nvdrv/nvdrv.h"
9#include "core/hle/service/nvdrv/nvmemp.h" 7#include "core/hle/service/nvdrv/nvmemp.h"
10 8
11namespace Service::Nvidia { 9namespace Service::Nvidia {
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 58da1fdfa..570aa8493 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -3,8 +3,11 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <boost/optional.hpp>
6 7
7#include "common/alignment.h" 8#include "common/alignment.h"
9#include "common/assert.h"
10#include "common/logging/log.h"
8#include "common/microprofile.h" 11#include "common/microprofile.h"
9#include "common/scope_exit.h" 12#include "common/scope_exit.h"
10#include "core/core.h" 13#include "core/core.h"
@@ -43,7 +46,7 @@ NVFlinger::~NVFlinger() {
43 CoreTiming::UnscheduleEvent(composition_event, 0); 46 CoreTiming::UnscheduleEvent(composition_event, 0);
44} 47}
45 48
46u64 NVFlinger::OpenDisplay(const std::string& name) { 49u64 NVFlinger::OpenDisplay(std::string_view name) {
47 LOG_WARNING(Service, "Opening display {}", name); 50 LOG_WARNING(Service, "Opening display {}", name);
48 51
49 // TODO(Subv): Currently we only support the Default display. 52 // TODO(Subv): Currently we only support the Default display.
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 2c908297b..5374df175 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -5,7 +5,11 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <boost/optional.hpp> 8#include <string>
9#include <string_view>
10#include <vector>
11
12#include "common/common_types.h"
9#include "core/hle/kernel/event.h" 13#include "core/hle/kernel/event.h"
10 14
11namespace CoreTiming { 15namespace CoreTiming {
@@ -41,7 +45,7 @@ public:
41 ~NVFlinger(); 45 ~NVFlinger();
42 46
43 /// Opens the specified display and returns the id. 47 /// Opens the specified display and returns the id.
44 u64 OpenDisplay(const std::string& name); 48 u64 OpenDisplay(std::string_view name);
45 49
46 /// Creates a layer on the specified display and returns the layer id. 50 /// Creates a layer on the specified display and returns the layer id.
47 u64 CreateLayer(u64 display_id); 51 u64 CreateLayer(u64 display_id);
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 31ea79773..889cdd41a 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -63,6 +63,7 @@
63#include "core/hle/service/spl/module.h" 63#include "core/hle/service/spl/module.h"
64#include "core/hle/service/ssl/ssl.h" 64#include "core/hle/service/ssl/ssl.h"
65#include "core/hle/service/time/time.h" 65#include "core/hle/service/time/time.h"
66#include "core/hle/service/usb/usb.h"
66#include "core/hle/service/vi/vi.h" 67#include "core/hle/service/vi/vi.h"
67#include "core/hle/service/wlan/wlan.h" 68#include "core/hle/service/wlan/wlan.h"
68 69
@@ -249,6 +250,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
249 SPL::InstallInterfaces(*sm); 250 SPL::InstallInterfaces(*sm);
250 SSL::InstallInterfaces(*sm); 251 SSL::InstallInterfaces(*sm);
251 Time::InstallInterfaces(*sm); 252 Time::InstallInterfaces(*sm);
253 USB::InstallInterfaces(*sm);
252 VI::InstallInterfaces(*sm, nv_flinger); 254 VI::InstallInterfaces(*sm, nv_flinger);
253 WLAN::InstallInterfaces(*sm); 255 WLAN::InstallInterfaces(*sm);
254 256
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 37b58bb77..2172c681b 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -80,8 +80,8 @@ public:
80 {5, nullptr, "GetTimeZoneRuleVersion"}, 80 {5, nullptr, "GetTimeZoneRuleVersion"},
81 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, 81 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
82 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, 82 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
83 {200, nullptr, "ToPosixTime"}, 83 {201, nullptr, "ToPosixTime"},
84 {201, nullptr, "ToPosixTimeWithMyRule"}, 84 {202, nullptr, "ToPosixTimeWithMyRule"},
85 }; 85 };
86 RegisterHandlers(functions); 86 RegisterHandlers(functions);
87 } 87 }
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
new file mode 100644
index 000000000..e7fb5a419
--- /dev/null
+++ b/src/core/hle/service/usb/usb.cpp
@@ -0,0 +1,238 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6
7#include "common/logging/log.h"
8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/hle_ipc.h"
10#include "core/hle/service/service.h"
11#include "core/hle/service/sm/sm.h"
12#include "core/hle/service/usb/usb.h"
13
14namespace Service::USB {
15
16class IDsInterface final : public ServiceFramework<IDsInterface> {
17public:
18 explicit IDsInterface() : ServiceFramework{"IDsInterface"} {
19 // clang-format off
20 static const FunctionInfo functions[] = {
21 {0, nullptr, "GetDsEndpoint"},
22 {1, nullptr, "GetSetupEvent"},
23 {2, nullptr, "Unknown"},
24 {3, nullptr, "EnableInterface"},
25 {4, nullptr, "DisableInterface"},
26 {5, nullptr, "CtrlInPostBufferAsync"},
27 {6, nullptr, "CtrlOutPostBufferAsync"},
28 {7, nullptr, "GetCtrlInCompletionEvent"},
29 {8, nullptr, "GetCtrlInReportData"},
30 {9, nullptr, "GetCtrlOutCompletionEvent"},
31 {10, nullptr, "GetCtrlOutReportData"},
32 {11, nullptr, "StallCtrl"},
33 {12, nullptr, "AppendConfigurationData"},
34 };
35 // clang-format on
36
37 RegisterHandlers(functions);
38 }
39};
40
41class USB_DS final : public ServiceFramework<USB_DS> {
42public:
43 explicit USB_DS() : ServiceFramework{"usb:ds"} {
44 // clang-format off
45 static const FunctionInfo functions[] = {
46 {0, nullptr, "BindDevice"},
47 {1, nullptr, "BindClientProcess"},
48 {2, nullptr, "GetDsInterface"},
49 {3, nullptr, "GetStateChangeEvent"},
50 {4, nullptr, "GetState"},
51 {5, nullptr, "ClearDeviceData"},
52 {6, nullptr, "AddUsbStringDescriptor"},
53 {7, nullptr, "DeleteUsbStringDescriptor"},
54 {8, nullptr, "SetUsbDeviceDescriptor"},
55 {9, nullptr, "SetBinaryObjectStore"},
56 {10, nullptr, "Enable"},
57 {11, nullptr, "Disable"},
58 };
59 // clang-format on
60
61 RegisterHandlers(functions);
62 }
63};
64
65class IClientEpSession final : public ServiceFramework<IClientEpSession> {
66public:
67 explicit IClientEpSession() : ServiceFramework{"IClientEpSession"} {
68 // clang-format off
69 static const FunctionInfo functions[] = {
70 {0, nullptr, "Unknown1"},
71 {1, nullptr, "Unknown2"},
72 {2, nullptr, "Unknown3"},
73 {3, nullptr, "Unknown4"},
74 {4, nullptr, "PostBufferAsync"},
75 {5, nullptr, "Unknown5"},
76 {6, nullptr, "Unknown6"},
77 {7, nullptr, "Unknown7"},
78 {8, nullptr, "Unknown8"},
79 };
80 // clang-format on
81
82 RegisterHandlers(functions);
83 }
84};
85
86class IClientIfSession final : public ServiceFramework<IClientIfSession> {
87public:
88 explicit IClientIfSession() : ServiceFramework{"IClientIfSession"} {
89 // clang-format off
90 static const FunctionInfo functions[] = {
91 {0, nullptr, "Unknown1"},
92 {1, nullptr, "Unknown2"},
93 {2, nullptr, "Unknown3"},
94 {3, nullptr, "Unknown4"},
95 {4, nullptr, "Unknown5"},
96 {5, nullptr, "CtrlXferAsync"},
97 {6, nullptr, "Unknown6"},
98 {7, nullptr, "GetCtrlXferReport"},
99 {8, nullptr, "Unknown7"},
100 {9, nullptr, "GetClientEpSession"},
101 };
102 // clang-format on
103
104 RegisterHandlers(functions);
105 }
106};
107
108class USB_HS final : public ServiceFramework<USB_HS> {
109public:
110 explicit USB_HS() : ServiceFramework{"usb:hs"} {
111 // clang-format off
112 static const FunctionInfo functions[] = {
113 {0, nullptr, "BindClientProcess"},
114 {1, nullptr, "Unknown1"},
115 {2, nullptr, "Unknown2"},
116 {3, nullptr, "Unknown3"},
117 {4, nullptr, "Unknown4"},
118 {5, nullptr, "Unknown5"},
119 {6, nullptr, "GetInterfaceStateChangeEvent"},
120 {7, nullptr, "GetClientIfSession"},
121 };
122 // clang-format on
123
124 RegisterHandlers(functions);
125 }
126};
127
128class IPdSession final : public ServiceFramework<IPdSession> {
129public:
130 explicit IPdSession() : ServiceFramework{"IPdSession"} {
131 // clang-format off
132 static const FunctionInfo functions[] = {
133 {0, nullptr, "BindNoticeEvent"},
134 {1, nullptr, "Unknown1"},
135 {2, nullptr, "GetStatus"},
136 {3, nullptr, "GetNotice"},
137 {4, nullptr, "Unknown2"},
138 {5, nullptr, "Unknown3"},
139 {6, nullptr, "ReplyPowerRequest"},
140 };
141 // clang-format on
142
143 RegisterHandlers(functions);
144 }
145};
146
147class USB_PD final : public ServiceFramework<USB_PD> {
148public:
149 explicit USB_PD() : ServiceFramework{"usb:pd"} {
150 // clang-format off
151 static const FunctionInfo functions[] = {
152 {0, &USB_PD::GetPdSession, "GetPdSession"},
153 };
154 // clang-format on
155
156 RegisterHandlers(functions);
157 }
158
159private:
160 void GetPdSession(Kernel::HLERequestContext& ctx) {
161 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
162 rb.Push(RESULT_SUCCESS);
163 rb.PushIpcInterface<IPdSession>();
164
165 LOG_DEBUG(Service_USB, "called");
166 }
167};
168
169class IPdCradleSession final : public ServiceFramework<IPdCradleSession> {
170public:
171 explicit IPdCradleSession() : ServiceFramework{"IPdCradleSession"} {
172 // clang-format off
173 static const FunctionInfo functions[] = {
174 {0, nullptr, "VdmUserWrite"},
175 {1, nullptr, "VdmUserRead"},
176 {2, nullptr, "Vdm20Init"},
177 {3, nullptr, "GetFwType"},
178 {4, nullptr, "GetFwRevision"},
179 {5, nullptr, "GetManufacturerId"},
180 {6, nullptr, "GetDeviceId"},
181 {7, nullptr, "Unknown1"},
182 {8, nullptr, "Unknown2"},
183 };
184 // clang-format on
185
186 RegisterHandlers(functions);
187 }
188};
189
190class USB_PD_C final : public ServiceFramework<USB_PD_C> {
191public:
192 explicit USB_PD_C() : ServiceFramework{"usb:pd:c"} {
193 // clang-format off
194 static const FunctionInfo functions[] = {
195 {0, &USB_PD_C::GetPdCradleSession, "GetPdCradleSession"},
196 };
197 // clang-format on
198
199 RegisterHandlers(functions);
200 }
201
202private:
203 void GetPdCradleSession(Kernel::HLERequestContext& ctx) {
204 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
205 rb.Push(RESULT_SUCCESS);
206 rb.PushIpcInterface<IPdCradleSession>();
207
208 LOG_DEBUG(Service_USB, "called");
209 }
210};
211
212class USB_PM final : public ServiceFramework<USB_PM> {
213public:
214 explicit USB_PM() : ServiceFramework{"usb:pm"} {
215 // clang-format off
216 static const FunctionInfo functions[] = {
217 {0, nullptr, "Unknown1"},
218 {1, nullptr, "Unknown2"},
219 {2, nullptr, "Unknown3"},
220 {3, nullptr, "Unknown4"},
221 {4, nullptr, "Unknown5"},
222 {5, nullptr, "Unknown6"},
223 };
224 // clang-format on
225
226 RegisterHandlers(functions);
227 }
228};
229
230void InstallInterfaces(SM::ServiceManager& sm) {
231 std::make_shared<USB_DS>()->InstallAsService(sm);
232 std::make_shared<USB_HS>()->InstallAsService(sm);
233 std::make_shared<USB_PD>()->InstallAsService(sm);
234 std::make_shared<USB_PD_C>()->InstallAsService(sm);
235 std::make_shared<USB_PM>()->InstallAsService(sm);
236}
237
238} // namespace Service::USB
diff --git a/src/core/hle/service/usb/usb.h b/src/core/hle/service/usb/usb.h
new file mode 100644
index 000000000..970a11fe8
--- /dev/null
+++ b/src/core/hle/service/usb/usb.h
@@ -0,0 +1,15 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7namespace Service::SM {
8class ServiceManager;
9}
10
11namespace Service::USB {
12
13void InstallInterfaces(SM::ServiceManager& sm);
14
15} // namespace Service::USB
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 076927dff..9a8cdd0ff 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -41,7 +41,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
41 if (dir == nullptr) { 41 if (dir == nullptr) {
42 if (file == nullptr) 42 if (file == nullptr)
43 return ResultStatus::ErrorInvalidFormat; 43 return ResultStatus::ErrorInvalidFormat;
44 const FileSys::VirtualDir dir = file->GetContainingDirectory(); 44 dir = file->GetContainingDirectory();
45 } 45 }
46 46
47 const FileSys::VirtualFile npdm = dir->GetFile("main.npdm"); 47 const FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 1ca7e876c..cc4b326ae 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -6,9 +6,12 @@
6#include "ui_configure.h" 6#include "ui_configure.h"
7#include "yuzu/configuration/config.h" 7#include "yuzu/configuration/config.h"
8#include "yuzu/configuration/configure_dialog.h" 8#include "yuzu/configuration/configure_dialog.h"
9#include "yuzu/hotkeys.h"
9 10
10ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { 11ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry)
12 : QDialog(parent), ui(new Ui::ConfigureDialog) {
11 ui->setupUi(this); 13 ui->setupUi(this);
14 ui->generalTab->PopulateHotkeyList(registry);
12 this->setConfiguration(); 15 this->setConfiguration();
13} 16}
14 17
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 21fa1f501..bbbdacc29 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -7,6 +7,8 @@
7#include <memory> 7#include <memory>
8#include <QDialog> 8#include <QDialog>
9 9
10class HotkeyRegistry;
11
10namespace Ui { 12namespace Ui {
11class ConfigureDialog; 13class ConfigureDialog;
12} 14}
@@ -15,7 +17,7 @@ class ConfigureDialog : public QDialog {
15 Q_OBJECT 17 Q_OBJECT
16 18
17public: 19public:
18 explicit ConfigureDialog(QWidget* parent); 20 explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry);
19 ~ConfigureDialog(); 21 ~ConfigureDialog();
20 22
21 void applyConfiguration(); 23 void applyConfiguration();
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 04afc8724..d8caee1e8 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -35,6 +35,10 @@ void ConfigureGeneral::setConfiguration() {
35 ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); 35 ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
36} 36}
37 37
38void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) {
39 ui->widget->Populate(registry);
40}
41
38void ConfigureGeneral::applyConfiguration() { 42void ConfigureGeneral::applyConfiguration() {
39 UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); 43 UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
40 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); 44 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index 447552d8c..4770034cc 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -7,6 +7,8 @@
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9 9
10class HotkeyRegistry;
11
10namespace Ui { 12namespace Ui {
11class ConfigureGeneral; 13class ConfigureGeneral;
12} 14}
@@ -18,11 +20,11 @@ public:
18 explicit ConfigureGeneral(QWidget* parent = nullptr); 20 explicit ConfigureGeneral(QWidget* parent = nullptr);
19 ~ConfigureGeneral(); 21 ~ConfigureGeneral();
20 22
23 void PopulateHotkeyList(const HotkeyRegistry& registry);
21 void applyConfiguration(); 24 void applyConfiguration();
22 25
23private: 26private:
24 void setConfiguration(); 27 void setConfiguration();
25 28
26private:
27 std::unique_ptr<Ui::ConfigureGeneral> ui; 29 std::unique_ptr<Ui::ConfigureGeneral> ui;
28}; 30};
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp
index 61acb38ee..dce399774 100644
--- a/src/yuzu/hotkeys.cpp
+++ b/src/yuzu/hotkeys.cpp
@@ -10,58 +10,53 @@
10#include "yuzu/hotkeys.h" 10#include "yuzu/hotkeys.h"
11#include "yuzu/ui_settings.h" 11#include "yuzu/ui_settings.h"
12 12
13struct Hotkey { 13HotkeyRegistry::HotkeyRegistry() = default;
14 Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {} 14HotkeyRegistry::~HotkeyRegistry() = default;
15 15
16 QKeySequence keyseq; 16void HotkeyRegistry::LoadHotkeys() {
17 QShortcut* shortcut;
18 Qt::ShortcutContext context;
19};
20
21typedef std::map<QString, Hotkey> HotkeyMap;
22typedef std::map<QString, HotkeyMap> HotkeyGroupMap;
23
24HotkeyGroupMap hotkey_groups;
25
26void SaveHotkeys() {
27 UISettings::values.shortcuts.clear();
28 for (auto group : hotkey_groups) {
29 for (auto hotkey : group.second) {
30 UISettings::values.shortcuts.emplace_back(
31 UISettings::Shortcut(group.first + "/" + hotkey.first,
32 UISettings::ContextualShortcut(hotkey.second.keyseq.toString(),
33 hotkey.second.context)));
34 }
35 }
36}
37
38void LoadHotkeys() {
39 // Make sure NOT to use a reference here because it would become invalid once we call 17 // Make sure NOT to use a reference here because it would become invalid once we call
40 // beginGroup() 18 // beginGroup()
41 for (auto shortcut : UISettings::values.shortcuts) { 19 for (auto shortcut : UISettings::values.shortcuts) {
42 QStringList cat = shortcut.first.split("/"); 20 const QStringList cat = shortcut.first.split('/');
43 Q_ASSERT(cat.size() >= 2); 21 Q_ASSERT(cat.size() >= 2);
44 22
45 // RegisterHotkey assigns default keybindings, so use old values as default parameters 23 // RegisterHotkey assigns default keybindings, so use old values as default parameters
46 Hotkey& hk = hotkey_groups[cat[0]][cat[1]]; 24 Hotkey& hk = hotkey_groups[cat[0]][cat[1]];
47 if (!shortcut.second.first.isEmpty()) { 25 if (!shortcut.second.first.isEmpty()) {
48 hk.keyseq = QKeySequence::fromString(shortcut.second.first); 26 hk.keyseq = QKeySequence::fromString(shortcut.second.first);
49 hk.context = (Qt::ShortcutContext)shortcut.second.second; 27 hk.context = static_cast<Qt::ShortcutContext>(shortcut.second.second);
50 } 28 }
51 if (hk.shortcut) 29 if (hk.shortcut)
52 hk.shortcut->setKey(hk.keyseq); 30 hk.shortcut->setKey(hk.keyseq);
53 } 31 }
54} 32}
55 33
56void RegisterHotkey(const QString& group, const QString& action, const QKeySequence& default_keyseq, 34void HotkeyRegistry::SaveHotkeys() {
57 Qt::ShortcutContext default_context) { 35 UISettings::values.shortcuts.clear();
58 if (hotkey_groups[group].find(action) == hotkey_groups[group].end()) { 36 for (const auto& group : hotkey_groups) {
59 hotkey_groups[group][action].keyseq = default_keyseq; 37 for (const auto& hotkey : group.second) {
60 hotkey_groups[group][action].context = default_context; 38 UISettings::values.shortcuts.emplace_back(
39 UISettings::Shortcut(group.first + '/' + hotkey.first,
40 UISettings::ContextualShortcut(hotkey.second.keyseq.toString(),
41 hotkey.second.context)));
42 }
61 } 43 }
62} 44}
63 45
64QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget) { 46void HotkeyRegistry::RegisterHotkey(const QString& group, const QString& action,
47 const QKeySequence& default_keyseq,
48 Qt::ShortcutContext default_context) {
49 auto& hotkey_group = hotkey_groups[group];
50 if (hotkey_group.find(action) != hotkey_group.end()) {
51 return;
52 }
53
54 auto& hotkey_action = hotkey_groups[group][action];
55 hotkey_action.keyseq = default_keyseq;
56 hotkey_action.context = default_context;
57}
58
59QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) {
65 Hotkey& hk = hotkey_groups[group][action]; 60 Hotkey& hk = hotkey_groups[group][action];
66 61
67 if (!hk.shortcut) 62 if (!hk.shortcut)
@@ -72,10 +67,12 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge
72 67
73GHotkeysDialog::GHotkeysDialog(QWidget* parent) : QWidget(parent) { 68GHotkeysDialog::GHotkeysDialog(QWidget* parent) : QWidget(parent) {
74 ui.setupUi(this); 69 ui.setupUi(this);
70}
75 71
76 for (auto group : hotkey_groups) { 72void GHotkeysDialog::Populate(const HotkeyRegistry& registry) {
73 for (const auto& group : registry.hotkey_groups) {
77 QTreeWidgetItem* toplevel_item = new QTreeWidgetItem(QStringList(group.first)); 74 QTreeWidgetItem* toplevel_item = new QTreeWidgetItem(QStringList(group.first));
78 for (auto hotkey : group.second) { 75 for (const auto& hotkey : group.second) {
79 QStringList columns; 76 QStringList columns;
80 columns << hotkey.first << hotkey.second.keyseq.toString(); 77 columns << hotkey.first << hotkey.second.keyseq.toString();
81 QTreeWidgetItem* item = new QTreeWidgetItem(columns); 78 QTreeWidgetItem* item = new QTreeWidgetItem(columns);
diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h
index a4ccc193b..f38e6c002 100644
--- a/src/yuzu/hotkeys.h
+++ b/src/yuzu/hotkeys.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <map>
7#include "ui_hotkeys.h" 8#include "ui_hotkeys.h"
8 9
9class QDialog; 10class QDialog;
@@ -11,47 +12,69 @@ class QKeySequence;
11class QSettings; 12class QSettings;
12class QShortcut; 13class QShortcut;
13 14
14/** 15class HotkeyRegistry final {
15 * Register a hotkey. 16public:
16 * 17 friend class GHotkeysDialog;
17 * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger") 18
18 * @param action Name of the action (e.g. "Start Emulation", "Load Image") 19 explicit HotkeyRegistry();
19 * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the settings 20 ~HotkeyRegistry();
20 * file before 21
21 * @param default_context Default context to assign if the hotkey wasn't present in the settings 22 /**
22 * file before 23 * Loads hotkeys from the settings file.
23 * @warning Both the group and action strings will be displayed in the hotkey settings dialog 24 *
24 */ 25 * @note Yet unregistered hotkeys which are present in the settings will automatically be
25void RegisterHotkey(const QString& group, const QString& action, 26 * registered.
26 const QKeySequence& default_keyseq = QKeySequence(), 27 */
27 Qt::ShortcutContext default_context = Qt::WindowShortcut); 28 void LoadHotkeys();
28 29
29/** 30 /**
30 * Returns a QShortcut object whose activated() signal can be connected to other QObjects' slots. 31 * Saves all registered hotkeys to the settings file.
31 * 32 *
32 * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger"). 33 * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a
33 * @param action Name of the action (e.g. "Start Emulation", "Load Image"). 34 * settings group will be created to store the key sequence and the hotkey context.
34 * @param widget Parent widget of the returned QShortcut. 35 */
35 * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut 36 void SaveHotkeys();
36 * will be the same. Thus, you shouldn't rely on the caller really being the QShortcut's parent. 37
37 */ 38 /**
38QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); 39 * Returns a QShortcut object whose activated() signal can be connected to other QObjects'
39 40 * slots.
40/** 41 *
41 * Saves all registered hotkeys to the settings file. 42 * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger").
42 * 43 * @param action Name of the action (e.g. "Start Emulation", "Load Image").
43 * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a 44 * @param widget Parent widget of the returned QShortcut.
44 * settings group will be created to store the key sequence and the hotkey context. 45 * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut
45 */ 46 * will be the same. Thus, you shouldn't rely on the caller really being the
46void SaveHotkeys(); 47 * QShortcut's parent.
47 48 */
48/** 49 QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget);
49 * Loads hotkeys from the settings file. 50
50 * 51 /**
51 * @note Yet unregistered hotkeys which are present in the settings will automatically be 52 * Register a hotkey.
52 * registered. 53 *
53 */ 54 * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger")
54void LoadHotkeys(); 55 * @param action Name of the action (e.g. "Start Emulation", "Load Image")
56 * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the
57 * settings file before
58 * @param default_context Default context to assign if the hotkey wasn't present in the settings
59 * file before
60 * @warning Both the group and action strings will be displayed in the hotkey settings dialog
61 */
62 void RegisterHotkey(const QString& group, const QString& action,
63 const QKeySequence& default_keyseq = {},
64 Qt::ShortcutContext default_context = Qt::WindowShortcut);
65
66private:
67 struct Hotkey {
68 QKeySequence keyseq;
69 QShortcut* shortcut = nullptr;
70 Qt::ShortcutContext context = Qt::WindowShortcut;
71 };
72
73 using HotkeyMap = std::map<QString, Hotkey>;
74 using HotkeyGroupMap = std::map<QString, HotkeyMap>;
75
76 HotkeyGroupMap hotkey_groups;
77};
55 78
56class GHotkeysDialog : public QWidget { 79class GHotkeysDialog : public QWidget {
57 Q_OBJECT 80 Q_OBJECT
@@ -59,6 +82,8 @@ class GHotkeysDialog : public QWidget {
59public: 82public:
60 explicit GHotkeysDialog(QWidget* parent = nullptr); 83 explicit GHotkeysDialog(QWidget* parent = nullptr);
61 84
85 void Populate(const HotkeyRegistry& registry);
86
62private: 87private:
63 Ui::hotkeys ui; 88 Ui::hotkeys ui;
64}; 89};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index dd71bd763..17ed62c72 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -208,43 +208,46 @@ void GMainWindow::InitializeRecentFileMenuActions() {
208} 208}
209 209
210void GMainWindow::InitializeHotkeys() { 210void GMainWindow::InitializeHotkeys() {
211 RegisterHotkey("Main Window", "Load File", QKeySequence::Open); 211 hotkey_registry.RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
212 RegisterHotkey("Main Window", "Start Emulation"); 212 hotkey_registry.RegisterHotkey("Main Window", "Start Emulation");
213 RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4)); 213 hotkey_registry.RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4));
214 RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen); 214 hotkey_registry.RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen);
215 RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape), 215 hotkey_registry.RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape),
216 Qt::ApplicationShortcut); 216 Qt::ApplicationShortcut);
217 RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"), 217 hotkey_registry.RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"),
218 Qt::ApplicationShortcut); 218 Qt::ApplicationShortcut);
219 LoadHotkeys(); 219 hotkey_registry.LoadHotkeys();
220 220
221 connect(GetHotkey("Main Window", "Load File", this), &QShortcut::activated, this, 221 connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated,
222 &GMainWindow::OnMenuLoadFile); 222 this, &GMainWindow::OnMenuLoadFile);
223 connect(GetHotkey("Main Window", "Start Emulation", this), &QShortcut::activated, this, 223 connect(hotkey_registry.GetHotkey("Main Window", "Start Emulation", this),
224 &GMainWindow::OnStartGame); 224 &QShortcut::activated, this, &GMainWindow::OnStartGame);
225 connect(GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated, this, [&] { 225 connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated,
226 if (emulation_running) { 226 this, [&] {
227 if (emu_thread->IsRunning()) { 227 if (emulation_running) {
228 OnPauseGame(); 228 if (emu_thread->IsRunning()) {
229 } else { 229 OnPauseGame();
230 OnStartGame(); 230 } else {
231 } 231 OnStartGame();
232 } 232 }
233 }); 233 }
234 connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activated, 234 });
235 ui.action_Fullscreen, &QAction::trigger); 235 connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window),
236 connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activatedAmbiguously, 236 &QShortcut::activated, ui.action_Fullscreen, &QAction::trigger);
237 ui.action_Fullscreen, &QAction::trigger); 237 connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window),
238 connect(GetHotkey("Main Window", "Exit Fullscreen", this), &QShortcut::activated, this, [&] { 238 &QShortcut::activatedAmbiguously, ui.action_Fullscreen, &QAction::trigger);
239 if (emulation_running) { 239 connect(hotkey_registry.GetHotkey("Main Window", "Exit Fullscreen", this),
240 ui.action_Fullscreen->setChecked(false); 240 &QShortcut::activated, this, [&] {
241 ToggleFullscreen(); 241 if (emulation_running) {
242 } 242 ui.action_Fullscreen->setChecked(false);
243 }); 243 ToggleFullscreen();
244 connect(GetHotkey("Main Window", "Toggle Speed Limit", this), &QShortcut::activated, this, [&] { 244 }
245 Settings::values.toggle_framelimit = !Settings::values.toggle_framelimit; 245 });
246 UpdateStatusBar(); 246 connect(hotkey_registry.GetHotkey("Main Window", "Toggle Speed Limit", this),
247 }); 247 &QShortcut::activated, this, [&] {
248 Settings::values.toggle_framelimit = !Settings::values.toggle_framelimit;
249 UpdateStatusBar();
250 });
248} 251}
249 252
250void GMainWindow::SetDefaultUIGeometry() { 253void GMainWindow::SetDefaultUIGeometry() {
@@ -323,7 +326,8 @@ void GMainWindow::ConnectMenuEvents() {
323 connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible); 326 connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
324 327
325 // Fullscreen 328 // Fullscreen
326 ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key()); 329 ui.action_Fullscreen->setShortcut(
330 hotkey_registry.GetHotkey("Main Window", "Fullscreen", this)->key());
327 connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); 331 connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
328 332
329 // Help 333 // Help
@@ -757,7 +761,7 @@ void GMainWindow::ToggleWindowMode() {
757} 761}
758 762
759void GMainWindow::OnConfigure() { 763void GMainWindow::OnConfigure() {
760 ConfigureDialog configureDialog(this); 764 ConfigureDialog configureDialog(this, hotkey_registry);
761 auto old_theme = UISettings::values.theme; 765 auto old_theme = UISettings::values.theme;
762 auto result = configureDialog.exec(); 766 auto result = configureDialog.exec();
763 if (result == QDialog::Accepted) { 767 if (result == QDialog::Accepted) {
@@ -896,7 +900,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
896 UISettings::values.first_start = false; 900 UISettings::values.first_start = false;
897 901
898 game_list->SaveInterfaceLayout(); 902 game_list->SaveInterfaceLayout();
899 SaveHotkeys(); 903 hotkey_registry.SaveHotkeys();
900 904
901 // Shutdown session if the emu thread is active... 905 // Shutdown session if the emu thread is active...
902 if (emu_thread != nullptr) 906 if (emu_thread != nullptr)
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index a60d831b9..6e335b8f8 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -9,6 +9,7 @@
9#include <QTimer> 9#include <QTimer>
10#include "core/core.h" 10#include "core/core.h"
11#include "ui_main.h" 11#include "ui_main.h"
12#include "yuzu/hotkeys.h"
12 13
13class Config; 14class Config;
14class EmuThread; 15class EmuThread;
@@ -172,6 +173,8 @@ private:
172 // stores default icon theme search paths for the platform 173 // stores default icon theme search paths for the platform
173 QStringList default_theme_paths; 174 QStringList default_theme_paths;
174 175
176 HotkeyRegistry hotkey_registry;
177
175protected: 178protected:
176 void dropEvent(QDropEvent* event) override; 179 void dropEvent(QDropEvent* event) override;
177 void dragEnterEvent(QDragEnterEvent* event) override; 180 void dragEnterEvent(QDragEnterEvent* event) override;