summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
authorGravatar darkf2014-12-29 19:47:41 -0800
committerGravatar darkf2014-12-29 19:47:41 -0800
commit8ba9ac0f74abb0408a26207a76a0c1808bad8de0 (patch)
treef1c7c3393fa726435b5b90bf335567c93e528ef1 /src/core/hle/svc.cpp
parentAdd comment regarding __WIN32__ in SkyEye code (diff)
parentMerge pull request #367 from bunnei/usat_ssat (diff)
downloadyuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.gz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.xz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.zip
Fix merge conflicts
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp126
1 files changed, 70 insertions, 56 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 87d768856..25944fc68 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 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 <map> 5#include <map>
@@ -12,6 +12,7 @@
12#include "core/hle/kernel/address_arbiter.h" 12#include "core/hle/kernel/address_arbiter.h"
13#include "core/hle/kernel/event.h" 13#include "core/hle/kernel/event.h"
14#include "core/hle/kernel/mutex.h" 14#include "core/hle/kernel/mutex.h"
15#include "core/hle/kernel/semaphore.h"
15#include "core/hle/kernel/shared_memory.h" 16#include "core/hle/kernel/shared_memory.h"
16#include "core/hle/kernel/thread.h" 17#include "core/hle/kernel/thread.h"
17 18
@@ -31,7 +32,7 @@ enum ControlMemoryOperation {
31 32
32/// Map application or GSP heap memory 33/// Map application or GSP heap memory
33static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 34static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
34 DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", 35 LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X",
35 operation, addr0, addr1, size, permissions); 36 operation, addr0, addr1, size, permissions);
36 37
37 switch (operation) { 38 switch (operation) {
@@ -43,19 +44,19 @@ static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1,
43 44
44 // Map GSP heap memory 45 // Map GSP heap memory
45 case MEMORY_OPERATION_GSP_HEAP: 46 case MEMORY_OPERATION_GSP_HEAP:
46 *out_addr = Memory::MapBlock_HeapGSP(size, operation, permissions); 47 *out_addr = Memory::MapBlock_HeapLinear(size, operation, permissions);
47 break; 48 break;
48 49
49 // Unknown ControlMemory operation 50 // Unknown ControlMemory operation
50 default: 51 default:
51 ERROR_LOG(SVC, "unknown operation=0x%08X", operation); 52 LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation);
52 } 53 }
53 return 0; 54 return 0;
54} 55}
55 56
56/// Maps a memory block to specified address 57/// Maps a memory block to specified address
57static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { 58static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
58 DEBUG_LOG(SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 59 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
59 handle, addr, permissions, other_permissions); 60 handle, addr, permissions, other_permissions);
60 61
61 Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); 62 Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions);
@@ -63,12 +64,16 @@ static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other
63 case Kernel::MemoryPermission::Read: 64 case Kernel::MemoryPermission::Read:
64 case Kernel::MemoryPermission::Write: 65 case Kernel::MemoryPermission::Write:
65 case Kernel::MemoryPermission::ReadWrite: 66 case Kernel::MemoryPermission::ReadWrite:
67 case Kernel::MemoryPermission::Execute:
68 case Kernel::MemoryPermission::ReadExecute:
69 case Kernel::MemoryPermission::WriteExecute:
70 case Kernel::MemoryPermission::ReadWriteExecute:
66 case Kernel::MemoryPermission::DontCare: 71 case Kernel::MemoryPermission::DontCare:
67 Kernel::MapSharedMemory(handle, addr, permissions_type, 72 Kernel::MapSharedMemory(handle, addr, permissions_type,
68 static_cast<Kernel::MemoryPermission>(other_permissions)); 73 static_cast<Kernel::MemoryPermission>(other_permissions));
69 break; 74 break;
70 default: 75 default:
71 ERROR_LOG(OSHLE, "unknown permissions=0x%08X", permissions); 76 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
72 } 77 }
73 return 0; 78 return 0;
74} 79}
@@ -77,7 +82,7 @@ static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other
77static Result ConnectToPort(Handle* out, const char* port_name) { 82static Result ConnectToPort(Handle* out, const char* port_name) {
78 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 83 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
79 84
80 DEBUG_LOG(SVC, "called port_name=%s", port_name); 85 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
81 _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); 86 _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!");
82 87
83 *out = service->GetHandle(); 88 *out = service->GetHandle();
@@ -87,17 +92,14 @@ static Result ConnectToPort(Handle* out, const char* port_name) {
87 92
88/// Synchronize to an OS service 93/// Synchronize to an OS service
89static Result SendSyncRequest(Handle handle) { 94static Result SendSyncRequest(Handle handle) {
90 // TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object, 95 Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle);
91 // so we are forced to use GetFast and manually verify the handle. 96 if (session == nullptr) {
92 if (!Kernel::g_object_pool.IsValid(handle)) {
93 return InvalidHandle(ErrorModule::Kernel).raw; 97 return InvalidHandle(ErrorModule::Kernel).raw;
94 } 98 }
95 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
96 99
97 _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); 100 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
98 DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str());
99 101
100 ResultVal<bool> wait = object->SyncRequest(); 102 ResultVal<bool> wait = session->SyncRequest();
101 if (wait.Succeeded() && *wait) { 103 if (wait.Succeeded() && *wait) {
102 Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? 104 Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
103 } 105 }
@@ -108,7 +110,7 @@ static Result SendSyncRequest(Handle handle) {
108/// Close a handle 110/// Close a handle
109static Result CloseHandle(Handle handle) { 111static Result CloseHandle(Handle handle) {
110 // ImplementMe 112 // ImplementMe
111 ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); 113 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
112 return 0; 114 return 0;
113} 115}
114 116
@@ -117,13 +119,11 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
117 // TODO(bunnei): Do something with nano_seconds, currently ignoring this 119 // TODO(bunnei): Do something with nano_seconds, currently ignoring this
118 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated 120 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
119 121
120 if (!Kernel::g_object_pool.IsValid(handle)) { 122 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle);
123 if (object == nullptr)
121 return InvalidHandle(ErrorModule::Kernel).raw; 124 return InvalidHandle(ErrorModule::Kernel).raw;
122 }
123 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
124 _dbg_assert_(KERNEL, object != nullptr);
125 125
126 DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), 126 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(),
127 object->GetName().c_str(), nano_seconds); 127 object->GetName().c_str(), nano_seconds);
128 128
129 ResultVal<bool> wait = object->WaitSynchronization(); 129 ResultVal<bool> wait = object->WaitSynchronization();
@@ -143,17 +143,16 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
143 bool unlock_all = true; 143 bool unlock_all = true;
144 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated 144 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
145 145
146 DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld", 146 LOG_TRACE(Kernel_SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld",
147 handle_count, (wait_all ? "true" : "false"), nano_seconds); 147 handle_count, (wait_all ? "true" : "false"), nano_seconds);
148 148
149 // Iterate through each handle, synchronize kernel object 149 // Iterate through each handle, synchronize kernel object
150 for (s32 i = 0; i < handle_count; i++) { 150 for (s32 i = 0; i < handle_count; i++) {
151 if (!Kernel::g_object_pool.IsValid(handles[i])) { 151 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]);
152 if (object == nullptr)
152 return InvalidHandle(ErrorModule::Kernel).raw; 153 return InvalidHandle(ErrorModule::Kernel).raw;
153 }
154 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]);
155 154
156 DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), 155 LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(),
157 object->GetName().c_str()); 156 object->GetName().c_str());
158 157
159 // TODO(yuriks): Verify how the real function behaves when an error happens here 158 // TODO(yuriks): Verify how the real function behaves when an error happens here
@@ -181,7 +180,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
181 180
182/// Create an address arbiter (to allocate access to shared resources) 181/// Create an address arbiter (to allocate access to shared resources)
183static Result CreateAddressArbiter(u32* arbiter) { 182static Result CreateAddressArbiter(u32* arbiter) {
184 DEBUG_LOG(SVC, "called"); 183 LOG_TRACE(Kernel_SVC, "called");
185 Handle handle = Kernel::CreateAddressArbiter(); 184 Handle handle = Kernel::CreateAddressArbiter();
186 *arbiter = handle; 185 *arbiter = handle;
187 return 0; 186 return 0;
@@ -189,13 +188,15 @@ static Result CreateAddressArbiter(u32* arbiter) {
189 188
190/// Arbitrate address 189/// Arbitrate address
191static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { 190static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) {
191 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter,
192 address, type, value);
192 return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), 193 return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type),
193 address, value).raw; 194 address, value).raw;
194} 195}
195 196
196/// Used to output a message on a debug hardware unit - does nothing on a retail unit 197/// Used to output a message on a debug hardware unit - does nothing on a retail unit
197static void OutputDebugString(const char* string) { 198static void OutputDebugString(const char* string) {
198 OS_LOG(SVC, "%s", string); 199 LOG_DEBUG(Debug_Emulated, "%s", string);
199} 200}
200 201
201/// Get resource limit 202/// Get resource limit
@@ -204,14 +205,14 @@ static Result GetResourceLimit(Handle* resource_limit, Handle process) {
204 // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for 205 // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for
205 // the current KThread. 206 // the current KThread.
206 *resource_limit = 0xDEADBEEF; 207 *resource_limit = 0xDEADBEEF;
207 ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); 208 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process);
208 return 0; 209 return 0;
209} 210}
210 211
211/// Get resource limit current values 212/// Get resource limit current values
212static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, 213static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names,
213 s32 name_count) { 214 s32 name_count) {
214 ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", 215 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d",
215 resource_limit, names, name_count); 216 resource_limit, names, name_count);
216 Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now 217 Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now
217 return 0; 218 return 0;
@@ -232,7 +233,7 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top
232 233
233 Core::g_app_core->SetReg(1, thread); 234 Core::g_app_core->SetReg(1, thread);
234 235
235 DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 236 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
236 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 237 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point,
237 name.c_str(), arg, stack_top, priority, processor_id, thread); 238 name.c_str(), arg, stack_top, priority, processor_id, thread);
238 239
@@ -243,7 +244,7 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top
243static u32 ExitThread() { 244static u32 ExitThread() {
244 Handle thread = Kernel::GetCurrentThreadHandle(); 245 Handle thread = Kernel::GetCurrentThreadHandle();
245 246
246 DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C 247 LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C
247 248
248 Kernel::StopThread(thread, __func__); 249 Kernel::StopThread(thread, __func__);
249 HLE::Reschedule(__func__); 250 HLE::Reschedule(__func__);
@@ -267,70 +268,83 @@ static Result SetThreadPriority(Handle handle, s32 priority) {
267/// Create a mutex 268/// Create a mutex
268static Result CreateMutex(Handle* mutex, u32 initial_locked) { 269static Result CreateMutex(Handle* mutex, u32 initial_locked) {
269 *mutex = Kernel::CreateMutex((initial_locked != 0)); 270 *mutex = Kernel::CreateMutex((initial_locked != 0));
270 DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", 271 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
271 initial_locked ? "true" : "false", *mutex); 272 initial_locked ? "true" : "false", *mutex);
272 return 0; 273 return 0;
273} 274}
274 275
275/// Release a mutex 276/// Release a mutex
276static Result ReleaseMutex(Handle handle) { 277static Result ReleaseMutex(Handle handle) {
277 DEBUG_LOG(SVC, "called handle=0x%08X", handle); 278 LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle);
278 ResultCode res = Kernel::ReleaseMutex(handle); 279 ResultCode res = Kernel::ReleaseMutex(handle);
279 return res.raw; 280 return res.raw;
280} 281}
281 282
282/// Get current thread ID 283/// Get the ID for the specified thread.
283static Result GetThreadId(u32* thread_id, Handle thread) { 284static Result GetThreadId(u32* thread_id, Handle handle) {
284 ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); 285 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle);
285 return 0; 286 ResultCode result = Kernel::GetThreadId(thread_id, handle);
287 return result.raw;
288}
289
290/// Creates a semaphore
291static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) {
292 ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count);
293 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
294 initial_count, max_count, *semaphore);
295 return res.raw;
296}
297
298/// Releases a certain number of slots in a semaphore
299static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) {
300 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore);
301 ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count);
302 return res.raw;
286} 303}
287 304
288/// Query memory 305/// Query memory
289static Result QueryMemory(void* info, void* out, u32 addr) { 306static Result QueryMemory(void* info, void* out, u32 addr) {
290 ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); 307 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr);
291 return 0; 308 return 0;
292} 309}
293 310
294/// Create an event 311/// Create an event
295static Result CreateEvent(Handle* evt, u32 reset_type) { 312static Result CreateEvent(Handle* evt, u32 reset_type) {
296 *evt = Kernel::CreateEvent((ResetType)reset_type); 313 *evt = Kernel::CreateEvent((ResetType)reset_type);
297 DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", 314 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
298 reset_type, *evt); 315 reset_type, *evt);
299 return 0; 316 return 0;
300} 317}
301 318
302/// Duplicates a kernel handle 319/// Duplicates a kernel handle
303static Result DuplicateHandle(Handle* out, Handle handle) { 320static Result DuplicateHandle(Handle* out, Handle handle) {
304 DEBUG_LOG(SVC, "called handle=0x%08X", handle); 321 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle);
305 322 if (out_h.Succeeded()) {
306 // Translate kernel handles -> real handles 323 *out = *out_h;
307 if (handle == Kernel::CurrentThread) { 324 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
308 handle = Kernel::GetCurrentThreadHandle();
309 } 325 }
310 _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), 326 return out_h.Code().raw;
311 "(UNIMPLEMENTED) process handle duplication!");
312
313 // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
314 *out = handle;
315
316 return 0;
317} 327}
318 328
319/// Signals an event 329/// Signals an event
320static Result SignalEvent(Handle evt) { 330static Result SignalEvent(Handle evt) {
321 DEBUG_LOG(SVC, "called event=0x%08X", evt); 331 LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt);
322 return Kernel::SignalEvent(evt).raw; 332 return Kernel::SignalEvent(evt).raw;
323} 333}
324 334
325/// Clears an event 335/// Clears an event
326static Result ClearEvent(Handle evt) { 336static Result ClearEvent(Handle evt) {
327 DEBUG_LOG(SVC, "called event=0x%08X", evt); 337 LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt);
328 return Kernel::ClearEvent(evt).raw; 338 return Kernel::ClearEvent(evt).raw;
329} 339}
330 340
331/// Sleep the current thread 341/// Sleep the current thread
332static void SleepThread(s64 nanoseconds) { 342static void SleepThread(s64 nanoseconds) {
333 DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds); 343 LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds);
344
345 // Sleep current thread and check for next thread to schedule
346 Kernel::WaitCurrentThread(WAITTYPE_SLEEP);
347 HLE::Reschedule(__func__);
334} 348}
335 349
336/// This returns the total CPU ticks elapsed since the CPU was powered-on 350/// This returns the total CPU ticks elapsed since the CPU was powered-on
@@ -360,8 +374,8 @@ const HLE::FunctionDef SVC_Table[] = {
360 {0x12, nullptr, "Run"}, 374 {0x12, nullptr, "Run"},
361 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 375 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
362 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 376 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
363 {0x15, nullptr, "CreateSemaphore"}, 377 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
364 {0x16, nullptr, "ReleaseSemaphore"}, 378 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
365 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 379 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
366 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 380 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
367 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 381 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},