summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/fs/file.h11
-rw-r--r--src/core/arm/arm_interface.h5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp31
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h14
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp29
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h10
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.h2
-rw-r--r--src/core/arm/dynarmic/arm_exclusive_monitor.h2
-rw-r--r--src/core/hle/kernel/k_client_port.h6
-rw-r--r--src/core/hle/kernel/k_client_session.h4
-rw-r--r--src/core/hle/kernel/k_event.h14
-rw-r--r--src/core/hle/kernel/k_port.h3
-rw-r--r--src/core/hle/kernel/k_process.h8
-rw-r--r--src/core/hle/kernel/k_readable_event.h4
-rw-r--r--src/core/hle/kernel/k_resource_limit.h4
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp1
-rw-r--r--src/core/hle/kernel/k_server_port.h12
-rw-r--r--src/core/hle/kernel/k_server_session.h6
-rw-r--r--src/core/hle/kernel/k_session.h10
-rw-r--r--src/core/hle/kernel/k_shared_memory.h4
-rw-r--r--src/core/hle/kernel/k_slab_heap.h199
-rw-r--r--src/core/hle/kernel/k_synchronization_object.h4
-rw-r--r--src/core/hle/kernel/k_thread.cpp10
-rw-r--r--src/core/hle/kernel/k_thread.h10
-rw-r--r--src/core/hle/kernel/k_transfer_memory.h10
-rw-r--r--src/core/hle/kernel/k_writable_event.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp5
-rw-r--r--src/core/hle/service/hid/hid.cpp11
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h4
-rw-r--r--src/video_core/rasterizer_accelerated.cpp6
-rw-r--r--src/video_core/rasterizer_accelerated.h12
-rw-r--r--src/yuzu/CMakeLists.txt13
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp14
-rw-r--r--src/yuzu/configuration/configure_dialog.h3
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp14
-rw-r--r--src/yuzu/configuration/configure_per_game.h2
-rw-r--r--src/yuzu/main.cpp40
-rw-r--r--src/yuzu/uisettings.h2
38 files changed, 394 insertions, 147 deletions
diff --git a/src/common/fs/file.h b/src/common/fs/file.h
index 209f9664b..50e270c5b 100644
--- a/src/common/fs/file.h
+++ b/src/common/fs/file.h
@@ -117,7 +117,7 @@ template <typename Path>
117} 117}
118#endif 118#endif
119 119
120class IOFile final : NonCopyable { 120class IOFile final {
121public: 121public:
122 IOFile(); 122 IOFile();
123 123
@@ -142,7 +142,10 @@ public:
142 FileType type = FileType::BinaryFile, 142 FileType type = FileType::BinaryFile,
143 FileShareFlag flag = FileShareFlag::ShareReadOnly); 143 FileShareFlag flag = FileShareFlag::ShareReadOnly);
144 144
145 virtual ~IOFile(); 145 ~IOFile();
146
147 IOFile(const IOFile&) = delete;
148 IOFile& operator=(const IOFile&) = delete;
146 149
147 IOFile(IOFile&& other) noexcept; 150 IOFile(IOFile&& other) noexcept;
148 IOFile& operator=(IOFile&& other) noexcept; 151 IOFile& operator=(IOFile&& other) noexcept;
@@ -441,8 +444,8 @@ public:
441 444
442private: 445private:
443 std::filesystem::path file_path; 446 std::filesystem::path file_path;
444 FileAccessMode file_access_mode; 447 FileAccessMode file_access_mode{};
445 FileType file_type; 448 FileType file_type{};
446 449
447 std::FILE* file = nullptr; 450 std::FILE* file = nullptr;
448}; 451};
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 9a0151736..689e3ceb5 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -65,9 +65,6 @@ public:
65 /// Step CPU by one instruction 65 /// Step CPU by one instruction
66 virtual void Step() = 0; 66 virtual void Step() = 0;
67 67
68 /// Exits execution from a callback, the callback must rewind the stack
69 virtual void ExceptionalExit() = 0;
70
71 /// Clear all instruction cache 68 /// Clear all instruction cache
72 virtual void ClearInstructionCache() = 0; 69 virtual void ClearInstructionCache() = 0;
73 70
@@ -159,8 +156,6 @@ public:
159 */ 156 */
160 virtual void SetTPIDR_EL0(u64 value) = 0; 157 virtual void SetTPIDR_EL0(u64 value) = 0;
161 158
162 virtual void ChangeProcessorID(std::size_t new_core_id) = 0;
163
164 virtual void SaveContext(ThreadContext32& ctx) = 0; 159 virtual void SaveContext(ThreadContext32& ctx) = 0;
165 virtual void SaveContext(ThreadContext64& ctx) = 0; 160 virtual void SaveContext(ThreadContext64& ctx) = 0;
166 virtual void LoadContext(const ThreadContext32& ctx) = 0; 161 virtual void LoadContext(const ThreadContext32& ctx) = 0;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 93d43e22e..e5b78210a 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -4,9 +4,9 @@
4 4
5#include <cinttypes> 5#include <cinttypes>
6#include <memory> 6#include <memory>
7#include <dynarmic/A32/a32.h> 7#include <dynarmic/interface/A32/a32.h>
8#include <dynarmic/A32/config.h> 8#include <dynarmic/interface/A32/config.h>
9#include <dynarmic/A32/context.h> 9#include <dynarmic/interface/A32/context.h>
10#include "common/assert.h" 10#include "common/assert.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/page_table.h" 12#include "common/page_table.h"
@@ -78,7 +78,9 @@ public:
78 } 78 }
79 79
80 void CallSVC(u32 swi) override { 80 void CallSVC(u32 swi) override {
81 Kernel::Svc::Call(parent.system, swi); 81 parent.svc_called = true;
82 parent.svc_swi = swi;
83 parent.jit->HaltExecution();
82 } 84 }
83 85
84 void AddTicks(u64 ticks) override { 86 void AddTicks(u64 ticks) override {
@@ -187,11 +189,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
187} 189}
188 190
189void ARM_Dynarmic_32::Run() { 191void ARM_Dynarmic_32::Run() {
190 jit->Run(); 192 while (true) {
191} 193 jit->Run();
192 194 if (!svc_called) {
193void ARM_Dynarmic_32::ExceptionalExit() { 195 break;
194 jit->ExceptionalExit(); 196 }
197 svc_called = false;
198 Kernel::Svc::Call(system, svc_swi);
199 if (shutdown) {
200 break;
201 }
202 }
195} 203}
196 204
197void ARM_Dynarmic_32::Step() { 205void ARM_Dynarmic_32::Step() {
@@ -255,10 +263,6 @@ void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
255 cp15->uprw = static_cast<u32>(value); 263 cp15->uprw = static_cast<u32>(value);
256} 264}
257 265
258void ARM_Dynarmic_32::ChangeProcessorID(std::size_t new_core_id) {
259 jit->ChangeProcessorID(new_core_id);
260}
261
262void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { 266void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
263 Dynarmic::A32::Context context; 267 Dynarmic::A32::Context context;
264 jit->SaveContext(context); 268 jit->SaveContext(context);
@@ -279,6 +283,7 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
279 283
280void ARM_Dynarmic_32::PrepareReschedule() { 284void ARM_Dynarmic_32::PrepareReschedule() {
281 jit->HaltExecution(); 285 jit->HaltExecution();
286 shutdown = true;
282} 287}
283 288
284void ARM_Dynarmic_32::ClearInstructionCache() { 289void ARM_Dynarmic_32::ClearInstructionCache() {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 42778c02c..063605b46 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -7,9 +7,9 @@
7#include <memory> 7#include <memory>
8#include <unordered_map> 8#include <unordered_map>
9 9
10#include <dynarmic/A32/a32.h> 10#include <dynarmic/interface/A32/a32.h>
11#include <dynarmic/A64/a64.h> 11#include <dynarmic/interface/A64/a64.h>
12#include <dynarmic/exclusive_monitor.h> 12#include <dynarmic/interface/exclusive_monitor.h>
13#include "common/common_types.h" 13#include "common/common_types.h"
14#include "common/hash.h" 14#include "common/hash.h"
15#include "core/arm/arm_interface.h" 15#include "core/arm/arm_interface.h"
@@ -42,13 +42,11 @@ public:
42 u32 GetPSTATE() const override; 42 u32 GetPSTATE() const override;
43 void SetPSTATE(u32 pstate) override; 43 void SetPSTATE(u32 pstate) override;
44 void Run() override; 44 void Run() override;
45 void ExceptionalExit() override;
46 void Step() override; 45 void Step() override;
47 VAddr GetTlsAddress() const override; 46 VAddr GetTlsAddress() const override;
48 void SetTlsAddress(VAddr address) override; 47 void SetTlsAddress(VAddr address) override;
49 void SetTPIDR_EL0(u64 value) override; 48 void SetTPIDR_EL0(u64 value) override;
50 u64 GetTPIDR_EL0() const override; 49 u64 GetTPIDR_EL0() const override;
51 void ChangeProcessorID(std::size_t new_core_id) override;
52 50
53 bool IsInThumbMode() const { 51 bool IsInThumbMode() const {
54 return (GetPSTATE() & 0x20) != 0; 52 return (GetPSTATE() & 0x20) != 0;
@@ -83,6 +81,12 @@ private:
83 std::size_t core_index; 81 std::size_t core_index;
84 DynarmicExclusiveMonitor& exclusive_monitor; 82 DynarmicExclusiveMonitor& exclusive_monitor;
85 std::shared_ptr<Dynarmic::A32::Jit> jit; 83 std::shared_ptr<Dynarmic::A32::Jit> jit;
84
85 // SVC callback
86 u32 svc_swi{};
87 bool svc_called{};
88
89 bool shutdown{};
86}; 90};
87 91
88} // namespace Core 92} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 08fa85904..dd439f55e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -4,8 +4,8 @@
4 4
5#include <cinttypes> 5#include <cinttypes>
6#include <memory> 6#include <memory>
7#include <dynarmic/A64/a64.h> 7#include <dynarmic/interface/A64/a64.h>
8#include <dynarmic/A64/config.h> 8#include <dynarmic/interface/A64/config.h>
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/page_table.h" 11#include "common/page_table.h"
@@ -102,7 +102,9 @@ public:
102 } 102 }
103 103
104 void CallSVC(u32 swi) override { 104 void CallSVC(u32 swi) override {
105 Kernel::Svc::Call(parent.system, swi); 105 parent.svc_called = true;
106 parent.svc_swi = swi;
107 parent.jit->HaltExecution();
106 } 108 }
107 109
108 void AddTicks(u64 ticks) override { 110 void AddTicks(u64 ticks) override {
@@ -227,11 +229,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
227} 229}
228 230
229void ARM_Dynarmic_64::Run() { 231void ARM_Dynarmic_64::Run() {
230 jit->Run(); 232 while (true) {
231} 233 jit->Run();
232 234 if (!svc_called) {
233void ARM_Dynarmic_64::ExceptionalExit() { 235 break;
234 jit->ExceptionalExit(); 236 }
237 svc_called = false;
238 Kernel::Svc::Call(system, svc_swi);
239 if (shutdown) {
240 break;
241 }
242 }
235} 243}
236 244
237void ARM_Dynarmic_64::Step() { 245void ARM_Dynarmic_64::Step() {
@@ -296,10 +304,6 @@ void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
296 cb->tpidr_el0 = value; 304 cb->tpidr_el0 = value;
297} 305}
298 306
299void ARM_Dynarmic_64::ChangeProcessorID(std::size_t new_core_id) {
300 jit->ChangeProcessorID(new_core_id);
301}
302
303void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { 307void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
304 ctx.cpu_registers = jit->GetRegisters(); 308 ctx.cpu_registers = jit->GetRegisters();
305 ctx.sp = jit->GetSP(); 309 ctx.sp = jit->GetSP();
@@ -324,6 +328,7 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
324 328
325void ARM_Dynarmic_64::PrepareReschedule() { 329void ARM_Dynarmic_64::PrepareReschedule() {
326 jit->HaltExecution(); 330 jit->HaltExecution();
331 shutdown = true;
327} 332}
328 333
329void ARM_Dynarmic_64::ClearInstructionCache() { 334void ARM_Dynarmic_64::ClearInstructionCache() {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index b81fbcc66..0c4e46c64 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -7,7 +7,7 @@
7#include <memory> 7#include <memory>
8#include <unordered_map> 8#include <unordered_map>
9 9
10#include <dynarmic/A64/a64.h> 10#include <dynarmic/interface/A64/a64.h>
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/hash.h" 12#include "common/hash.h"
13#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
@@ -40,12 +40,10 @@ public:
40 void SetPSTATE(u32 pstate) override; 40 void SetPSTATE(u32 pstate) override;
41 void Run() override; 41 void Run() override;
42 void Step() override; 42 void Step() override;
43 void ExceptionalExit() override;
44 VAddr GetTlsAddress() const override; 43 VAddr GetTlsAddress() const override;
45 void SetTlsAddress(VAddr address) override; 44 void SetTlsAddress(VAddr address) override;
46 void SetTPIDR_EL0(u64 value) override; 45 void SetTPIDR_EL0(u64 value) override;
47 u64 GetTPIDR_EL0() const override; 46 u64 GetTPIDR_EL0() const override;
48 void ChangeProcessorID(std::size_t new_core_id) override;
49 47
50 void SaveContext(ThreadContext32& ctx) override {} 48 void SaveContext(ThreadContext32& ctx) override {}
51 void SaveContext(ThreadContext64& ctx) override; 49 void SaveContext(ThreadContext64& ctx) override;
@@ -76,6 +74,12 @@ private:
76 DynarmicExclusiveMonitor& exclusive_monitor; 74 DynarmicExclusiveMonitor& exclusive_monitor;
77 75
78 std::shared_ptr<Dynarmic::A64::Jit> jit; 76 std::shared_ptr<Dynarmic::A64::Jit> jit;
77
78 // SVC callback
79 u32 svc_swi{};
80 bool svc_called{};
81
82 bool shutdown{};
79}; 83};
80 84
81} // namespace Core 85} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
index 8597beddf..7c7ede79e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
@@ -7,7 +7,7 @@
7#include <memory> 7#include <memory>
8#include <optional> 8#include <optional>
9 9
10#include <dynarmic/A32/coprocessor.h> 10#include <dynarmic/interface/A32/coprocessor.h>
11#include "common/common_types.h" 11#include "common/common_types.h"
12 12
13namespace Core { 13namespace Core {
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.h b/src/core/arm/dynarmic/arm_exclusive_monitor.h
index f9f056a59..73d41f223 100644
--- a/src/core/arm/dynarmic/arm_exclusive_monitor.h
+++ b/src/core/arm/dynarmic/arm_exclusive_monitor.h
@@ -7,7 +7,7 @@
7#include <memory> 7#include <memory>
8#include <unordered_map> 8#include <unordered_map>
9 9
10#include <dynarmic/exclusive_monitor.h> 10#include <dynarmic/interface/exclusive_monitor.h>
11 11
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "core/arm/dynarmic/arm_dynarmic_32.h" 13#include "core/arm/dynarmic/arm_dynarmic_32.h"
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index 8501156e8..f2fff3b01 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -22,7 +22,7 @@ class KClientPort final : public KSynchronizationObject {
22 22
23public: 23public:
24 explicit KClientPort(KernelCore& kernel_); 24 explicit KClientPort(KernelCore& kernel_);
25 virtual ~KClientPort() override; 25 ~KClientPort() override;
26 26
27 void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_); 27 void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_);
28 void OnSessionFinalized(); 28 void OnSessionFinalized();
@@ -49,8 +49,8 @@ public:
49 bool IsServerClosed() const; 49 bool IsServerClosed() const;
50 50
51 // Overridden virtual functions. 51 // Overridden virtual functions.
52 virtual void Destroy() override; 52 void Destroy() override;
53 virtual bool IsSignaled() const override; 53 bool IsSignaled() const override;
54 54
55 ResultCode CreateSession(KClientSession** out); 55 ResultCode CreateSession(KClientSession** out);
56 56
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h
index 720a8c243..b11d5b4e3 100644
--- a/src/core/hle/kernel/k_client_session.h
+++ b/src/core/hle/kernel/k_client_session.h
@@ -34,7 +34,7 @@ class KClientSession final
34 34
35public: 35public:
36 explicit KClientSession(KernelCore& kernel_); 36 explicit KClientSession(KernelCore& kernel_);
37 virtual ~KClientSession(); 37 ~KClientSession() override;
38 38
39 void Initialize(KSession* parent_, std::string&& name_) { 39 void Initialize(KSession* parent_, std::string&& name_) {
40 // Set member variables. 40 // Set member variables.
@@ -42,7 +42,7 @@ public:
42 name = std::move(name_); 42 name = std::move(name_);
43 } 43 }
44 44
45 virtual void Destroy() override; 45 void Destroy() override;
46 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 46 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
47 47
48 KSession* GetParent() const { 48 KSession* GetParent() const {
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
index 9a59ffb70..3d3ec99e2 100644
--- a/src/core/hle/kernel/k_event.h
+++ b/src/core/hle/kernel/k_event.h
@@ -20,23 +20,21 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj
20 20
21public: 21public:
22 explicit KEvent(KernelCore& kernel_); 22 explicit KEvent(KernelCore& kernel_);
23 virtual ~KEvent(); 23 ~KEvent() override;
24 24
25 void Initialize(std::string&& name); 25 void Initialize(std::string&& name);
26 26
27 virtual void Finalize() override; 27 void Finalize() override;
28 28
29 virtual bool IsInitialized() const override { 29 bool IsInitialized() const override {
30 return initialized; 30 return initialized;
31 } 31 }
32 32
33 virtual uintptr_t GetPostDestroyArgument() const override { 33 uintptr_t GetPostDestroyArgument() const override {
34 return reinterpret_cast<uintptr_t>(owner); 34 return reinterpret_cast<uintptr_t>(owner);
35 } 35 }
36 36
37 static void PostDestroy(uintptr_t arg); 37 KProcess* GetOwner() const override {
38
39 virtual KProcess* GetOwner() const override {
40 return owner; 38 return owner;
41 } 39 }
42 40
@@ -48,6 +46,8 @@ public:
48 return writable_event; 46 return writable_event;
49 } 47 }
50 48
49 static void PostDestroy(uintptr_t arg);
50
51private: 51private:
52 KReadableEvent readable_event; 52 KReadableEvent readable_event;
53 KWritableEvent writable_event; 53 KWritableEvent writable_event;
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h
index 960f1f3a3..4018ea2df 100644
--- a/src/core/hle/kernel/k_port.h
+++ b/src/core/hle/kernel/k_port.h
@@ -22,7 +22,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjec
22 22
23public: 23public:
24 explicit KPort(KernelCore& kernel_); 24 explicit KPort(KernelCore& kernel_);
25 virtual ~KPort(); 25 ~KPort() override;
26 26
27 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 27 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
28 28
@@ -59,7 +59,6 @@ private:
59 ServerClosed = 3, 59 ServerClosed = 3,
60 }; 60 };
61 61
62private:
63 KServerPort server; 62 KServerPort server;
64 KClientPort client; 63 KClientPort client;
65 State state{State::Invalid}; 64 State state{State::Invalid};
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 123d71cd3..c0656b9af 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -331,19 +331,19 @@ public:
331 331
332 void LoadModule(CodeSet code_set, VAddr base_addr); 332 void LoadModule(CodeSet code_set, VAddr base_addr);
333 333
334 virtual bool IsInitialized() const override { 334 bool IsInitialized() const override {
335 return is_initialized; 335 return is_initialized;
336 } 336 }
337 337
338 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 338 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
339 339
340 virtual void Finalize(); 340 void Finalize() override;
341 341
342 virtual u64 GetId() const override final { 342 u64 GetId() const override {
343 return GetProcessID(); 343 return GetProcessID();
344 } 344 }
345 345
346 virtual bool IsSignaled() const override; 346 bool IsSignaled() const override;
347 347
348 void PinCurrentThread(); 348 void PinCurrentThread();
349 void UnpinCurrentThread(); 349 void UnpinCurrentThread();
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
index 33cd1dd3e..b2850ac7b 100644
--- a/src/core/hle/kernel/k_readable_event.h
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -31,8 +31,8 @@ public:
31 return parent; 31 return parent;
32 } 32 }
33 33
34 virtual bool IsSignaled() const override; 34 bool IsSignaled() const override;
35 virtual void Destroy() override; 35 void Destroy() override;
36 36
37 ResultCode Signal(); 37 ResultCode Signal();
38 ResultCode Clear(); 38 ResultCode Clear();
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 0debbbb51..fab6005ff 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -37,10 +37,10 @@ class KResourceLimit final
37 37
38public: 38public:
39 explicit KResourceLimit(KernelCore& kernel_); 39 explicit KResourceLimit(KernelCore& kernel_);
40 virtual ~KResourceLimit(); 40 ~KResourceLimit() override;
41 41
42 void Initialize(const Core::Timing::CoreTiming* core_timing_); 42 void Initialize(const Core::Timing::CoreTiming* core_timing_);
43 virtual void Finalize() override; 43 void Finalize() override;
44 44
45 s64 GetLimitValue(LimitableResource which) const; 45 s64 GetLimitValue(LimitableResource which) const;
46 s64 GetCurrentValue(LimitableResource which) const; 46 s64 GetCurrentValue(LimitableResource which) const;
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 2f82fbcd6..6a7d80d03 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -659,7 +659,6 @@ void KScheduler::Unload(KThread* thread) {
659 659
660 if (thread) { 660 if (thread) {
661 if (thread->IsCallingSvc()) { 661 if (thread->IsCallingSvc()) {
662 system.ArmInterface(core_id).ExceptionalExit();
663 thread->ClearIsCallingSvc(); 662 thread->ClearIsCallingSvc();
664 } 663 }
665 if (!thread->IsTerminationRequested()) { 664 if (!thread->IsTerminationRequested()) {
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h
index d1a757ec3..55481d63f 100644
--- a/src/core/hle/kernel/k_server_port.h
+++ b/src/core/hle/kernel/k_server_port.h
@@ -25,12 +25,9 @@ class SessionRequestHandler;
25class KServerPort final : public KSynchronizationObject { 25class KServerPort final : public KSynchronizationObject {
26 KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); 26 KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject);
27 27
28private:
29 using SessionList = boost::intrusive::list<KServerSession>;
30
31public: 28public:
32 explicit KServerPort(KernelCore& kernel_); 29 explicit KServerPort(KernelCore& kernel_);
33 virtual ~KServerPort() override; 30 ~KServerPort() override;
34 31
35 void Initialize(KPort* parent_, std::string&& name_); 32 void Initialize(KPort* parent_, std::string&& name_);
36 33
@@ -63,13 +60,14 @@ public:
63 bool IsLight() const; 60 bool IsLight() const;
64 61
65 // Overridden virtual functions. 62 // Overridden virtual functions.
66 virtual void Destroy() override; 63 void Destroy() override;
67 virtual bool IsSignaled() const override; 64 bool IsSignaled() const override;
68 65
69private: 66private:
67 using SessionList = boost::intrusive::list<KServerSession>;
68
70 void CleanupSessions(); 69 void CleanupSessions();
71 70
72private:
73 SessionList session_list; 71 SessionList session_list;
74 SessionRequestHandlerPtr session_handler; 72 SessionRequestHandlerPtr session_handler;
75 KPort* parent{}; 73 KPort* parent{};
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index dd4de2904..27b757ad2 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -42,9 +42,9 @@ class KServerSession final : public KSynchronizationObject,
42 42
43public: 43public:
44 explicit KServerSession(KernelCore& kernel_); 44 explicit KServerSession(KernelCore& kernel_);
45 virtual ~KServerSession() override; 45 ~KServerSession() override;
46 46
47 virtual void Destroy() override; 47 void Destroy() override;
48 48
49 void Initialize(KSession* parent_, std::string&& name_); 49 void Initialize(KSession* parent_, std::string&& name_);
50 50
@@ -56,7 +56,7 @@ public:
56 return parent; 56 return parent;
57 } 57 }
58 58
59 virtual bool IsSignaled() const override; 59 bool IsSignaled() const override;
60 60
61 void OnClientClosed(); 61 void OnClientClosed();
62 62
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
index a981fd1f6..4ddd080d2 100644
--- a/src/core/hle/kernel/k_session.h
+++ b/src/core/hle/kernel/k_session.h
@@ -18,17 +18,17 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAut
18 18
19public: 19public:
20 explicit KSession(KernelCore& kernel_); 20 explicit KSession(KernelCore& kernel_);
21 virtual ~KSession() override; 21 ~KSession() override;
22 22
23 void Initialize(KClientPort* port_, const std::string& name_); 23 void Initialize(KClientPort* port_, const std::string& name_);
24 24
25 virtual void Finalize() override; 25 void Finalize() override;
26 26
27 virtual bool IsInitialized() const override { 27 bool IsInitialized() const override {
28 return initialized; 28 return initialized;
29 } 29 }
30 30
31 virtual uintptr_t GetPostDestroyArgument() const override { 31 uintptr_t GetPostDestroyArgument() const override {
32 return reinterpret_cast<uintptr_t>(process); 32 return reinterpret_cast<uintptr_t>(process);
33 } 33 }
34 34
@@ -78,7 +78,6 @@ private:
78 ServerClosed = 3, 78 ServerClosed = 3,
79 }; 79 };
80 80
81private:
82 void SetState(State state) { 81 void SetState(State state) {
83 atomic_state = static_cast<u8>(state); 82 atomic_state = static_cast<u8>(state);
84 } 83 }
@@ -87,7 +86,6 @@ private:
87 return static_cast<State>(atomic_state.load(std::memory_order_relaxed)); 86 return static_cast<State>(atomic_state.load(std::memory_order_relaxed));
88 } 87 }
89 88
90private:
91 KServerSession server; 89 KServerSession server;
92 KClientSession client; 90 KClientSession client;
93 std::atomic<std::underlying_type_t<State>> atomic_state{ 91 std::atomic<std::underlying_type_t<State>> atomic_state{
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index 553a56327..e9815f90b 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -68,9 +68,9 @@ public:
68 return device_memory->GetPointer(physical_address + offset); 68 return device_memory->GetPointer(physical_address + offset);
69 } 69 }
70 70
71 virtual void Finalize() override; 71 void Finalize() override;
72 72
73 virtual bool IsInitialized() const override { 73 bool IsInitialized() const override {
74 return is_initialized; 74 return is_initialized;
75 } 75 }
76 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 76 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h
index 81d472a3e..0ad74b0a0 100644
--- a/src/core/hle/kernel/k_slab_heap.h
+++ b/src/core/hle/kernel/k_slab_heap.h
@@ -4,34 +4,213 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
8
9#include "common/assert.h"
10#include "common/common_types.h"
11
7namespace Kernel { 12namespace Kernel {
8 13
9class KernelCore; 14class KernelCore;
10 15
11/// This is a placeholder class to manage slab heaps for kernel objects. For now, we just allocate 16namespace impl {
12/// these with new/delete, but this can be re-implemented later to allocate these in emulated 17
13/// memory. 18class KSlabHeapImpl final : NonCopyable {
19public:
20 struct Node {
21 Node* next{};
22 };
23
24 constexpr KSlabHeapImpl() = default;
25
26 void Initialize(std::size_t size) {
27 ASSERT(head == nullptr);
28 obj_size = size;
29 }
30
31 constexpr std::size_t GetObjectSize() const {
32 return obj_size;
33 }
34
35 Node* GetHead() const {
36 return head;
37 }
38
39 void* Allocate() {
40 Node* ret = head.load();
41
42 do {
43 if (ret == nullptr) {
44 break;
45 }
46 } while (!head.compare_exchange_weak(ret, ret->next));
47
48 return ret;
49 }
50
51 void Free(void* obj) {
52 Node* node = static_cast<Node*>(obj);
53
54 Node* cur_head = head.load();
55 do {
56 node->next = cur_head;
57 } while (!head.compare_exchange_weak(cur_head, node));
58 }
59
60private:
61 std::atomic<Node*> head{};
62 std::size_t obj_size{};
63};
64
65} // namespace impl
66
67class KSlabHeapBase : NonCopyable {
68public:
69 constexpr KSlabHeapBase() = default;
70
71 constexpr bool Contains(uintptr_t addr) const {
72 return start <= addr && addr < end;
73 }
74
75 constexpr std::size_t GetSlabHeapSize() const {
76 return (end - start) / GetObjectSize();
77 }
78
79 constexpr std::size_t GetObjectSize() const {
80 return impl.GetObjectSize();
81 }
82
83 constexpr uintptr_t GetSlabHeapAddress() const {
84 return start;
85 }
86
87 std::size_t GetObjectIndexImpl(const void* obj) const {
88 return (reinterpret_cast<uintptr_t>(obj) - start) / GetObjectSize();
89 }
90
91 std::size_t GetPeakIndex() const {
92 return GetObjectIndexImpl(reinterpret_cast<const void*>(peak));
93 }
94
95 void* AllocateImpl() {
96 return impl.Allocate();
97 }
98
99 void FreeImpl(void* obj) {
100 // Don't allow freeing an object that wasn't allocated from this heap
101 ASSERT(Contains(reinterpret_cast<uintptr_t>(obj)));
102
103 impl.Free(obj);
104 }
105
106 void InitializeImpl(std::size_t obj_size, void* memory, std::size_t memory_size) {
107 // Ensure we don't initialize a slab using null memory
108 ASSERT(memory != nullptr);
109
110 // Initialize the base allocator
111 impl.Initialize(obj_size);
112
113 // Set our tracking variables
114 const std::size_t num_obj = (memory_size / obj_size);
115 start = reinterpret_cast<uintptr_t>(memory);
116 end = start + num_obj * obj_size;
117 peak = start;
118
119 // Free the objects
120 u8* cur = reinterpret_cast<u8*>(end);
121
122 for (std::size_t i{}; i < num_obj; i++) {
123 cur -= obj_size;
124 impl.Free(cur);
125 }
126 }
127
128private:
129 using Impl = impl::KSlabHeapImpl;
130
131 Impl impl;
132 uintptr_t peak{};
133 uintptr_t start{};
134 uintptr_t end{};
135};
14 136
15template <typename T> 137template <typename T>
16class KSlabHeap final : NonCopyable { 138class KSlabHeap final : public KSlabHeapBase {
17public: 139public:
18 KSlabHeap() = default; 140 enum class AllocationType {
141 Host,
142 Guest,
143 };
19 144
20 void Initialize([[maybe_unused]] void* memory, [[maybe_unused]] std::size_t memory_size) { 145 explicit constexpr KSlabHeap(AllocationType allocation_type_ = AllocationType::Host)
21 // Placeholder that should initialize the backing slab heap implementation. 146 : KSlabHeapBase(), allocation_type{allocation_type_} {}
147
148 void Initialize(void* memory, std::size_t memory_size) {
149 if (allocation_type == AllocationType::Guest) {
150 InitializeImpl(sizeof(T), memory, memory_size);
151 }
22 } 152 }
23 153
24 T* Allocate() { 154 T* Allocate() {
25 return new T(); 155 switch (allocation_type) {
156 case AllocationType::Host:
157 // Fallback for cases where we do not yet support allocating guest memory from the slab
158 // heap, such as for kernel memory regions.
159 return new T;
160
161 case AllocationType::Guest:
162 T* obj = static_cast<T*>(AllocateImpl());
163 if (obj != nullptr) {
164 new (obj) T();
165 }
166 return obj;
167 }
168
169 UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
170 return nullptr;
26 } 171 }
27 172
28 T* AllocateWithKernel(KernelCore& kernel) { 173 T* AllocateWithKernel(KernelCore& kernel) {
29 return new T(kernel); 174 switch (allocation_type) {
175 case AllocationType::Host:
176 // Fallback for cases where we do not yet support allocating guest memory from the slab
177 // heap, such as for kernel memory regions.
178 return new T(kernel);
179
180 case AllocationType::Guest:
181 T* obj = static_cast<T*>(AllocateImpl());
182 if (obj != nullptr) {
183 new (obj) T(kernel);
184 }
185 return obj;
186 }
187
188 UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
189 return nullptr;
30 } 190 }
31 191
32 void Free(T* obj) { 192 void Free(T* obj) {
33 delete obj; 193 switch (allocation_type) {
194 case AllocationType::Host:
195 // Fallback for cases where we do not yet support allocating guest memory from the slab
196 // heap, such as for kernel memory regions.
197 delete obj;
198 return;
199
200 case AllocationType::Guest:
201 FreeImpl(obj);
202 return;
203 }
204
205 UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
34 } 206 }
207
208 constexpr std::size_t GetObjectIndex(const T* obj) const {
209 return GetObjectIndexImpl(obj);
210 }
211
212private:
213 const AllocationType allocation_type;
35}; 214};
36 215
37} // namespace Kernel 216} // namespace Kernel
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index a41dd1220..3d4ce1fbc 100644
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -29,7 +29,7 @@ public:
29 KSynchronizationObject** objects, const s32 num_objects, 29 KSynchronizationObject** objects, const s32 num_objects,
30 s64 timeout); 30 s64 timeout);
31 31
32 virtual void Finalize() override; 32 void Finalize() override;
33 33
34 [[nodiscard]] virtual bool IsSignaled() const = 0; 34 [[nodiscard]] virtual bool IsSignaled() const = 0;
35 35
@@ -37,7 +37,7 @@ public:
37 37
38protected: 38protected:
39 explicit KSynchronizationObject(KernelCore& kernel); 39 explicit KSynchronizationObject(KernelCore& kernel);
40 virtual ~KSynchronizationObject(); 40 ~KSynchronizationObject() override;
41 41
42 virtual void OnFinalizeSynchronizationObject() {} 42 virtual void OnFinalizeSynchronizationObject() {}
43 43
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index e3f08f256..3cf43d290 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -168,13 +168,13 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
168 std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0, 168 std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0,
169 sizeof(StackParameters)); 169 sizeof(StackParameters));
170 170
171 // Setup the TLS, if needed.
172 if (type == ThreadType::User) {
173 tls_address = owner->CreateTLSRegion();
174 }
175
176 // Set parent, if relevant. 171 // Set parent, if relevant.
177 if (owner != nullptr) { 172 if (owner != nullptr) {
173 // Setup the TLS, if needed.
174 if (type == ThreadType::User) {
175 tls_address = owner->CreateTLSRegion();
176 }
177
178 parent = owner; 178 parent = owner;
179 parent->Open(); 179 parent->Open();
180 parent->IncrementThreadCount(); 180 parent->IncrementThreadCount();
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 4abfc2b49..01eebb165 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -358,21 +358,21 @@ public:
358 return termination_requested || GetRawState() == ThreadState::Terminated; 358 return termination_requested || GetRawState() == ThreadState::Terminated;
359 } 359 }
360 360
361 [[nodiscard]] virtual u64 GetId() const override final { 361 [[nodiscard]] u64 GetId() const override {
362 return this->GetThreadID(); 362 return this->GetThreadID();
363 } 363 }
364 364
365 [[nodiscard]] virtual bool IsInitialized() const override { 365 [[nodiscard]] bool IsInitialized() const override {
366 return initialized; 366 return initialized;
367 } 367 }
368 368
369 [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override { 369 [[nodiscard]] uintptr_t GetPostDestroyArgument() const override {
370 return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0); 370 return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0);
371 } 371 }
372 372
373 virtual void Finalize() override; 373 void Finalize() override;
374 374
375 [[nodiscard]] virtual bool IsSignaled() const override; 375 [[nodiscard]] bool IsSignaled() const override;
376 376
377 static void PostDestroy(uintptr_t arg); 377 static void PostDestroy(uintptr_t arg);
378 378
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h
index c2d0f1eaf..31029a5c2 100644
--- a/src/core/hle/kernel/k_transfer_memory.h
+++ b/src/core/hle/kernel/k_transfer_memory.h
@@ -27,23 +27,23 @@ class KTransferMemory final
27 27
28public: 28public:
29 explicit KTransferMemory(KernelCore& kernel_); 29 explicit KTransferMemory(KernelCore& kernel_);
30 virtual ~KTransferMemory() override; 30 ~KTransferMemory() override;
31 31
32 ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); 32 ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_);
33 33
34 virtual void Finalize() override; 34 void Finalize() override;
35 35
36 virtual bool IsInitialized() const override { 36 bool IsInitialized() const override {
37 return is_initialized; 37 return is_initialized;
38 } 38 }
39 39
40 virtual uintptr_t GetPostDestroyArgument() const override { 40 uintptr_t GetPostDestroyArgument() const override {
41 return reinterpret_cast<uintptr_t>(owner); 41 return reinterpret_cast<uintptr_t>(owner);
42 } 42 }
43 43
44 static void PostDestroy(uintptr_t arg); 44 static void PostDestroy(uintptr_t arg);
45 45
46 KProcess* GetOwner() const { 46 KProcess* GetOwner() const override {
47 return owner; 47 return owner;
48 } 48 }
49 49
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
index 607b0eadb..858d982c4 100644
--- a/src/core/hle/kernel/k_writable_event.h
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -21,7 +21,7 @@ public:
21 explicit KWritableEvent(KernelCore& kernel_); 21 explicit KWritableEvent(KernelCore& kernel_);
22 ~KWritableEvent() override; 22 ~KWritableEvent() override;
23 23
24 virtual void Destroy() override; 24 void Destroy() override;
25 25
26 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 26 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
27 27
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8b55df82e..0ffb78d51 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -258,7 +258,7 @@ struct KernelCore::Impl {
258 KAutoObject::Create(thread.get()); 258 KAutoObject::Create(thread.get());
259 ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess()); 259 ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess());
260 thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); 260 thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
261 return std::move(thread); 261 return thread;
262 }; 262 };
263 263
264 thread_local auto thread = make_thread(); 264 thread_local auto thread = make_thread();
@@ -620,7 +620,8 @@ struct KernelCore::Impl {
620 620
621 void InitializePageSlab() { 621 void InitializePageSlab() {
622 // Allocate slab heaps 622 // Allocate slab heaps
623 user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); 623 user_slab_heap_pages =
624 std::make_unique<KSlabHeap<Page>>(KSlabHeap<Page>::AllocationType::Guest);
624 625
625 // TODO(ameerj): This should be derived, not hardcoded within the kernel 626 // TODO(ameerj): This should be derived, not hardcoded within the kernel
626 constexpr u64 user_slab_heap_size{0x3de000}; 627 constexpr u64 user_slab_heap_size{0x3de000};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 49c17fd14..df0fe1c8e 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1770,7 +1770,7 @@ public:
1770 {232, nullptr, "GetIrSensorState"}, 1770 {232, nullptr, "GetIrSensorState"},
1771 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"}, 1771 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
1772 {301, nullptr, "ActivateNpadSystem"}, 1772 {301, nullptr, "ActivateNpadSystem"},
1773 {303, nullptr, "ApplyNpadSystemCommonPolicy"}, 1773 {303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
1774 {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, 1774 {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
1775 {305, nullptr, "DisableAssigningSingleOnSlSrPress"}, 1775 {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
1776 {306, nullptr, "GetLastActiveNpad"}, 1776 {306, nullptr, "GetLastActiveNpad"},
@@ -1949,6 +1949,15 @@ public:
1949 1949
1950 RegisterHandlers(functions); 1950 RegisterHandlers(functions);
1951 } 1951 }
1952
1953private:
1954 void ApplyNpadSystemCommonPolicy(Kernel::HLERequestContext& ctx) {
1955 // We already do this for homebrew so we can just stub it out
1956 LOG_WARNING(Service_HID, "called");
1957
1958 IPC::ResponseBuilder rb{ctx, 2};
1959 rb.Push(RESULT_SUCCESS);
1960 }
1952}; 1961};
1953 1962
1954class HidTmp final : public ServiceFramework<HidTmp> { 1963class HidTmp final : public ServiceFramework<HidTmp> {
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index de971041f..9e6b87960 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -596,7 +596,7 @@ void BufferCache<P>::PopAsyncFlushes() {
596 runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies); 596 runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies);
597 } 597 }
598 runtime.Finish(); 598 runtime.Finish();
599 for (const auto [copy, buffer_id] : downloads) { 599 for (const auto& [copy, buffer_id] : downloads) {
600 const Buffer& buffer = slot_buffers[buffer_id]; 600 const Buffer& buffer = slot_buffers[buffer_id];
601 const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; 601 const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset;
602 // Undo the modified offset 602 // Undo the modified offset
@@ -606,7 +606,7 @@ void BufferCache<P>::PopAsyncFlushes() {
606 } 606 }
607 } else { 607 } else {
608 const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); 608 const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy);
609 for (const auto [copy, buffer_id] : downloads) { 609 for (const auto& [copy, buffer_id] : downloads) {
610 Buffer& buffer = slot_buffers[buffer_id]; 610 Buffer& buffer = slot_buffers[buffer_id];
611 buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size)); 611 buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size));
612 const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; 612 const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset;
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index 62d84c0f8..6decd2546 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -18,10 +18,10 @@ RasterizerAccelerated::~RasterizerAccelerated() = default;
18void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 18void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
19 const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE); 19 const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE);
20 for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) { 20 for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) {
21 auto& count = cached_pages.at(page >> 3).Count(page); 21 auto& count = cached_pages.at(page >> 2).Count(page);
22 22
23 if (delta > 0) { 23 if (delta > 0) {
24 ASSERT_MSG(count < UINT8_MAX, "Count may overflow!"); 24 ASSERT_MSG(count < UINT16_MAX, "Count may overflow!");
25 } else if (delta < 0) { 25 } else if (delta < 0) {
26 ASSERT_MSG(count > 0, "Count may underflow!"); 26 ASSERT_MSG(count > 0, "Count may underflow!");
27 } else { 27 } else {
@@ -29,7 +29,7 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
29 } 29 }
30 30
31 // Adds or subtracts 1, as count is a unsigned 8-bit value 31 // Adds or subtracts 1, as count is a unsigned 8-bit value
32 count += static_cast<u8>(delta); 32 count += static_cast<u16>(delta);
33 33
34 // Assume delta is either -1 or 1 34 // Assume delta is either -1 or 1
35 if (count == 0) { 35 if (count == 0) {
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
index 9227a4adc..ea879bfdd 100644
--- a/src/video_core/rasterizer_accelerated.h
+++ b/src/video_core/rasterizer_accelerated.h
@@ -29,20 +29,20 @@ private:
29 public: 29 public:
30 CacheEntry() = default; 30 CacheEntry() = default;
31 31
32 std::atomic_uint8_t& Count(std::size_t page) { 32 std::atomic_uint16_t& Count(std::size_t page) {
33 return values[page & 7]; 33 return values[page & 3];
34 } 34 }
35 35
36 const std::atomic_uint8_t& Count(std::size_t page) const { 36 const std::atomic_uint16_t& Count(std::size_t page) const {
37 return values[page & 7]; 37 return values[page & 3];
38 } 38 }
39 39
40 private: 40 private:
41 std::array<std::atomic_uint8_t, 8> values{}; 41 std::array<std::atomic_uint16_t, 4> values{};
42 }; 42 };
43 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); 43 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
44 44
45 std::array<CacheEntry, 0x800000> cached_pages; 45 std::array<CacheEntry, 0x1000000> cached_pages;
46 Core::Memory::Memory& cpu_memory; 46 Core::Memory::Memory& cpu_memory;
47}; 47};
48 48
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index cc0790e07..634fe66a5 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -4,6 +4,12 @@ set(CMAKE_AUTOUIC ON)
4set(CMAKE_INCLUDE_CURRENT_DIR ON) 4set(CMAKE_INCLUDE_CURRENT_DIR ON)
5set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) 5set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules)
6 6
7# Set the RPATH for Qt Libraries
8# This must be done before the `yuzu` target is created
9if (YUZU_USE_BUNDLED_QT AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
10 set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/bin/lib/")
11endif()
12
7add_executable(yuzu 13add_executable(yuzu
8 Info.plist 14 Info.plist
9 about_dialog.cpp 15 about_dialog.cpp
@@ -278,11 +284,14 @@ if(UNIX AND NOT APPLE)
278 install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") 284 install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
279endif() 285endif()
280 286
281if (MSVC) 287if (YUZU_USE_BUNDLED_QT)
282 include(CopyYuzuQt5Deps) 288 include(CopyYuzuQt5Deps)
289 copy_yuzu_Qt5_deps(yuzu)
290endif()
291
292if (MSVC)
283 include(CopyYuzuSDLDeps) 293 include(CopyYuzuSDLDeps)
284 include(CopyYuzuFFmpegDeps) 294 include(CopyYuzuFFmpegDeps)
285 copy_yuzu_Qt5_deps(yuzu)
286 copy_yuzu_SDL_deps(yuzu) 295 copy_yuzu_SDL_deps(yuzu)
287 copy_yuzu_FFmpeg_deps(yuzu) 296 copy_yuzu_FFmpeg_deps(yuzu)
288endif() 297endif()
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 3ad40d2b3..6028135c5 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -2,8 +2,11 @@
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 <QAbstractButton>
6#include <QDialogButtonBox>
5#include <QHash> 7#include <QHash>
6#include <QListWidgetItem> 8#include <QListWidgetItem>
9#include <QPushButton>
7#include <QSignalBlocker> 10#include <QSignalBlocker>
8#include "common/settings.h" 11#include "common/settings.h"
9#include "core/core.h" 12#include "core/core.h"
@@ -31,6 +34,12 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
31 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, 34 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
32 &ConfigureDialog::UpdateVisibleTabs); 35 &ConfigureDialog::UpdateVisibleTabs);
33 36
37 if (Core::System::GetInstance().IsPoweredOn()) {
38 QPushButton* apply_button = ui->buttonBox->addButton(QDialogButtonBox::Apply);
39 connect(apply_button, &QAbstractButton::clicked, this,
40 &ConfigureDialog::HandleApplyButtonClicked);
41 }
42
34 adjustSize(); 43 adjustSize();
35 ui->selectorList->setCurrentRow(0); 44 ui->selectorList->setCurrentRow(0);
36} 45}
@@ -80,6 +89,11 @@ void ConfigureDialog::RetranslateUI() {
80 ui->tabWidget->setCurrentIndex(old_index); 89 ui->tabWidget->setCurrentIndex(old_index);
81} 90}
82 91
92void ConfigureDialog::HandleApplyButtonClicked() {
93 UISettings::values.configuration_applied = true;
94 ApplyConfiguration();
95}
96
83Q_DECLARE_METATYPE(QList<QWidget*>); 97Q_DECLARE_METATYPE(QList<QWidget*>);
84 98
85void ConfigureDialog::PopulateSelectionList() { 99void ConfigureDialog::PopulateSelectionList() {
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 570c3b941..abe019635 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -35,9 +35,10 @@ signals:
35 35
36private: 36private:
37 void changeEvent(QEvent* event) override; 37 void changeEvent(QEvent* event) override;
38
39 void RetranslateUI(); 38 void RetranslateUI();
40 39
40 void HandleApplyButtonClicked();
41
41 void SetConfiguration(); 42 void SetConfiguration();
42 void UpdateVisibleTabs(); 43 void UpdateVisibleTabs();
43 void PopulateSelectionList(); 44 void PopulateSelectionList();
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 3e13bd438..d89f1ad4b 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -6,9 +6,12 @@
6#include <memory> 6#include <memory>
7#include <utility> 7#include <utility>
8 8
9#include <QAbstractButton>
9#include <QCheckBox> 10#include <QCheckBox>
11#include <QDialogButtonBox>
10#include <QHeaderView> 12#include <QHeaderView>
11#include <QMenu> 13#include <QMenu>
14#include <QPushButton>
12#include <QStandardItemModel> 15#include <QStandardItemModel>
13#include <QString> 16#include <QString>
14#include <QTimer> 17#include <QTimer>
@@ -42,6 +45,12 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id)
42 scene = new QGraphicsScene; 45 scene = new QGraphicsScene;
43 ui->icon_view->setScene(scene); 46 ui->icon_view->setScene(scene);
44 47
48 if (Core::System::GetInstance().IsPoweredOn()) {
49 QPushButton* apply_button = ui->buttonBox->addButton(QDialogButtonBox::Apply);
50 connect(apply_button, &QAbstractButton::clicked, this,
51 &ConfigurePerGame::HandleApplyButtonClicked);
52 }
53
45 LoadConfiguration(); 54 LoadConfiguration();
46} 55}
47 56
@@ -74,6 +83,11 @@ void ConfigurePerGame::RetranslateUI() {
74 ui->retranslateUi(this); 83 ui->retranslateUi(this);
75} 84}
76 85
86void ConfigurePerGame::HandleApplyButtonClicked() {
87 UISettings::values.configuration_applied = true;
88 ApplyConfiguration();
89}
90
77void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) { 91void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) {
78 this->file = std::move(file); 92 this->file = std::move(file);
79 LoadConfiguration(); 93 LoadConfiguration();
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index 5f9a08cef..f6e6ab7c4 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -39,6 +39,8 @@ private:
39 void changeEvent(QEvent* event) override; 39 void changeEvent(QEvent* event) override;
40 void RetranslateUI(); 40 void RetranslateUI();
41 41
42 void HandleApplyButtonClicked();
43
42 void LoadConfiguration(); 44 void LoadConfiguration();
43 45
44 std::unique_ptr<Ui::ConfigurePerGame> ui; 46 std::unique_ptr<Ui::ConfigurePerGame> ui;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 37ef62967..0f0e228b0 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2587,12 +2587,12 @@ void GMainWindow::OnConfigure() {
2587 &GMainWindow::OnLanguageChanged); 2587 &GMainWindow::OnLanguageChanged);
2588 2588
2589 const auto result = configure_dialog.exec(); 2589 const auto result = configure_dialog.exec();
2590 if (result != QDialog::Accepted) { 2590 if (result != QDialog::Accepted && !UISettings::values.configuration_applied) {
2591 return; 2591 return;
2592 } else if (result == QDialog::Accepted) {
2593 configure_dialog.ApplyConfiguration();
2594 controller_dialog->refreshConfiguration();
2592 } 2595 }
2593
2594 configure_dialog.ApplyConfiguration();
2595 controller_dialog->refreshConfiguration();
2596 InitializeHotkeys(); 2596 InitializeHotkeys();
2597 if (UISettings::values.theme != old_theme) { 2597 if (UISettings::values.theme != old_theme) {
2598 UpdateUITheme(); 2598 UpdateUITheme();
@@ -2607,6 +2607,8 @@ void GMainWindow::OnConfigure() {
2607 game_list->PopulateAsync(UISettings::values.game_dirs); 2607 game_list->PopulateAsync(UISettings::values.game_dirs);
2608 } 2608 }
2609 2609
2610 UISettings::values.configuration_applied = false;
2611
2610 config->Save(); 2612 config->Save();
2611 2613
2612 if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) { 2614 if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) {
@@ -2636,23 +2638,27 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file
2636 ConfigurePerGame dialog(this, title_id); 2638 ConfigurePerGame dialog(this, title_id);
2637 dialog.LoadFromFile(v_file); 2639 dialog.LoadFromFile(v_file);
2638 const auto result = dialog.exec(); 2640 const auto result = dialog.exec();
2639 if (result == QDialog::Accepted) { 2641
2642 if (result != QDialog::Accepted && !UISettings::values.configuration_applied) {
2643 Settings::RestoreGlobalState(system.IsPoweredOn());
2644 return;
2645 } else if (result == QDialog::Accepted) {
2640 dialog.ApplyConfiguration(); 2646 dialog.ApplyConfiguration();
2647 }
2641 2648
2642 const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); 2649 const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false);
2643 if (reload) { 2650 if (reload) {
2644 game_list->PopulateAsync(UISettings::values.game_dirs); 2651 game_list->PopulateAsync(UISettings::values.game_dirs);
2645 } 2652 }
2646 2653
2647 // Do not cause the global config to write local settings into the config file 2654 // Do not cause the global config to write local settings into the config file
2648 const bool is_powered_on = system.IsPoweredOn(); 2655 const bool is_powered_on = system.IsPoweredOn();
2649 Settings::RestoreGlobalState(is_powered_on); 2656 Settings::RestoreGlobalState(is_powered_on);
2650 2657
2651 if (!is_powered_on) { 2658 UISettings::values.configuration_applied = false;
2652 config->Save(); 2659
2653 } 2660 if (!is_powered_on) {
2654 } else { 2661 config->Save();
2655 Settings::RestoreGlobalState(system.IsPoweredOn());
2656 } 2662 }
2657} 2663}
2658 2664
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 5ba00b8c8..49122ec32 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -95,6 +95,8 @@ struct Values {
95 uint8_t row_2_text_id; 95 uint8_t row_2_text_id;
96 std::atomic_bool is_game_list_reload_pending{false}; 96 std::atomic_bool is_game_list_reload_pending{false};
97 bool cache_game_list; 97 bool cache_game_list;
98
99 bool configuration_applied;
98}; 100};
99 101
100extern Values values; 102extern Values values;