summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio_core/command_generator.cpp5
-rw-r--r--src/common/scope_exit.h6
-rw-r--r--src/core/CMakeLists.txt15
-rw-r--r--src/core/crypto/key_manager.cpp5
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp4
-rw-r--r--src/core/hle/kernel/hle_ipc.h4
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp90
-rw-r--r--src/core/hle/kernel/k_affinity_mask.h2
-rw-r--r--src/core/hle/kernel/k_event.cpp32
-rw-r--r--src/core/hle/kernel/k_event.h57
-rw-r--r--src/core/hle/kernel/k_light_condition_variable.h57
-rw-r--r--src/core/hle/kernel/k_priority_queue.h18
-rw-r--r--src/core/hle/kernel/k_readable_event.cpp57
-rw-r--r--src/core/hle/kernel/k_readable_event.h51
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp152
-rw-r--r--src/core/hle/kernel/k_resource_limit.h81
-rw-r--r--src/core/hle/kernel/k_synchronization_object.cpp3
-rw-r--r--src/core/hle/kernel/k_synchronization_object.h1
-rw-r--r--src/core/hle/kernel/k_thread.cpp4
-rw-r--r--src/core/hle/kernel/k_writable_event.cpp27
-rw-r--r--src/core/hle/kernel/k_writable_event.h44
-rw-r--r--src/core/hle/kernel/kernel.cpp26
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp10
-rw-r--r--src/core/hle/kernel/object.cpp6
-rw-r--r--src/core/hle/kernel/object.h7
-rw-r--r--src/core/hle/kernel/process.cpp43
-rw-r--r--src/core/hle/kernel/process.h8
-rw-r--r--src/core/hle/kernel/readable_event.cpp52
-rw-r--r--src/core/hle/kernel/readable_event.h59
-rw-r--r--src/core/hle/kernel/resource_limit.cpp73
-rw-r--r--src/core/hle/kernel/resource_limit.h106
-rw-r--r--src/core/hle/kernel/svc.cpp165
-rw-r--r--src/core/hle/kernel/svc_results.h1
-rw-r--r--src/core/hle/kernel/writable_event.cpp41
-rw-r--r--src/core/hle/kernel/writable_event.h60
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp10
-rw-r--r--src/core/hle/service/am/am.cpp80
-rw-r--r--src/core/hle/service/am/am.h23
-rw-r--r--src/core/hle/service/am/applets/applets.cpp40
-rw-r--r--src/core/hle/service/am/applets/applets.h18
-rw-r--r--src/core/hle/service/am/applets/controller.cpp2
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp20
-rw-r--r--src/core/hle/service/aoc/aoc_u.h4
-rw-r--r--src/core/hle/service/audio/audout_u.cpp15
-rw-r--r--src/core/hle/service/audio/audren_u.cpp43
-rw-r--r--src/core/hle/service/bcat/backend/backend.cpp16
-rw-r--r--src/core/hle/service/bcat/backend/backend.h10
-rw-r--r--src/core/hle/service/bcat/module.cpp8
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp11
-rw-r--r--src/core/hle/service/btm/btm.cpp34
-rw-r--r--src/core/hle/service/friend/friend.cpp14
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp17
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h21
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h26
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp227
-rw-r--r--src/core/hle/service/hid/controllers/npad.h199
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h70
-rw-r--r--src/core/hle/service/hid/hid.cpp37
-rw-r--r--src/core/hle/service/hid/hid.h10
-rw-r--r--src/core/hle/service/nfp/nfp.cpp31
-rw-r--r--src/core/hle/service/nfp/nfp.h11
-rw-r--r--src/core/hle/service/nifm/nifm.cpp15
-rw-r--r--src/core/hle/service/nim/nim.cpp18
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp10
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp4
-rw-r--r--src/core/hle/service/nvdrv/interface.h2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp18
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h12
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp23
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h12
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp4
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h6
-rw-r--r--src/core/hle/service/ptm/psm.cpp20
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.cpp8
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.h7
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.cpp4
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.h6
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp14
-rw-r--r--src/core/hle/service/vi/display/vi_display.h9
-rw-r--r--src/core/hle/service/vi/vi.cpp4
-rw-r--r--src/core/settings.cpp3
-rw-r--r--src/video_core/host_shaders/CMakeLists.txt20
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp8
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp6
-rw-r--r--src/yuzu/debugger/wait_tree.h4
88 files changed, 1587 insertions, 1036 deletions
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp
index a4a9a757d..5b1065520 100644
--- a/src/audio_core/command_generator.cpp
+++ b/src/audio_core/command_generator.cpp
@@ -383,11 +383,14 @@ void CommandGenerator::GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, E
383 const auto channel_count = params.channel_count; 383 const auto channel_count = params.channel_count;
384 for (s32 i = 0; i < channel_count; i++) { 384 for (s32 i = 0; i < channel_count; i++) {
385 // TODO(ogniK): Actually implement reverb 385 // TODO(ogniK): Actually implement reverb
386 /*
386 if (params.input[i] != params.output[i]) { 387 if (params.input[i] != params.output[i]) {
387 const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]); 388 const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]);
388 auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]); 389 auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
389 ApplyMix<1>(output, input, 32768, worker_params.sample_count); 390 ApplyMix<1>(output, input, 32768, worker_params.sample_count);
390 } 391 }*/
392 auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
393 std::memset(output, 0, worker_params.sample_count * sizeof(s32));
391 } 394 }
392} 395}
393 396
diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h
index fa46cb394..35dac3a8f 100644
--- a/src/common/scope_exit.h
+++ b/src/common/scope_exit.h
@@ -49,3 +49,9 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
49 * \endcode 49 * \endcode
50 */ 50 */
51#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) 51#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
52
53/**
54 * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
55 * used when the caller might want to cancel the ScopeExit.
56 */
57#define SCOPE_GUARD(body) detail::ScopeExit([&]() body)
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 397cc028f..386d7bddf 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -160,9 +160,16 @@ add_library(core STATIC
160 hle/kernel/k_affinity_mask.h 160 hle/kernel/k_affinity_mask.h
161 hle/kernel/k_condition_variable.cpp 161 hle/kernel/k_condition_variable.cpp
162 hle/kernel/k_condition_variable.h 162 hle/kernel/k_condition_variable.h
163 hle/kernel/k_event.cpp
164 hle/kernel/k_event.h
165 hle/kernel/k_light_condition_variable.h
163 hle/kernel/k_light_lock.cpp 166 hle/kernel/k_light_lock.cpp
164 hle/kernel/k_light_lock.h 167 hle/kernel/k_light_lock.h
165 hle/kernel/k_priority_queue.h 168 hle/kernel/k_priority_queue.h
169 hle/kernel/k_readable_event.cpp
170 hle/kernel/k_readable_event.h
171 hle/kernel/k_resource_limit.cpp
172 hle/kernel/k_resource_limit.h
166 hle/kernel/k_scheduler.cpp 173 hle/kernel/k_scheduler.cpp
167 hle/kernel/k_scheduler.h 174 hle/kernel/k_scheduler.h
168 hle/kernel/k_scheduler_lock.h 175 hle/kernel/k_scheduler_lock.h
@@ -173,6 +180,8 @@ add_library(core STATIC
173 hle/kernel/k_thread.cpp 180 hle/kernel/k_thread.cpp
174 hle/kernel/k_thread.h 181 hle/kernel/k_thread.h
175 hle/kernel/k_thread_queue.h 182 hle/kernel/k_thread_queue.h
183 hle/kernel/k_writable_event.cpp
184 hle/kernel/k_writable_event.h
176 hle/kernel/kernel.cpp 185 hle/kernel/kernel.cpp
177 hle/kernel/kernel.h 186 hle/kernel/kernel.h
178 hle/kernel/memory/address_space_info.cpp 187 hle/kernel/memory/address_space_info.cpp
@@ -201,10 +210,6 @@ add_library(core STATIC
201 hle/kernel/process.h 210 hle/kernel/process.h
202 hle/kernel/process_capability.cpp 211 hle/kernel/process_capability.cpp
203 hle/kernel/process_capability.h 212 hle/kernel/process_capability.h
204 hle/kernel/readable_event.cpp
205 hle/kernel/readable_event.h
206 hle/kernel/resource_limit.cpp
207 hle/kernel/resource_limit.h
208 hle/kernel/server_port.cpp 213 hle/kernel/server_port.cpp
209 hle/kernel/server_port.h 214 hle/kernel/server_port.h
210 hle/kernel/server_session.cpp 215 hle/kernel/server_session.cpp
@@ -225,8 +230,6 @@ add_library(core STATIC
225 hle/kernel/time_manager.h 230 hle/kernel/time_manager.h
226 hle/kernel/transfer_memory.cpp 231 hle/kernel/transfer_memory.cpp
227 hle/kernel/transfer_memory.h 232 hle/kernel/transfer_memory.h
228 hle/kernel/writable_event.cpp
229 hle/kernel/writable_event.h
230 hle/lock.cpp 233 hle/lock.cpp
231 hle/lock.h 234 hle/lock.h
232 hle/result.h 235 hle/result.h
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index cebe2ce37..ad116dcc0 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -568,6 +568,11 @@ KeyManager::KeyManager() {
568 // Initialize keys 568 // Initialize keys
569 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath(); 569 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath();
570 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); 570 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir);
571
572 if (!Common::FS::Exists(yuzu_keys_dir)) {
573 Common::FS::CreateDir(yuzu_keys_dir);
574 }
575
571 if (Settings::values.use_dev_keys) { 576 if (Settings::values.use_dev_keys) {
572 dev_mode = true; 577 dev_mode = true;
573 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false); 578 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false);
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index c7b10ca7a..7ec62cf18 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -17,16 +17,16 @@
17#include "core/hle/kernel/errors.h" 17#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/handle_table.h" 18#include "core/hle/kernel/handle_table.h"
19#include "core/hle/kernel/hle_ipc.h" 19#include "core/hle/kernel/hle_ipc.h"
20#include "core/hle/kernel/k_readable_event.h"
20#include "core/hle/kernel/k_scheduler.h" 21#include "core/hle/kernel/k_scheduler.h"
21#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 22#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
22#include "core/hle/kernel/k_thread.h" 23#include "core/hle/kernel/k_thread.h"
24#include "core/hle/kernel/k_writable_event.h"
23#include "core/hle/kernel/kernel.h" 25#include "core/hle/kernel/kernel.h"
24#include "core/hle/kernel/object.h" 26#include "core/hle/kernel/object.h"
25#include "core/hle/kernel/process.h" 27#include "core/hle/kernel/process.h"
26#include "core/hle/kernel/readable_event.h"
27#include "core/hle/kernel/server_session.h" 28#include "core/hle/kernel/server_session.h"
28#include "core/hle/kernel/time_manager.h" 29#include "core/hle/kernel/time_manager.h"
29#include "core/hle/kernel/writable_event.h"
30#include "core/memory.h" 30#include "core/memory.h"
31 31
32namespace Kernel { 32namespace Kernel {
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 9f764c79a..9a769781b 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -41,8 +41,8 @@ class KernelCore;
41class Process; 41class Process;
42class ServerSession; 42class ServerSession;
43class KThread; 43class KThread;
44class ReadableEvent; 44class KReadableEvent;
45class WritableEvent; 45class KWritableEvent;
46 46
47enum class ThreadWakeupReason; 47enum class ThreadWakeupReason;
48 48
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index 1685d25bb..d0e90fd60 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -118,9 +118,13 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
118 118
119 // Check the userspace value. 119 // Check the userspace value.
120 s32 user_value{}; 120 s32 user_value{};
121 R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1), 121 if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) {
122 Svc::ResultInvalidCurrentMemory); 122 LOG_ERROR(Kernel, "Invalid current memory!");
123 R_UNLESS(user_value == value, Svc::ResultInvalidState); 123 return Svc::ResultInvalidCurrentMemory;
124 }
125 if (user_value != value) {
126 return Svc::ResultInvalidState;
127 }
124 128
125 auto it = thread_tree.nfind_light({addr, -1}); 129 auto it = thread_tree.nfind_light({addr, -1});
126 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && 130 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
@@ -143,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
143 // Perform signaling. 147 // Perform signaling.
144 s32 num_waiters{}; 148 s32 num_waiters{};
145 { 149 {
146 KScopedSchedulerLock sl(kernel); 150 [[maybe_unused]] const KScopedSchedulerLock sl(kernel);
147 151
148 auto it = thread_tree.nfind_light({addr, -1}); 152 auto it = thread_tree.nfind_light({addr, -1});
149 // Determine the updated value. 153 // Determine the updated value.
150 s32 new_value{}; 154 s32 new_value{};
151 if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) { 155 if (count <= 0) {
152 if (count <= 0) { 156 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
153 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 157 new_value = value - 2;
154 new_value = value - 2;
155 } else {
156 new_value = value + 1;
157 }
158 } else { 158 } else {
159 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 159 new_value = value + 1;
160 auto tmp_it = it;
161 s32 tmp_num_waiters{};
162 while ((++tmp_it != thread_tree.end()) &&
163 (tmp_it->GetAddressArbiterKey() == addr)) {
164 if ((tmp_num_waiters++) >= count) {
165 break;
166 }
167 }
168
169 if (tmp_num_waiters < count) {
170 new_value = value - 1;
171 } else {
172 new_value = value;
173 }
174 } else {
175 new_value = value + 1;
176 }
177 } 160 }
178 } else { 161 } else {
179 if (count <= 0) { 162 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
180 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
181 new_value = value - 1;
182 } else {
183 new_value = value + 1;
184 }
185 } else {
186 auto tmp_it = it; 163 auto tmp_it = it;
187 s32 tmp_num_waiters{}; 164 s32 tmp_num_waiters{};
188 while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && 165 while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) {
189 (tmp_num_waiters < count + 1)) { 166 if (tmp_num_waiters++ >= count) {
190 ++tmp_num_waiters; 167 break;
191 ++tmp_it; 168 }
192 } 169 }
193 170
194 if (tmp_num_waiters == 0) { 171 if (tmp_num_waiters < count) {
195 new_value = value + 1;
196 } else if (tmp_num_waiters <= count) {
197 new_value = value - 1; 172 new_value = value - 1;
198 } else { 173 } else {
199 new_value = value; 174 new_value = value;
200 } 175 }
176 } else {
177 new_value = value + 1;
201 } 178 }
202 } 179 }
203 180
@@ -205,13 +182,18 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
205 s32 user_value{}; 182 s32 user_value{};
206 bool succeeded{}; 183 bool succeeded{};
207 if (value != new_value) { 184 if (value != new_value) {
208 succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value); 185 succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value);
209 } else { 186 } else {
210 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 187 succeeded = ReadFromUser(system, &user_value, addr);
211 } 188 }
212 189
213 R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); 190 if (!succeeded) {
214 R_UNLESS(user_value == value, Svc::ResultInvalidState); 191 LOG_ERROR(Kernel, "Invalid current memory!");
192 return Svc::ResultInvalidCurrentMemory;
193 }
194 if (user_value != value) {
195 return Svc::ResultInvalidState;
196 }
215 197
216 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && 198 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
217 (it->GetAddressArbiterKey() == addr)) { 199 (it->GetAddressArbiterKey() == addr)) {
@@ -249,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
249 s32 user_value{}; 231 s32 user_value{};
250 bool succeeded{}; 232 bool succeeded{};
251 if (decrement) { 233 if (decrement) {
252 succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value); 234 succeeded = DecrementIfLessThan(system, &user_value, addr, value);
253 } else { 235 } else {
254 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 236 succeeded = ReadFromUser(system, &user_value, addr);
255 } 237 }
256 238
257 if (!succeeded) { 239 if (!succeeded) {
@@ -272,7 +254,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
272 } 254 }
273 255
274 // Set the arbiter. 256 // Set the arbiter.
275 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 257 cur_thread->SetAddressArbiter(&thread_tree, addr);
276 thread_tree.insert(*cur_thread); 258 thread_tree.insert(*cur_thread);
277 cur_thread->SetState(ThreadState::Waiting); 259 cur_thread->SetState(ThreadState::Waiting);
278 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 260 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -293,7 +275,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
293 275
294 // Get the result. 276 // Get the result.
295 KSynchronizationObject* dummy{}; 277 KSynchronizationObject* dummy{};
296 return cur_thread->GetWaitResult(std::addressof(dummy)); 278 return cur_thread->GetWaitResult(&dummy);
297} 279}
298 280
299ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { 281ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
@@ -314,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
314 296
315 // Read the value from userspace. 297 // Read the value from userspace.
316 s32 user_value{}; 298 s32 user_value{};
317 if (!ReadFromUser(system, std::addressof(user_value), addr)) { 299 if (!ReadFromUser(system, &user_value, addr)) {
318 slp.CancelSleep(); 300 slp.CancelSleep();
319 return Svc::ResultInvalidCurrentMemory; 301 return Svc::ResultInvalidCurrentMemory;
320 } 302 }
@@ -332,7 +314,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
332 } 314 }
333 315
334 // Set the arbiter. 316 // Set the arbiter.
335 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 317 cur_thread->SetAddressArbiter(&thread_tree, addr);
336 thread_tree.insert(*cur_thread); 318 thread_tree.insert(*cur_thread);
337 cur_thread->SetState(ThreadState::Waiting); 319 cur_thread->SetState(ThreadState::Waiting);
338 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 320 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -353,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
353 335
354 // Get the result. 336 // Get the result.
355 KSynchronizationObject* dummy{}; 337 KSynchronizationObject* dummy{};
356 return cur_thread->GetWaitResult(std::addressof(dummy)); 338 return cur_thread->GetWaitResult(&dummy);
357} 339}
358 340
359} // namespace Kernel 341} // namespace Kernel
diff --git a/src/core/hle/kernel/k_affinity_mask.h b/src/core/hle/kernel/k_affinity_mask.h
index dd73781cd..b906895fc 100644
--- a/src/core/hle/kernel/k_affinity_mask.h
+++ b/src/core/hle/kernel/k_affinity_mask.h
@@ -27,7 +27,7 @@ public:
27 } 27 }
28 28
29 [[nodiscard]] constexpr bool GetAffinity(s32 core) const { 29 [[nodiscard]] constexpr bool GetAffinity(s32 core) const {
30 return this->mask & GetCoreBit(core); 30 return (this->mask & GetCoreBit(core)) != 0;
31 } 31 }
32 32
33 constexpr void SetAffinity(s32 core, bool set) { 33 constexpr void SetAffinity(s32 core, bool set) {
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
new file mode 100644
index 000000000..bb2fa4ad5
--- /dev/null
+++ b/src/core/hle/kernel/k_event.cpp
@@ -0,0 +1,32 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_event.h"
6#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/k_writable_event.h"
8
9namespace Kernel {
10
11KEvent::KEvent(KernelCore& kernel, std::string&& name) : Object{kernel, std::move(name)} {}
12
13KEvent::~KEvent() = default;
14
15std::shared_ptr<KEvent> KEvent::Create(KernelCore& kernel, std::string&& name) {
16 return std::make_shared<KEvent>(kernel, std::move(name));
17}
18
19void KEvent::Initialize() {
20 // Create our sub events.
21 readable_event = std::make_shared<KReadableEvent>(kernel, GetName() + ":Readable");
22 writable_event = std::make_shared<KWritableEvent>(kernel, GetName() + ":Writable");
23
24 // Initialize our sub sessions.
25 readable_event->Initialize(this);
26 writable_event->Initialize(this);
27
28 // Mark initialized.
29 initialized = true;
30}
31
32} // namespace Kernel
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
new file mode 100644
index 000000000..2fb887129
--- /dev/null
+++ b/src/core/hle/kernel/k_event.h
@@ -0,0 +1,57 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/object.h"
8
9namespace Kernel {
10
11class KernelCore;
12class KReadableEvent;
13class KWritableEvent;
14
15class KEvent final : public Object {
16public:
17 explicit KEvent(KernelCore& kernel, std::string&& name);
18 ~KEvent() override;
19
20 static std::shared_ptr<KEvent> Create(KernelCore& kernel, std::string&& name);
21
22 void Initialize();
23
24 void Finalize() override {}
25
26 std::string GetTypeName() const override {
27 return "KEvent";
28 }
29
30 static constexpr HandleType HANDLE_TYPE = HandleType::Event;
31 HandleType GetHandleType() const override {
32 return HANDLE_TYPE;
33 }
34
35 std::shared_ptr<KReadableEvent>& GetReadableEvent() {
36 return readable_event;
37 }
38
39 std::shared_ptr<KWritableEvent>& GetWritableEvent() {
40 return writable_event;
41 }
42
43 const std::shared_ptr<KReadableEvent>& GetReadableEvent() const {
44 return readable_event;
45 }
46
47 const std::shared_ptr<KWritableEvent>& GetWritableEvent() const {
48 return writable_event;
49 }
50
51private:
52 std::shared_ptr<KReadableEvent> readable_event;
53 std::shared_ptr<KWritableEvent> writable_event;
54 bool initialized{};
55};
56
57} // namespace Kernel
diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h
new file mode 100644
index 000000000..362d0db28
--- /dev/null
+++ b/src/core/hle/kernel/k_light_condition_variable.h
@@ -0,0 +1,57 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once
9
10#include "common/common_types.h"
11#include "core/hle/kernel/k_scheduler.h"
12#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
13#include "core/hle/kernel/k_thread_queue.h"
14#include "core/hle/kernel/time_manager.h"
15
16namespace Kernel {
17class KernelCore;
18
19class KLightConditionVariable {
20public:
21 explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {}
22
23 void Wait(KLightLock* lock, s64 timeout = -1) {
24 WaitImpl(lock, timeout);
25 lock->Lock();
26 }
27
28 void Broadcast() {
29 KScopedSchedulerLock lk{kernel};
30 while (thread_queue.WakeupFrontThread() != nullptr) {
31 // We want to signal all threads, and so should continue waking up until there's nothing
32 // to wake.
33 }
34 }
35
36private:
37 void WaitImpl(KLightLock* lock, s64 timeout) {
38 KThread* owner = GetCurrentThreadPointer(kernel);
39
40 // Sleep the thread.
41 {
42 KScopedSchedulerLockAndSleep lk(kernel, owner, timeout);
43 lock->Unlock();
44
45 if (!thread_queue.SleepThread(owner)) {
46 lk.CancelSleep();
47 return;
48 }
49 }
50
51 // Cancel the task that the sleep setup.
52 kernel.TimeManager().UnscheduleTimeEvent(owner);
53 }
54 KThreadQueue thread_queue;
55 KernelCore& kernel;
56};
57} // namespace Kernel
diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h
index 13d628b85..4aa669d95 100644
--- a/src/core/hle/kernel/k_priority_queue.h
+++ b/src/core/hle/kernel/k_priority_queue.h
@@ -24,11 +24,11 @@ template <typename T>
24concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) { 24concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) {
25 { t.GetAffinityMask() } 25 { t.GetAffinityMask() }
26 ->Common::ConvertibleTo<u64>; 26 ->Common::ConvertibleTo<u64>;
27 {t.SetAffinityMask(std::declval<u64>())}; 27 {t.SetAffinityMask(0)};
28 28
29 { t.GetAffinity(std::declval<int32_t>()) } 29 { t.GetAffinity(0) }
30 ->std::same_as<bool>; 30 ->std::same_as<bool>;
31 {t.SetAffinity(std::declval<int32_t>(), std::declval<bool>())}; 31 {t.SetAffinity(0, false)};
32 {t.SetAll()}; 32 {t.SetAll()};
33}; 33};
34 34
@@ -42,11 +42,11 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
42 ->std::same_as<T*>; 42 ->std::same_as<T*>;
43 { (typename T::QueueEntry()).GetPrev() } 43 { (typename T::QueueEntry()).GetPrev() }
44 ->std::same_as<T*>; 44 ->std::same_as<T*>;
45 { t.GetPriorityQueueEntry(std::declval<s32>()) } 45 { t.GetPriorityQueueEntry(0) }
46 ->std::same_as<typename T::QueueEntry&>; 46 ->std::same_as<typename T::QueueEntry&>;
47 47
48 {t.GetAffinityMask()}; 48 {t.GetAffinityMask()};
49 { typename std::remove_cvref<decltype(t.GetAffinityMask())>::type() } 49 { std::remove_cvref_t<decltype(t.GetAffinityMask())>() }
50 ->KPriorityQueueAffinityMask; 50 ->KPriorityQueueAffinityMask;
51 51
52 { t.GetActiveCore() } 52 { t.GetActiveCore() }
@@ -55,17 +55,17 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
55 ->Common::ConvertibleTo<s32>; 55 ->Common::ConvertibleTo<s32>;
56}; 56};
57 57
58template <typename Member, size_t _NumCores, int LowestPriority, int HighestPriority> 58template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
59requires KPriorityQueueMember<Member> class KPriorityQueue { 59requires KPriorityQueueMember<Member> class KPriorityQueue {
60public: 60public:
61 using AffinityMaskType = typename std::remove_cv_t< 61 using AffinityMaskType = std::remove_cv_t<
62 typename std::remove_reference<decltype(std::declval<Member>().GetAffinityMask())>::type>; 62 std::remove_reference_t<decltype(std::declval<Member>().GetAffinityMask())>>;
63 63
64 static_assert(LowestPriority >= 0); 64 static_assert(LowestPriority >= 0);
65 static_assert(HighestPriority >= 0); 65 static_assert(HighestPriority >= 0);
66 static_assert(LowestPriority >= HighestPriority); 66 static_assert(LowestPriority >= HighestPriority);
67 static constexpr size_t NumPriority = LowestPriority - HighestPriority + 1; 67 static constexpr size_t NumPriority = LowestPriority - HighestPriority + 1;
68 static constexpr size_t NumCores = _NumCores; 68 static constexpr size_t NumCores = NumCores_;
69 69
70 static constexpr bool IsValidCore(s32 core) { 70 static constexpr bool IsValidCore(s32 core) {
71 return 0 <= core && core < static_cast<s32>(NumCores); 71 return 0 <= core && core < static_cast<s32>(NumCores);
diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp
new file mode 100644
index 000000000..d8a42dbaf
--- /dev/null
+++ b/src/core/hle/kernel/k_readable_event.cpp
@@ -0,0 +1,57 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "common/common_funcs.h"
8#include "common/logging/log.h"
9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/k_scheduler.h"
12#include "core/hle/kernel/k_thread.h"
13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/object.h"
15#include "core/hle/kernel/svc_results.h"
16
17namespace Kernel {
18
19KReadableEvent::KReadableEvent(KernelCore& kernel, std::string&& name)
20 : KSynchronizationObject{kernel, std::move(name)} {}
21KReadableEvent::~KReadableEvent() = default;
22
23bool KReadableEvent::IsSignaled() const {
24 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
25
26 return is_signaled;
27}
28
29ResultCode KReadableEvent::Signal() {
30 KScopedSchedulerLock lk{kernel};
31
32 if (!is_signaled) {
33 is_signaled = true;
34 NotifyAvailable();
35 }
36
37 return RESULT_SUCCESS;
38}
39
40ResultCode KReadableEvent::Clear() {
41 Reset();
42
43 return RESULT_SUCCESS;
44}
45
46ResultCode KReadableEvent::Reset() {
47 KScopedSchedulerLock lk{kernel};
48
49 if (!is_signaled) {
50 return Svc::ResultInvalidState;
51 }
52
53 is_signaled = false;
54 return RESULT_SUCCESS;
55}
56
57} // namespace Kernel
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
new file mode 100644
index 000000000..e6f0fd900
--- /dev/null
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -0,0 +1,51 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/k_synchronization_object.h"
8#include "core/hle/kernel/object.h"
9#include "core/hle/result.h"
10
11namespace Kernel {
12
13class KernelCore;
14class KEvent;
15
16class KReadableEvent final : public KSynchronizationObject {
17public:
18 explicit KReadableEvent(KernelCore& kernel, std::string&& name);
19 ~KReadableEvent() override;
20
21 std::string GetTypeName() const override {
22 return "KReadableEvent";
23 }
24
25 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
26 HandleType GetHandleType() const override {
27 return HANDLE_TYPE;
28 }
29
30 KEvent* GetParent() const {
31 return parent;
32 }
33
34 void Initialize(KEvent* parent_) {
35 is_signaled = false;
36 parent = parent_;
37 }
38
39 bool IsSignaled() const override;
40 void Finalize() override {}
41
42 ResultCode Signal();
43 ResultCode Clear();
44 ResultCode Reset();
45
46private:
47 bool is_signaled{};
48 KEvent* parent{};
49};
50
51} // namespace Kernel
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
new file mode 100644
index 000000000..ab2ab683f
--- /dev/null
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -0,0 +1,152 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#include "common/assert.h"
9#include "core/core.h"
10#include "core/core_timing.h"
11#include "core/core_timing_util.h"
12#include "core/hle/kernel/k_resource_limit.h"
13#include "core/hle/kernel/svc_results.h"
14
15namespace Kernel {
16constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
17
18KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system)
19 : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {}
20KResourceLimit::~KResourceLimit() = default;
21
22s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
23 const auto index = static_cast<std::size_t>(which);
24 s64 value{};
25 {
26 KScopedLightLock lk{lock};
27 value = limit_values[index];
28 ASSERT(value >= 0);
29 ASSERT(current_values[index] <= limit_values[index]);
30 ASSERT(current_hints[index] <= current_values[index]);
31 }
32 return value;
33}
34
35s64 KResourceLimit::GetCurrentValue(LimitableResource which) const {
36 const auto index = static_cast<std::size_t>(which);
37 s64 value{};
38 {
39 KScopedLightLock lk{lock};
40 value = current_values[index];
41 ASSERT(value >= 0);
42 ASSERT(current_values[index] <= limit_values[index]);
43 ASSERT(current_hints[index] <= current_values[index]);
44 }
45 return value;
46}
47
48s64 KResourceLimit::GetPeakValue(LimitableResource which) const {
49 const auto index = static_cast<std::size_t>(which);
50 s64 value{};
51 {
52 KScopedLightLock lk{lock};
53 value = peak_values[index];
54 ASSERT(value >= 0);
55 ASSERT(current_values[index] <= limit_values[index]);
56 ASSERT(current_hints[index] <= current_values[index]);
57 }
58 return value;
59}
60
61s64 KResourceLimit::GetFreeValue(LimitableResource which) const {
62 const auto index = static_cast<std::size_t>(which);
63 s64 value{};
64 {
65 KScopedLightLock lk(lock);
66 ASSERT(current_values[index] >= 0);
67 ASSERT(current_values[index] <= limit_values[index]);
68 ASSERT(current_hints[index] <= current_values[index]);
69 value = limit_values[index] - current_values[index];
70 }
71
72 return value;
73}
74
75ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
76 const auto index = static_cast<std::size_t>(which);
77 KScopedLightLock lk(lock);
78 R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState);
79
80 limit_values[index] = value;
81
82 return RESULT_SUCCESS;
83}
84
85bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
86 return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout);
87}
88
89bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
90 ASSERT(value >= 0);
91 const auto index = static_cast<std::size_t>(which);
92 KScopedLightLock lk(lock);
93
94 ASSERT(current_hints[index] <= current_values[index]);
95 if (current_hints[index] >= limit_values[index]) {
96 return false;
97 }
98
99 // Loop until we reserve or run out of time.
100 while (true) {
101 ASSERT(current_values[index] <= limit_values[index]);
102 ASSERT(current_hints[index] <= current_values[index]);
103
104 // If we would overflow, don't allow to succeed.
105 if (current_values[index] + value <= current_values[index]) {
106 break;
107 }
108
109 if (current_values[index] + value <= limit_values[index]) {
110 current_values[index] += value;
111 current_hints[index] += value;
112 peak_values[index] = std::max(peak_values[index], current_values[index]);
113 return true;
114 }
115
116 if (current_hints[index] + value <= limit_values[index] &&
117 (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) {
118 waiter_count++;
119 cond_var.Wait(&lock, timeout);
120 waiter_count--;
121 } else {
122 break;
123 }
124 }
125
126 return false;
127}
128
129void KResourceLimit::Release(LimitableResource which, s64 value) {
130 Release(which, value, value);
131}
132
133void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
134 ASSERT(value >= 0);
135 ASSERT(hint >= 0);
136
137 const auto index = static_cast<std::size_t>(which);
138 KScopedLightLock lk(lock);
139 ASSERT(current_values[index] <= limit_values[index]);
140 ASSERT(current_hints[index] <= current_values[index]);
141 ASSERT(value <= current_values[index]);
142 ASSERT(hint <= current_hints[index]);
143
144 current_values[index] -= value;
145 current_hints[index] -= hint;
146
147 if (waiter_count != 0) {
148 cond_var.Broadcast();
149 }
150}
151
152} // namespace Kernel
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
new file mode 100644
index 000000000..58ae456f1
--- /dev/null
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -0,0 +1,81 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once
9
10#include <array>
11#include "common/common_types.h"
12#include "core/hle/kernel/k_light_condition_variable.h"
13#include "core/hle/kernel/k_light_lock.h"
14#include "core/hle/kernel/object.h"
15
16union ResultCode;
17
18namespace Core {
19class System;
20}
21
22namespace Kernel {
23class KernelCore;
24enum class LimitableResource : u32 {
25 PhysicalMemory = 0,
26 Threads = 1,
27 Events = 2,
28 TransferMemory = 3,
29 Sessions = 4,
30
31 Count,
32};
33
34constexpr bool IsValidResourceType(LimitableResource type) {
35 return type < LimitableResource::Count;
36}
37
38class KResourceLimit final : public Object {
39public:
40 explicit KResourceLimit(KernelCore& kernel, Core::System& system);
41 ~KResourceLimit();
42
43 s64 GetLimitValue(LimitableResource which) const;
44 s64 GetCurrentValue(LimitableResource which) const;
45 s64 GetPeakValue(LimitableResource which) const;
46 s64 GetFreeValue(LimitableResource which) const;
47
48 ResultCode SetLimitValue(LimitableResource which, s64 value);
49
50 bool Reserve(LimitableResource which, s64 value);
51 bool Reserve(LimitableResource which, s64 value, s64 timeout);
52 void Release(LimitableResource which, s64 value);
53 void Release(LimitableResource which, s64 value, s64 hint);
54
55 std::string GetTypeName() const override {
56 return "KResourceLimit";
57 }
58 std::string GetName() const override {
59 return GetTypeName();
60 }
61
62 static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
63 HandleType GetHandleType() const override {
64 return HANDLE_TYPE;
65 }
66
67 virtual void Finalize() override {}
68
69private:
70 using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>;
71 ResourceArray limit_values{};
72 ResourceArray current_values{};
73 ResourceArray current_hints{};
74 ResourceArray peak_values{};
75 mutable KLightLock lock;
76 s32 waiter_count{};
77 KLightConditionVariable cond_var;
78 KernelCore& kernel;
79 Core::System& system;
80};
81} // namespace Kernel
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp
index a3b34f82f..140cc46a7 100644
--- a/src/core/hle/kernel/k_synchronization_object.cpp
+++ b/src/core/hle/kernel/k_synchronization_object.cpp
@@ -132,6 +132,9 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
132 132
133KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {} 133KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {}
134 134
135KSynchronizationObject::KSynchronizationObject(KernelCore& kernel, std::string&& name)
136 : Object{kernel, std::move(name)} {}
137
135KSynchronizationObject::~KSynchronizationObject() = default; 138KSynchronizationObject::~KSynchronizationObject() = default;
136 139
137void KSynchronizationObject::NotifyAvailable(ResultCode result) { 140void KSynchronizationObject::NotifyAvailable(ResultCode result) {
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index f65c71c28..5803718fd 100644
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -33,6 +33,7 @@ public:
33 33
34protected: 34protected:
35 explicit KSynchronizationObject(KernelCore& kernel); 35 explicit KSynchronizationObject(KernelCore& kernel);
36 explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
36 virtual ~KSynchronizationObject(); 37 virtual ~KSynchronizationObject();
37 38
38 void NotifyAvailable(ResultCode result); 39 void NotifyAvailable(ResultCode result);
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index aa100e139..b59259c4f 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -21,6 +21,7 @@
21#include "core/hle/kernel/errors.h" 21#include "core/hle/kernel/errors.h"
22#include "core/hle/kernel/handle_table.h" 22#include "core/hle/kernel/handle_table.h"
23#include "core/hle/kernel/k_condition_variable.h" 23#include "core/hle/kernel/k_condition_variable.h"
24#include "core/hle/kernel/k_resource_limit.h"
24#include "core/hle/kernel/k_scheduler.h" 25#include "core/hle/kernel/k_scheduler.h"
25#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 26#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
26#include "core/hle/kernel/k_thread.h" 27#include "core/hle/kernel/k_thread.h"
@@ -29,7 +30,6 @@
29#include "core/hle/kernel/memory/memory_layout.h" 30#include "core/hle/kernel/memory/memory_layout.h"
30#include "core/hle/kernel/object.h" 31#include "core/hle/kernel/object.h"
31#include "core/hle/kernel/process.h" 32#include "core/hle/kernel/process.h"
32#include "core/hle/kernel/resource_limit.h"
33#include "core/hle/kernel/svc_results.h" 33#include "core/hle/kernel/svc_results.h"
34#include "core/hle/kernel/time_manager.h" 34#include "core/hle/kernel/time_manager.h"
35#include "core/hle/result.h" 35#include "core/hle/result.h"
@@ -247,7 +247,7 @@ void KThread::Finalize() {
247 // Decrement the parent process's thread count. 247 // Decrement the parent process's thread count.
248 if (parent != nullptr) { 248 if (parent != nullptr) {
249 parent->DecrementThreadCount(); 249 parent->DecrementThreadCount();
250 parent->GetResourceLimit()->Release(ResourceType::Threads, 1); 250 parent->GetResourceLimit()->Release(LimitableResource::Threads, 1);
251 } 251 }
252} 252}
253 253
diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp
new file mode 100644
index 000000000..25c52edb2
--- /dev/null
+++ b/src/core/hle/kernel/k_writable_event.cpp
@@ -0,0 +1,27 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_event.h"
6#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/k_writable_event.h"
8
9namespace Kernel {
10
11KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name)
12 : Object{kernel, std::move(name)} {}
13KWritableEvent::~KWritableEvent() = default;
14
15void KWritableEvent::Initialize(KEvent* parent_) {
16 parent = parent_;
17}
18
19ResultCode KWritableEvent::Signal() {
20 return parent->GetReadableEvent()->Signal();
21}
22
23ResultCode KWritableEvent::Clear() {
24 return parent->GetReadableEvent()->Clear();
25}
26
27} // namespace Kernel
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
new file mode 100644
index 000000000..518f5448d
--- /dev/null
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -0,0 +1,44 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/object.h"
8#include "core/hle/result.h"
9
10namespace Kernel {
11
12class KernelCore;
13class KEvent;
14
15class KWritableEvent final : public Object {
16public:
17 explicit KWritableEvent(KernelCore& kernel, std::string&& name);
18 ~KWritableEvent() override;
19
20 std::string GetTypeName() const override {
21 return "KWritableEvent";
22 }
23
24 static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
25 HandleType GetHandleType() const override {
26 return HANDLE_TYPE;
27 }
28
29 void Initialize(KEvent* parent_);
30
31 void Finalize() override {}
32
33 ResultCode Signal();
34 ResultCode Clear();
35
36 KEvent* GetParent() const {
37 return parent;
38 }
39
40private:
41 KEvent* parent{};
42};
43
44} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index df309d523..b20c2d13a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -28,6 +28,7 @@
28#include "core/hle/kernel/client_port.h" 28#include "core/hle/kernel/client_port.h"
29#include "core/hle/kernel/errors.h" 29#include "core/hle/kernel/errors.h"
30#include "core/hle/kernel/handle_table.h" 30#include "core/hle/kernel/handle_table.h"
31#include "core/hle/kernel/k_resource_limit.h"
31#include "core/hle/kernel/k_scheduler.h" 32#include "core/hle/kernel/k_scheduler.h"
32#include "core/hle/kernel/k_thread.h" 33#include "core/hle/kernel/k_thread.h"
33#include "core/hle/kernel/kernel.h" 34#include "core/hle/kernel/kernel.h"
@@ -36,7 +37,6 @@
36#include "core/hle/kernel/memory/slab_heap.h" 37#include "core/hle/kernel/memory/slab_heap.h"
37#include "core/hle/kernel/physical_core.h" 38#include "core/hle/kernel/physical_core.h"
38#include "core/hle/kernel/process.h" 39#include "core/hle/kernel/process.h"
39#include "core/hle/kernel/resource_limit.h"
40#include "core/hle/kernel/service_thread.h" 40#include "core/hle/kernel/service_thread.h"
41#include "core/hle/kernel/shared_memory.h" 41#include "core/hle/kernel/shared_memory.h"
42#include "core/hle/kernel/time_manager.h" 42#include "core/hle/kernel/time_manager.h"
@@ -66,7 +66,7 @@ struct KernelCore::Impl {
66 is_phantom_mode_for_singlecore = false; 66 is_phantom_mode_for_singlecore = false;
67 67
68 InitializePhysicalCores(); 68 InitializePhysicalCores();
69 InitializeSystemResourceLimit(kernel); 69 InitializeSystemResourceLimit(kernel, system);
70 InitializeMemoryLayout(); 70 InitializeMemoryLayout();
71 InitializePreemption(kernel); 71 InitializePreemption(kernel);
72 InitializeSchedulers(); 72 InitializeSchedulers();
@@ -131,19 +131,19 @@ struct KernelCore::Impl {
131 } 131 }
132 132
133 // Creates the default system resource limit 133 // Creates the default system resource limit
134 void InitializeSystemResourceLimit(KernelCore& kernel) { 134 void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
135 system_resource_limit = ResourceLimit::Create(kernel); 135 system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
136 136
137 // If setting the default system values fails, then something seriously wrong has occurred. 137 // If setting the default system values fails, then something seriously wrong has occurred.
138 ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000) 138 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
139 .IsSuccess()); 139 .IsSuccess());
140 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess()); 140 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
141 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess()); 141 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess());
142 ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess()); 142 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
143 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); 143 .IsSuccess());
144 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 900).IsSuccess());
144 145
145 if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) || 146 if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 0x60000)) {
146 !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
147 UNREACHABLE(); 147 UNREACHABLE();
148 } 148 }
149 } 149 }
@@ -320,7 +320,7 @@ struct KernelCore::Impl {
320 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 320 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
321 Kernel::TimeManager time_manager; 321 Kernel::TimeManager time_manager;
322 322
323 std::shared_ptr<ResourceLimit> system_resource_limit; 323 std::shared_ptr<KResourceLimit> system_resource_limit;
324 324
325 std::shared_ptr<Core::Timing::EventType> preemption_event; 325 std::shared_ptr<Core::Timing::EventType> preemption_event;
326 326
@@ -390,7 +390,7 @@ void KernelCore::Shutdown() {
390 impl->Shutdown(); 390 impl->Shutdown();
391} 391}
392 392
393std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const { 393std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const {
394 return impl->system_resource_limit; 394 return impl->system_resource_limit;
395} 395}
396 396
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index e7c77727b..806a0d986 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -38,7 +38,7 @@ class GlobalSchedulerContext;
38class HandleTable; 38class HandleTable;
39class PhysicalCore; 39class PhysicalCore;
40class Process; 40class Process;
41class ResourceLimit; 41class KResourceLimit;
42class KScheduler; 42class KScheduler;
43class SharedMemory; 43class SharedMemory;
44class ServiceThread; 44class ServiceThread;
@@ -85,7 +85,7 @@ public:
85 void Shutdown(); 85 void Shutdown();
86 86
87 /// Retrieves a shared pointer to the system resource limit instance. 87 /// Retrieves a shared pointer to the system resource limit instance.
88 std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const; 88 std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const;
89 89
90 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. 90 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
91 std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; 91 std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp
index 080886554..7de91c768 100644
--- a/src/core/hle/kernel/memory/page_table.cpp
+++ b/src/core/hle/kernel/memory/page_table.cpp
@@ -7,6 +7,7 @@
7#include "common/scope_exit.h" 7#include "common/scope_exit.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/errors.h" 9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/k_resource_limit.h"
10#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/memory/address_space_info.h" 12#include "core/hle/kernel/memory/address_space_info.h"
12#include "core/hle/kernel/memory/memory_block.h" 13#include "core/hle/kernel/memory/memory_block.h"
@@ -15,7 +16,6 @@
15#include "core/hle/kernel/memory/page_table.h" 16#include "core/hle/kernel/memory/page_table.h"
16#include "core/hle/kernel/memory/system_control.h" 17#include "core/hle/kernel/memory/system_control.h"
17#include "core/hle/kernel/process.h" 18#include "core/hle/kernel/process.h"
18#include "core/hle/kernel/resource_limit.h"
19#include "core/memory.h" 19#include "core/memory.h"
20 20
21namespace Kernel::Memory { 21namespace Kernel::Memory {
@@ -414,7 +414,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
414 const std::size_t remaining_pages{remaining_size / PageSize}; 414 const std::size_t remaining_pages{remaining_size / PageSize};
415 415
416 if (process->GetResourceLimit() && 416 if (process->GetResourceLimit() &&
417 !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, remaining_size)) { 417 !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, remaining_size)) {
418 return ERR_RESOURCE_LIMIT_EXCEEDED; 418 return ERR_RESOURCE_LIMIT_EXCEEDED;
419 } 419 }
420 420
@@ -422,7 +422,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
422 { 422 {
423 auto block_guard = detail::ScopeExit([&] { 423 auto block_guard = detail::ScopeExit([&] {
424 system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool); 424 system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool);
425 process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, remaining_size); 425 process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, remaining_size);
426 }); 426 });
427 427
428 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, 428 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
@@ -474,7 +474,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
474 CASCADE_CODE(UnmapMemory(addr, size)); 474 CASCADE_CODE(UnmapMemory(addr, size));
475 475
476 auto process{system.Kernel().CurrentProcess()}; 476 auto process{system.Kernel().CurrentProcess()};
477 process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, mapped_size); 477 process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
478 physical_memory_usage -= mapped_size; 478 physical_memory_usage -= mapped_size;
479 479
480 return RESULT_SUCCESS; 480 return RESULT_SUCCESS;
@@ -783,7 +783,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
783 783
784 auto process{system.Kernel().CurrentProcess()}; 784 auto process{system.Kernel().CurrentProcess()};
785 if (process->GetResourceLimit() && delta != 0 && 785 if (process->GetResourceLimit() && delta != 0 &&
786 !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, delta)) { 786 !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, delta)) {
787 return ERR_RESOURCE_LIMIT_EXCEEDED; 787 return ERR_RESOURCE_LIMIT_EXCEEDED;
788 } 788 }
789 789
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 2c571792b..d7f40c403 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -8,7 +8,10 @@
8 8
9namespace Kernel { 9namespace Kernel {
10 10
11Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {} 11Object::Object(KernelCore& kernel_)
12 : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{"[UNKNOWN KERNEL OBJECT]"} {}
13Object::Object(KernelCore& kernel_, std::string&& name_)
14 : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{std::move(name_)} {}
12Object::~Object() = default; 15Object::~Object() = default;
13 16
14bool Object::IsWaitable() const { 17bool Object::IsWaitable() const {
@@ -21,6 +24,7 @@ bool Object::IsWaitable() const {
21 return true; 24 return true;
22 25
23 case HandleType::Unknown: 26 case HandleType::Unknown:
27 case HandleType::Event:
24 case HandleType::WritableEvent: 28 case HandleType::WritableEvent:
25 case HandleType::SharedMemory: 29 case HandleType::SharedMemory:
26 case HandleType::TransferMemory: 30 case HandleType::TransferMemory:
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index be7fcb5fb..501e58b33 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -18,6 +18,7 @@ using Handle = u32;
18 18
19enum class HandleType : u32 { 19enum class HandleType : u32 {
20 Unknown, 20 Unknown,
21 Event,
21 WritableEvent, 22 WritableEvent,
22 ReadableEvent, 23 ReadableEvent,
23 SharedMemory, 24 SharedMemory,
@@ -34,7 +35,8 @@ enum class HandleType : u32 {
34 35
35class Object : NonCopyable, public std::enable_shared_from_this<Object> { 36class Object : NonCopyable, public std::enable_shared_from_this<Object> {
36public: 37public:
37 explicit Object(KernelCore& kernel); 38 explicit Object(KernelCore& kernel_);
39 explicit Object(KernelCore& kernel_, std::string&& name_);
38 virtual ~Object(); 40 virtual ~Object();
39 41
40 /// Returns a unique identifier for the object. For debugging purposes only. 42 /// Returns a unique identifier for the object. For debugging purposes only.
@@ -46,7 +48,7 @@ public:
46 return "[BAD KERNEL OBJECT TYPE]"; 48 return "[BAD KERNEL OBJECT TYPE]";
47 } 49 }
48 virtual std::string GetName() const { 50 virtual std::string GetName() const {
49 return "[UNKNOWN KERNEL OBJECT]"; 51 return name;
50 } 52 }
51 virtual HandleType GetHandleType() const = 0; 53 virtual HandleType GetHandleType() const = 0;
52 54
@@ -69,6 +71,7 @@ protected:
69 71
70private: 72private:
71 std::atomic<u32> object_id{0}; 73 std::atomic<u32> object_id{0};
74 std::string name;
72}; 75};
73 76
74template <typename T> 77template <typename T>
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0edbfc4cc..2286b292d 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -15,6 +15,7 @@
15#include "core/file_sys/program_metadata.h" 15#include "core/file_sys/program_metadata.h"
16#include "core/hle/kernel/code_set.h" 16#include "core/hle/kernel/code_set.h"
17#include "core/hle/kernel/errors.h" 17#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/k_resource_limit.h"
18#include "core/hle/kernel/k_scheduler.h" 19#include "core/hle/kernel/k_scheduler.h"
19#include "core/hle/kernel/k_thread.h" 20#include "core/hle/kernel/k_thread.h"
20#include "core/hle/kernel/kernel.h" 21#include "core/hle/kernel/kernel.h"
@@ -22,7 +23,7 @@
22#include "core/hle/kernel/memory/page_table.h" 23#include "core/hle/kernel/memory/page_table.h"
23#include "core/hle/kernel/memory/slab_heap.h" 24#include "core/hle/kernel/memory/slab_heap.h"
24#include "core/hle/kernel/process.h" 25#include "core/hle/kernel/process.h"
25#include "core/hle/kernel/resource_limit.h" 26#include "core/hle/kernel/svc_results.h"
26#include "core/hle/lock.h" 27#include "core/hle/lock.h"
27#include "core/memory.h" 28#include "core/memory.h"
28#include "core/settings.h" 29#include "core/settings.h"
@@ -116,7 +117,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
116 117
117 std::shared_ptr<Process> process = std::make_shared<Process>(system); 118 std::shared_ptr<Process> process = std::make_shared<Process>(system);
118 process->name = std::move(name); 119 process->name = std::move(name);
119 process->resource_limit = ResourceLimit::Create(kernel); 120 process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
120 process->status = ProcessStatus::Created; 121 process->status = ProcessStatus::Created;
121 process->program_id = 0; 122 process->program_id = 0;
122 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() 123 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -132,7 +133,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
132 return process; 133 return process;
133} 134}
134 135
135std::shared_ptr<ResourceLimit> Process::GetResourceLimit() const { 136std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const {
136 return resource_limit; 137 return resource_limit;
137} 138}
138 139
@@ -154,7 +155,7 @@ void Process::DecrementThreadCount() {
154} 155}
155 156
156u64 Process::GetTotalPhysicalMemoryAvailable() const { 157u64 Process::GetTotalPhysicalMemoryAvailable() const {
157 const u64 capacity{resource_limit->GetCurrentResourceValue(ResourceType::PhysicalMemory) + 158 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
158 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + 159 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
159 main_thread_stack_size}; 160 main_thread_stack_size};
160 161
@@ -241,18 +242,16 @@ void Process::UnregisterThread(const KThread* thread) {
241 thread_list.remove(thread); 242 thread_list.remove(thread);
242} 243}
243 244
244ResultCode Process::ClearSignalState() { 245ResultCode Process::Reset() {
245 KScopedSchedulerLock lock(system.Kernel()); 246 // Lock the process and the scheduler.
246 if (status == ProcessStatus::Exited) { 247 KScopedLightLock lk(state_lock);
247 LOG_ERROR(Kernel, "called on a terminated process instance."); 248 KScopedSchedulerLock sl{kernel};
248 return ERR_INVALID_STATE;
249 }
250 249
251 if (!is_signaled) { 250 // Validate that we're in a state that we can reset.
252 LOG_ERROR(Kernel, "called on a process instance that isn't signaled."); 251 R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState);
253 return ERR_INVALID_STATE; 252 R_UNLESS(is_signaled, Svc::ResultInvalidState);
254 }
255 253
254 // Clear signaled.
256 is_signaled = false; 255 is_signaled = false;
257 return RESULT_SUCCESS; 256 return RESULT_SUCCESS;
258} 257}
@@ -308,13 +307,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
308 307
309 // Set initial resource limits 308 // Set initial resource limits
310 resource_limit->SetLimitValue( 309 resource_limit->SetLimitValue(
311 ResourceType::PhysicalMemory, 310 LimitableResource::PhysicalMemory,
312 kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); 311 kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application));
313 resource_limit->SetLimitValue(ResourceType::Threads, 608); 312 resource_limit->SetLimitValue(LimitableResource::Threads, 608);
314 resource_limit->SetLimitValue(ResourceType::Events, 700); 313 resource_limit->SetLimitValue(LimitableResource::Events, 700);
315 resource_limit->SetLimitValue(ResourceType::TransferMemory, 128); 314 resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
316 resource_limit->SetLimitValue(ResourceType::Sessions, 894); 315 resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
317 ASSERT(resource_limit->Reserve(ResourceType::PhysicalMemory, code_size)); 316 ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemory, code_size));
318 317
319 // Create TLS region 318 // Create TLS region
320 tls_region_address = CreateTLSRegion(); 319 tls_region_address = CreateTLSRegion();
@@ -331,8 +330,8 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) {
331 ChangeStatus(ProcessStatus::Running); 330 ChangeStatus(ProcessStatus::Running);
332 331
333 SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); 332 SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top);
334 resource_limit->Reserve(ResourceType::Threads, 1); 333 resource_limit->Reserve(LimitableResource::Threads, 1);
335 resource_limit->Reserve(ResourceType::PhysicalMemory, main_thread_stack_size); 334 resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
336} 335}
337 336
338void Process::PrepareForTermination() { 337void Process::PrepareForTermination() {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 26e647743..320b0f347 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -29,7 +29,7 @@ class ProgramMetadata;
29namespace Kernel { 29namespace Kernel {
30 30
31class KernelCore; 31class KernelCore;
32class ResourceLimit; 32class KResourceLimit;
33class KThread; 33class KThread;
34class TLSPage; 34class TLSPage;
35 35
@@ -170,7 +170,7 @@ public:
170 } 170 }
171 171
172 /// Gets the resource limit descriptor for this process 172 /// Gets the resource limit descriptor for this process
173 std::shared_ptr<ResourceLimit> GetResourceLimit() const; 173 std::shared_ptr<KResourceLimit> GetResourceLimit() const;
174 174
175 /// Gets the ideal CPU core ID for this process 175 /// Gets the ideal CPU core ID for this process
176 u8 GetIdealCoreId() const { 176 u8 GetIdealCoreId() const {
@@ -312,7 +312,7 @@ public:
312 /// @pre The process must be in a signaled state. If this is called on a 312 /// @pre The process must be in a signaled state. If this is called on a
313 /// process instance that is not signaled, ERR_INVALID_STATE will be 313 /// process instance that is not signaled, ERR_INVALID_STATE will be
314 /// returned. 314 /// returned.
315 ResultCode ClearSignalState(); 315 ResultCode Reset();
316 316
317 /** 317 /**
318 * Loads process-specifics configuration info with metadata provided 318 * Loads process-specifics configuration info with metadata provided
@@ -402,7 +402,7 @@ private:
402 u32 system_resource_size = 0; 402 u32 system_resource_size = 0;
403 403
404 /// Resource limit descriptor for this process 404 /// Resource limit descriptor for this process
405 std::shared_ptr<ResourceLimit> resource_limit; 405 std::shared_ptr<KResourceLimit> resource_limit;
406 406
407 /// The ideal CPU core for this process, threads are scheduled on this core by default. 407 /// The ideal CPU core for this process, threads are scheduled on this core by default.
408 u8 ideal_core = 0; 408 u8 ideal_core = 0;
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
deleted file mode 100644
index 596d01479..000000000
--- a/src/core/hle/kernel/readable_event.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "common/logging/log.h"
8#include "core/hle/kernel/errors.h"
9#include "core/hle/kernel/k_scheduler.h"
10#include "core/hle/kernel/k_thread.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/object.h"
13#include "core/hle/kernel/readable_event.h"
14
15namespace Kernel {
16
17ReadableEvent::ReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
18ReadableEvent::~ReadableEvent() = default;
19
20void ReadableEvent::Signal() {
21 if (is_signaled) {
22 return;
23 }
24
25 is_signaled = true;
26 NotifyAvailable();
27}
28
29bool ReadableEvent::IsSignaled() const {
30 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
31
32 return is_signaled;
33}
34
35void ReadableEvent::Clear() {
36 is_signaled = false;
37}
38
39ResultCode ReadableEvent::Reset() {
40 KScopedSchedulerLock lock(kernel);
41 if (!is_signaled) {
42 LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}",
43 GetObjectId(), GetTypeName(), GetName());
44 return ERR_INVALID_STATE;
45 }
46
47 Clear();
48
49 return RESULT_SUCCESS;
50}
51
52} // namespace Kernel
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
deleted file mode 100644
index 2195710c2..000000000
--- a/src/core/hle/kernel/readable_event.h
+++ /dev/null
@@ -1,59 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/k_synchronization_object.h"
8#include "core/hle/kernel/object.h"
9
10union ResultCode;
11
12namespace Kernel {
13
14class KernelCore;
15class WritableEvent;
16
17class ReadableEvent final : public KSynchronizationObject {
18 friend class WritableEvent;
19
20public:
21 ~ReadableEvent() override;
22
23 std::string GetTypeName() const override {
24 return "ReadableEvent";
25 }
26 std::string GetName() const override {
27 return name;
28 }
29
30 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
31 HandleType GetHandleType() const override {
32 return HANDLE_TYPE;
33 }
34
35 /// Unconditionally clears the readable event's state.
36 void Clear();
37
38 /// Clears the readable event's state if and only if it
39 /// has already been signaled.
40 ///
41 /// @pre The event must be in a signaled state. If this event
42 /// is in an unsignaled state and this function is called,
43 /// then ERR_INVALID_STATE will be returned.
44 ResultCode Reset();
45
46 void Signal();
47
48 bool IsSignaled() const override;
49
50 void Finalize() override {}
51
52private:
53 explicit ReadableEvent(KernelCore& kernel);
54
55 bool is_signaled{};
56 std::string name; ///< Name of event (optional)
57};
58
59} // namespace Kernel
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
deleted file mode 100644
index 7bf50339d..000000000
--- a/src/core/hle/kernel/resource_limit.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/errors.h"
6#include "core/hle/kernel/resource_limit.h"
7#include "core/hle/result.h"
8
9namespace Kernel {
10namespace {
11constexpr std::size_t ResourceTypeToIndex(ResourceType type) {
12 return static_cast<std::size_t>(type);
13}
14} // Anonymous namespace
15
16ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {}
17ResourceLimit::~ResourceLimit() = default;
18
19bool ResourceLimit::Reserve(ResourceType resource, s64 amount) {
20 return Reserve(resource, amount, 10000000000);
21}
22
23bool ResourceLimit::Reserve(ResourceType resource, s64 amount, u64 timeout) {
24 const std::size_t index{ResourceTypeToIndex(resource)};
25
26 s64 new_value = current[index] + amount;
27 if (new_value > limit[index] && available[index] + amount <= limit[index]) {
28 // TODO(bunnei): This is wrong for multicore, we should wait the calling thread for timeout
29 new_value = current[index] + amount;
30 }
31
32 if (new_value <= limit[index]) {
33 current[index] = new_value;
34 return true;
35 }
36 return false;
37}
38
39void ResourceLimit::Release(ResourceType resource, u64 amount) {
40 Release(resource, amount, amount);
41}
42
43void ResourceLimit::Release(ResourceType resource, u64 used_amount, u64 available_amount) {
44 const std::size_t index{ResourceTypeToIndex(resource)};
45
46 current[index] -= used_amount;
47 available[index] -= available_amount;
48}
49
50std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel) {
51 return std::make_shared<ResourceLimit>(kernel);
52}
53
54s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
55 return limit.at(ResourceTypeToIndex(resource)) - current.at(ResourceTypeToIndex(resource));
56}
57
58s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
59 return limit.at(ResourceTypeToIndex(resource));
60}
61
62ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) {
63 const std::size_t index{ResourceTypeToIndex(resource)};
64 if (current[index] <= value) {
65 limit[index] = value;
66 return RESULT_SUCCESS;
67 } else {
68 LOG_ERROR(Kernel, "Limit value is too large! resource={}, value={}, index={}", resource,
69 value, index);
70 return ERR_INVALID_STATE;
71 }
72}
73} // namespace Kernel
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
deleted file mode 100644
index 464d4f2a6..000000000
--- a/src/core/hle/kernel/resource_limit.h
+++ /dev/null
@@ -1,106 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <memory>
9
10#include "common/common_types.h"
11#include "core/hle/kernel/object.h"
12
13union ResultCode;
14
15namespace Kernel {
16
17class KernelCore;
18
19enum class ResourceType : u32 {
20 PhysicalMemory,
21 Threads,
22 Events,
23 TransferMemory,
24 Sessions,
25
26 // Used as a count, not an actual type.
27 ResourceTypeCount
28};
29
30constexpr bool IsValidResourceType(ResourceType type) {
31 return type < ResourceType::ResourceTypeCount;
32}
33
34class ResourceLimit final : public Object {
35public:
36 explicit ResourceLimit(KernelCore& kernel);
37 ~ResourceLimit() override;
38
39 /// Creates a resource limit object.
40 static std::shared_ptr<ResourceLimit> Create(KernelCore& kernel);
41
42 std::string GetTypeName() const override {
43 return "ResourceLimit";
44 }
45 std::string GetName() const override {
46 return GetTypeName();
47 }
48
49 static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
50 HandleType GetHandleType() const override {
51 return HANDLE_TYPE;
52 }
53
54 bool Reserve(ResourceType resource, s64 amount);
55 bool Reserve(ResourceType resource, s64 amount, u64 timeout);
56 void Release(ResourceType resource, u64 amount);
57 void Release(ResourceType resource, u64 used_amount, u64 available_amount);
58
59 /**
60 * Gets the current value for the specified resource.
61 * @param resource Requested resource type
62 * @returns The current value of the resource type
63 */
64 s64 GetCurrentResourceValue(ResourceType resource) const;
65
66 /**
67 * Gets the max value for the specified resource.
68 * @param resource Requested resource type
69 * @returns The max value of the resource type
70 */
71 s64 GetMaxResourceValue(ResourceType resource) const;
72
73 /**
74 * Sets the limit value for a given resource type.
75 *
76 * @param resource The resource type to apply the limit to.
77 * @param value The limit to apply to the given resource type.
78 *
79 * @return A result code indicating if setting the limit value
80 * was successful or not.
81 *
82 * @note The supplied limit value *must* be greater than or equal to
83 * the current resource value for the given resource type,
84 * otherwise ERR_INVALID_STATE will be returned.
85 */
86 ResultCode SetLimitValue(ResourceType resource, s64 value);
87
88 void Finalize() override {}
89
90private:
91 // TODO(Subv): Increment resource limit current values in their respective Kernel::T::Create
92 // functions
93 //
94 // Currently we have no way of distinguishing if a Create was called by the running application,
95 // or by a service module. Approach this once we have separated the service modules into their
96 // own processes
97
98 using ResourceArray =
99 std::array<s64, static_cast<std::size_t>(ResourceType::ResourceTypeCount)>;
100
101 ResourceArray limit{};
102 ResourceArray current{};
103 ResourceArray available{};
104};
105
106} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 7fd514e9d..edf208eff 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -14,6 +14,7 @@
14#include "common/fiber.h" 14#include "common/fiber.h"
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/microprofile.h" 16#include "common/microprofile.h"
17#include "common/scope_exit.h"
17#include "common/string_util.h" 18#include "common/string_util.h"
18#include "core/arm/exclusive_monitor.h" 19#include "core/arm/exclusive_monitor.h"
19#include "core/core.h" 20#include "core/core.h"
@@ -26,18 +27,20 @@
26#include "core/hle/kernel/handle_table.h" 27#include "core/hle/kernel/handle_table.h"
27#include "core/hle/kernel/k_address_arbiter.h" 28#include "core/hle/kernel/k_address_arbiter.h"
28#include "core/hle/kernel/k_condition_variable.h" 29#include "core/hle/kernel/k_condition_variable.h"
30#include "core/hle/kernel/k_event.h"
31#include "core/hle/kernel/k_readable_event.h"
32#include "core/hle/kernel/k_resource_limit.h"
29#include "core/hle/kernel/k_scheduler.h" 33#include "core/hle/kernel/k_scheduler.h"
30#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 34#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
31#include "core/hle/kernel/k_synchronization_object.h" 35#include "core/hle/kernel/k_synchronization_object.h"
32#include "core/hle/kernel/k_thread.h" 36#include "core/hle/kernel/k_thread.h"
37#include "core/hle/kernel/k_writable_event.h"
33#include "core/hle/kernel/kernel.h" 38#include "core/hle/kernel/kernel.h"
34#include "core/hle/kernel/memory/memory_block.h" 39#include "core/hle/kernel/memory/memory_block.h"
35#include "core/hle/kernel/memory/memory_layout.h" 40#include "core/hle/kernel/memory/memory_layout.h"
36#include "core/hle/kernel/memory/page_table.h" 41#include "core/hle/kernel/memory/page_table.h"
37#include "core/hle/kernel/physical_core.h" 42#include "core/hle/kernel/physical_core.h"
38#include "core/hle/kernel/process.h" 43#include "core/hle/kernel/process.h"
39#include "core/hle/kernel/readable_event.h"
40#include "core/hle/kernel/resource_limit.h"
41#include "core/hle/kernel/shared_memory.h" 44#include "core/hle/kernel/shared_memory.h"
42#include "core/hle/kernel/svc.h" 45#include "core/hle/kernel/svc.h"
43#include "core/hle/kernel/svc_results.h" 46#include "core/hle/kernel/svc_results.h"
@@ -45,7 +48,6 @@
45#include "core/hle/kernel/svc_wrap.h" 48#include "core/hle/kernel/svc_wrap.h"
46#include "core/hle/kernel/time_manager.h" 49#include "core/hle/kernel/time_manager.h"
47#include "core/hle/kernel/transfer_memory.h" 50#include "core/hle/kernel/transfer_memory.h"
48#include "core/hle/kernel/writable_event.h"
49#include "core/hle/lock.h" 51#include "core/hle/lock.h"
50#include "core/hle/result.h" 52#include "core/hle/result.h"
51#include "core/hle/service/service.h" 53#include "core/hle/service/service.h"
@@ -141,7 +143,7 @@ enum class ResourceLimitValueType {
141ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, 143ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit,
142 u32 resource_type, ResourceLimitValueType value_type) { 144 u32 resource_type, ResourceLimitValueType value_type) {
143 std::lock_guard lock{HLE::g_hle_lock}; 145 std::lock_guard lock{HLE::g_hle_lock};
144 const auto type = static_cast<ResourceType>(resource_type); 146 const auto type = static_cast<LimitableResource>(resource_type);
145 if (!IsValidResourceType(type)) { 147 if (!IsValidResourceType(type)) {
146 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); 148 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
147 return ERR_INVALID_ENUM_VALUE; 149 return ERR_INVALID_ENUM_VALUE;
@@ -151,7 +153,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
151 ASSERT(current_process != nullptr); 153 ASSERT(current_process != nullptr);
152 154
153 const auto resource_limit_object = 155 const auto resource_limit_object =
154 current_process->GetHandleTable().Get<ResourceLimit>(resource_limit); 156 current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
155 if (!resource_limit_object) { 157 if (!resource_limit_object) {
156 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", 158 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
157 resource_limit); 159 resource_limit);
@@ -159,10 +161,10 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
159 } 161 }
160 162
161 if (value_type == ResourceLimitValueType::CurrentValue) { 163 if (value_type == ResourceLimitValueType::CurrentValue) {
162 return MakeResult(resource_limit_object->GetCurrentResourceValue(type)); 164 return MakeResult(resource_limit_object->GetCurrentValue(type));
163 } 165 }
164 166
165 return MakeResult(resource_limit_object->GetMaxResourceValue(type)); 167 return MakeResult(resource_limit_object->GetLimitValue(type));
166} 168}
167} // Anonymous namespace 169} // Anonymous namespace
168 170
@@ -312,7 +314,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
312 return ERR_NOT_FOUND; 314 return ERR_NOT_FOUND;
313 } 315 }
314 316
315 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1)); 317 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::Sessions, 1));
316 318
317 auto client_port = it->second; 319 auto client_port = it->second;
318 320
@@ -1450,7 +1452,8 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1450 Svc::ResultInvalidPriority); 1452 Svc::ResultInvalidPriority);
1451 R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); 1453 R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
1452 1454
1453 ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1)); 1455 ASSERT(process.GetResourceLimit()->Reserve(
1456 LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000));
1454 1457
1455 std::shared_ptr<KThread> thread; 1458 std::shared_ptr<KThread> thread;
1456 { 1459 {
@@ -1724,20 +1727,28 @@ static ResultCode CloseHandle32(Core::System& system, Handle handle) {
1724static ResultCode ResetSignal(Core::System& system, Handle handle) { 1727static ResultCode ResetSignal(Core::System& system, Handle handle) {
1725 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); 1728 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
1726 1729
1730 // Get the current handle table.
1727 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1731 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1728 1732
1729 auto event = handle_table.Get<ReadableEvent>(handle); 1733 // Try to reset as readable event.
1730 if (event) { 1734 {
1731 return event->Reset(); 1735 auto readable_event = handle_table.Get<KReadableEvent>(handle);
1736 if (readable_event) {
1737 return readable_event->Reset();
1738 }
1732 } 1739 }
1733 1740
1734 auto process = handle_table.Get<Process>(handle); 1741 // Try to reset as process.
1735 if (process) { 1742 {
1736 return process->ClearSignalState(); 1743 auto process = handle_table.Get<Process>(handle);
1744 if (process) {
1745 return process->Reset();
1746 }
1737 } 1747 }
1738 1748
1739 LOG_ERROR(Kernel_SVC, "Invalid handle (0x{:08X})", handle); 1749 LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
1740 return ERR_INVALID_HANDLE; 1750
1751 return Svc::ResultInvalidHandle;
1741} 1752}
1742 1753
1743static ResultCode ResetSignal32(Core::System& system, Handle handle) { 1754static ResultCode ResetSignal32(Core::System& system, Handle handle) {
@@ -1865,80 +1876,92 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle
1865 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask); 1876 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
1866} 1877}
1867 1878
1868static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { 1879static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
1869 LOG_DEBUG(Kernel_SVC, "called"); 1880 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
1870 1881
1871 auto& kernel = system.Kernel(); 1882 // Get the current handle table.
1872 const auto [readable_event, writable_event] = 1883 const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1873 WritableEvent::CreateEventPair(kernel, "CreateEvent");
1874 1884
1875 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); 1885 // Get the writable event.
1886 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
1887 R_UNLESS(writable_event, Svc::ResultInvalidHandle);
1876 1888
1877 const auto write_create_result = handle_table.Create(writable_event); 1889 return writable_event->Signal();
1878 if (write_create_result.Failed()) {
1879 return write_create_result.Code();
1880 }
1881 *write_handle = *write_create_result;
1882
1883 const auto read_create_result = handle_table.Create(readable_event);
1884 if (read_create_result.Failed()) {
1885 handle_table.Close(*write_create_result);
1886 return read_create_result.Code();
1887 }
1888 *read_handle = *read_create_result;
1889
1890 LOG_DEBUG(Kernel_SVC,
1891 "successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}",
1892 *write_create_result, *read_create_result);
1893 return RESULT_SUCCESS;
1894} 1890}
1895 1891
1896static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) { 1892static ResultCode SignalEvent32(Core::System& system, Handle event_handle) {
1897 return CreateEvent(system, write_handle, read_handle); 1893 return SignalEvent(system, event_handle);
1898} 1894}
1899 1895
1900static ResultCode ClearEvent(Core::System& system, Handle handle) { 1896static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
1901 LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); 1897 LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
1902 1898
1899 // Get the current handle table.
1903 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1900 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1904 1901
1905 auto writable_event = handle_table.Get<WritableEvent>(handle); 1902 // Try to clear the writable event.
1906 if (writable_event) { 1903 {
1907 writable_event->Clear(); 1904 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
1908 return RESULT_SUCCESS; 1905 if (writable_event) {
1906 return writable_event->Clear();
1907 }
1909 } 1908 }
1910 1909
1911 auto readable_event = handle_table.Get<ReadableEvent>(handle); 1910 // Try to clear the readable event.
1912 if (readable_event) { 1911 {
1913 readable_event->Clear(); 1912 auto readable_event = handle_table.Get<KReadableEvent>(event_handle);
1914 return RESULT_SUCCESS; 1913 if (readable_event) {
1914 return readable_event->Clear();
1915 }
1915 } 1916 }
1916 1917
1917 LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); 1918 LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
1918 return ERR_INVALID_HANDLE; 1919
1920 return Svc::ResultInvalidHandle;
1919} 1921}
1920 1922
1921static ResultCode ClearEvent32(Core::System& system, Handle handle) { 1923static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
1922 return ClearEvent(system, handle); 1924 return ClearEvent(system, event_handle);
1923} 1925}
1924 1926
1925static ResultCode SignalEvent(Core::System& system, Handle handle) { 1927static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
1926 LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle); 1928 LOG_DEBUG(Kernel_SVC, "called");
1929
1930 // Get the kernel reference and handle table.
1931 auto& kernel = system.Kernel();
1932 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
1933
1934 // Create a new event.
1935 const auto event = KEvent::Create(kernel, "CreateEvent");
1936 R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
1927 1937
1928 HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1938 // Initialize the event.
1929 auto writable_event = handle_table.Get<WritableEvent>(handle); 1939 event->Initialize();
1930 1940
1931 if (!writable_event) { 1941 // Add the writable event to the handle table.
1932 LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle); 1942 const auto write_create_result = handle_table.Create(event->GetWritableEvent());
1933 return ERR_INVALID_HANDLE; 1943 if (write_create_result.Failed()) {
1944 return write_create_result.Code();
1945 }
1946 *out_write = *write_create_result;
1947
1948 // Add the writable event to the handle table.
1949 auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); });
1950
1951 // Add the readable event to the handle table.
1952 const auto read_create_result = handle_table.Create(event->GetReadableEvent());
1953 if (read_create_result.Failed()) {
1954 return read_create_result.Code();
1934 } 1955 }
1956 *out_read = *read_create_result;
1935 1957
1936 writable_event->Signal(); 1958 // We succeeded.
1959 handle_guard.Cancel();
1937 return RESULT_SUCCESS; 1960 return RESULT_SUCCESS;
1938} 1961}
1939 1962
1940static ResultCode SignalEvent32(Core::System& system, Handle handle) { 1963static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
1941 return SignalEvent(system, handle); 1964 return CreateEvent(system, out_write, out_read);
1942} 1965}
1943 1966
1944static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { 1967static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
@@ -1972,7 +1995,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
1972 LOG_DEBUG(Kernel_SVC, "called"); 1995 LOG_DEBUG(Kernel_SVC, "called");
1973 1996
1974 auto& kernel = system.Kernel(); 1997 auto& kernel = system.Kernel();
1975 auto resource_limit = ResourceLimit::Create(kernel); 1998 auto resource_limit = std::make_shared<KResourceLimit>(kernel, system);
1976 1999
1977 auto* const current_process = kernel.CurrentProcess(); 2000 auto* const current_process = kernel.CurrentProcess();
1978 ASSERT(current_process != nullptr); 2001 ASSERT(current_process != nullptr);
@@ -2019,7 +2042,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
2019 LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, 2042 LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit,
2020 resource_type, value); 2043 resource_type, value);
2021 2044
2022 const auto type = static_cast<ResourceType>(resource_type); 2045 const auto type = static_cast<LimitableResource>(resource_type);
2023 if (!IsValidResourceType(type)) { 2046 if (!IsValidResourceType(type)) {
2024 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); 2047 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
2025 return ERR_INVALID_ENUM_VALUE; 2048 return ERR_INVALID_ENUM_VALUE;
@@ -2029,7 +2052,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
2029 ASSERT(current_process != nullptr); 2052 ASSERT(current_process != nullptr);
2030 2053
2031 auto resource_limit_object = 2054 auto resource_limit_object =
2032 current_process->GetHandleTable().Get<ResourceLimit>(resource_limit); 2055 current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
2033 if (!resource_limit_object) { 2056 if (!resource_limit_object) {
2034 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", 2057 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
2035 resource_limit); 2058 resource_limit);
@@ -2041,8 +2064,8 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
2041 LOG_ERROR( 2064 LOG_ERROR(
2042 Kernel_SVC, 2065 Kernel_SVC,
2043 "Attempted to lower resource limit ({}) for category '{}' below its current value ({})", 2066 "Attempted to lower resource limit ({}) for category '{}' below its current value ({})",
2044 resource_limit_object->GetMaxResourceValue(type), resource_type, 2067 resource_limit_object->GetLimitValue(type), resource_type,
2045 resource_limit_object->GetCurrentResourceValue(type)); 2068 resource_limit_object->GetCurrentValue(type));
2046 return set_result; 2069 return set_result;
2047 } 2070 }
2048 2071
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h
index 7b897fbce..204cd989d 100644
--- a/src/core/hle/kernel/svc_results.h
+++ b/src/core/hle/kernel/svc_results.h
@@ -11,6 +11,7 @@ namespace Kernel::Svc {
11constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; 11constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
12constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; 12constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
13constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; 13constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
14constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
14constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; 15constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
15constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; 16constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
16constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; 17constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};
diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp
deleted file mode 100644
index 142212ee4..000000000
--- a/src/core/hle/kernel/writable_event.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "core/hle/kernel/k_thread.h"
8#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/object.h"
10#include "core/hle/kernel/readable_event.h"
11#include "core/hle/kernel/writable_event.h"
12
13namespace Kernel {
14
15WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
16WritableEvent::~WritableEvent() = default;
17
18EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
19 std::shared_ptr<WritableEvent> writable_event(new WritableEvent(kernel));
20 std::shared_ptr<ReadableEvent> readable_event(new ReadableEvent(kernel));
21
22 writable_event->name = name + ":Writable";
23 writable_event->readable = readable_event;
24 readable_event->name = name + ":Readable";
25
26 return {std::move(readable_event), std::move(writable_event)};
27}
28
29std::shared_ptr<ReadableEvent> WritableEvent::GetReadableEvent() const {
30 return readable;
31}
32
33void WritableEvent::Signal() {
34 readable->Signal();
35}
36
37void WritableEvent::Clear() {
38 readable->Clear();
39}
40
41} // namespace Kernel
diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h
deleted file mode 100644
index 467eb2c21..000000000
--- a/src/core/hle/kernel/writable_event.h
+++ /dev/null
@@ -1,60 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8
9#include "core/hle/kernel/object.h"
10
11namespace Kernel {
12
13class KernelCore;
14class ReadableEvent;
15class WritableEvent;
16
17struct EventPair {
18 std::shared_ptr<ReadableEvent> readable;
19 std::shared_ptr<WritableEvent> writable;
20};
21
22class WritableEvent final : public Object {
23public:
24 ~WritableEvent() override;
25
26 /**
27 * Creates an event
28 * @param kernel The kernel instance to create this event under.
29 * @param name Optional name of event
30 */
31 static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
32
33 std::string GetTypeName() const override {
34 return "WritableEvent";
35 }
36 std::string GetName() const override {
37 return name;
38 }
39
40 static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
41 HandleType GetHandleType() const override {
42 return HANDLE_TYPE;
43 }
44
45 std::shared_ptr<ReadableEvent> GetReadableEvent() const;
46
47 void Signal();
48 void Clear();
49
50 void Finalize() override {}
51
52private:
53 explicit WritableEvent(KernelCore& kernel);
54
55 std::shared_ptr<ReadableEvent> readable;
56
57 std::string name; ///< Name of event (optional)
58};
59
60} // namespace Kernel
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index d9865d56f..50b2c58e2 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -41,12 +41,18 @@ constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "/system/save/8000000000000010/su/
41ProfileManager::ProfileManager() { 41ProfileManager::ProfileManager() {
42 ParseUserSaveFile(); 42 ParseUserSaveFile();
43 43
44 if (user_count == 0) 44 // Create an user if none are present
45 if (user_count == 0) {
45 CreateNewUser(UUID::Generate(), "yuzu"); 46 CreateNewUser(UUID::Generate(), "yuzu");
47 }
46 48
47 auto current = std::clamp<int>(Settings::values.current_user, 0, MAX_USERS - 1); 49 auto current = std::clamp<int>(Settings::values.current_user, 0, MAX_USERS - 1);
48 if (UserExistsIndex(current)) 50
51 // If user index don't exist. Load the first user and change the active user
52 if (!UserExistsIndex(current)) {
49 current = 0; 53 current = 0;
54 Settings::values.current_user = 0;
55 }
50 56
51 OpenUser(*GetUser(current)); 57 OpenUser(*GetUser(current));
52} 58}
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d42236a3a..bb77c2569 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -13,11 +13,12 @@
13#include "core/file_sys/registered_cache.h" 13#include "core/file_sys/registered_cache.h"
14#include "core/file_sys/savedata_factory.h" 14#include "core/file_sys/savedata_factory.h"
15#include "core/hle/ipc_helpers.h" 15#include "core/hle/ipc_helpers.h"
16#include "core/hle/kernel/k_event.h"
17#include "core/hle/kernel/k_readable_event.h"
18#include "core/hle/kernel/k_writable_event.h"
16#include "core/hle/kernel/kernel.h" 19#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/process.h" 20#include "core/hle/kernel/process.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/kernel/transfer_memory.h" 21#include "core/hle/kernel/transfer_memory.h"
20#include "core/hle/kernel/writable_event.h"
21#include "core/hle/service/acc/profile_manager.h" 22#include "core/hle/service/acc/profile_manager.h"
22#include "core/hle/service/am/am.h" 23#include "core/hle/service/am/am.h"
23#include "core/hle/service/am/applet_ae.h" 24#include "core/hle/service/am/applet_ae.h"
@@ -303,17 +304,18 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
303 RegisterHandlers(functions); 304 RegisterHandlers(functions);
304 305
305 auto& kernel = system.Kernel(); 306 auto& kernel = system.Kernel();
306 launchable_event = 307 launchable_event = Kernel::KEvent::Create(kernel, "ISelfController:LaunchableEvent");
307 Kernel::WritableEvent::CreateEventPair(kernel, "ISelfController:LaunchableEvent"); 308 launchable_event->Initialize();
308 309
309 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is 310 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
310 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple 311 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
311 // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not 312 // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
312 // suspended if the event has previously been created by a call to 313 // suspended if the event has previously been created by a call to
313 // GetAccumulatedSuspendedTickChangedEvent. 314 // GetAccumulatedSuspendedTickChangedEvent.
314 accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair( 315 accumulated_suspended_tick_changed_event =
315 kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent"); 316 Kernel::KEvent::Create(kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
316 accumulated_suspended_tick_changed_event.writable->Signal(); 317 accumulated_suspended_tick_changed_event->Initialize();
318 accumulated_suspended_tick_changed_event->GetWritableEvent()->Signal();
317} 319}
318 320
319ISelfController::~ISelfController() = default; 321ISelfController::~ISelfController() = default;
@@ -372,11 +374,11 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
372void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { 374void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
373 LOG_WARNING(Service_AM, "(STUBBED) called"); 375 LOG_WARNING(Service_AM, "(STUBBED) called");
374 376
375 launchable_event.writable->Signal(); 377 launchable_event->GetWritableEvent()->Signal();
376 378
377 IPC::ResponseBuilder rb{ctx, 2, 1}; 379 IPC::ResponseBuilder rb{ctx, 2, 1};
378 rb.Push(RESULT_SUCCESS); 380 rb.Push(RESULT_SUCCESS);
379 rb.PushCopyObjects(launchable_event.readable); 381 rb.PushCopyObjects(launchable_event->GetReadableEvent());
380} 382}
381 383
382void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { 384void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
@@ -555,41 +557,42 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
555 557
556 IPC::ResponseBuilder rb{ctx, 2, 1}; 558 IPC::ResponseBuilder rb{ctx, 2, 1};
557 rb.Push(RESULT_SUCCESS); 559 rb.Push(RESULT_SUCCESS);
558 rb.PushCopyObjects(accumulated_suspended_tick_changed_event.readable); 560 rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
559} 561}
560 562
561AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) { 563AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) {
562 on_new_message = 564 on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived");
563 Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OnMessageReceived"); 565 on_new_message->Initialize();
564 on_operation_mode_changed = 566 on_operation_mode_changed =
565 Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OperationModeChanged"); 567 Kernel::KEvent::Create(kernel, "AMMessageQueue:OperationModeChanged");
568 on_operation_mode_changed->Initialize();
566} 569}
567 570
568AppletMessageQueue::~AppletMessageQueue() = default; 571AppletMessageQueue::~AppletMessageQueue() = default;
569 572
570const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const { 573const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const {
571 return on_new_message.readable; 574 return on_new_message->GetReadableEvent();
572} 575}
573 576
574const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent() 577const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
575 const { 578 const {
576 return on_operation_mode_changed.readable; 579 return on_operation_mode_changed->GetReadableEvent();
577} 580}
578 581
579void AppletMessageQueue::PushMessage(AppletMessage msg) { 582void AppletMessageQueue::PushMessage(AppletMessage msg) {
580 messages.push(msg); 583 messages.push(msg);
581 on_new_message.writable->Signal(); 584 on_new_message->GetWritableEvent()->Signal();
582} 585}
583 586
584AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { 587AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
585 if (messages.empty()) { 588 if (messages.empty()) {
586 on_new_message.writable->Clear(); 589 on_new_message->GetWritableEvent()->Clear();
587 return AppletMessage::NoMessage; 590 return AppletMessage::NoMessage;
588 } 591 }
589 auto msg = messages.front(); 592 auto msg = messages.front();
590 messages.pop(); 593 messages.pop();
591 if (messages.empty()) { 594 if (messages.empty()) {
592 on_new_message.writable->Clear(); 595 on_new_message->GetWritableEvent()->Clear();
593 } 596 }
594 return msg; 597 return msg;
595} 598}
@@ -601,7 +604,7 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
601void AppletMessageQueue::OperationModeChanged() { 604void AppletMessageQueue::OperationModeChanged() {
602 PushMessage(AppletMessage::OperationModeChanged); 605 PushMessage(AppletMessage::OperationModeChanged);
603 PushMessage(AppletMessage::PerformanceModeChanged); 606 PushMessage(AppletMessage::PerformanceModeChanged);
604 on_operation_mode_changed.writable->Signal(); 607 on_operation_mode_changed->GetWritableEvent()->Signal();
605} 608}
606 609
607void AppletMessageQueue::RequestExit() { 610void AppletMessageQueue::RequestExit() {
@@ -1216,7 +1219,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1216 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, 1219 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
1217 {150, nullptr, "GetNotificationStorageChannelEvent"}, 1220 {150, nullptr, "GetNotificationStorageChannelEvent"},
1218 {151, nullptr, "TryPopFromNotificationStorageChannel"}, 1221 {151, nullptr, "TryPopFromNotificationStorageChannel"},
1219 {160, nullptr, "GetHealthWarningDisappearedSystemEvent"}, 1222 {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
1220 {170, nullptr, "SetHdcpAuthenticationActivated"}, 1223 {170, nullptr, "SetHdcpAuthenticationActivated"},
1221 {180, nullptr, "GetLaunchRequiredVersion"}, 1224 {180, nullptr, "GetLaunchRequiredVersion"},
1222 {181, nullptr, "UpgradeLaunchRequiredVersion"}, 1225 {181, nullptr, "UpgradeLaunchRequiredVersion"},
@@ -1229,11 +1232,15 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1229 RegisterHandlers(functions); 1232 RegisterHandlers(functions);
1230 1233
1231 auto& kernel = system.Kernel(); 1234 auto& kernel = system.Kernel();
1232 gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair( 1235 gpu_error_detected_event =
1233 kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent"); 1236 Kernel::KEvent::Create(kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
1234 1237 gpu_error_detected_event->Initialize();
1235 friend_invitation_storage_channel_event = Kernel::WritableEvent::CreateEventPair( 1238 friend_invitation_storage_channel_event =
1236 kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent"); 1239 Kernel::KEvent::Create(kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent");
1240 friend_invitation_storage_channel_event->Initialize();
1241 health_warning_disappeared_system_event =
1242 Kernel::KEvent::Create(kernel, "IApplicationFunctions:HealthWarningDisappearedSystemEvent");
1243 health_warning_disappeared_system_event->Initialize();
1237} 1244}
1238 1245
1239IApplicationFunctions::~IApplicationFunctions() = default; 1246IApplicationFunctions::~IApplicationFunctions() = default;
@@ -1630,7 +1637,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon
1630 1637
1631 IPC::ResponseBuilder rb{ctx, 2, 1}; 1638 IPC::ResponseBuilder rb{ctx, 2, 1};
1632 rb.Push(RESULT_SUCCESS); 1639 rb.Push(RESULT_SUCCESS);
1633 rb.PushCopyObjects(gpu_error_detected_event.readable); 1640 rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
1634} 1641}
1635 1642
1636void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) { 1643void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
@@ -1638,7 +1645,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe
1638 1645
1639 IPC::ResponseBuilder rb{ctx, 2, 1}; 1646 IPC::ResponseBuilder rb{ctx, 2, 1};
1640 rb.Push(RESULT_SUCCESS); 1647 rb.Push(RESULT_SUCCESS);
1641 rb.PushCopyObjects(friend_invitation_storage_channel_event.readable); 1648 rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
1642} 1649}
1643 1650
1644void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( 1651void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
@@ -1649,6 +1656,14 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
1649 rb.Push(ERR_NO_DATA_IN_CHANNEL); 1656 rb.Push(ERR_NO_DATA_IN_CHANNEL);
1650} 1657}
1651 1658
1659void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) {
1660 LOG_DEBUG(Service_AM, "called");
1661
1662 IPC::ResponseBuilder rb{ctx, 2, 1};
1663 rb.Push(RESULT_SUCCESS);
1664 rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
1665}
1666
1652void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, 1667void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
1653 Core::System& system) { 1668 Core::System& system) {
1654 auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel()); 1669 auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel());
@@ -1682,8 +1697,9 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
1682 1697
1683 RegisterHandlers(functions); 1698 RegisterHandlers(functions);
1684 1699
1685 pop_from_general_channel_event = Kernel::WritableEvent::CreateEventPair( 1700 pop_from_general_channel_event =
1686 system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent"); 1701 Kernel::KEvent::Create(system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent");
1702 pop_from_general_channel_event->Initialize();
1687} 1703}
1688 1704
1689IHomeMenuFunctions::~IHomeMenuFunctions() = default; 1705IHomeMenuFunctions::~IHomeMenuFunctions() = default;
@@ -1700,7 +1716,7 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext
1700 1716
1701 IPC::ResponseBuilder rb{ctx, 2, 1}; 1717 IPC::ResponseBuilder rb{ctx, 2, 1};
1702 rb.Push(RESULT_SUCCESS); 1718 rb.Push(RESULT_SUCCESS);
1703 rb.PushCopyObjects(pop_from_general_channel_event.readable); 1719 rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
1704} 1720}
1705 1721
1706IGlobalStateController::IGlobalStateController(Core::System& system_) 1722IGlobalStateController::IGlobalStateController(Core::System& system_)
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index f5db41ac8..6911f0d6e 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -7,11 +7,12 @@
7#include <chrono> 7#include <chrono>
8#include <memory> 8#include <memory>
9#include <queue> 9#include <queue>
10#include "core/hle/kernel/writable_event.h" 10
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12 12
13namespace Kernel { 13namespace Kernel {
14class KernelCore; 14class KernelCore;
15class KEvent;
15class TransferMemory; 16class TransferMemory;
16} // namespace Kernel 17} // namespace Kernel
17 18
@@ -55,8 +56,8 @@ public:
55 explicit AppletMessageQueue(Kernel::KernelCore& kernel); 56 explicit AppletMessageQueue(Kernel::KernelCore& kernel);
56 ~AppletMessageQueue(); 57 ~AppletMessageQueue();
57 58
58 const std::shared_ptr<Kernel::ReadableEvent>& GetMessageReceiveEvent() const; 59 const std::shared_ptr<Kernel::KReadableEvent>& GetMessageReceiveEvent() const;
59 const std::shared_ptr<Kernel::ReadableEvent>& GetOperationModeChangedEvent() const; 60 const std::shared_ptr<Kernel::KReadableEvent>& GetOperationModeChangedEvent() const;
60 void PushMessage(AppletMessage msg); 61 void PushMessage(AppletMessage msg);
61 AppletMessage PopMessage(); 62 AppletMessage PopMessage();
62 std::size_t GetMessageCount() const; 63 std::size_t GetMessageCount() const;
@@ -65,8 +66,8 @@ public:
65 66
66private: 67private:
67 std::queue<AppletMessage> messages; 68 std::queue<AppletMessage> messages;
68 Kernel::EventPair on_new_message; 69 std::shared_ptr<Kernel::KEvent> on_new_message;
69 Kernel::EventPair on_operation_mode_changed; 70 std::shared_ptr<Kernel::KEvent> on_operation_mode_changed;
70}; 71};
71 72
72class IWindowController final : public ServiceFramework<IWindowController> { 73class IWindowController final : public ServiceFramework<IWindowController> {
@@ -153,8 +154,8 @@ private:
153 }; 154 };
154 155
155 NVFlinger::NVFlinger& nvflinger; 156 NVFlinger::NVFlinger& nvflinger;
156 Kernel::EventPair launchable_event; 157 std::shared_ptr<Kernel::KEvent> launchable_event;
157 Kernel::EventPair accumulated_suspended_tick_changed_event; 158 std::shared_ptr<Kernel::KEvent> accumulated_suspended_tick_changed_event;
158 159
159 u32 idle_time_detection_extension = 0; 160 u32 idle_time_detection_extension = 0;
160 u64 num_fatal_sections_entered = 0; 161 u64 num_fatal_sections_entered = 0;
@@ -290,12 +291,14 @@ private:
290 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); 291 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
291 void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); 292 void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
292 void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx); 293 void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx);
294 void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx);
293 295
294 bool launch_popped_application_specific = false; 296 bool launch_popped_application_specific = false;
295 bool launch_popped_account_preselect = false; 297 bool launch_popped_account_preselect = false;
296 s32 previous_program_index{-1}; 298 s32 previous_program_index{-1};
297 Kernel::EventPair gpu_error_detected_event; 299 std::shared_ptr<Kernel::KEvent> gpu_error_detected_event;
298 Kernel::EventPair friend_invitation_storage_channel_event; 300 std::shared_ptr<Kernel::KEvent> friend_invitation_storage_channel_event;
301 std::shared_ptr<Kernel::KEvent> health_warning_disappeared_system_event;
299}; 302};
300 303
301class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { 304class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
@@ -307,7 +310,7 @@ private:
307 void RequestToGetForeground(Kernel::HLERequestContext& ctx); 310 void RequestToGetForeground(Kernel::HLERequestContext& ctx);
308 void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx); 311 void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx);
309 312
310 Kernel::EventPair pop_from_general_channel_event; 313 std::shared_ptr<Kernel::KEvent> pop_from_general_channel_event;
311}; 314};
312 315
313class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { 316class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 08676c3fc..e2f3b7563 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include <cstring>
6
6#include "common/assert.h" 7#include "common/assert.h"
7#include "core/core.h" 8#include "core/core.h"
8#include "core/frontend/applets/controller.h" 9#include "core/frontend/applets/controller.h"
@@ -11,9 +12,10 @@
11#include "core/frontend/applets/profile_select.h" 12#include "core/frontend/applets/profile_select.h"
12#include "core/frontend/applets/software_keyboard.h" 13#include "core/frontend/applets/software_keyboard.h"
13#include "core/frontend/applets/web_browser.h" 14#include "core/frontend/applets/web_browser.h"
14#include "core/hle/kernel/readable_event.h" 15#include "core/hle/kernel/k_event.h"
16#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/k_writable_event.h"
15#include "core/hle/kernel/server_session.h" 18#include "core/hle/kernel/server_session.h"
16#include "core/hle/kernel/writable_event.h"
17#include "core/hle/service/am/am.h" 19#include "core/hle/service/am/am.h"
18#include "core/hle/service/am/applets/applets.h" 20#include "core/hle/service/am/applets/applets.h"
19#include "core/hle/service/am/applets/controller.h" 21#include "core/hle/service/am/applets/controller.h"
@@ -27,11 +29,13 @@ namespace Service::AM::Applets {
27 29
28AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) { 30AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
29 state_changed_event = 31 state_changed_event =
30 Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent"); 32 Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:StateChangedEvent");
31 pop_out_data_event = 33 state_changed_event->Initialize();
32 Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent"); 34 pop_out_data_event = Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
33 pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair( 35 pop_out_data_event->Initialize();
34 kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); 36 pop_interactive_out_data_event =
37 Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
38 pop_interactive_out_data_event->Initialize();
35} 39}
36 40
37AppletDataBroker::~AppletDataBroker() = default; 41AppletDataBroker::~AppletDataBroker() = default;
@@ -58,7 +62,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
58 62
59 auto out = std::move(out_channel.front()); 63 auto out = std::move(out_channel.front());
60 out_channel.pop_front(); 64 out_channel.pop_front();
61 pop_out_data_event.writable->Clear(); 65 pop_out_data_event->GetWritableEvent()->Clear();
62 return out; 66 return out;
63} 67}
64 68
@@ -77,7 +81,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
77 81
78 auto out = std::move(out_interactive_channel.front()); 82 auto out = std::move(out_interactive_channel.front());
79 out_interactive_channel.pop_front(); 83 out_interactive_channel.pop_front();
80 pop_interactive_out_data_event.writable->Clear(); 84 pop_interactive_out_data_event->GetWritableEvent()->Clear();
81 return out; 85 return out;
82} 86}
83 87
@@ -96,7 +100,7 @@ void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storag
96 100
97void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) { 101void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) {
98 out_channel.emplace_back(std::move(storage)); 102 out_channel.emplace_back(std::move(storage));
99 pop_out_data_event.writable->Signal(); 103 pop_out_data_event->GetWritableEvent()->Signal();
100} 104}
101 105
102void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) { 106void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) {
@@ -105,23 +109,23 @@ void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& s
105 109
106void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) { 110void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) {
107 out_interactive_channel.emplace_back(std::move(storage)); 111 out_interactive_channel.emplace_back(std::move(storage));
108 pop_interactive_out_data_event.writable->Signal(); 112 pop_interactive_out_data_event->GetWritableEvent()->Signal();
109} 113}
110 114
111void AppletDataBroker::SignalStateChanged() const { 115void AppletDataBroker::SignalStateChanged() const {
112 state_changed_event.writable->Signal(); 116 state_changed_event->GetWritableEvent()->Signal();
113} 117}
114 118
115std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const { 119std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
116 return pop_out_data_event.readable; 120 return pop_out_data_event->GetReadableEvent();
117} 121}
118 122
119std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const { 123std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
120 return pop_interactive_out_data_event.readable; 124 return pop_interactive_out_data_event->GetReadableEvent();
121} 125}
122 126
123std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const { 127std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
124 return state_changed_event.readable; 128 return state_changed_event->GetReadableEvent();
125} 129}
126 130
127Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {} 131Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {}
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 4fd792c05..b9a006317 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -6,9 +6,9 @@
6 6
7#include <memory> 7#include <memory>
8#include <queue> 8#include <queue>
9
9#include "common/swap.h" 10#include "common/swap.h"
10#include "core/hle/kernel/object.h" 11#include "core/hle/kernel/object.h"
11#include "core/hle/kernel/writable_event.h"
12 12
13union ResultCode; 13union ResultCode;
14 14
@@ -29,7 +29,9 @@ class WebBrowserApplet;
29 29
30namespace Kernel { 30namespace Kernel {
31class KernelCore; 31class KernelCore;
32} 32class KEvent;
33class KReadableEvent;
34} // namespace Kernel
33 35
34namespace Service::AM { 36namespace Service::AM {
35 37
@@ -87,9 +89,9 @@ public:
87 89
88 void SignalStateChanged() const; 90 void SignalStateChanged() const;
89 91
90 std::shared_ptr<Kernel::ReadableEvent> GetNormalDataEvent() const; 92 std::shared_ptr<Kernel::KReadableEvent> GetNormalDataEvent() const;
91 std::shared_ptr<Kernel::ReadableEvent> GetInteractiveDataEvent() const; 93 std::shared_ptr<Kernel::KReadableEvent> GetInteractiveDataEvent() const;
92 std::shared_ptr<Kernel::ReadableEvent> GetStateChangedEvent() const; 94 std::shared_ptr<Kernel::KReadableEvent> GetStateChangedEvent() const;
93 95
94private: 96private:
95 // Queues are named from applet's perspective 97 // Queues are named from applet's perspective
@@ -106,13 +108,13 @@ private:
106 // PopInteractiveDataToGame and PushInteractiveDataFromApplet 108 // PopInteractiveDataToGame and PushInteractiveDataFromApplet
107 std::deque<std::shared_ptr<IStorage>> out_interactive_channel; 109 std::deque<std::shared_ptr<IStorage>> out_interactive_channel;
108 110
109 Kernel::EventPair state_changed_event; 111 std::shared_ptr<Kernel::KEvent> state_changed_event;
110 112
111 // Signaled on PushNormalDataFromApplet 113 // Signaled on PushNormalDataFromApplet
112 Kernel::EventPair pop_out_data_event; 114 std::shared_ptr<Kernel::KEvent> pop_out_data_event;
113 115
114 // Signaled on PushInteractiveDataFromApplet 116 // Signaled on PushInteractiveDataFromApplet
115 Kernel::EventPair pop_interactive_out_data_event; 117 std::shared_ptr<Kernel::KEvent> pop_interactive_out_data_event;
116}; 118};
117 119
118class Applet { 120class Applet {
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp
index 7edfca64e..d7d3ee99a 100644
--- a/src/core/hle/service/am/applets/controller.cpp
+++ b/src/core/hle/service/am/applets/controller.cpp
@@ -37,7 +37,7 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
37 .border_colors = std::move(identification_colors), 37 .border_colors = std::move(identification_colors),
38 .enable_explain_text = enable_text, 38 .enable_explain_text = enable_text,
39 .explain_text = std::move(text), 39 .explain_text = std::move(text),
40 .allow_pro_controller = npad_style_set.pro_controller == 1, 40 .allow_pro_controller = npad_style_set.fullkey == 1,
41 .allow_handheld = npad_style_set.handheld == 1, 41 .allow_handheld = npad_style_set.handheld == 1,
42 .allow_dual_joycons = npad_style_set.joycon_dual == 1, 42 .allow_dual_joycons = npad_style_set.joycon_dual == 1,
43 .allow_left_joycon = npad_style_set.joycon_left == 1, 43 .allow_left_joycon = npad_style_set.joycon_left == 1,
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 23e28565b..8d657c0bf 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -5,6 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6#include <numeric> 6#include <numeric>
7#include <vector> 7#include <vector>
8
8#include "common/logging/log.h" 9#include "common/logging/log.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/file_sys/common_funcs.h" 11#include "core/file_sys/common_funcs.h"
@@ -14,10 +15,10 @@
14#include "core/file_sys/patch_manager.h" 15#include "core/file_sys/patch_manager.h"
15#include "core/file_sys/registered_cache.h" 16#include "core/file_sys/registered_cache.h"
16#include "core/hle/ipc_helpers.h" 17#include "core/hle/ipc_helpers.h"
18#include "core/hle/kernel/k_event.h"
19#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/process.h" 21#include "core/hle/kernel/process.h"
19#include "core/hle/kernel/readable_event.h"
20#include "core/hle/kernel/writable_event.h"
21#include "core/hle/service/aoc/aoc_u.h" 22#include "core/hle/service/aoc/aoc_u.h"
22#include "core/loader/loader.h" 23#include "core/loader/loader.h"
23#include "core/settings.h" 24#include "core/settings.h"
@@ -62,8 +63,9 @@ public:
62 63
63 RegisterHandlers(functions); 64 RegisterHandlers(functions);
64 65
65 purchased_event = Kernel::WritableEvent::CreateEventPair( 66 purchased_event =
66 system.Kernel(), "IPurchaseEventManager:PurchasedEvent"); 67 Kernel::KEvent::Create(system.Kernel(), "IPurchaseEventManager:PurchasedEvent");
68 purchased_event->Initialize();
67 } 69 }
68 70
69private: 71private:
@@ -96,10 +98,10 @@ private:
96 98
97 IPC::ResponseBuilder rb{ctx, 2, 1}; 99 IPC::ResponseBuilder rb{ctx, 2, 1};
98 rb.Push(RESULT_SUCCESS); 100 rb.Push(RESULT_SUCCESS);
99 rb.PushCopyObjects(purchased_event.readable); 101 rb.PushCopyObjects(purchased_event->GetReadableEvent());
100 } 102 }
101 103
102 Kernel::EventPair purchased_event; 104 std::shared_ptr<Kernel::KEvent> purchased_event;
103}; 105};
104 106
105AOC_U::AOC_U(Core::System& system_) 107AOC_U::AOC_U(Core::System& system_)
@@ -124,8 +126,8 @@ AOC_U::AOC_U(Core::System& system_)
124 RegisterHandlers(functions); 126 RegisterHandlers(functions);
125 127
126 auto& kernel = system.Kernel(); 128 auto& kernel = system.Kernel();
127 aoc_change_event = 129 aoc_change_event = Kernel::KEvent::Create(kernel, "GetAddOnContentListChanged:Event");
128 Kernel::WritableEvent::CreateEventPair(kernel, "GetAddOnContentListChanged:Event"); 130 aoc_change_event->Initialize();
129} 131}
130 132
131AOC_U::~AOC_U() = default; 133AOC_U::~AOC_U() = default;
@@ -252,7 +254,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
252 254
253 IPC::ResponseBuilder rb{ctx, 2, 1}; 255 IPC::ResponseBuilder rb{ctx, 2, 1};
254 rb.Push(RESULT_SUCCESS); 256 rb.Push(RESULT_SUCCESS);
255 rb.PushCopyObjects(aoc_change_event.readable); 257 rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
256} 258}
257 259
258void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) { 260void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 26ee51be0..1aa23529e 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -11,7 +11,7 @@ class System;
11} 11}
12 12
13namespace Kernel { 13namespace Kernel {
14class WritableEvent; 14class KEvent;
15} 15}
16 16
17namespace Service::AOC { 17namespace Service::AOC {
@@ -31,7 +31,7 @@ private:
31 void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx); 31 void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
32 32
33 std::vector<u64> add_on_content; 33 std::vector<u64> add_on_content;
34 Kernel::EventPair aoc_change_event; 34 std::shared_ptr<Kernel::KEvent> aoc_change_event;
35}; 35};
36 36
37/// Registers all AOC services with the specified service manager. 37/// Registers all AOC services with the specified service manager.
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 273a46265..5ed9cb20e 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -14,9 +14,10 @@
14#include "core/core.h" 14#include "core/core.h"
15#include "core/hle/ipc_helpers.h" 15#include "core/hle/ipc_helpers.h"
16#include "core/hle/kernel/hle_ipc.h" 16#include "core/hle/kernel/hle_ipc.h"
17#include "core/hle/kernel/k_event.h"
18#include "core/hle/kernel/k_readable_event.h"
19#include "core/hle/kernel/k_writable_event.h"
17#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/kernel/writable_event.h"
20#include "core/hle/service/audio/audout_u.h" 21#include "core/hle/service/audio/audout_u.h"
21#include "core/hle/service/audio/errors.h" 22#include "core/hle/service/audio/errors.h"
22#include "core/memory.h" 23#include "core/memory.h"
@@ -66,13 +67,13 @@ public:
66 RegisterHandlers(functions); 67 RegisterHandlers(functions);
67 68
68 // This is the event handle used to check if the audio buffer was released 69 // This is the event handle used to check if the audio buffer was released
69 buffer_event = 70 buffer_event = Kernel::KEvent::Create(system.Kernel(), "IAudioOutBufferReleased");
70 Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased"); 71 buffer_event->Initialize();
71 72
72 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, 73 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
73 audio_params.channel_count, std::move(unique_name), [this] { 74 audio_params.channel_count, std::move(unique_name), [this] {
74 const auto guard = LockService(); 75 const auto guard = LockService();
75 buffer_event.writable->Signal(); 76 buffer_event->GetWritableEvent()->Signal();
76 }); 77 });
77 } 78 }
78 79
@@ -125,7 +126,7 @@ private:
125 126
126 IPC::ResponseBuilder rb{ctx, 2, 1}; 127 IPC::ResponseBuilder rb{ctx, 2, 1};
127 rb.Push(RESULT_SUCCESS); 128 rb.Push(RESULT_SUCCESS);
128 rb.PushCopyObjects(buffer_event.readable); 129 rb.PushCopyObjects(buffer_event->GetReadableEvent());
129 } 130 }
130 131
131 void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) { 132 void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
@@ -219,7 +220,7 @@ private:
219 [[maybe_unused]] AudoutParams audio_params{}; 220 [[maybe_unused]] AudoutParams audio_params{};
220 221
221 /// This is the event handle used to check if the audio buffer was released 222 /// This is the event handle used to check if the audio buffer was released
222 Kernel::EventPair buffer_event; 223 std::shared_ptr<Kernel::KEvent> buffer_event;
223 Core::Memory::Memory& main_memory; 224 Core::Memory::Memory& main_memory;
224}; 225};
225 226
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index c5c22d053..b2b2ffc5a 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -16,9 +16,10 @@
16#include "core/core.h" 16#include "core/core.h"
17#include "core/hle/ipc_helpers.h" 17#include "core/hle/ipc_helpers.h"
18#include "core/hle/kernel/hle_ipc.h" 18#include "core/hle/kernel/hle_ipc.h"
19#include "core/hle/kernel/k_event.h"
20#include "core/hle/kernel/k_readable_event.h"
21#include "core/hle/kernel/k_writable_event.h"
19#include "core/hle/kernel/kernel.h" 22#include "core/hle/kernel/kernel.h"
20#include "core/hle/kernel/readable_event.h"
21#include "core/hle/kernel/writable_event.h"
22#include "core/hle/service/audio/audren_u.h" 23#include "core/hle/service/audio/audren_u.h"
23#include "core/hle/service/audio/errors.h" 24#include "core/hle/service/audio/errors.h"
24 25
@@ -47,13 +48,13 @@ public:
47 // clang-format on 48 // clang-format on
48 RegisterHandlers(functions); 49 RegisterHandlers(functions);
49 50
50 system_event = 51 system_event = Kernel::KEvent::Create(system.Kernel(), "IAudioRenderer:SystemEvent");
51 Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent"); 52 system_event->Initialize();
52 renderer = std::make_unique<AudioCore::AudioRenderer>( 53 renderer = std::make_unique<AudioCore::AudioRenderer>(
53 system.CoreTiming(), system.Memory(), audren_params, 54 system.CoreTiming(), system.Memory(), audren_params,
54 [this]() { 55 [this]() {
55 const auto guard = LockService(); 56 const auto guard = LockService();
56 system_event.writable->Signal(); 57 system_event->GetWritableEvent()->Signal();
57 }, 58 },
58 instance_number); 59 instance_number);
59 } 60 }
@@ -126,7 +127,7 @@ private:
126 127
127 IPC::ResponseBuilder rb{ctx, 2, 1}; 128 IPC::ResponseBuilder rb{ctx, 2, 1};
128 rb.Push(RESULT_SUCCESS); 129 rb.Push(RESULT_SUCCESS);
129 rb.PushCopyObjects(system_event.readable); 130 rb.PushCopyObjects(system_event->GetReadableEvent());
130 } 131 }
131 132
132 void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { 133 void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
@@ -160,7 +161,7 @@ private:
160 rb.Push(ERR_NOT_SUPPORTED); 161 rb.Push(ERR_NOT_SUPPORTED);
161 } 162 }
162 163
163 Kernel::EventPair system_event; 164 std::shared_ptr<Kernel::KEvent> system_event;
164 std::unique_ptr<AudioCore::AudioRenderer> renderer; 165 std::unique_ptr<AudioCore::AudioRenderer> renderer;
165 u32 rendering_time_limit_percent = 100; 166 u32 rendering_time_limit_percent = 100;
166}; 167};
@@ -187,17 +188,19 @@ public:
187 RegisterHandlers(functions); 188 RegisterHandlers(functions);
188 189
189 auto& kernel = system.Kernel(); 190 auto& kernel = system.Kernel();
190 buffer_event = 191 buffer_event = Kernel::KEvent::Create(kernel, "IAudioOutBufferReleasedEvent");
191 Kernel::WritableEvent::CreateEventPair(kernel, "IAudioOutBufferReleasedEvent"); 192 buffer_event->Initialize();
192 193
193 // Should be similar to audio_output_device_switch_event 194 // Should be similar to audio_output_device_switch_event
194 audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair( 195 audio_input_device_switch_event =
195 kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent"); 196 Kernel::KEvent::Create(kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
197 audio_input_device_switch_event->Initialize();
196 198
197 // Should only be signalled when an audio output device has been changed, example: speaker 199 // Should only be signalled when an audio output device has been changed, example: speaker
198 // to headset 200 // to headset
199 audio_output_device_switch_event = Kernel::WritableEvent::CreateEventPair( 201 audio_output_device_switch_event =
200 kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent"); 202 Kernel::KEvent::Create(kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
203 audio_output_device_switch_event->Initialize();
201 } 204 }
202 205
203private: 206private:
@@ -286,11 +289,11 @@ private:
286 void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { 289 void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
287 LOG_WARNING(Service_Audio, "(STUBBED) called"); 290 LOG_WARNING(Service_Audio, "(STUBBED) called");
288 291
289 buffer_event.writable->Signal(); 292 buffer_event->GetWritableEvent()->Signal();
290 293
291 IPC::ResponseBuilder rb{ctx, 2, 1}; 294 IPC::ResponseBuilder rb{ctx, 2, 1};
292 rb.Push(RESULT_SUCCESS); 295 rb.Push(RESULT_SUCCESS);
293 rb.PushCopyObjects(buffer_event.readable); 296 rb.PushCopyObjects(buffer_event->GetReadableEvent());
294 } 297 }
295 298
296 void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { 299 void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
@@ -307,7 +310,7 @@ private:
307 310
308 IPC::ResponseBuilder rb{ctx, 2, 1}; 311 IPC::ResponseBuilder rb{ctx, 2, 1};
309 rb.Push(RESULT_SUCCESS); 312 rb.Push(RESULT_SUCCESS);
310 rb.PushCopyObjects(audio_input_device_switch_event.readable); 313 rb.PushCopyObjects(audio_input_device_switch_event->GetReadableEvent());
311 } 314 }
312 315
313 void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { 316 void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) {
@@ -315,13 +318,13 @@ private:
315 318
316 IPC::ResponseBuilder rb{ctx, 2, 1}; 319 IPC::ResponseBuilder rb{ctx, 2, 1};
317 rb.Push(RESULT_SUCCESS); 320 rb.Push(RESULT_SUCCESS);
318 rb.PushCopyObjects(audio_output_device_switch_event.readable); 321 rb.PushCopyObjects(audio_output_device_switch_event->GetReadableEvent());
319 } 322 }
320 323
321 u32_le revision = 0; 324 u32_le revision = 0;
322 Kernel::EventPair buffer_event; 325 std::shared_ptr<Kernel::KEvent> buffer_event;
323 Kernel::EventPair audio_input_device_switch_event; 326 std::shared_ptr<Kernel::KEvent> audio_input_device_switch_event;
324 Kernel::EventPair audio_output_device_switch_event; 327 std::shared_ptr<Kernel::KEvent> audio_output_device_switch_event;
325 328
326}; // namespace Audio 329}; // namespace Audio
327 330
diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp
index 174388445..92d25dbe4 100644
--- a/src/core/hle/service/bcat/backend/backend.cpp
+++ b/src/core/hle/service/bcat/backend/backend.cpp
@@ -5,6 +5,9 @@
5#include "common/hex_util.h" 5#include "common/hex_util.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/kernel/k_event.h"
9#include "core/hle/kernel/k_readable_event.h"
10#include "core/hle/kernel/k_writable_event.h"
8#include "core/hle/lock.h" 11#include "core/hle/lock.h"
9#include "core/hle/service/bcat/backend/backend.h" 12#include "core/hle/service/bcat/backend/backend.h"
10 13
@@ -12,12 +15,13 @@ namespace Service::BCAT {
12 15
13ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel, 16ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel,
14 std::string_view event_name) { 17 std::string_view event_name) {
15 event = Kernel::WritableEvent::CreateEventPair( 18 event = Kernel::KEvent::Create(kernel,
16 kernel, std::string("ProgressServiceBackend:UpdateEvent:").append(event_name)); 19 "ProgressServiceBackend:UpdateEvent:" + std::string(event_name));
20 event->Initialize();
17} 21}
18 22
19std::shared_ptr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const { 23std::shared_ptr<Kernel::KReadableEvent> ProgressServiceBackend::GetEvent() const {
20 return event.readable; 24 return event->GetReadableEvent();
21} 25}
22 26
23DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() { 27DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
@@ -85,9 +89,9 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
85void ProgressServiceBackend::SignalUpdate() const { 89void ProgressServiceBackend::SignalUpdate() const {
86 if (need_hle_lock) { 90 if (need_hle_lock) {
87 std::lock_guard lock(HLE::g_hle_lock); 91 std::lock_guard lock(HLE::g_hle_lock);
88 event.writable->Signal(); 92 event->GetWritableEvent()->Signal();
89 } else { 93 } else {
90 event.writable->Signal(); 94 event->GetWritableEvent()->Signal();
91 } 95 }
92} 96}
93 97
diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h
index 48bbbe66f..db585b069 100644
--- a/src/core/hle/service/bcat/backend/backend.h
+++ b/src/core/hle/service/bcat/backend/backend.h
@@ -11,8 +11,6 @@
11 11
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "core/file_sys/vfs_types.h" 13#include "core/file_sys/vfs_types.h"
14#include "core/hle/kernel/readable_event.h"
15#include "core/hle/kernel/writable_event.h"
16#include "core/hle/result.h" 14#include "core/hle/result.h"
17 15
18namespace Core { 16namespace Core {
@@ -21,7 +19,9 @@ class System;
21 19
22namespace Kernel { 20namespace Kernel {
23class KernelCore; 21class KernelCore;
24} 22class KEvent;
23class KReadableEvent;
24} // namespace Kernel
25 25
26namespace Service::BCAT { 26namespace Service::BCAT {
27 27
@@ -98,13 +98,13 @@ public:
98private: 98private:
99 explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name); 99 explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name);
100 100
101 std::shared_ptr<Kernel::ReadableEvent> GetEvent() const; 101 std::shared_ptr<Kernel::KReadableEvent> GetEvent() const;
102 DeliveryCacheProgressImpl& GetImpl(); 102 DeliveryCacheProgressImpl& GetImpl();
103 103
104 void SignalUpdate() const; 104 void SignalUpdate() const;
105 105
106 DeliveryCacheProgressImpl impl{}; 106 DeliveryCacheProgressImpl impl{};
107 Kernel::EventPair event; 107 std::shared_ptr<Kernel::KEvent> event;
108 bool need_hle_lock = false; 108 bool need_hle_lock = false;
109}; 109};
110 110
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index b8696a395..503109fdd 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -11,9 +11,9 @@
11#include "core/core.h" 11#include "core/core.h"
12#include "core/file_sys/vfs.h" 12#include "core/file_sys/vfs.h"
13#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
14#include "core/hle/kernel/k_readable_event.h"
15#include "core/hle/kernel/k_writable_event.h"
14#include "core/hle/kernel/process.h" 16#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/readable_event.h"
16#include "core/hle/kernel/writable_event.h"
17#include "core/hle/service/bcat/backend/backend.h" 17#include "core/hle/service/bcat/backend/backend.h"
18#include "core/hle/service/bcat/bcat.h" 18#include "core/hle/service/bcat/bcat.h"
19#include "core/hle/service/bcat/module.h" 19#include "core/hle/service/bcat/module.h"
@@ -89,7 +89,7 @@ struct DeliveryCacheDirectoryEntry {
89class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> { 89class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> {
90public: 90public:
91 explicit IDeliveryCacheProgressService(Core::System& system_, 91 explicit IDeliveryCacheProgressService(Core::System& system_,
92 std::shared_ptr<Kernel::ReadableEvent> event_, 92 std::shared_ptr<Kernel::KReadableEvent> event_,
93 const DeliveryCacheProgressImpl& impl_) 93 const DeliveryCacheProgressImpl& impl_)
94 : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)}, 94 : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)},
95 impl{impl_} { 95 impl{impl_} {
@@ -121,7 +121,7 @@ private:
121 rb.Push(RESULT_SUCCESS); 121 rb.Push(RESULT_SUCCESS);
122 } 122 }
123 123
124 std::shared_ptr<Kernel::ReadableEvent> event; 124 std::shared_ptr<Kernel::KReadableEvent> event;
125 const DeliveryCacheProgressImpl& impl; 125 const DeliveryCacheProgressImpl& impl;
126}; 126};
127 127
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 2de86f1f1..17a2ac899 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -6,9 +6,9 @@
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/ipc_helpers.h" 7#include "core/hle/ipc_helpers.h"
8#include "core/hle/kernel/hle_ipc.h" 8#include "core/hle/kernel/hle_ipc.h"
9#include "core/hle/kernel/k_event.h"
10#include "core/hle/kernel/k_readable_event.h"
9#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/readable_event.h"
11#include "core/hle/kernel/writable_event.h"
12#include "core/hle/service/btdrv/btdrv.h" 12#include "core/hle/service/btdrv/btdrv.h"
13#include "core/hle/service/service.h" 13#include "core/hle/service/service.h"
14#include "core/hle/service/sm/sm.h" 14#include "core/hle/service/sm/sm.h"
@@ -35,7 +35,8 @@ public:
35 RegisterHandlers(functions); 35 RegisterHandlers(functions);
36 36
37 auto& kernel = system.Kernel(); 37 auto& kernel = system.Kernel();
38 register_event = Kernel::WritableEvent::CreateEventPair(kernel, "BT:RegisterEvent"); 38 register_event = Kernel::KEvent::Create(kernel, "BT:RegisterEvent");
39 register_event->Initialize();
39 } 40 }
40 41
41private: 42private:
@@ -44,10 +45,10 @@ private:
44 45
45 IPC::ResponseBuilder rb{ctx, 2, 1}; 46 IPC::ResponseBuilder rb{ctx, 2, 1};
46 rb.Push(RESULT_SUCCESS); 47 rb.Push(RESULT_SUCCESS);
47 rb.PushCopyObjects(register_event.readable); 48 rb.PushCopyObjects(register_event->GetReadableEvent());
48 } 49 }
49 50
50 Kernel::EventPair register_event; 51 std::shared_ptr<Kernel::KEvent> register_event;
51}; 52};
52 53
53class BtDrv final : public ServiceFramework<BtDrv> { 54class BtDrv final : public ServiceFramework<BtDrv> {
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 38b55300e..9cf2ee92a 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -8,9 +8,9 @@
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/hle_ipc.h" 10#include "core/hle/kernel/hle_ipc.h"
11#include "core/hle/kernel/k_event.h"
12#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/readable_event.h"
13#include "core/hle/kernel/writable_event.h"
14#include "core/hle/service/btm/btm.h" 14#include "core/hle/service/btm/btm.h"
15#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
16 16
@@ -58,12 +58,14 @@ public:
58 RegisterHandlers(functions); 58 RegisterHandlers(functions);
59 59
60 auto& kernel = system.Kernel(); 60 auto& kernel = system.Kernel();
61 scan_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ScanEvent"); 61 scan_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ScanEvent");
62 connection_event = 62 scan_event->Initialize();
63 Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConnectionEvent"); 63 connection_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConnectionEvent");
64 service_discovery = 64 connection_event->Initialize();
65 Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:Discovery"); 65 service_discovery = Kernel::KEvent::Create(kernel, "IBtmUserCore:Discovery");
66 config_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConfigEvent"); 66 service_discovery->Initialize();
67 config_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConfigEvent");
68 config_event->Initialize();
67 } 69 }
68 70
69private: 71private:
@@ -72,7 +74,7 @@ private:
72 74
73 IPC::ResponseBuilder rb{ctx, 2, 1}; 75 IPC::ResponseBuilder rb{ctx, 2, 1};
74 rb.Push(RESULT_SUCCESS); 76 rb.Push(RESULT_SUCCESS);
75 rb.PushCopyObjects(scan_event.readable); 77 rb.PushCopyObjects(scan_event->GetReadableEvent());
76 } 78 }
77 79
78 void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) { 80 void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) {
@@ -80,7 +82,7 @@ private:
80 82
81 IPC::ResponseBuilder rb{ctx, 2, 1}; 83 IPC::ResponseBuilder rb{ctx, 2, 1};
82 rb.Push(RESULT_SUCCESS); 84 rb.Push(RESULT_SUCCESS);
83 rb.PushCopyObjects(connection_event.readable); 85 rb.PushCopyObjects(connection_event->GetReadableEvent());
84 } 86 }
85 87
86 void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) { 88 void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) {
@@ -88,7 +90,7 @@ private:
88 90
89 IPC::ResponseBuilder rb{ctx, 2, 1}; 91 IPC::ResponseBuilder rb{ctx, 2, 1};
90 rb.Push(RESULT_SUCCESS); 92 rb.Push(RESULT_SUCCESS);
91 rb.PushCopyObjects(service_discovery.readable); 93 rb.PushCopyObjects(service_discovery->GetReadableEvent());
92 } 94 }
93 95
94 void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) { 96 void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) {
@@ -96,13 +98,13 @@ private:
96 98
97 IPC::ResponseBuilder rb{ctx, 2, 1}; 99 IPC::ResponseBuilder rb{ctx, 2, 1};
98 rb.Push(RESULT_SUCCESS); 100 rb.Push(RESULT_SUCCESS);
99 rb.PushCopyObjects(config_event.readable); 101 rb.PushCopyObjects(config_event->GetReadableEvent());
100 } 102 }
101 103
102 Kernel::EventPair scan_event; 104 std::shared_ptr<Kernel::KEvent> scan_event;
103 Kernel::EventPair connection_event; 105 std::shared_ptr<Kernel::KEvent> connection_event;
104 Kernel::EventPair service_discovery; 106 std::shared_ptr<Kernel::KEvent> service_discovery;
105 Kernel::EventPair config_event; 107 std::shared_ptr<Kernel::KEvent> config_event;
106}; 108};
107 109
108class BTM_USR final : public ServiceFramework<BTM_USR> { 110class BTM_USR final : public ServiceFramework<BTM_USR> {
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index c5b053c31..72a877d68 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -7,8 +7,9 @@
7#include "common/uuid.h" 7#include "common/uuid.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/readable_event.h" 10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/writable_event.h" 11#include "core/hle/kernel/k_readable_event.h"
12#include "core/hle/kernel/k_writable_event.h"
12#include "core/hle/service/friend/errors.h" 13#include "core/hle/service/friend/errors.h"
13#include "core/hle/service/friend/friend.h" 14#include "core/hle/service/friend/friend.h"
14#include "core/hle/service/friend/interface.h" 15#include "core/hle/service/friend/interface.h"
@@ -183,8 +184,9 @@ public:
183 184
184 RegisterHandlers(functions); 185 RegisterHandlers(functions);
185 186
186 notification_event = Kernel::WritableEvent::CreateEventPair( 187 notification_event =
187 system.Kernel(), "INotificationService:NotifyEvent"); 188 Kernel::KEvent::Create(system.Kernel(), "INotificationService:NotifyEvent");
189 notification_event->Initialize();
188 } 190 }
189 191
190private: 192private:
@@ -193,7 +195,7 @@ private:
193 195
194 IPC::ResponseBuilder rb{ctx, 2, 1}; 196 IPC::ResponseBuilder rb{ctx, 2, 1};
195 rb.Push(RESULT_SUCCESS); 197 rb.Push(RESULT_SUCCESS);
196 rb.PushCopyObjects(notification_event.readable); 198 rb.PushCopyObjects(notification_event->GetReadableEvent());
197 } 199 }
198 200
199 void Clear(Kernel::HLERequestContext& ctx) { 201 void Clear(Kernel::HLERequestContext& ctx) {
@@ -258,7 +260,7 @@ private:
258 }; 260 };
259 261
260 Common::UUID uuid{Common::INVALID_UUID}; 262 Common::UUID uuid{Common::INVALID_UUID};
261 Kernel::EventPair notification_event; 263 std::shared_ptr<Kernel::KEvent> notification_event;
262 std::queue<SizedNotificationInfo> notifications; 264 std::queue<SizedNotificationInfo> notifications;
263 States states{}; 265 States states{};
264}; 266};
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 59b694cd4..c4a59147d 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -39,16 +39,25 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
39 cur_entry.sampling_number2 = cur_entry.sampling_number; 39 cur_entry.sampling_number2 = cur_entry.sampling_number;
40 40
41 cur_entry.key.fill(0); 41 cur_entry.key.fill(0);
42 cur_entry.modifier = 0;
43 if (Settings::values.keyboard_enabled) { 42 if (Settings::values.keyboard_enabled) {
44 for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { 43 for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
45 auto& entry = cur_entry.key[i / KEYS_PER_BYTE]; 44 auto& entry = cur_entry.key[i / KEYS_PER_BYTE];
46 entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE))); 45 entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
47 } 46 }
48 47
49 for (std::size_t i = 0; i < keyboard_mods.size(); ++i) { 48 using namespace Settings::NativeKeyboard;
50 cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i); 49
51 } 50 // TODO: Assign the correct key to all modifiers
51 cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus());
52 cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus());
53 cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus());
54 cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus());
55 cur_entry.modifier.gui.Assign(0);
56 cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus());
57 cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus());
58 cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus());
59 cur_entry.modifier.katakana.Assign(0);
60 cur_entry.modifier.hiragana.Assign(0);
52 } 61 }
53 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 62 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
54} 63}
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index f3eef5936..b5b281752 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include "common/bit_field.h"
8#include "common/common_funcs.h" 9#include "common/common_funcs.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "common/swap.h" 11#include "common/swap.h"
@@ -31,12 +32,28 @@ public:
31 void OnLoadInputDevices() override; 32 void OnLoadInputDevices() override;
32 33
33private: 34private:
35 struct Modifiers {
36 union {
37 u32_le raw{};
38 BitField<0, 1, u32> control;
39 BitField<1, 1, u32> shift;
40 BitField<2, 1, u32> left_alt;
41 BitField<3, 1, u32> right_alt;
42 BitField<4, 1, u32> gui;
43 BitField<8, 1, u32> caps_lock;
44 BitField<9, 1, u32> scroll_lock;
45 BitField<10, 1, u32> num_lock;
46 BitField<11, 1, u32> katakana;
47 BitField<12, 1, u32> hiragana;
48 };
49 };
50 static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size");
51
34 struct KeyboardState { 52 struct KeyboardState {
35 s64_le sampling_number; 53 s64_le sampling_number;
36 s64_le sampling_number2; 54 s64_le sampling_number2;
37 55
38 s32_le modifier; 56 Modifiers modifier;
39 s32_le attribute;
40 std::array<u8, 32> key; 57 std::array<u8, 32> key;
41 }; 58 };
42 static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size"); 59 static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size");
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index ac40989c5..2e7457604 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -36,6 +36,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
36 cur_entry.sampling_number = last_entry.sampling_number + 1; 36 cur_entry.sampling_number = last_entry.sampling_number + 1;
37 cur_entry.sampling_number2 = cur_entry.sampling_number; 37 cur_entry.sampling_number2 = cur_entry.sampling_number;
38 38
39 cur_entry.attribute.raw = 0;
39 if (Settings::values.mouse_enabled) { 40 if (Settings::values.mouse_enabled) {
40 const auto [px, py, sx, sy] = mouse_device->GetStatus(); 41 const auto [px, py, sx, sy] = mouse_device->GetStatus();
41 const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width); 42 const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width);
@@ -46,10 +47,14 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
46 cur_entry.delta_y = y - last_entry.y; 47 cur_entry.delta_y = y - last_entry.y;
47 cur_entry.mouse_wheel_x = sx; 48 cur_entry.mouse_wheel_x = sx;
48 cur_entry.mouse_wheel_y = sy; 49 cur_entry.mouse_wheel_y = sy;
50 cur_entry.attribute.is_connected.Assign(1);
49 51
50 for (std::size_t i = 0; i < mouse_button_devices.size(); ++i) { 52 using namespace Settings::NativeMouseButton;
51 cur_entry.button |= (mouse_button_devices[i]->GetStatus() << i); 53 cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus());
52 } 54 cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus());
55 cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus());
56 cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus());
57 cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus());
53 } 58 }
54 59
55 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 60 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 357ab7107..3b432a36e 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include "common/bit_field.h"
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "common/swap.h" 10#include "common/swap.h"
10#include "core/frontend/input.h" 11#include "core/frontend/input.h"
@@ -30,6 +31,27 @@ public:
30 void OnLoadInputDevices() override; 31 void OnLoadInputDevices() override;
31 32
32private: 33private:
34 struct Buttons {
35 union {
36 u32_le raw{};
37 BitField<0, 1, u32> left;
38 BitField<1, 1, u32> right;
39 BitField<2, 1, u32> middle;
40 BitField<3, 1, u32> forward;
41 BitField<4, 1, u32> back;
42 };
43 };
44 static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size");
45
46 struct Attributes {
47 union {
48 u32_le raw{};
49 BitField<0, 1, u32> transferable;
50 BitField<1, 1, u32> is_connected;
51 };
52 };
53 static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
54
33 struct MouseState { 55 struct MouseState {
34 s64_le sampling_number; 56 s64_le sampling_number;
35 s64_le sampling_number2; 57 s64_le sampling_number2;
@@ -39,8 +61,8 @@ private:
39 s32_le delta_y; 61 s32_le delta_y;
40 s32_le mouse_wheel_x; 62 s32_le mouse_wheel_x;
41 s32_le mouse_wheel_y; 63 s32_le mouse_wheel_y;
42 s32_le button; 64 Buttons button;
43 s32_le attribute; 65 Attributes attribute;
44 }; 66 };
45 static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size"); 67 static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size");
46 68
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 0c227b135..dbf198345 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -12,9 +12,10 @@
12#include "core/core.h" 12#include "core/core.h"
13#include "core/core_timing.h" 13#include "core/core_timing.h"
14#include "core/frontend/input.h" 14#include "core/frontend/input.h"
15#include "core/hle/kernel/k_event.h"
16#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/k_writable_event.h"
15#include "core/hle/kernel/kernel.h" 18#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/readable_event.h"
17#include "core/hle/kernel/writable_event.h"
18#include "core/hle/service/hid/controllers/npad.h" 19#include "core/hle/service/hid/controllers/npad.h"
19#include "core/settings.h" 20#include "core/settings.h"
20 21
@@ -153,79 +154,86 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
153 const auto controller_type = connected_controllers[controller_idx].type; 154 const auto controller_type = connected_controllers[controller_idx].type;
154 auto& controller = shared_memory_entries[controller_idx]; 155 auto& controller = shared_memory_entries[controller_idx];
155 if (controller_type == NPadControllerType::None) { 156 if (controller_type == NPadControllerType::None) {
156 styleset_changed_events[controller_idx].writable->Signal(); 157 styleset_changed_events[controller_idx]->GetWritableEvent()->Signal();
157 return; 158 return;
158 } 159 }
159 controller.joy_styles.raw = 0; // Zero out 160 controller.style_set.raw = 0; // Zero out
160 controller.device_type.raw = 0; 161 controller.device_type.raw = 0;
161 controller.properties.raw = 0; 162 controller.system_properties.raw = 0;
162 switch (controller_type) { 163 switch (controller_type) {
163 case NPadControllerType::None: 164 case NPadControllerType::None:
164 UNREACHABLE(); 165 UNREACHABLE();
165 break; 166 break;
166 case NPadControllerType::ProController: 167 case NPadControllerType::ProController:
167 controller.joy_styles.pro_controller.Assign(1); 168 controller.style_set.fullkey.Assign(1);
168 controller.device_type.pro_controller.Assign(1); 169 controller.device_type.fullkey.Assign(1);
169 controller.properties.is_vertical.Assign(1); 170 controller.system_properties.is_vertical.Assign(1);
170 controller.properties.use_plus.Assign(1); 171 controller.system_properties.use_plus.Assign(1);
171 controller.properties.use_minus.Assign(1); 172 controller.system_properties.use_minus.Assign(1);
172 controller.pad_assignment = NpadAssignments::Single; 173 controller.assignment_mode = NpadAssignments::Single;
174 controller.footer_type = AppletFooterUiType::SwitchProController;
173 break; 175 break;
174 case NPadControllerType::Handheld: 176 case NPadControllerType::Handheld:
175 controller.joy_styles.handheld.Assign(1); 177 controller.style_set.handheld.Assign(1);
176 controller.device_type.handheld.Assign(1); 178 controller.device_type.handheld_left.Assign(1);
177 controller.properties.is_vertical.Assign(1); 179 controller.device_type.handheld_right.Assign(1);
178 controller.properties.use_plus.Assign(1); 180 controller.system_properties.is_vertical.Assign(1);
179 controller.properties.use_minus.Assign(1); 181 controller.system_properties.use_plus.Assign(1);
180 controller.pad_assignment = NpadAssignments::Dual; 182 controller.system_properties.use_minus.Assign(1);
183 controller.assignment_mode = NpadAssignments::Dual;
184 controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
181 break; 185 break;
182 case NPadControllerType::JoyDual: 186 case NPadControllerType::JoyDual:
183 controller.joy_styles.joycon_dual.Assign(1); 187 controller.style_set.joycon_dual.Assign(1);
184 controller.device_type.joycon_left.Assign(1); 188 controller.device_type.joycon_left.Assign(1);
185 controller.device_type.joycon_right.Assign(1); 189 controller.device_type.joycon_right.Assign(1);
186 controller.properties.is_vertical.Assign(1); 190 controller.system_properties.is_vertical.Assign(1);
187 controller.properties.use_plus.Assign(1); 191 controller.system_properties.use_plus.Assign(1);
188 controller.properties.use_minus.Assign(1); 192 controller.system_properties.use_minus.Assign(1);
189 controller.pad_assignment = NpadAssignments::Dual; 193 controller.assignment_mode = NpadAssignments::Dual;
194 controller.footer_type = AppletFooterUiType::JoyDual;
190 break; 195 break;
191 case NPadControllerType::JoyLeft: 196 case NPadControllerType::JoyLeft:
192 controller.joy_styles.joycon_left.Assign(1); 197 controller.style_set.joycon_left.Assign(1);
193 controller.device_type.joycon_left.Assign(1); 198 controller.device_type.joycon_left.Assign(1);
194 controller.properties.is_horizontal.Assign(1); 199 controller.system_properties.is_horizontal.Assign(1);
195 controller.properties.use_minus.Assign(1); 200 controller.system_properties.use_minus.Assign(1);
196 controller.pad_assignment = NpadAssignments::Single; 201 controller.assignment_mode = NpadAssignments::Single;
202 controller.footer_type = AppletFooterUiType::JoyLeftHorizontal;
197 break; 203 break;
198 case NPadControllerType::JoyRight: 204 case NPadControllerType::JoyRight:
199 controller.joy_styles.joycon_right.Assign(1); 205 controller.style_set.joycon_right.Assign(1);
200 controller.device_type.joycon_right.Assign(1); 206 controller.device_type.joycon_right.Assign(1);
201 controller.properties.is_horizontal.Assign(1); 207 controller.system_properties.is_horizontal.Assign(1);
202 controller.properties.use_plus.Assign(1); 208 controller.system_properties.use_plus.Assign(1);
203 controller.pad_assignment = NpadAssignments::Single; 209 controller.assignment_mode = NpadAssignments::Single;
210 controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
204 break; 211 break;
205 case NPadControllerType::Pokeball: 212 case NPadControllerType::Pokeball:
206 controller.joy_styles.pokeball.Assign(1); 213 controller.style_set.palma.Assign(1);
207 controller.device_type.pokeball.Assign(1); 214 controller.device_type.palma.Assign(1);
208 controller.pad_assignment = NpadAssignments::Single; 215 controller.assignment_mode = NpadAssignments::Single;
209 break; 216 break;
210 } 217 }
211 218
212 controller.single_color_error = ColorReadError::ReadOk; 219 controller.fullkey_color.attribute = ColorAttributes::Ok;
213 controller.single_color.body_color = 0; 220 controller.fullkey_color.fullkey.body = 0;
214 controller.single_color.button_color = 0; 221 controller.fullkey_color.fullkey.button = 0;
215 222
216 controller.dual_color_error = ColorReadError::ReadOk; 223 controller.joycon_color.attribute = ColorAttributes::Ok;
217 controller.left_color.body_color = 224 controller.joycon_color.left.body =
218 Settings::values.players.GetValue()[controller_idx].body_color_left; 225 Settings::values.players.GetValue()[controller_idx].body_color_left;
219 controller.left_color.button_color = 226 controller.joycon_color.left.button =
220 Settings::values.players.GetValue()[controller_idx].button_color_left; 227 Settings::values.players.GetValue()[controller_idx].button_color_left;
221 controller.right_color.body_color = 228 controller.joycon_color.right.body =
222 Settings::values.players.GetValue()[controller_idx].body_color_right; 229 Settings::values.players.GetValue()[controller_idx].body_color_right;
223 controller.right_color.button_color = 230 controller.joycon_color.right.button =
224 Settings::values.players.GetValue()[controller_idx].button_color_right; 231 Settings::values.players.GetValue()[controller_idx].button_color_right;
225 232
226 controller.battery_level[0] = BATTERY_FULL; 233 // TODO: Investigate when we should report all batery types
227 controller.battery_level[1] = BATTERY_FULL; 234 controller.battery_level_dual = BATTERY_FULL;
228 controller.battery_level[2] = BATTERY_FULL; 235 controller.battery_level_left = BATTERY_FULL;
236 controller.battery_level_right = BATTERY_FULL;
229 237
230 SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); 238 SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
231} 239}
@@ -233,8 +241,9 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
233void Controller_NPad::OnInit() { 241void Controller_NPad::OnInit() {
234 auto& kernel = system.Kernel(); 242 auto& kernel = system.Kernel();
235 for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { 243 for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
236 styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( 244 styleset_changed_events[i] =
237 kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); 245 Kernel::KEvent::Create(kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
246 styleset_changed_events[i]->Initialize();
238 } 247 }
239 248
240 if (!IsControllerActivated()) { 249 if (!IsControllerActivated()) {
@@ -249,8 +258,8 @@ void Controller_NPad::OnInit() {
249 style.joycon_left.Assign(1); 258 style.joycon_left.Assign(1);
250 style.joycon_right.Assign(1); 259 style.joycon_right.Assign(1);
251 style.joycon_dual.Assign(1); 260 style.joycon_dual.Assign(1);
252 style.pro_controller.Assign(1); 261 style.fullkey.Assign(1);
253 style.pokeball.Assign(1); 262 style.palma.Assign(1);
254 } 263 }
255 264
256 std::transform(Settings::values.players.GetValue().begin(), 265 std::transform(Settings::values.players.GetValue().begin(),
@@ -404,13 +413,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
404 } 413 }
405 for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { 414 for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
406 auto& npad = shared_memory_entries[i]; 415 auto& npad = shared_memory_entries[i];
407 const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, 416 const std::array<NPadGeneric*, 7> controller_npads{
408 &npad.handheld_states, 417 &npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states,
409 &npad.dual_states, 418 &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
410 &npad.left_joy_states, 419 &npad.system_ext_states};
411 &npad.right_joy_states,
412 &npad.pokeball_states,
413 &npad.libnx};
414 420
415 for (auto* main_controller : controller_npads) { 421 for (auto* main_controller : controller_npads) {
416 main_controller->common.entry_count = 16; 422 main_controller->common.entry_count = 16;
@@ -440,19 +446,19 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
440 auto& pad_state = npad_pad_states[npad_index]; 446 auto& pad_state = npad_pad_states[npad_index];
441 447
442 auto& main_controller = 448 auto& main_controller =
443 npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index]; 449 npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
444 auto& handheld_entry = 450 auto& handheld_entry =
445 npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; 451 npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
446 auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index]; 452 auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index];
447 auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index]; 453 auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index];
448 auto& right_entry = 454 auto& right_entry =
449 npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index]; 455 npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index];
450 auto& pokeball_entry = 456 auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
451 npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index]; 457 auto& libnx_entry =
452 auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; 458 npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
453 459
454 libnx_entry.connection_status.raw = 0; 460 libnx_entry.connection_status.raw = 0;
455 libnx_entry.connection_status.IsConnected.Assign(1); 461 libnx_entry.connection_status.is_connected.Assign(1);
456 462
457 switch (controller_type) { 463 switch (controller_type) {
458 case NPadControllerType::None: 464 case NPadControllerType::None:
@@ -460,67 +466,67 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
460 break; 466 break;
461 case NPadControllerType::ProController: 467 case NPadControllerType::ProController:
462 main_controller.connection_status.raw = 0; 468 main_controller.connection_status.raw = 0;
463 main_controller.connection_status.IsConnected.Assign(1); 469 main_controller.connection_status.is_connected.Assign(1);
464 main_controller.connection_status.IsWired.Assign(1); 470 main_controller.connection_status.is_wired.Assign(1);
465 main_controller.pad.pad_states.raw = pad_state.pad_states.raw; 471 main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
466 main_controller.pad.l_stick = pad_state.l_stick; 472 main_controller.pad.l_stick = pad_state.l_stick;
467 main_controller.pad.r_stick = pad_state.r_stick; 473 main_controller.pad.r_stick = pad_state.r_stick;
468 474
469 libnx_entry.connection_status.IsWired.Assign(1); 475 libnx_entry.connection_status.is_wired.Assign(1);
470 break; 476 break;
471 case NPadControllerType::Handheld: 477 case NPadControllerType::Handheld:
472 handheld_entry.connection_status.raw = 0; 478 handheld_entry.connection_status.raw = 0;
473 handheld_entry.connection_status.IsConnected.Assign(1); 479 handheld_entry.connection_status.is_connected.Assign(1);
474 handheld_entry.connection_status.IsWired.Assign(1); 480 handheld_entry.connection_status.is_wired.Assign(1);
475 handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); 481 handheld_entry.connection_status.is_left_connected.Assign(1);
476 handheld_entry.connection_status.IsRightJoyConnected.Assign(1); 482 handheld_entry.connection_status.is_right_connected.Assign(1);
477 handheld_entry.connection_status.IsLeftJoyWired.Assign(1); 483 handheld_entry.connection_status.is_left_wired.Assign(1);
478 handheld_entry.connection_status.IsRightJoyWired.Assign(1); 484 handheld_entry.connection_status.is_right_wired.Assign(1);
479 handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; 485 handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
480 handheld_entry.pad.l_stick = pad_state.l_stick; 486 handheld_entry.pad.l_stick = pad_state.l_stick;
481 handheld_entry.pad.r_stick = pad_state.r_stick; 487 handheld_entry.pad.r_stick = pad_state.r_stick;
482 488
483 libnx_entry.connection_status.IsWired.Assign(1); 489 libnx_entry.connection_status.is_wired.Assign(1);
484 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 490 libnx_entry.connection_status.is_left_connected.Assign(1);
485 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 491 libnx_entry.connection_status.is_right_connected.Assign(1);
486 libnx_entry.connection_status.IsLeftJoyWired.Assign(1); 492 libnx_entry.connection_status.is_left_wired.Assign(1);
487 libnx_entry.connection_status.IsRightJoyWired.Assign(1); 493 libnx_entry.connection_status.is_right_wired.Assign(1);
488 break; 494 break;
489 case NPadControllerType::JoyDual: 495 case NPadControllerType::JoyDual:
490 dual_entry.connection_status.raw = 0; 496 dual_entry.connection_status.raw = 0;
491 dual_entry.connection_status.IsConnected.Assign(1); 497 dual_entry.connection_status.is_connected.Assign(1);
492 dual_entry.connection_status.IsLeftJoyConnected.Assign(1); 498 dual_entry.connection_status.is_left_connected.Assign(1);
493 dual_entry.connection_status.IsRightJoyConnected.Assign(1); 499 dual_entry.connection_status.is_right_connected.Assign(1);
494 dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; 500 dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
495 dual_entry.pad.l_stick = pad_state.l_stick; 501 dual_entry.pad.l_stick = pad_state.l_stick;
496 dual_entry.pad.r_stick = pad_state.r_stick; 502 dual_entry.pad.r_stick = pad_state.r_stick;
497 503
498 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 504 libnx_entry.connection_status.is_left_connected.Assign(1);
499 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 505 libnx_entry.connection_status.is_right_connected.Assign(1);
500 break; 506 break;
501 case NPadControllerType::JoyLeft: 507 case NPadControllerType::JoyLeft:
502 left_entry.connection_status.raw = 0; 508 left_entry.connection_status.raw = 0;
503 left_entry.connection_status.IsConnected.Assign(1); 509 left_entry.connection_status.is_connected.Assign(1);
504 left_entry.connection_status.IsLeftJoyConnected.Assign(1); 510 left_entry.connection_status.is_left_connected.Assign(1);
505 left_entry.pad.pad_states.raw = pad_state.pad_states.raw; 511 left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
506 left_entry.pad.l_stick = pad_state.l_stick; 512 left_entry.pad.l_stick = pad_state.l_stick;
507 left_entry.pad.r_stick = pad_state.r_stick; 513 left_entry.pad.r_stick = pad_state.r_stick;
508 514
509 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 515 libnx_entry.connection_status.is_left_connected.Assign(1);
510 break; 516 break;
511 case NPadControllerType::JoyRight: 517 case NPadControllerType::JoyRight:
512 right_entry.connection_status.raw = 0; 518 right_entry.connection_status.raw = 0;
513 right_entry.connection_status.IsConnected.Assign(1); 519 right_entry.connection_status.is_connected.Assign(1);
514 right_entry.connection_status.IsRightJoyConnected.Assign(1); 520 right_entry.connection_status.is_right_connected.Assign(1);
515 right_entry.pad.pad_states.raw = pad_state.pad_states.raw; 521 right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
516 right_entry.pad.l_stick = pad_state.l_stick; 522 right_entry.pad.l_stick = pad_state.l_stick;
517 right_entry.pad.r_stick = pad_state.r_stick; 523 right_entry.pad.r_stick = pad_state.r_stick;
518 524
519 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 525 libnx_entry.connection_status.is_right_connected.Assign(1);
520 break; 526 break;
521 case NPadControllerType::Pokeball: 527 case NPadControllerType::Pokeball:
522 pokeball_entry.connection_status.raw = 0; 528 pokeball_entry.connection_status.raw = 0;
523 pokeball_entry.connection_status.IsConnected.Assign(1); 529 pokeball_entry.connection_status.is_connected.Assign(1);
524 pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; 530 pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
525 pokeball_entry.pad.l_stick = pad_state.l_stick; 531 pokeball_entry.pad.l_stick = pad_state.l_stick;
526 pokeball_entry.pad.r_stick = pad_state.r_stick; 532 pokeball_entry.pad.r_stick = pad_state.r_stick;
@@ -554,7 +560,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
554 } 560 }
555 561
556 const std::array<SixAxisGeneric*, 6> controller_sixaxes{ 562 const std::array<SixAxisGeneric*, 6> controller_sixaxes{
557 &npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left, 563 &npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
558 &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right, 564 &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
559 }; 565 };
560 566
@@ -592,7 +598,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
592 } 598 }
593 599
594 auto& full_sixaxis_entry = 600 auto& full_sixaxis_entry =
595 npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index]; 601 npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index];
596 auto& handheld_sixaxis_entry = 602 auto& handheld_sixaxis_entry =
597 npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index]; 603 npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
598 auto& dual_left_sixaxis_entry = 604 auto& dual_left_sixaxis_entry =
@@ -609,7 +615,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
609 UNREACHABLE(); 615 UNREACHABLE();
610 break; 616 break;
611 case NPadControllerType::ProController: 617 case NPadControllerType::ProController:
618 full_sixaxis_entry.attribute.raw = 0;
612 if (sixaxis_sensors_enabled && motions[i][0]) { 619 if (sixaxis_sensors_enabled && motions[i][0]) {
620 full_sixaxis_entry.attribute.is_connected.Assign(1);
613 full_sixaxis_entry.accel = motion_devices[0].accel; 621 full_sixaxis_entry.accel = motion_devices[0].accel;
614 full_sixaxis_entry.gyro = motion_devices[0].gyro; 622 full_sixaxis_entry.gyro = motion_devices[0].gyro;
615 full_sixaxis_entry.rotation = motion_devices[0].rotation; 623 full_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -617,7 +625,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
617 } 625 }
618 break; 626 break;
619 case NPadControllerType::Handheld: 627 case NPadControllerType::Handheld:
628 handheld_sixaxis_entry.attribute.raw = 0;
620 if (sixaxis_sensors_enabled && motions[i][0]) { 629 if (sixaxis_sensors_enabled && motions[i][0]) {
630 handheld_sixaxis_entry.attribute.is_connected.Assign(1);
621 handheld_sixaxis_entry.accel = motion_devices[0].accel; 631 handheld_sixaxis_entry.accel = motion_devices[0].accel;
622 handheld_sixaxis_entry.gyro = motion_devices[0].gyro; 632 handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
623 handheld_sixaxis_entry.rotation = motion_devices[0].rotation; 633 handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -625,8 +635,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
625 } 635 }
626 break; 636 break;
627 case NPadControllerType::JoyDual: 637 case NPadControllerType::JoyDual:
638 dual_left_sixaxis_entry.attribute.raw = 0;
639 dual_right_sixaxis_entry.attribute.raw = 0;
628 if (sixaxis_sensors_enabled && motions[i][0]) { 640 if (sixaxis_sensors_enabled && motions[i][0]) {
629 // Set motion for the left joycon 641 // Set motion for the left joycon
642 dual_left_sixaxis_entry.attribute.is_connected.Assign(1);
630 dual_left_sixaxis_entry.accel = motion_devices[0].accel; 643 dual_left_sixaxis_entry.accel = motion_devices[0].accel;
631 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro; 644 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
632 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation; 645 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -634,6 +647,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
634 } 647 }
635 if (sixaxis_sensors_enabled && motions[i][1]) { 648 if (sixaxis_sensors_enabled && motions[i][1]) {
636 // Set motion for the right joycon 649 // Set motion for the right joycon
650 dual_right_sixaxis_entry.attribute.is_connected.Assign(1);
637 dual_right_sixaxis_entry.accel = motion_devices[1].accel; 651 dual_right_sixaxis_entry.accel = motion_devices[1].accel;
638 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro; 652 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
639 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation; 653 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -641,7 +655,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
641 } 655 }
642 break; 656 break;
643 case NPadControllerType::JoyLeft: 657 case NPadControllerType::JoyLeft:
658 left_sixaxis_entry.attribute.raw = 0;
644 if (sixaxis_sensors_enabled && motions[i][0]) { 659 if (sixaxis_sensors_enabled && motions[i][0]) {
660 left_sixaxis_entry.attribute.is_connected.Assign(1);
645 left_sixaxis_entry.accel = motion_devices[0].accel; 661 left_sixaxis_entry.accel = motion_devices[0].accel;
646 left_sixaxis_entry.gyro = motion_devices[0].gyro; 662 left_sixaxis_entry.gyro = motion_devices[0].gyro;
647 left_sixaxis_entry.rotation = motion_devices[0].rotation; 663 left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -649,7 +665,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
649 } 665 }
650 break; 666 break;
651 case NPadControllerType::JoyRight: 667 case NPadControllerType::JoyRight:
668 right_sixaxis_entry.attribute.raw = 0;
652 if (sixaxis_sensors_enabled && motions[i][1]) { 669 if (sixaxis_sensors_enabled && motions[i][1]) {
670 right_sixaxis_entry.attribute.is_connected.Assign(1);
653 right_sixaxis_entry.accel = motion_devices[1].accel; 671 right_sixaxis_entry.accel = motion_devices[1].accel;
654 right_sixaxis_entry.gyro = motion_devices[1].gyro; 672 right_sixaxis_entry.gyro = motion_devices[1].gyro;
655 right_sixaxis_entry.rotation = motion_devices[1].rotation; 673 right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -715,8 +733,8 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
715void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { 733void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
716 const std::size_t npad_index = NPadIdToIndex(npad_id); 734 const std::size_t npad_index = NPadIdToIndex(npad_id);
717 ASSERT(npad_index < shared_memory_entries.size()); 735 ASSERT(npad_index < shared_memory_entries.size());
718 if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { 736 if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) {
719 shared_memory_entries[npad_index].pad_assignment = assignment_mode; 737 shared_memory_entries[npad_index].assignment_mode = assignment_mode;
720 } 738 }
721} 739}
722 740
@@ -872,13 +890,14 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev
872 return vibration_devices_mounted[npad_index][device_index]; 890 return vibration_devices_mounted[npad_index][device_index];
873} 891}
874 892
875std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { 893std::shared_ptr<Kernel::KReadableEvent> Controller_NPad::GetStyleSetChangedEvent(
894 u32 npad_id) const {
876 const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; 895 const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
877 return styleset_event.readable; 896 return styleset_event->GetReadableEvent();
878} 897}
879 898
880void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { 899void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
881 styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal(); 900 styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent()->Signal();
882} 901}
883 902
884void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { 903void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
@@ -923,9 +942,17 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
923 connected_controllers[npad_index].is_connected = false; 942 connected_controllers[npad_index].is_connected = false;
924 943
925 auto& controller = shared_memory_entries[npad_index]; 944 auto& controller = shared_memory_entries[npad_index];
926 controller.joy_styles.raw = 0; // Zero out 945 controller.style_set.raw = 0; // Zero out
927 controller.device_type.raw = 0; 946 controller.device_type.raw = 0;
928 controller.properties.raw = 0; 947 controller.system_properties.raw = 0;
948 controller.button_properties.raw = 0;
949 controller.battery_level_dual = 0;
950 controller.battery_level_left = 0;
951 controller.battery_level_right = 0;
952 controller.fullkey_color = {};
953 controller.joycon_color = {};
954 controller.assignment_mode = NpadAssignments::Dual;
955 controller.footer_type = AppletFooterUiType::None;
929 956
930 SignalStyleSetChangedEvent(IndexToNPad(npad_index)); 957 SignalStyleSetChangedEvent(IndexToNPad(npad_index));
931} 958}
@@ -1101,7 +1128,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1101 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { 1128 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
1102 switch (controller) { 1129 switch (controller) {
1103 case NPadControllerType::ProController: 1130 case NPadControllerType::ProController:
1104 return style.pro_controller; 1131 return style.fullkey;
1105 case NPadControllerType::JoyDual: 1132 case NPadControllerType::JoyDual:
1106 return style.joycon_dual; 1133 return style.joycon_dual;
1107 case NPadControllerType::JoyLeft: 1134 case NPadControllerType::JoyLeft:
@@ -1109,7 +1136,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1109 case NPadControllerType::JoyRight: 1136 case NPadControllerType::JoyRight:
1110 return style.joycon_right; 1137 return style.joycon_right;
1111 case NPadControllerType::Pokeball: 1138 case NPadControllerType::Pokeball:
1112 return style.pokeball; 1139 return style.palma;
1113 default: 1140 default:
1114 return false; 1141 return false;
1115 } 1142 }
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 2e13922b9..48bab988c 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -10,10 +10,14 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/frontend/input.h" 11#include "core/frontend/input.h"
12#include "core/hle/kernel/object.h" 12#include "core/hle/kernel/object.h"
13#include "core/hle/kernel/writable_event.h"
14#include "core/hle/service/hid/controllers/controller_base.h" 13#include "core/hle/service/hid/controllers/controller_base.h"
15#include "core/settings.h" 14#include "core/settings.h"
16 15
16namespace Kernel {
17class KEvent;
18class KReadableEvent;
19} // namespace Kernel
20
17namespace Service::HID { 21namespace Service::HID {
18 22
19constexpr u32 NPAD_HANDHELD = 32; 23constexpr u32 NPAD_HANDHELD = 32;
@@ -90,10 +94,10 @@ public:
90 }; 94 };
91 95
92 enum class NpadCommunicationMode : u64 { 96 enum class NpadCommunicationMode : u64 {
93 Unknown0 = 0, 97 Mode_5ms = 0,
94 Unknown1 = 1, 98 Mode_10ms = 1,
95 Unknown2 = 2, 99 Mode_15ms = 2,
96 Unknown3 = 3, 100 Default = 3,
97 }; 101 };
98 102
99 struct DeviceHandle { 103 struct DeviceHandle {
@@ -108,13 +112,18 @@ public:
108 union { 112 union {
109 u32_le raw{}; 113 u32_le raw{};
110 114
111 BitField<0, 1, u32> pro_controller; 115 BitField<0, 1, u32> fullkey;
112 BitField<1, 1, u32> handheld; 116 BitField<1, 1, u32> handheld;
113 BitField<2, 1, u32> joycon_dual; 117 BitField<2, 1, u32> joycon_dual;
114 BitField<3, 1, u32> joycon_left; 118 BitField<3, 1, u32> joycon_left;
115 BitField<4, 1, u32> joycon_right; 119 BitField<4, 1, u32> joycon_right;
116 120 BitField<5, 1, u32> gamecube;
117 BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible 121 BitField<6, 1, u32> palma;
122 BitField<7, 1, u32> lark;
123 BitField<8, 1, u32> handheld_lark;
124 BitField<9, 1, u32> lucia;
125 BitField<29, 1, u32> system_ext;
126 BitField<30, 1, u32> system;
118 }; 127 };
119 }; 128 };
120 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); 129 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
@@ -187,7 +196,7 @@ public:
187 196
188 bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; 197 bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
189 198
190 std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; 199 std::shared_ptr<Kernel::KReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
191 void SignalStyleSetChangedEvent(u32 npad_id) const; 200 void SignalStyleSetChangedEvent(u32 npad_id) const;
192 201
193 // Adds a new controller at an index. 202 // Adds a new controller at an index.
@@ -238,12 +247,32 @@ private:
238 }; 247 };
239 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); 248 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
240 249
250 enum class ColorAttributes : u32_le {
251 Ok = 0,
252 ReadError = 1,
253 NoController = 2,
254 };
255 static_assert(sizeof(ColorAttributes) == 4, "ColorAttributes is an invalid size");
256
241 struct ControllerColor { 257 struct ControllerColor {
242 u32_le body_color; 258 u32_le body;
243 u32_le button_color; 259 u32_le button;
244 }; 260 };
245 static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size"); 261 static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size");
246 262
263 struct FullKeyColor {
264 ColorAttributes attribute;
265 ControllerColor fullkey;
266 };
267 static_assert(sizeof(FullKeyColor) == 0xC, "FullKeyColor is an invalid size");
268
269 struct JoyconColor {
270 ColorAttributes attribute;
271 ControllerColor left;
272 ControllerColor right;
273 };
274 static_assert(sizeof(JoyconColor) == 0x14, "JoyconColor is an invalid size");
275
247 struct ControllerPadState { 276 struct ControllerPadState {
248 union { 277 union {
249 u64_le raw{}; 278 u64_le raw{};
@@ -285,6 +314,9 @@ private:
285 314
286 BitField<26, 1, u64> right_sl; 315 BitField<26, 1, u64> right_sl;
287 BitField<27, 1, u64> right_sr; 316 BitField<27, 1, u64> right_sr;
317
318 BitField<28, 1, u64> palma;
319 BitField<30, 1, u64> handheld_left_b;
288 }; 320 };
289 }; 321 };
290 static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); 322 static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
@@ -298,12 +330,12 @@ private:
298 struct ConnectionState { 330 struct ConnectionState {
299 union { 331 union {
300 u32_le raw{}; 332 u32_le raw{};
301 BitField<0, 1, u32> IsConnected; 333 BitField<0, 1, u32> is_connected;
302 BitField<1, 1, u32> IsWired; 334 BitField<1, 1, u32> is_wired;
303 BitField<2, 1, u32> IsLeftJoyConnected; 335 BitField<2, 1, u32> is_left_connected;
304 BitField<3, 1, u32> IsLeftJoyWired; 336 BitField<3, 1, u32> is_left_wired;
305 BitField<4, 1, u32> IsRightJoyConnected; 337 BitField<4, 1, u32> is_right_connected;
306 BitField<5, 1, u32> IsRightJoyWired; 338 BitField<5, 1, u32> is_right_wired;
307 }; 339 };
308 }; 340 };
309 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); 341 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size");
@@ -329,6 +361,15 @@ private:
329 }; 361 };
330 static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); 362 static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
331 363
364 struct SixAxisAttributes {
365 union {
366 u32_le raw{};
367 BitField<0, 1, u32> is_connected;
368 BitField<1, 1, u32> is_interpolated;
369 };
370 };
371 static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size");
372
332 struct SixAxisStates { 373 struct SixAxisStates {
333 s64_le timestamp{}; 374 s64_le timestamp{};
334 INSERT_PADDING_WORDS(2); 375 INSERT_PADDING_WORDS(2);
@@ -337,7 +378,8 @@ private:
337 Common::Vec3f gyro{}; 378 Common::Vec3f gyro{};
338 Common::Vec3f rotation{}; 379 Common::Vec3f rotation{};
339 std::array<Common::Vec3f, 3> orientation{}; 380 std::array<Common::Vec3f, 3> orientation{};
340 s64_le always_one{1}; 381 SixAxisAttributes attribute;
382 INSERT_PADDING_BYTES(4); // Reserved
341 }; 383 };
342 static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size"); 384 static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
343 385
@@ -347,32 +389,54 @@ private:
347 }; 389 };
348 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size"); 390 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
349 391
350 enum class ColorReadError : u32_le { 392 struct NPadSystemProperties {
351 ReadOk = 0,
352 ColorDoesntExist = 1,
353 NoController = 2,
354 };
355
356 struct NPadProperties {
357 union { 393 union {
358 s64_le raw{}; 394 s64_le raw{};
395 BitField<0, 1, s64> is_charging_joy_dual;
396 BitField<1, 1, s64> is_charging_joy_left;
397 BitField<2, 1, s64> is_charging_joy_right;
398 BitField<3, 1, s64> is_powered_joy_dual;
399 BitField<4, 1, s64> is_powered_joy_left;
400 BitField<5, 1, s64> is_powered_joy_right;
401 BitField<9, 1, s64> is_system_unsupported_button;
402 BitField<10, 1, s64> is_system_ext_unsupported_button;
359 BitField<11, 1, s64> is_vertical; 403 BitField<11, 1, s64> is_vertical;
360 BitField<12, 1, s64> is_horizontal; 404 BitField<12, 1, s64> is_horizontal;
361 BitField<13, 1, s64> use_plus; 405 BitField<13, 1, s64> use_plus;
362 BitField<14, 1, s64> use_minus; 406 BitField<14, 1, s64> use_minus;
407 BitField<15, 1, s64> use_directional_buttons;
408 };
409 };
410 static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
411
412 struct NPadButtonProperties {
413 union {
414 s32_le raw{};
415 BitField<0, 1, s32> is_home_button_protection_enabled;
363 }; 416 };
364 }; 417 };
418 static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
365 419
366 struct NPadDevice { 420 struct NPadDevice {
367 union { 421 union {
368 u32_le raw{}; 422 u32_le raw{};
369 BitField<0, 1, s32> pro_controller; 423 BitField<0, 1, s32> fullkey;
370 BitField<1, 1, s32> handheld; 424 BitField<1, 1, s32> debug_pad;
371 BitField<2, 1, s32> handheld_left; 425 BitField<2, 1, s32> handheld_left;
372 BitField<3, 1, s32> handheld_right; 426 BitField<3, 1, s32> handheld_right;
373 BitField<4, 1, s32> joycon_left; 427 BitField<4, 1, s32> joycon_left;
374 BitField<5, 1, s32> joycon_right; 428 BitField<5, 1, s32> joycon_right;
375 BitField<6, 1, s32> pokeball; 429 BitField<6, 1, s32> palma;
430 BitField<7, 1, s32> lark_hvc_left;
431 BitField<8, 1, s32> lark_hvc_right;
432 BitField<9, 1, s32> lark_nes_left;
433 BitField<10, 1, s32> lark_nes_right;
434 BitField<11, 1, s32> handheld_lark_hvc_left;
435 BitField<12, 1, s32> handheld_lark_hvc_right;
436 BitField<13, 1, s32> handheld_lark_nes_left;
437 BitField<14, 1, s32> handheld_lark_nes_right;
438 BitField<15, 1, s32> lucia;
439 BitField<31, 1, s32> system;
376 }; 440 };
377 }; 441 };
378 442
@@ -383,37 +447,69 @@ private:
383 std::array<Common::Vec3f, 3> orientation; 447 std::array<Common::Vec3f, 3> orientation;
384 }; 448 };
385 449
386 struct NPadEntry { 450 struct NfcXcdHandle {
387 NpadStyleSet joy_styles; 451 INSERT_PADDING_BYTES(0x60);
388 NpadAssignments pad_assignment; 452 };
389 453
390 ColorReadError single_color_error; 454 struct AppletFooterUiAttributes {
391 ControllerColor single_color; 455 INSERT_PADDING_BYTES(0x4);
456 };
392 457
393 ColorReadError dual_color_error; 458 enum class AppletFooterUiType : u8 {
394 ControllerColor left_color; 459 None = 0,
395 ControllerColor right_color; 460 HandheldNone = 1,
461 HandheldJoyConLeftOnly = 1,
462 HandheldJoyConRightOnly = 3,
463 HandheldJoyConLeftJoyConRight = 4,
464 JoyDual = 5,
465 JoyDualLeftOnly = 6,
466 JoyDualRightOnly = 7,
467 JoyLeftHorizontal = 8,
468 JoyLeftVertical = 9,
469 JoyRightHorizontal = 10,
470 JoyRightVertical = 11,
471 SwitchProController = 12,
472 CompatibleProController = 13,
473 CompatibleJoyCon = 14,
474 LarkHvc1 = 15,
475 LarkHvc2 = 16,
476 LarkNesLeft = 17,
477 LarkNesRight = 18,
478 Lucia = 19,
479 Verification = 20,
480 };
481
482 struct NPadEntry {
483 NpadStyleSet style_set;
484 NpadAssignments assignment_mode;
485 FullKeyColor fullkey_color;
486 JoyconColor joycon_color;
396 487
397 NPadGeneric main_controller_states; 488 NPadGeneric fullkey_states;
398 NPadGeneric handheld_states; 489 NPadGeneric handheld_states;
399 NPadGeneric dual_states; 490 NPadGeneric joy_dual_states;
400 NPadGeneric left_joy_states; 491 NPadGeneric joy_left_states;
401 NPadGeneric right_joy_states; 492 NPadGeneric joy_right_states;
402 NPadGeneric pokeball_states; 493 NPadGeneric palma_states;
403 NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be 494 NPadGeneric system_ext_states;
404 // relying on this for the time being 495 SixAxisGeneric sixaxis_fullkey;
405 SixAxisGeneric sixaxis_full;
406 SixAxisGeneric sixaxis_handheld; 496 SixAxisGeneric sixaxis_handheld;
407 SixAxisGeneric sixaxis_dual_left; 497 SixAxisGeneric sixaxis_dual_left;
408 SixAxisGeneric sixaxis_dual_right; 498 SixAxisGeneric sixaxis_dual_right;
409 SixAxisGeneric sixaxis_left; 499 SixAxisGeneric sixaxis_left;
410 SixAxisGeneric sixaxis_right; 500 SixAxisGeneric sixaxis_right;
411 NPadDevice device_type; 501 NPadDevice device_type;
412 NPadProperties properties; 502 INSERT_PADDING_BYTES(0x4); // reserved
413 INSERT_PADDING_WORDS(1); 503 NPadSystemProperties system_properties;
414 std::array<u32, 3> battery_level; 504 NPadButtonProperties button_properties;
415 INSERT_PADDING_BYTES(0x5c); 505 u32 battery_level_dual;
416 INSERT_PADDING_BYTES(0xdf8); 506 u32 battery_level_left;
507 u32 battery_level_right;
508 AppletFooterUiAttributes footer_attributes;
509 AppletFooterUiType footer_type;
510 // nfc_states needs to be checked switchbrew does not match with HW
511 NfcXcdHandle nfc_states;
512 INSERT_PADDING_BYTES(0xdef);
417 }; 513 };
418 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); 514 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
419 515
@@ -449,10 +545,9 @@ private:
449 std::vector<u32> supported_npad_id_types{}; 545 std::vector<u32> supported_npad_id_types{};
450 NpadHoldType hold_type{NpadHoldType::Vertical}; 546 NpadHoldType hold_type{NpadHoldType::Vertical};
451 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; 547 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
452 // NpadCommunicationMode is unknown, default value is 1 548 NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
453 NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1};
454 // Each controller should have their own styleset changed event 549 // Each controller should have their own styleset changed event
455 std::array<Kernel::EventPair, 10> styleset_changed_events; 550 std::array<std::shared_ptr<Kernel::KEvent>, 10> styleset_changed_events;
456 std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; 551 std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
457 std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; 552 std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
458 bool permit_vibration_session_enabled{false}; 553 bool permit_vibration_session_enabled{false};
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index ad229787c..5b59961bd 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/bit_field.h"
7#include "common/common_funcs.h" 8#include "common/common_funcs.h"
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "common/swap.h" 10#include "common/swap.h"
@@ -28,6 +29,67 @@ public:
28 void OnLoadInputDevices() override; 29 void OnLoadInputDevices() override;
29 30
30private: 31private:
32 struct Attributes {
33 union {
34 u32_le raw{};
35 BitField<0, 1, u32> is_connected;
36 BitField<1, 1, u32> is_wired;
37 BitField<2, 1, u32> is_left_connected;
38 BitField<3, 1, u32> is_left_wired;
39 BitField<4, 1, u32> is_right_connected;
40 BitField<5, 1, u32> is_right_wired;
41 };
42 };
43 static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size");
44
45 struct Buttons {
46 union {
47 u32_le raw{};
48 // Button states
49 BitField<0, 1, u32> a;
50 BitField<1, 1, u32> b;
51 BitField<2, 1, u32> x;
52 BitField<3, 1, u32> y;
53 BitField<4, 1, u32> l_stick;
54 BitField<5, 1, u32> r_stick;
55 BitField<6, 1, u32> l;
56 BitField<7, 1, u32> r;
57 BitField<8, 1, u32> zl;
58 BitField<9, 1, u32> zr;
59 BitField<10, 1, u32> plus;
60 BitField<11, 1, u32> minus;
61
62 // D-Pad
63 BitField<12, 1, u32> d_left;
64 BitField<13, 1, u32> d_up;
65 BitField<14, 1, u32> d_right;
66 BitField<15, 1, u32> d_down;
67
68 // Left JoyStick
69 BitField<16, 1, u32> l_stick_left;
70 BitField<17, 1, u32> l_stick_up;
71 BitField<18, 1, u32> l_stick_right;
72 BitField<19, 1, u32> l_stick_down;
73
74 // Right JoyStick
75 BitField<20, 1, u32> r_stick_left;
76 BitField<21, 1, u32> r_stick_up;
77 BitField<22, 1, u32> r_stick_right;
78 BitField<23, 1, u32> r_stick_down;
79
80 // Not always active?
81 BitField<24, 1, u32> left_sl;
82 BitField<25, 1, u32> left_sr;
83
84 BitField<26, 1, u32> right_sl;
85 BitField<27, 1, u32> right_sr;
86
87 BitField<28, 1, u32> palma;
88 BitField<30, 1, u32> handheld_left_b;
89 };
90 };
91 static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size");
92
31 struct AnalogStick { 93 struct AnalogStick {
32 s32_le x; 94 s32_le x;
33 s32_le y; 95 s32_le y;
@@ -37,10 +99,10 @@ private:
37 struct XPadState { 99 struct XPadState {
38 s64_le sampling_number; 100 s64_le sampling_number;
39 s64_le sampling_number2; 101 s64_le sampling_number2;
40 s32_le attributes; 102 Attributes attributes;
41 u32_le pad_states; 103 Buttons pad_states;
42 AnalogStick x_stick; 104 AnalogStick l_stick;
43 AnalogStick y_stick; 105 AnalogStick r_stick;
44 }; 106 };
45 static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size"); 107 static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size");
46 108
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 5efc1237e..51a010a55 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -14,10 +14,10 @@
14#include "core/hle/ipc_helpers.h" 14#include "core/hle/ipc_helpers.h"
15#include "core/hle/kernel/client_port.h" 15#include "core/hle/kernel/client_port.h"
16#include "core/hle/kernel/client_session.h" 16#include "core/hle/kernel/client_session.h"
17#include "core/hle/kernel/k_readable_event.h"
18#include "core/hle/kernel/k_writable_event.h"
17#include "core/hle/kernel/kernel.h" 19#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/kernel/shared_memory.h" 20#include "core/hle/kernel/shared_memory.h"
20#include "core/hle/kernel/writable_event.h"
21#include "core/hle/service/hid/errors.h" 21#include "core/hle/service/hid/errors.h"
22#include "core/hle/service/hid/hid.h" 22#include "core/hle/service/hid/hid.h"
23#include "core/hle/service/hid/irs.h" 23#include "core/hle/service/hid/irs.h"
@@ -59,20 +59,26 @@ IAppletResource::IAppletResource(Core::System& system_)
59 MakeController<Controller_Mouse>(HidController::Mouse); 59 MakeController<Controller_Mouse>(HidController::Mouse);
60 MakeController<Controller_Keyboard>(HidController::Keyboard); 60 MakeController<Controller_Keyboard>(HidController::Keyboard);
61 MakeController<Controller_XPad>(HidController::XPad); 61 MakeController<Controller_XPad>(HidController::XPad);
62 MakeController<Controller_Stubbed>(HidController::Unknown1); 62 MakeController<Controller_Stubbed>(HidController::HomeButton);
63 MakeController<Controller_Stubbed>(HidController::Unknown2); 63 MakeController<Controller_Stubbed>(HidController::SleepButton);
64 MakeController<Controller_Stubbed>(HidController::Unknown3); 64 MakeController<Controller_Stubbed>(HidController::CaptureButton);
65 MakeController<Controller_Stubbed>(HidController::SixAxisSensor); 65 MakeController<Controller_Stubbed>(HidController::InputDetector);
66 MakeController<Controller_Stubbed>(HidController::UniquePad);
66 MakeController<Controller_NPad>(HidController::NPad); 67 MakeController<Controller_NPad>(HidController::NPad);
67 MakeController<Controller_Gesture>(HidController::Gesture); 68 MakeController<Controller_Gesture>(HidController::Gesture);
69 MakeController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor);
68 70
69 // Homebrew doesn't try to activate some controllers, so we activate them by default 71 // Homebrew doesn't try to activate some controllers, so we activate them by default
70 GetController<Controller_NPad>(HidController::NPad).ActivateController(); 72 GetController<Controller_NPad>(HidController::NPad).ActivateController();
71 GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController(); 73 GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController();
72 74
73 GetController<Controller_Stubbed>(HidController::Unknown1).SetCommonHeaderOffset(0x4c00); 75 GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
74 GetController<Controller_Stubbed>(HidController::Unknown2).SetCommonHeaderOffset(0x4e00); 76 GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
75 GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000); 77 GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
78 GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
79 GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
80 GetController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor)
81 .SetCommonHeaderOffset(0x3C200);
76 82
77 // Register update callbacks 83 // Register update callbacks
78 pad_update_event = Core::Timing::CreateEvent( 84 pad_update_event = Core::Timing::CreateEvent(
@@ -126,14 +132,23 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
126 controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); 132 controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
127 } 133 }
128 134
135 // If ns_late is higher than the update rate ignore the delay
136 if (ns_late > motion_update_ns) {
137 ns_late = {};
138 }
139
129 core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); 140 core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
130} 141}
131 142
132void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 143void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
133 auto& core_timing = system.CoreTiming(); 144 auto& core_timing = system.CoreTiming();
134 145
135 for (const auto& controller : controllers) { 146 controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(
136 controller->OnMotionUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); 147 core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
148
149 // If ns_late is higher than the update rate ignore the delay
150 if (ns_late > motion_update_ns) {
151 ns_late = {};
137 } 152 }
138 153
139 core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event); 154 core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event);
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index d991bd721..7cc0433e2 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -29,12 +29,14 @@ enum class HidController : std::size_t {
29 Mouse, 29 Mouse,
30 Keyboard, 30 Keyboard,
31 XPad, 31 XPad,
32 Unknown1, 32 HomeButton,
33 Unknown2, 33 SleepButton,
34 Unknown3, 34 CaptureButton,
35 SixAxisSensor, 35 InputDetector,
36 UniquePad,
36 NPad, 37 NPad,
37 Gesture, 38 Gesture,
39 ConsoleSixAxisSensor,
38 40
39 MaxControllers, 41 MaxControllers,
40}; 42};
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index a515fdc60..5d6d25696 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -8,10 +8,11 @@
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
11#include "core/hle/kernel/k_event.h"
12#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/k_thread.h" 13#include "core/hle/kernel/k_thread.h"
14#include "core/hle/kernel/k_writable_event.h"
12#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/readable_event.h"
14#include "core/hle/kernel/writable_event.h"
15#include "core/hle/lock.h" 16#include "core/hle/lock.h"
16#include "core/hle/service/nfp/nfp.h" 17#include "core/hle/service/nfp/nfp.h"
17#include "core/hle/service/nfp/nfp_user.h" 18#include "core/hle/service/nfp/nfp_user.h"
@@ -25,7 +26,8 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst
25 const char* name) 26 const char* name)
26 : ServiceFramework{system_, name}, module{std::move(module_)} { 27 : ServiceFramework{system_, name}, module{std::move(module_)} {
27 auto& kernel = system.Kernel(); 28 auto& kernel = system.Kernel();
28 nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected"); 29 nfc_tag_load = Kernel::KEvent::Create(kernel, "IUser:NFCTagDetected");
30 nfc_tag_load->Initialize();
29} 31}
30 32
31Module::Interface::~Interface() = default; 33Module::Interface::~Interface() = default;
@@ -64,9 +66,10 @@ public:
64 RegisterHandlers(functions); 66 RegisterHandlers(functions);
65 67
66 auto& kernel = system.Kernel(); 68 auto& kernel = system.Kernel();
67 deactivate_event = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:DeactivateEvent"); 69 deactivate_event = Kernel::KEvent::Create(kernel, "IUser:DeactivateEvent");
68 availability_change_event = 70 deactivate_event->Initialize();
69 Kernel::WritableEvent::CreateEventPair(kernel, "IUser:AvailabilityChangeEvent"); 71 availability_change_event = Kernel::KEvent::Create(kernel, "IUser:AvailabilityChangeEvent");
72 availability_change_event->Initialize();
70 } 73 }
71 74
72private: 75private:
@@ -164,7 +167,7 @@ private:
164 167
165 IPC::ResponseBuilder rb{ctx, 2, 1}; 168 IPC::ResponseBuilder rb{ctx, 2, 1};
166 rb.Push(RESULT_SUCCESS); 169 rb.Push(RESULT_SUCCESS);
167 rb.PushCopyObjects(deactivate_event.readable); 170 rb.PushCopyObjects(deactivate_event->GetReadableEvent());
168 } 171 }
169 172
170 void StopDetection(Kernel::HLERequestContext& ctx) { 173 void StopDetection(Kernel::HLERequestContext& ctx) {
@@ -173,7 +176,7 @@ private:
173 switch (device_state) { 176 switch (device_state) {
174 case DeviceState::TagFound: 177 case DeviceState::TagFound:
175 case DeviceState::TagNearby: 178 case DeviceState::TagNearby:
176 deactivate_event.writable->Signal(); 179 deactivate_event->GetWritableEvent()->Signal();
177 device_state = DeviceState::Initialized; 180 device_state = DeviceState::Initialized;
178 break; 181 break;
179 case DeviceState::SearchingForTag: 182 case DeviceState::SearchingForTag:
@@ -262,7 +265,7 @@ private:
262 265
263 IPC::ResponseBuilder rb{ctx, 2, 1}; 266 IPC::ResponseBuilder rb{ctx, 2, 1};
264 rb.Push(RESULT_SUCCESS); 267 rb.Push(RESULT_SUCCESS);
265 rb.PushCopyObjects(availability_change_event.readable); 268 rb.PushCopyObjects(availability_change_event->GetReadableEvent());
266 } 269 }
267 270
268 void GetRegisterInfo(Kernel::HLERequestContext& ctx) { 271 void GetRegisterInfo(Kernel::HLERequestContext& ctx) {
@@ -316,8 +319,8 @@ private:
316 const u32 npad_id{0}; // Player 1 controller 319 const u32 npad_id{0}; // Player 1 controller
317 State state{State::NonInitialized}; 320 State state{State::NonInitialized};
318 DeviceState device_state{DeviceState::Initialized}; 321 DeviceState device_state{DeviceState::Initialized};
319 Kernel::EventPair deactivate_event; 322 std::shared_ptr<Kernel::KEvent> deactivate_event;
320 Kernel::EventPair availability_change_event; 323 std::shared_ptr<Kernel::KEvent> availability_change_event;
321 const Module::Interface& nfp_interface; 324 const Module::Interface& nfp_interface;
322}; 325};
323 326
@@ -336,12 +339,12 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
336 } 339 }
337 340
338 std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); 341 std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
339 nfc_tag_load.writable->Signal(); 342 nfc_tag_load->GetWritableEvent()->Signal();
340 return true; 343 return true;
341} 344}
342 345
343const std::shared_ptr<Kernel::ReadableEvent>& Module::Interface::GetNFCEvent() const { 346const std::shared_ptr<Kernel::KReadableEvent>& Module::Interface::GetNFCEvent() const {
344 return nfc_tag_load.readable; 347 return nfc_tag_load->GetReadableEvent();
345} 348}
346 349
347const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const { 350const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const {
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 295de535b..c46551760 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -6,10 +6,13 @@
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9#include "core/hle/kernel/readable_event.h" 9
10#include "core/hle/kernel/writable_event.h"
11#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
12 11
12namespace Kernel {
13class KEvent;
14}
15
13namespace Service::NFP { 16namespace Service::NFP {
14 17
15class Module final { 18class Module final {
@@ -35,11 +38,11 @@ public:
35 38
36 void CreateUserInterface(Kernel::HLERequestContext& ctx); 39 void CreateUserInterface(Kernel::HLERequestContext& ctx);
37 bool LoadAmiibo(const std::vector<u8>& buffer); 40 bool LoadAmiibo(const std::vector<u8>& buffer);
38 const std::shared_ptr<Kernel::ReadableEvent>& GetNFCEvent() const; 41 const std::shared_ptr<Kernel::KReadableEvent>& GetNFCEvent() const;
39 const AmiiboFile& GetAmiiboBuffer() const; 42 const AmiiboFile& GetAmiiboBuffer() const;
40 43
41 private: 44 private:
42 Kernel::EventPair nfc_tag_load{}; 45 std::shared_ptr<Kernel::KEvent> nfc_tag_load;
43 AmiiboFile amiibo{}; 46 AmiiboFile amiibo{};
44 47
45 protected: 48 protected:
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 8372e170c..afb3342d6 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -4,9 +4,9 @@
4 4
5#include "core/core.h" 5#include "core/core.h"
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/readable_event.h"
9#include "core/hle/kernel/writable_event.h"
10#include "core/hle/service/nifm/nifm.h" 10#include "core/hle/service/nifm/nifm.h"
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12#include "core/network/network.h" 12#include "core/network/network.h"
@@ -158,8 +158,11 @@ public:
158 RegisterHandlers(functions); 158 RegisterHandlers(functions);
159 159
160 auto& kernel = system.Kernel(); 160 auto& kernel = system.Kernel();
161 event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1"); 161
162 event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2"); 162 event1 = Kernel::KEvent::Create(kernel, "IRequest:Event1");
163 event1->Initialize();
164 event2 = Kernel::KEvent::Create(kernel, "IRequest:Event2");
165 event2->Initialize();
163 } 166 }
164 167
165private: 168private:
@@ -195,7 +198,7 @@ private:
195 198
196 IPC::ResponseBuilder rb{ctx, 2, 2}; 199 IPC::ResponseBuilder rb{ctx, 2, 2};
197 rb.Push(RESULT_SUCCESS); 200 rb.Push(RESULT_SUCCESS);
198 rb.PushCopyObjects(event1.readable, event2.readable); 201 rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent());
199 } 202 }
200 203
201 void Cancel(Kernel::HLERequestContext& ctx) { 204 void Cancel(Kernel::HLERequestContext& ctx) {
@@ -226,7 +229,7 @@ private:
226 rb.Push<u32>(0); 229 rb.Push<u32>(0);
227 } 230 }
228 231
229 Kernel::EventPair event1, event2; 232 std::shared_ptr<Kernel::KEvent> event1, event2;
230}; 233};
231 234
232class INetworkProfile final : public ServiceFramework<INetworkProfile> { 235class INetworkProfile final : public ServiceFramework<INetworkProfile> {
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index d16223064..f3be0b878 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -6,9 +6,10 @@
6#include <ctime> 6#include <ctime>
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/k_event.h"
10#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/k_writable_event.h"
9#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/readable_event.h"
11#include "core/hle/kernel/writable_event.h"
12#include "core/hle/service/nim/nim.h" 13#include "core/hle/service/nim/nim.h"
13#include "core/hle/service/service.h" 14#include "core/hle/service/service.h"
14#include "core/hle/service/sm/sm.h" 15#include "core/hle/service/sm/sm.h"
@@ -301,17 +302,18 @@ public:
301 RegisterHandlers(functions); 302 RegisterHandlers(functions);
302 303
303 auto& kernel = system.Kernel(); 304 auto& kernel = system.Kernel();
304 finished_event = Kernel::WritableEvent::CreateEventPair( 305 finished_event =
305 kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent"); 306 Kernel::KEvent::Create(kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
307 finished_event->Initialize();
306 } 308 }
307 309
308private: 310private:
309 Kernel::EventPair finished_event; 311 std::shared_ptr<Kernel::KEvent> finished_event;
310 312
311 void StartTask(Kernel::HLERequestContext& ctx) { 313 void StartTask(Kernel::HLERequestContext& ctx) {
312 // No need to connect to the internet, just finish the task straight away. 314 // No need to connect to the internet, just finish the task straight away.
313 LOG_DEBUG(Service_NIM, "called"); 315 LOG_DEBUG(Service_NIM, "called");
314 finished_event.writable->Signal(); 316 finished_event->GetWritableEvent()->Signal();
315 IPC::ResponseBuilder rb{ctx, 2}; 317 IPC::ResponseBuilder rb{ctx, 2};
316 rb.Push(RESULT_SUCCESS); 318 rb.Push(RESULT_SUCCESS);
317 } 319 }
@@ -321,7 +323,7 @@ private:
321 323
322 IPC::ResponseBuilder rb{ctx, 2, 1}; 324 IPC::ResponseBuilder rb{ctx, 2, 1};
323 rb.Push(RESULT_SUCCESS); 325 rb.Push(RESULT_SUCCESS);
324 rb.PushCopyObjects(finished_event.readable); 326 rb.PushCopyObjects(finished_event->GetReadableEvent());
325 } 327 }
326 328
327 void GetResult(Kernel::HLERequestContext& ctx) { 329 void GetResult(Kernel::HLERequestContext& ctx) {
@@ -333,7 +335,7 @@ private:
333 335
334 void Cancel(Kernel::HLERequestContext& ctx) { 336 void Cancel(Kernel::HLERequestContext& ctx) {
335 LOG_DEBUG(Service_NIM, "called"); 337 LOG_DEBUG(Service_NIM, "called");
336 finished_event.writable->Clear(); 338 finished_event->GetWritableEvent()->Clear();
337 IPC::ResponseBuilder rb{ctx, 2}; 339 IPC::ResponseBuilder rb{ctx, 2};
338 rb.Push(RESULT_SUCCESS); 340 rb.Push(RESULT_SUCCESS);
339 } 341 }
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 060599bab..f6129ef10 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -8,8 +8,8 @@
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/hle/kernel/readable_event.h" 11#include "core/hle/kernel/k_event.h"
12#include "core/hle/kernel/writable_event.h" 12#include "core/hle/kernel/k_writable_event.h"
13#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" 13#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
14#include "video_core/gpu.h" 14#include "video_core/gpu.h"
15 15
@@ -103,14 +103,14 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
103 // This is mostly to take into account unimplemented features. As synced 103 // This is mostly to take into account unimplemented features. As synced
104 // gpu is always synced. 104 // gpu is always synced.
105 if (!gpu.IsAsync()) { 105 if (!gpu.IsAsync()) {
106 event.event.writable->Signal(); 106 event.event->GetWritableEvent()->Signal();
107 return NvResult::Success; 107 return NvResult::Success;
108 } 108 }
109 auto lock = gpu.LockSync(); 109 auto lock = gpu.LockSync();
110 const u32 current_syncpoint_value = event.fence.value; 110 const u32 current_syncpoint_value = event.fence.value;
111 const s32 diff = current_syncpoint_value - params.threshold; 111 const s32 diff = current_syncpoint_value - params.threshold;
112 if (diff >= 0) { 112 if (diff >= 0) {
113 event.event.writable->Signal(); 113 event.event->GetWritableEvent()->Signal();
114 params.value = current_syncpoint_value; 114 params.value = current_syncpoint_value;
115 std::memcpy(output.data(), &params, sizeof(params)); 115 std::memcpy(output.data(), &params, sizeof(params));
116 return NvResult::Success; 116 return NvResult::Success;
@@ -137,7 +137,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
137 params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; 137 params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
138 } 138 }
139 params.value |= event_id; 139 params.value |= event_id;
140 event.event.writable->Clear(); 140 event.event->GetWritableEvent()->Clear();
141 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); 141 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
142 std::memcpy(output.data(), &params, sizeof(params)); 142 std::memcpy(output.data(), &params, sizeof(params));
143 return NvResult::Timeout; 143 return NvResult::Timeout;
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 1328b64d0..2e1150867 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -6,10 +6,10 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/k_readable_event.h"
9#include "core/hle/kernel/k_thread.h" 10#include "core/hle/kernel/k_thread.h"
11#include "core/hle/kernel/k_writable_event.h"
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/readable_event.h"
12#include "core/hle/kernel/writable_event.h"
13#include "core/hle/service/nvdrv/interface.h" 13#include "core/hle/service/nvdrv/interface.h"
14#include "core/hle/service/nvdrv/nvdata.h" 14#include "core/hle/service/nvdrv/nvdata.h"
15#include "core/hle/service/nvdrv/nvdrv.h" 15#include "core/hle/service/nvdrv/nvdrv.h"
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index 5c777c59b..0e764c53f 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -9,7 +9,7 @@
9#include "core/hle/service/service.h" 9#include "core/hle/service/service.h"
10 10
11namespace Kernel { 11namespace Kernel {
12class WritableEvent; 12class KWritableEvent;
13} 13}
14 14
15namespace Service::Nvidia { 15namespace Service::Nvidia {
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 620c18728..abba80112 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -7,8 +7,9 @@
7#include <fmt/format.h> 7#include <fmt/format.h>
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/readable_event.h" 10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/writable_event.h" 11#include "core/hle/kernel/k_readable_event.h"
12#include "core/hle/kernel/k_writable_event.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 13#include "core/hle/service/nvdrv/devices/nvdevice.h"
13#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 14#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
14#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" 15#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
@@ -42,7 +43,8 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} {
42 auto& kernel = system.Kernel(); 43 auto& kernel = system.Kernel();
43 for (u32 i = 0; i < MaxNvEvents; i++) { 44 for (u32 i = 0; i < MaxNvEvents; i++) {
44 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); 45 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i);
45 events_interface.events[i] = {Kernel::WritableEvent::CreateEventPair(kernel, event_label)}; 46 events_interface.events[i] = {Kernel::KEvent::Create(kernel, std::move(event_label))};
47 events_interface.events[i].event->Initialize();
46 events_interface.status[i] = EventState::Free; 48 events_interface.status[i] = EventState::Free;
47 events_interface.registered[i] = false; 49 events_interface.registered[i] = false;
48 } 50 }
@@ -166,17 +168,17 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) {
166 if (events_interface.assigned_syncpt[i] == syncpoint_id && 168 if (events_interface.assigned_syncpt[i] == syncpoint_id &&
167 events_interface.assigned_value[i] == value) { 169 events_interface.assigned_value[i] == value) {
168 events_interface.LiberateEvent(i); 170 events_interface.LiberateEvent(i);
169 events_interface.events[i].event.writable->Signal(); 171 events_interface.events[i].event->GetWritableEvent()->Signal();
170 } 172 }
171 } 173 }
172} 174}
173 175
174std::shared_ptr<Kernel::ReadableEvent> Module::GetEvent(const u32 event_id) const { 176std::shared_ptr<Kernel::KReadableEvent> Module::GetEvent(const u32 event_id) const {
175 return events_interface.events[event_id].event.readable; 177 return events_interface.events[event_id].event->GetReadableEvent();
176} 178}
177 179
178std::shared_ptr<Kernel::WritableEvent> Module::GetEventWriteable(const u32 event_id) const { 180std::shared_ptr<Kernel::KWritableEvent> Module::GetEventWriteable(const u32 event_id) const {
179 return events_interface.events[event_id].event.writable; 181 return events_interface.events[event_id].event->GetWritableEvent();
180} 182}
181 183
182} // namespace Service::Nvidia 184} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 144e657e5..53719aadd 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -7,8 +7,8 @@
7#include <memory> 7#include <memory>
8#include <unordered_map> 8#include <unordered_map>
9#include <vector> 9#include <vector>
10
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "core/hle/kernel/writable_event.h"
12#include "core/hle/service/nvdrv/nvdata.h" 12#include "core/hle/service/nvdrv/nvdata.h"
13#include "core/hle/service/nvdrv/syncpoint_manager.h" 13#include "core/hle/service/nvdrv/syncpoint_manager.h"
14#include "core/hle/service/service.h" 14#include "core/hle/service/service.h"
@@ -17,6 +17,10 @@ namespace Core {
17class System; 17class System;
18} 18}
19 19
20namespace Kernel {
21class KEvent;
22}
23
20namespace Service::NVFlinger { 24namespace Service::NVFlinger {
21class NVFlinger; 25class NVFlinger;
22} 26}
@@ -31,7 +35,7 @@ class nvdevice;
31 35
32/// Represents an Nvidia event 36/// Represents an Nvidia event
33struct NvEvent { 37struct NvEvent {
34 Kernel::EventPair event; 38 std::shared_ptr<Kernel::KEvent> event;
35 Fence fence{}; 39 Fence fence{};
36}; 40};
37 41
@@ -132,9 +136,9 @@ public:
132 136
133 void SignalSyncpt(const u32 syncpoint_id, const u32 value); 137 void SignalSyncpt(const u32 syncpoint_id, const u32 value);
134 138
135 std::shared_ptr<Kernel::ReadableEvent> GetEvent(u32 event_id) const; 139 std::shared_ptr<Kernel::KReadableEvent> GetEvent(u32 event_id) const;
136 140
137 std::shared_ptr<Kernel::WritableEvent> GetEventWriteable(u32 event_id) const; 141 std::shared_ptr<Kernel::KWritableEvent> GetEventWriteable(u32 event_id) const;
138 142
139private: 143private:
140 /// Manages syncpoints on the host 144 /// Manages syncpoints on the host
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 5578181a4..7842a82ed 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -7,16 +7,17 @@
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/k_writable_event.h"
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/readable_event.h"
12#include "core/hle/kernel/writable_event.h"
13#include "core/hle/service/nvflinger/buffer_queue.h" 13#include "core/hle/service/nvflinger/buffer_queue.h"
14 14
15namespace Service::NVFlinger { 15namespace Service::NVFlinger {
16 16
17BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id) 17BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
18 : id(id), layer_id(layer_id) { 18 : id(id), layer_id(layer_id) {
19 buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, "BufferQueue NativeHandle"); 19 buffer_wait_event = Kernel::KEvent::Create(kernel, "BufferQueue:WaitEvent");
20 buffer_wait_event->Initialize();
20} 21}
21 22
22BufferQueue::~BufferQueue() = default; 23BufferQueue::~BufferQueue() = default;
@@ -41,7 +42,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
41 .multi_fence = {}, 42 .multi_fence = {},
42 }; 43 };
43 44
44 buffer_wait_event.writable->Signal(); 45 buffer_wait_event->GetWritableEvent()->Signal();
45} 46}
46 47
47std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width, 48std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
@@ -119,7 +120,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
119 } 120 }
120 free_buffers_condition.notify_one(); 121 free_buffers_condition.notify_one();
121 122
122 buffer_wait_event.writable->Signal(); 123 buffer_wait_event->GetWritableEvent()->Signal();
123} 124}
124 125
125std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { 126std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
@@ -154,7 +155,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
154 } 155 }
155 free_buffers_condition.notify_one(); 156 free_buffers_condition.notify_one();
156 157
157 buffer_wait_event.writable->Signal(); 158 buffer_wait_event->GetWritableEvent()->Signal();
158} 159}
159 160
160void BufferQueue::Connect() { 161void BufferQueue::Connect() {
@@ -169,7 +170,7 @@ void BufferQueue::Disconnect() {
169 std::unique_lock lock{queue_sequence_mutex}; 170 std::unique_lock lock{queue_sequence_mutex};
170 queue_sequence.clear(); 171 queue_sequence.clear();
171 } 172 }
172 buffer_wait_event.writable->Signal(); 173 buffer_wait_event->GetWritableEvent()->Signal();
173 is_connect = false; 174 is_connect = false;
174 free_buffers_condition.notify_one(); 175 free_buffers_condition.notify_one();
175} 176}
@@ -188,12 +189,12 @@ u32 BufferQueue::Query(QueryType type) {
188 return 0; 189 return 0;
189} 190}
190 191
191std::shared_ptr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const { 192std::shared_ptr<Kernel::KWritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
192 return buffer_wait_event.writable; 193 return buffer_wait_event->GetWritableEvent();
193} 194}
194 195
195std::shared_ptr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const { 196std::shared_ptr<Kernel::KReadableEvent> BufferQueue::GetBufferWaitEvent() const {
196 return buffer_wait_event.readable; 197 return buffer_wait_event->GetReadableEvent();
197} 198}
198 199
199} // namespace Service::NVFlinger 200} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index ad7469277..163fa4c54 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -14,12 +14,14 @@
14#include "common/math_util.h" 14#include "common/math_util.h"
15#include "common/swap.h" 15#include "common/swap.h"
16#include "core/hle/kernel/object.h" 16#include "core/hle/kernel/object.h"
17#include "core/hle/kernel/writable_event.h"
18#include "core/hle/service/nvdrv/nvdata.h" 17#include "core/hle/service/nvdrv/nvdata.h"
19 18
20namespace Kernel { 19namespace Kernel {
21class KernelCore; 20class KernelCore;
22} 21class KEvent;
22class KReadableEvent;
23class KWritableEvent;
24} // namespace Kernel
23 25
24namespace Service::NVFlinger { 26namespace Service::NVFlinger {
25 27
@@ -113,9 +115,9 @@ public:
113 return is_connect; 115 return is_connect;
114 } 116 }
115 117
116 std::shared_ptr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const; 118 std::shared_ptr<Kernel::KWritableEvent> GetWritableBufferWaitEvent() const;
117 119
118 std::shared_ptr<Kernel::ReadableEvent> GetBufferWaitEvent() const; 120 std::shared_ptr<Kernel::KReadableEvent> GetBufferWaitEvent() const;
119 121
120private: 122private:
121 BufferQueue(const BufferQueue&) = delete; 123 BufferQueue(const BufferQueue&) = delete;
@@ -127,7 +129,7 @@ private:
127 std::list<u32> free_buffers; 129 std::list<u32> free_buffers;
128 std::array<Buffer, buffer_slots> buffers; 130 std::array<Buffer, buffer_slots> buffers;
129 std::list<u32> queue_sequence; 131 std::list<u32> queue_sequence;
130 Kernel::EventPair buffer_wait_event; 132 std::shared_ptr<Kernel::KEvent> buffer_wait_event;
131 133
132 std::mutex free_buffers_mutex; 134 std::mutex free_buffers_mutex;
133 std::condition_variable free_buffers_condition; 135 std::condition_variable free_buffers_condition;
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index ceaa93d28..ac2906e5b 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -14,8 +14,8 @@
14#include "core/core_timing.h" 14#include "core/core_timing.h"
15#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
16#include "core/hardware_properties.h" 16#include "core/hardware_properties.h"
17#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/kernel.h" 18#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 19#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
20#include "core/hle/service/nvdrv/nvdrv.h" 20#include "core/hle/service/nvdrv/nvdrv.h"
21#include "core/hle/service/nvflinger/buffer_queue.h" 21#include "core/hle/service/nvflinger/buffer_queue.h"
@@ -165,7 +165,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co
165 return layer->GetBufferQueue().GetId(); 165 return layer->GetBufferQueue().GetId();
166} 166}
167 167
168std::shared_ptr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const { 168std::shared_ptr<Kernel::KReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
169 const auto guard = Lock(); 169 const auto guard = Lock();
170 auto* const display = FindDisplay(display_id); 170 auto* const display = FindDisplay(display_id);
171 171
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index c6765259f..6fe2c7f2a 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -26,8 +26,8 @@ struct EventType;
26} // namespace Core::Timing 26} // namespace Core::Timing
27 27
28namespace Kernel { 28namespace Kernel {
29class ReadableEvent; 29class KReadableEvent;
30class WritableEvent; 30class KWritableEvent;
31} // namespace Kernel 31} // namespace Kernel
32 32
33namespace Service::Nvidia { 33namespace Service::Nvidia {
@@ -72,7 +72,7 @@ public:
72 /// Gets the vsync event for the specified display. 72 /// Gets the vsync event for the specified display.
73 /// 73 ///
74 /// If an invalid display ID is provided, then nullptr is returned. 74 /// If an invalid display ID is provided, then nullptr is returned.
75 [[nodiscard]] std::shared_ptr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const; 75 [[nodiscard]] std::shared_ptr<Kernel::KReadableEvent> FindVsyncEvent(u64 display_id) const;
76 76
77 /// Obtains a buffer queue identified by the ID. 77 /// Obtains a buffer queue identified by the ID.
78 [[nodiscard]] BufferQueue* FindBufferQueue(u32 id); 78 [[nodiscard]] BufferQueue* FindBufferQueue(u32 id);
diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp
index a7cfccda3..26ed52273 100644
--- a/src/core/hle/service/ptm/psm.cpp
+++ b/src/core/hle/service/ptm/psm.cpp
@@ -7,9 +7,10 @@
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/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/k_readable_event.h"
12#include "core/hle/kernel/k_writable_event.h"
10#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/readable_event.h"
12#include "core/hle/kernel/writable_event.h"
13#include "core/hle/service/ptm/psm.h" 14#include "core/hle/service/ptm/psm.h"
14#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
15#include "core/hle/service/sm/sm.h" 16#include "core/hle/service/sm/sm.h"
@@ -31,27 +32,28 @@ public:
31 32
32 RegisterHandlers(functions); 33 RegisterHandlers(functions);
33 34
34 state_change_event = Kernel::WritableEvent::CreateEventPair( 35 state_change_event =
35 system_.Kernel(), "IPsmSession::state_change_event"); 36 Kernel::KEvent::Create(system_.Kernel(), "IPsmSession::state_change_event");
37 state_change_event->Initialize();
36 } 38 }
37 39
38 ~IPsmSession() override = default; 40 ~IPsmSession() override = default;
39 41
40 void SignalChargerTypeChanged() { 42 void SignalChargerTypeChanged() {
41 if (should_signal && should_signal_charger_type) { 43 if (should_signal && should_signal_charger_type) {
42 state_change_event.writable->Signal(); 44 state_change_event->GetWritableEvent()->Signal();
43 } 45 }
44 } 46 }
45 47
46 void SignalPowerSupplyChanged() { 48 void SignalPowerSupplyChanged() {
47 if (should_signal && should_signal_power_supply) { 49 if (should_signal && should_signal_power_supply) {
48 state_change_event.writable->Signal(); 50 state_change_event->GetWritableEvent()->Signal();
49 } 51 }
50 } 52 }
51 53
52 void SignalBatteryVoltageStateChanged() { 54 void SignalBatteryVoltageStateChanged() {
53 if (should_signal && should_signal_battery_voltage) { 55 if (should_signal && should_signal_battery_voltage) {
54 state_change_event.writable->Signal(); 56 state_change_event->GetWritableEvent()->Signal();
55 } 57 }
56 } 58 }
57 59
@@ -63,7 +65,7 @@ private:
63 65
64 IPC::ResponseBuilder rb{ctx, 2, 1}; 66 IPC::ResponseBuilder rb{ctx, 2, 1};
65 rb.Push(RESULT_SUCCESS); 67 rb.Push(RESULT_SUCCESS);
66 rb.PushCopyObjects(state_change_event.readable); 68 rb.PushCopyObjects(state_change_event->GetReadableEvent());
67 } 69 }
68 70
69 void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) { 71 void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
@@ -112,7 +114,7 @@ private:
112 bool should_signal_power_supply{}; 114 bool should_signal_power_supply{};
113 bool should_signal_battery_voltage{}; 115 bool should_signal_battery_voltage{};
114 bool should_signal{}; 116 bool should_signal{};
115 Kernel::EventPair state_change_event; 117 std::shared_ptr<Kernel::KEvent> state_change_event;
116}; 118};
117 119
118class PSM final : public ServiceFramework<PSM> { 120class PSM final : public ServiceFramework<PSM> {
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.cpp b/src/core/hle/service/time/standard_user_system_clock_core.cpp
index 8af17091c..b9faa474e 100644
--- a/src/core/hle/service/time/standard_user_system_clock_core.cpp
+++ b/src/core/hle/service/time/standard_user_system_clock_core.cpp
@@ -4,7 +4,7 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/kernel/writable_event.h" 7#include "core/hle/kernel/k_event.h"
8#include "core/hle/service/time/standard_local_system_clock_core.h" 8#include "core/hle/service/time/standard_local_system_clock_core.h"
9#include "core/hle/service/time/standard_network_system_clock_core.h" 9#include "core/hle/service/time/standard_network_system_clock_core.h"
10#include "core/hle/service/time/standard_user_system_clock_core.h" 10#include "core/hle/service/time/standard_user_system_clock_core.h"
@@ -18,8 +18,10 @@ StandardUserSystemClockCore::StandardUserSystemClockCore(
18 local_system_clock_core{local_system_clock_core}, 18 local_system_clock_core{local_system_clock_core},
19 network_system_clock_core{network_system_clock_core}, auto_correction_enabled{}, 19 network_system_clock_core{network_system_clock_core}, auto_correction_enabled{},
20 auto_correction_time{SteadyClockTimePoint::GetRandom()}, 20 auto_correction_time{SteadyClockTimePoint::GetRandom()},
21 auto_correction_event{Kernel::WritableEvent::CreateEventPair( 21 auto_correction_event{Kernel::KEvent::Create(
22 system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {} 22 system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {
23 auto_correction_event->Initialize();
24}
23 25
24ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system, 26ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
25 bool value) { 27 bool value) {
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.h b/src/core/hle/service/time/standard_user_system_clock_core.h
index ef3d468b7..aac44d72f 100644
--- a/src/core/hle/service/time/standard_user_system_clock_core.h
+++ b/src/core/hle/service/time/standard_user_system_clock_core.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/kernel/writable_event.h"
8#include "core/hle/service/time/clock_types.h" 7#include "core/hle/service/time/clock_types.h"
9#include "core/hle/service/time/system_clock_core.h" 8#include "core/hle/service/time/system_clock_core.h"
10 9
@@ -12,6 +11,10 @@ namespace Core {
12class System; 11class System;
13} 12}
14 13
14namespace Kernel {
15class KEvent;
16}
17
15namespace Service::Time::Clock { 18namespace Service::Time::Clock {
16 19
17class StandardLocalSystemClockCore; 20class StandardLocalSystemClockCore;
@@ -51,7 +54,7 @@ private:
51 StandardNetworkSystemClockCore& network_system_clock_core; 54 StandardNetworkSystemClockCore& network_system_clock_core;
52 bool auto_correction_enabled{}; 55 bool auto_correction_enabled{};
53 SteadyClockTimePoint auto_correction_time; 56 SteadyClockTimePoint auto_correction_time;
54 Kernel::EventPair auto_correction_event; 57 std::shared_ptr<Kernel::KEvent> auto_correction_event;
55}; 58};
56 59
57} // namespace Service::Time::Clock 60} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.cpp b/src/core/hle/service/time/system_clock_context_update_callback.cpp
index 5cdb80703..bca7d869e 100644
--- a/src/core/hle/service/time/system_clock_context_update_callback.cpp
+++ b/src/core/hle/service/time/system_clock_context_update_callback.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 "core/hle/kernel/writable_event.h" 5#include "core/hle/kernel/k_writable_event.h"
6#include "core/hle/service/time/errors.h" 6#include "core/hle/service/time/errors.h"
7#include "core/hle/service/time/system_clock_context_update_callback.h" 7#include "core/hle/service/time/system_clock_context_update_callback.h"
8 8
@@ -21,7 +21,7 @@ bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& valu
21} 21}
22 22
23void SystemClockContextUpdateCallback::RegisterOperationEvent( 23void SystemClockContextUpdateCallback::RegisterOperationEvent(
24 std::shared_ptr<Kernel::WritableEvent>&& writable_event) { 24 std::shared_ptr<Kernel::KWritableEvent>&& writable_event) {
25 operation_event_list.emplace_back(std::move(writable_event)); 25 operation_event_list.emplace_back(std::move(writable_event));
26} 26}
27 27
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.h b/src/core/hle/service/time/system_clock_context_update_callback.h
index 2b0fa7e75..797954958 100644
--- a/src/core/hle/service/time/system_clock_context_update_callback.h
+++ b/src/core/hle/service/time/system_clock_context_update_callback.h
@@ -9,7 +9,7 @@
9#include "core/hle/service/time/clock_types.h" 9#include "core/hle/service/time/clock_types.h"
10 10
11namespace Kernel { 11namespace Kernel {
12class WritableEvent; 12class KWritableEvent;
13} 13}
14 14
15namespace Service::Time::Clock { 15namespace Service::Time::Clock {
@@ -24,7 +24,7 @@ public:
24 24
25 bool NeedUpdate(const SystemClockContext& value) const; 25 bool NeedUpdate(const SystemClockContext& value) const;
26 26
27 void RegisterOperationEvent(std::shared_ptr<Kernel::WritableEvent>&& writable_event); 27 void RegisterOperationEvent(std::shared_ptr<Kernel::KWritableEvent>&& writable_event);
28 28
29 void BroadcastOperationEvent(); 29 void BroadcastOperationEvent();
30 30
@@ -37,7 +37,7 @@ protected:
37 37
38private: 38private:
39 bool has_context{}; 39 bool has_context{};
40 std::vector<std::shared_ptr<Kernel::WritableEvent>> operation_event_list; 40 std::vector<std::shared_ptr<Kernel::KWritableEvent>> operation_event_list;
41}; 41};
42 42
43} // namespace Service::Time::Clock 43} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 5a202ac81..7f42aa4a0 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -9,7 +9,9 @@
9 9
10#include "common/assert.h" 10#include "common/assert.h"
11#include "core/core.h" 11#include "core/core.h"
12#include "core/hle/kernel/readable_event.h" 12#include "core/hle/kernel/k_event.h"
13#include "core/hle/kernel/k_readable_event.h"
14#include "core/hle/kernel/k_writable_event.h"
13#include "core/hle/service/vi/display/vi_display.h" 15#include "core/hle/service/vi/display/vi_display.h"
14#include "core/hle/service/vi/layer/vi_layer.h" 16#include "core/hle/service/vi/layer/vi_layer.h"
15 17
@@ -17,8 +19,8 @@ namespace Service::VI {
17 19
18Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} { 20Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} {
19 auto& kernel = system.Kernel(); 21 auto& kernel = system.Kernel();
20 vsync_event = 22 vsync_event = Kernel::KEvent::Create(kernel, fmt::format("Display VSync Event {}", id));
21 Kernel::WritableEvent::CreateEventPair(kernel, fmt::format("Display VSync Event {}", id)); 23 vsync_event->Initialize();
22} 24}
23 25
24Display::~Display() = default; 26Display::~Display() = default;
@@ -31,12 +33,12 @@ const Layer& Display::GetLayer(std::size_t index) const {
31 return *layers.at(index); 33 return *layers.at(index);
32} 34}
33 35
34std::shared_ptr<Kernel::ReadableEvent> Display::GetVSyncEvent() const { 36std::shared_ptr<Kernel::KReadableEvent> Display::GetVSyncEvent() const {
35 return vsync_event.readable; 37 return vsync_event->GetReadableEvent();
36} 38}
37 39
38void Display::SignalVSyncEvent() { 40void Display::SignalVSyncEvent() {
39 vsync_event.writable->Signal(); 41 vsync_event->GetWritableEvent()->Signal();
40} 42}
41 43
42void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) { 44void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) {
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index a3855d8cd..931c898f6 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -9,7 +9,10 @@
9#include <vector> 9#include <vector>
10 10
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/hle/kernel/writable_event.h" 12
13namespace Kernel {
14class KEvent;
15}
13 16
14namespace Service::NVFlinger { 17namespace Service::NVFlinger {
15class BufferQueue; 18class BufferQueue;
@@ -58,7 +61,7 @@ public:
58 const Layer& GetLayer(std::size_t index) const; 61 const Layer& GetLayer(std::size_t index) const;
59 62
60 /// Gets the readable vsync event. 63 /// Gets the readable vsync event.
61 std::shared_ptr<Kernel::ReadableEvent> GetVSyncEvent() const; 64 std::shared_ptr<Kernel::KReadableEvent> GetVSyncEvent() const;
62 65
63 /// Signals the internal vsync event. 66 /// Signals the internal vsync event.
64 void SignalVSyncEvent(); 67 void SignalVSyncEvent();
@@ -99,7 +102,7 @@ private:
99 std::string name; 102 std::string name;
100 103
101 std::vector<std::shared_ptr<Layer>> layers; 104 std::vector<std::shared_ptr<Layer>> layers;
102 Kernel::EventPair vsync_event; 105 std::shared_ptr<Kernel::KEvent> vsync_event;
103}; 106};
104 107
105} // namespace Service::VI 108} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index f3de2c428..8661895ae 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -18,9 +18,9 @@
18#include "common/swap.h" 18#include "common/swap.h"
19#include "core/core_timing.h" 19#include "core/core_timing.h"
20#include "core/hle/ipc_helpers.h" 20#include "core/hle/ipc_helpers.h"
21#include "core/hle/kernel/k_readable_event.h"
21#include "core/hle/kernel/k_thread.h" 22#include "core/hle/kernel/k_thread.h"
22#include "core/hle/kernel/readable_event.h" 23#include "core/hle/kernel/k_writable_event.h"
23#include "core/hle/kernel/writable_event.h"
24#include "core/hle/service/nvdrv/nvdata.h" 24#include "core/hle/service/nvdrv/nvdata.h"
25#include "core/hle/service/nvdrv/nvdrv.h" 25#include "core/hle/service/nvdrv/nvdrv.h"
26#include "core/hle/service/nvflinger/buffer_queue.h" 26#include "core/hle/service/nvflinger/buffer_queue.h"
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 39306509a..2ae5196e0 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -70,6 +70,9 @@ void LogSettings() {
70 log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); 70 log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
71 log_setting("Audio_OutputDevice", values.audio_device_id); 71 log_setting("Audio_OutputDevice", values.audio_device_id);
72 log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); 72 log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd);
73 log_setting("DataStorage_CacheDir", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir));
74 log_setting("DataStorage_ConfigDir", Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir));
75 log_setting("DataStorage_LoadDir", Common::FS::GetUserPath(Common::FS::UserPath::LoadDir));
73 log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir)); 76 log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir));
74 log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir)); 77 log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir));
75 log_setting("Debugging_ProgramArgs", values.program_args); 78 log_setting("Debugging_ProgramArgs", values.program_args);
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt
index 73f331d4c..28f2b8614 100644
--- a/src/video_core/host_shaders/CMakeLists.txt
+++ b/src/video_core/host_shaders/CMakeLists.txt
@@ -20,6 +20,7 @@ set(SHADER_FILES
20find_program(GLSLANGVALIDATOR "glslangValidator" REQUIRED) 20find_program(GLSLANGVALIDATOR "glslangValidator" REQUIRED)
21 21
22set(GLSL_FLAGS "") 22set(GLSL_FLAGS "")
23set(QUIET_FLAG "--quiet")
23 24
24set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) 25set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include)
25set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) 26set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders)
@@ -28,6 +29,23 @@ set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE)
28set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) 29set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in)
29set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) 30set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake)
30 31
32# Check if `--quiet` is available on host's glslangValidator version
33# glslangValidator prints to STDERR iff an unrecognized flag is passed to it
34execute_process(
35 COMMAND
36 ${GLSLANGVALIDATOR} ${QUIET_FLAG}
37 ERROR_VARIABLE
38 GLSLANG_ERROR
39 # STDOUT variable defined to silence unnecessary output during CMake configuration
40 OUTPUT_VARIABLE
41 GLSLANG_OUTPUT
42)
43
44if (NOT GLSLANG_ERROR STREQUAL "")
45 message(WARNING "Refusing to use unavailable flag `${QUIET_FLAG}` on `${GLSLANGVALIDATOR}`")
46 set(QUIET_FLAG "")
47endif()
48
31foreach(FILENAME IN ITEMS ${SHADER_FILES}) 49foreach(FILENAME IN ITEMS ${SHADER_FILES})
32 string(REPLACE "." "_" SHADER_NAME ${FILENAME}) 50 string(REPLACE "." "_" SHADER_NAME ${FILENAME})
33 set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}) 51 set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME})
@@ -55,7 +73,7 @@ foreach(FILENAME IN ITEMS ${SHADER_FILES})
55 OUTPUT 73 OUTPUT
56 ${SPIRV_HEADER_FILE} 74 ${SPIRV_HEADER_FILE}
57 COMMAND 75 COMMAND
58 ${GLSLANGVALIDATOR} -V --quiet ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} 76 ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE}
59 MAIN_DEPENDENCY 77 MAIN_DEPENDENCY
60 ${SOURCE_FILE} 78 ${SOURCE_FILE}
61 ) 79 )
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index fbe36046b..b40d7c5e2 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -580,9 +580,7 @@ void ConfigureInputPlayer::ApplyConfiguration() {
580 if (player_index == 0) { 580 if (player_index == 0) {
581 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; 581 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
582 const auto handheld_connected = handheld.connected; 582 const auto handheld_connected = handheld.connected;
583 if (player.controller_type == Settings::ControllerType::Handheld) { 583 handheld = player;
584 handheld = player;
585 }
586 handheld.connected = handheld_connected; 584 handheld.connected = handheld_connected;
587 } 585 }
588} 586}
@@ -596,7 +594,7 @@ void ConfigureInputPlayer::TryConnectSelectedController() {
596 controller_type != Settings::ControllerType::Handheld; 594 controller_type != Settings::ControllerType::Handheld;
597 595
598 // Connect Handheld depending on Player 1's controller configuration. 596 // Connect Handheld depending on Player 1's controller configuration.
599 if (player_index == 0 && controller_type == Settings::ControllerType::Handheld) { 597 if (player_index == 0) {
600 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; 598 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
601 const auto handheld_connected = ui->groupConnectedController->isChecked() && 599 const auto handheld_connected = ui->groupConnectedController->isChecked() &&
602 controller_type == Settings::ControllerType::Handheld; 600 controller_type == Settings::ControllerType::Handheld;
@@ -886,7 +884,7 @@ void ConfigureInputPlayer::SetConnectableControllers() {
886 index_controller_type_pairs.clear(); 884 index_controller_type_pairs.clear();
887 ui->comboControllerType->clear(); 885 ui->comboControllerType->clear();
888 886
889 if (enable_all || npad_style_set.pro_controller == 1) { 887 if (enable_all || npad_style_set.fullkey == 1) {
890 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 888 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
891 Settings::ControllerType::ProController); 889 Settings::ControllerType::ProController);
892 ui->comboControllerType->addItem(tr("Pro Controller")); 890 ui->comboControllerType->addItem(tr("Pro Controller"));
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index d102a43af..51647a028 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -116,8 +116,8 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
116 scene = new QGraphicsScene; 116 scene = new QGraphicsScene;
117 ui->current_user_icon->setScene(scene); 117 ui->current_user_icon->setScene(scene);
118 118
119 SetConfiguration();
120 RetranslateUI(); 119 RetranslateUI();
120 SetConfiguration();
121} 121}
122 122
123ConfigureProfileManager::~ConfigureProfileManager() = default; 123ConfigureProfileManager::~ConfigureProfileManager() = default;
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 0e5156dcc..3bca6277b 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -13,11 +13,11 @@
13#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/core.h" 14#include "core/core.h"
15#include "core/hle/kernel/handle_table.h" 15#include "core/hle/kernel/handle_table.h"
16#include "core/hle/kernel/k_readable_event.h"
16#include "core/hle/kernel/k_scheduler.h" 17#include "core/hle/kernel/k_scheduler.h"
17#include "core/hle/kernel/k_synchronization_object.h" 18#include "core/hle/kernel/k_synchronization_object.h"
18#include "core/hle/kernel/k_thread.h" 19#include "core/hle/kernel/k_thread.h"
19#include "core/hle/kernel/process.h" 20#include "core/hle/kernel/process.h"
20#include "core/hle/kernel/readable_event.h"
21#include "core/hle/kernel/svc_common.h" 21#include "core/hle/kernel/svc_common.h"
22#include "core/hle/kernel/svc_types.h" 22#include "core/hle/kernel/svc_types.h"
23#include "core/memory.h" 23#include "core/memory.h"
@@ -193,7 +193,7 @@ std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::ma
193 const Kernel::KSynchronizationObject& object) { 193 const Kernel::KSynchronizationObject& object) {
194 switch (object.GetHandleType()) { 194 switch (object.GetHandleType()) {
195 case Kernel::HandleType::ReadableEvent: 195 case Kernel::HandleType::ReadableEvent:
196 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); 196 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object));
197 case Kernel::HandleType::Thread: 197 case Kernel::HandleType::Thread:
198 return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object)); 198 return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object));
199 default: 199 default:
@@ -373,7 +373,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
373 return list; 373 return list;
374} 374}
375 375
376WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) 376WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object)
377 : WaitTreeSynchronizationObject(object) {} 377 : WaitTreeSynchronizationObject(object) {}
378WaitTreeEvent::~WaitTreeEvent() = default; 378WaitTreeEvent::~WaitTreeEvent() = default;
379 379
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index b202c5567..3da2fdfd2 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -18,9 +18,9 @@ class EmuThread;
18 18
19namespace Kernel { 19namespace Kernel {
20class HandleTable; 20class HandleTable;
21class KReadableEvent;
21class KSynchronizationObject; 22class KSynchronizationObject;
22class KThread; 23class KThread;
23class ReadableEvent;
24} // namespace Kernel 24} // namespace Kernel
25 25
26class WaitTreeThread; 26class WaitTreeThread;
@@ -142,7 +142,7 @@ public:
142class WaitTreeEvent : public WaitTreeSynchronizationObject { 142class WaitTreeEvent : public WaitTreeSynchronizationObject {
143 Q_OBJECT 143 Q_OBJECT
144public: 144public:
145 explicit WaitTreeEvent(const Kernel::ReadableEvent& object); 145 explicit WaitTreeEvent(const Kernel::KReadableEvent& object);
146 ~WaitTreeEvent() override; 146 ~WaitTreeEvent() override;
147}; 147};
148 148