summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp512
1 files changed, 278 insertions, 234 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 5d71d5619..9d0a9c54c 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -10,8 +10,8 @@
10#include "common/string_util.h" 10#include "common/string_util.h"
11#include "common/symbols.h" 11#include "common/symbols.h"
12 12
13#include "core/core_timing.h"
14#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/core_timing.h"
15 15
16#include "core/hle/kernel/address_arbiter.h" 16#include "core/hle/kernel/address_arbiter.h"
17#include "core/hle/kernel/client_port.h" 17#include "core/hle/kernel/client_port.h"
@@ -40,43 +40,46 @@ using Kernel::ERR_INVALID_HANDLE;
40namespace SVC { 40namespace SVC {
41 41
42const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, 42const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
43 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA 43 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
44const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, 44const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
45 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E 45 ErrorSummary::InvalidArgument,
46 46 ErrorLevel::Usage); // 0xE0E0181E
47const ResultCode ERR_MISALIGNED_ADDRESS{ // 0xE0E01BF1 47
48 ErrorDescription::MisalignedAddress, ErrorModule::OS, 48const ResultCode ERR_MISALIGNED_ADDRESS{// 0xE0E01BF1
49 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 49 ErrorDescription::MisalignedAddress, ErrorModule::OS,
50const ResultCode ERR_MISALIGNED_SIZE{ // 0xE0E01BF2 50 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
51 ErrorDescription::MisalignedSize, ErrorModule::OS, 51const ResultCode ERR_MISALIGNED_SIZE{// 0xE0E01BF2
52 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 52 ErrorDescription::MisalignedSize, ErrorModule::OS,
53const ResultCode ERR_INVALID_COMBINATION{ // 0xE0E01BEE 53 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
54 ErrorDescription::InvalidCombination, ErrorModule::OS, 54const ResultCode ERR_INVALID_COMBINATION{// 0xE0E01BEE
55 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 55 ErrorDescription::InvalidCombination, ErrorModule::OS,
56 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
56 57
57enum ControlMemoryOperation { 58enum ControlMemoryOperation {
58 MEMOP_FREE = 1, 59 MEMOP_FREE = 1,
59 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel 60 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel
60 MEMOP_COMMIT = 3, 61 MEMOP_COMMIT = 3,
61 MEMOP_MAP = 4, 62 MEMOP_MAP = 4,
62 MEMOP_UNMAP = 5, 63 MEMOP_UNMAP = 5,
63 MEMOP_PROTECT = 6, 64 MEMOP_PROTECT = 6,
64 MEMOP_OPERATION_MASK = 0xFF, 65 MEMOP_OPERATION_MASK = 0xFF,
65 66
66 MEMOP_REGION_APP = 0x100, 67 MEMOP_REGION_APP = 0x100,
67 MEMOP_REGION_SYSTEM = 0x200, 68 MEMOP_REGION_SYSTEM = 0x200,
68 MEMOP_REGION_BASE = 0x300, 69 MEMOP_REGION_BASE = 0x300,
69 MEMOP_REGION_MASK = 0xF00, 70 MEMOP_REGION_MASK = 0xF00,
70 71
71 MEMOP_LINEAR = 0x10000, 72 MEMOP_LINEAR = 0x10000,
72}; 73};
73 74
74/// Map application or GSP heap memory 75/// Map application or GSP heap memory
75static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 76static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size,
77 u32 permissions) {
76 using namespace Kernel; 78 using namespace Kernel;
77 79
78 LOG_DEBUG(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X", 80 LOG_DEBUG(Kernel_SVC,
79 operation, addr0, addr1, size, permissions); 81 "called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X",
82 operation, addr0, addr1, size, permissions);
80 83
81 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) { 84 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) {
82 return ERR_MISALIGNED_ADDRESS; 85 return ERR_MISALIGNED_ADDRESS;
@@ -89,7 +92,8 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
89 operation &= ~MEMOP_REGION_MASK; 92 operation &= ~MEMOP_REGION_MASK;
90 93
91 if (region != 0) { 94 if (region != 0) {
92 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X", region); 95 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X",
96 region);
93 } 97 }
94 98
95 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) { 99 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) {
@@ -100,15 +104,17 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
100 auto& process = *g_current_process; 104 auto& process = *g_current_process;
101 105
102 switch (operation & MEMOP_OPERATION_MASK) { 106 switch (operation & MEMOP_OPERATION_MASK) {
103 case MEMOP_FREE: 107 case MEMOP_FREE: {
104 { 108 // TODO(Subv): What happens if an application tries to FREE a block of memory that has a
105 // TODO(Subv): What happens if an application tries to FREE a block of memory that has a SharedMemory pointing to it? 109 // SharedMemory pointing to it?
106 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { 110 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) {
107 ResultCode result = process.HeapFree(addr0, size); 111 ResultCode result = process.HeapFree(addr0, size);
108 if (result.IsError()) return result; 112 if (result.IsError())
113 return result;
109 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { 114 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) {
110 ResultCode result = process.LinearFree(addr0, size); 115 ResultCode result = process.LinearFree(addr0, size);
111 if (result.IsError()) return result; 116 if (result.IsError())
117 return result;
112 } else { 118 } else {
113 return ERR_INVALID_ADDRESS; 119 return ERR_INVALID_ADDRESS;
114 } 120 }
@@ -116,8 +122,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
116 break; 122 break;
117 } 123 }
118 124
119 case MEMOP_COMMIT: 125 case MEMOP_COMMIT: {
120 {
121 if (operation & MEMOP_LINEAR) { 126 if (operation & MEMOP_LINEAR) {
122 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions)); 127 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions));
123 } else { 128 } else {
@@ -126,23 +131,26 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
126 break; 131 break;
127 } 132 }
128 133
129 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 134 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
130 { 135 // implemented
131 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions)); 136 {
132 break; 137 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions));
133 } 138 break;
139 }
134 140
135 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 141 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
136 { 142 // implemented
137 ResultCode result = process.HeapFree(addr0, size); 143 {
138 if (result.IsError()) return result; 144 ResultCode result = process.HeapFree(addr0, size);
139 break; 145 if (result.IsError())
140 } 146 return result;
147 break;
148 }
141 149
142 case MEMOP_PROTECT: 150 case MEMOP_PROTECT: {
143 {
144 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions); 151 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions);
145 if (result.IsError()) return result; 152 if (result.IsError())
153 return result;
146 break; 154 break;
147 } 155 }
148 156
@@ -161,8 +169,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
161 using Kernel::SharedMemory; 169 using Kernel::SharedMemory;
162 using Kernel::MemoryPermission; 170 using Kernel::MemoryPermission;
163 171
164 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 172 LOG_TRACE(Kernel_SVC,
165 handle, addr, permissions, other_permissions); 173 "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
174 handle, addr, permissions, other_permissions);
166 175
167 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); 176 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
168 if (shared_memory == nullptr) 177 if (shared_memory == nullptr)
@@ -179,12 +188,13 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
179 case MemoryPermission::ReadWriteExecute: 188 case MemoryPermission::ReadWriteExecute:
180 case MemoryPermission::DontCare: 189 case MemoryPermission::DontCare:
181 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, 190 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type,
182 static_cast<MemoryPermission>(other_permissions)); 191 static_cast<MemoryPermission>(other_permissions));
183 default: 192 default:
184 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 193 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
185 } 194 }
186 195
187 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 196 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
197 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
188} 198}
189 199
190static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { 200static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
@@ -249,7 +259,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
249 return ERR_INVALID_HANDLE; 259 return ERR_INVALID_HANDLE;
250 260
251 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 261 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
252 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 262 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
253 263
254 HLE::Reschedule(__func__); 264 HLE::Reschedule(__func__);
255 265
@@ -257,7 +267,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
257 if (object->ShouldWait()) { 267 if (object->ShouldWait()) {
258 268
259 object->AddWaitingThread(thread); 269 object->AddWaitingThread(thread);
260 Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false); 270 Kernel::WaitCurrentThread_WaitSynchronization({object}, false, false);
261 271
262 // Create an event to wake the thread up after the specified nanosecond delay has passed 272 // Create an event to wake the thread up after the specified nanosecond delay has passed
263 thread->WakeAfterDelay(nano_seconds); 273 thread->WakeAfterDelay(nano_seconds);
@@ -272,7 +282,8 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
272} 282}
273 283
274/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 284/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
275static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { 285static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
286 s64 nano_seconds) {
276 bool wait_thread = !wait_all; 287 bool wait_thread = !wait_all;
277 int handle_index = 0; 288 int handle_index = 0;
278 Kernel::Thread* thread = Kernel::GetCurrentThread(); 289 Kernel::Thread* thread = Kernel::GetCurrentThread();
@@ -281,7 +292,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
281 292
282 // Check if 'handles' is invalid 293 // Check if 'handles' is invalid
283 if (handles == nullptr) 294 if (handles == nullptr)
284 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 295 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel,
296 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
285 297
286 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 298 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
287 // this happens, the running application will crash. 299 // this happens, the running application will crash.
@@ -289,7 +301,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
289 301
290 // Check if 'handle_count' is invalid 302 // Check if 'handle_count' is invalid
291 if (handle_count < 0) 303 if (handle_count < 0)
292 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 304 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS,
305 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
293 306
294 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if 307 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if
295 // necessary 308 // necessary
@@ -329,7 +342,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
329 } 342 }
330 } 343 }
331 344
332 SCOPE_EXIT({HLE::Reschedule("WaitSynchronizationN");}); // Reschedule after putting the threads to sleep. 345 SCOPE_EXIT({
346 HLE::Reschedule("WaitSynchronizationN");
347 }); // Reschedule after putting the threads to sleep.
333 348
334 // If thread should wait, then set its state to waiting 349 // If thread should wait, then set its state to waiting
335 if (wait_thread) { 350 if (wait_thread) {
@@ -386,18 +401,19 @@ static ResultCode CreateAddressArbiter(Handle* out_handle) {
386} 401}
387 402
388/// Arbitrate address 403/// Arbitrate address
389static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { 404static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value,
405 s64 nanoseconds) {
390 using Kernel::AddressArbiter; 406 using Kernel::AddressArbiter;
391 407
392 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, 408 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle,
393 address, type, value); 409 address, type, value);
394 410
395 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle); 411 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle);
396 if (arbiter == nullptr) 412 if (arbiter == nullptr)
397 return ERR_INVALID_HANDLE; 413 return ERR_INVALID_HANDLE;
398 414
399 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), 415 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), address, value,
400 address, value, nanoseconds); 416 nanoseconds);
401 417
402 return res; 418 return res;
403} 419}
@@ -406,10 +422,18 @@ static void Break(u8 break_reason) {
406 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); 422 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
407 std::string reason_str; 423 std::string reason_str;
408 switch (break_reason) { 424 switch (break_reason) {
409 case 0: reason_str = "PANIC"; break; 425 case 0:
410 case 1: reason_str = "ASSERT"; break; 426 reason_str = "PANIC";
411 case 2: reason_str = "USER"; break; 427 break;
412 default: reason_str = "UNKNOWN"; break; 428 case 1:
429 reason_str = "ASSERT";
430 break;
431 case 2:
432 reason_str = "USER";
433 break;
434 default:
435 reason_str = "UNKNOWN";
436 break;
413 } 437 }
414 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str()); 438 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str());
415} 439}
@@ -423,7 +447,8 @@ static void OutputDebugString(const char* string) {
423static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { 447static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
424 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 448 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
425 449
426 SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 450 SharedPtr<Kernel::Process> process =
451 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
427 if (process == nullptr) 452 if (process == nullptr)
428 return ERR_INVALID_HANDLE; 453 return ERR_INVALID_HANDLE;
429 454
@@ -433,12 +458,13 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle
433} 458}
434 459
435/// Get resource limit current values 460/// Get resource limit current values
436static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, 461static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle,
437 u32 name_count) { 462 u32* names, u32 name_count) {
438 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 463 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
439 resource_limit_handle, names, name_count); 464 resource_limit_handle, names, name_count);
440 465
441 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 466 SharedPtr<Kernel::ResourceLimit> resource_limit =
467 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
442 if (resource_limit == nullptr) 468 if (resource_limit == nullptr)
443 return ERR_INVALID_HANDLE; 469 return ERR_INVALID_HANDLE;
444 470
@@ -450,11 +476,12 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim
450 476
451/// Get resource limit max values 477/// Get resource limit max values
452static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, 478static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names,
453 u32 name_count) { 479 u32 name_count) {
454 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 480 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
455 resource_limit_handle, names, name_count); 481 resource_limit_handle, names, name_count);
456 482
457 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 483 SharedPtr<Kernel::ResourceLimit> resource_limit =
484 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
458 if (resource_limit == nullptr) 485 if (resource_limit == nullptr)
459 return ERR_INVALID_HANDLE; 486 return ERR_INVALID_HANDLE;
460 487
@@ -465,7 +492,8 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit
465} 492}
466 493
467/// Creates a new thread 494/// Creates a new thread
468static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { 495static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg,
496 u32 stack_top, s32 processor_id) {
469 using Kernel::Thread; 497 using Kernel::Thread;
470 498
471 std::string name; 499 std::string name;
@@ -499,20 +527,23 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point
499 } 527 }
500 528
501 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL || 529 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL ||
502 (processor_id == THREADPROCESSORID_DEFAULT && Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) { 530 (processor_id == THREADPROCESSORID_DEFAULT &&
503 LOG_WARNING(Kernel_SVC, "Newly created thread is allowed to be run in the SysCore, unimplemented."); 531 Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) {
532 LOG_WARNING(Kernel_SVC,
533 "Newly created thread is allowed to be run in the SysCore, unimplemented.");
504 } 534 }
505 535
506 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( 536 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(name, entry_point, priority,
507 name, entry_point, priority, arg, processor_id, stack_top)); 537 arg, processor_id, stack_top));
508 538
509 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 539 thread->context.fpscr =
540 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000
510 541
511 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); 542 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
512 543
513 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 544 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
514 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 545 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X",
515 name.c_str(), arg, stack_top, priority, processor_id, *out_handle); 546 entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
516 547
517 return RESULT_SUCCESS; 548 return RESULT_SUCCESS;
518} 549}
@@ -552,7 +583,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
552 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 583 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
553 584
554 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 585 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
555 initial_locked ? "true" : "false", *out_handle); 586 initial_locked ? "true" : "false", *out_handle);
556 587
557 return RESULT_SUCCESS; 588 return RESULT_SUCCESS;
558} 589}
@@ -576,7 +607,8 @@ static ResultCode ReleaseMutex(Handle handle) {
576static ResultCode GetProcessId(u32* process_id, Handle process_handle) { 607static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
577 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 608 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
578 609
579 const SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 610 const SharedPtr<Kernel::Process> process =
611 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
580 if (process == nullptr) 612 if (process == nullptr)
581 return ERR_INVALID_HANDLE; 613 return ERR_INVALID_HANDLE;
582 614
@@ -588,7 +620,8 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
588static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { 620static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
589 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); 621 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
590 622
591 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); 623 const SharedPtr<Kernel::Thread> thread =
624 Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle);
592 if (thread == nullptr) 625 if (thread == nullptr)
593 return ERR_INVALID_HANDLE; 626 return ERR_INVALID_HANDLE;
594 627
@@ -620,7 +653,7 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max
620 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); 653 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
621 654
622 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 655 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
623 initial_count, max_count, *out_handle); 656 initial_count, max_count, *out_handle);
624 return RESULT_SUCCESS; 657 return RESULT_SUCCESS;
625} 658}
626 659
@@ -640,7 +673,8 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
640} 673}
641 674
642/// Query process memory 675/// Query process memory
643static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, Handle process_handle, u32 addr) { 676static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
677 Handle process_handle, u32 addr) {
644 using Kernel::Process; 678 using Kernel::Process;
645 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); 679 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
646 if (process == nullptr) 680 if (process == nullptr)
@@ -649,7 +683,8 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf
649 auto vma = process->vm_manager.FindVMA(addr); 683 auto vma = process->vm_manager.FindVMA(addr);
650 684
651 if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) 685 if (vma == Kernel::g_current_process->vm_manager.vma_map.end())
652 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 686 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
687 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
653 688
654 memory_info->base_address = vma->second.base; 689 memory_info->base_address = vma->second.base;
655 memory_info->permission = static_cast<u32>(vma->second.permissions); 690 memory_info->permission = static_cast<u32>(vma->second.permissions);
@@ -673,8 +708,8 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
673 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); 708 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type));
674 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); 709 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
675 710
676 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 711 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
677 reset_type, *out_handle); 712 *out_handle);
678 return RESULT_SUCCESS; 713 return RESULT_SUCCESS;
679} 714}
680 715
@@ -719,8 +754,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
719 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); 754 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type));
720 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); 755 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
721 756
722 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 757 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
723 reset_type, *out_handle); 758 *out_handle);
724 return RESULT_SUCCESS; 759 return RESULT_SUCCESS;
725} 760}
726 761
@@ -783,17 +818,19 @@ static void SleepThread(s64 nanoseconds) {
783static s64 GetSystemTick() { 818static s64 GetSystemTick() {
784 s64 result = CoreTiming::GetTicks(); 819 s64 result = CoreTiming::GetTicks();
785 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. 820 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end.
786 Core::g_app_core->AddTicks(150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b 821 Core::g_app_core->AddTicks(
822 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b
787 return result; 823 return result;
788} 824}
789 825
790/// Creates a memory block at the specified address with the specified permissions and size 826/// Creates a memory block at the specified address with the specified permissions and size
791static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, 827static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
792 u32 other_permission) { 828 u32 other_permission) {
793 using Kernel::SharedMemory; 829 using Kernel::SharedMemory;
794 830
795 if (size % Memory::PAGE_SIZE != 0) 831 if (size % Memory::PAGE_SIZE != 0)
796 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 832 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS,
833 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
797 834
798 SharedPtr<SharedMemory> shared_memory = nullptr; 835 SharedPtr<SharedMemory> shared_memory = nullptr;
799 836
@@ -818,25 +855,29 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
818 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 855 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
819 856
820 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) { 857 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) {
821 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 858 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
859 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
822 } 860 }
823 861
824 // When trying to create a memory block with address = 0, 862 // When trying to create a memory block with address = 0,
825 // if the process has the Shared Device Memory flag in the exheader, 863 // if the process has the Shared Device Memory flag in the exheader,
826 // then we have to allocate from the same region as the caller process instead of the BASE region. 864 // then we have to allocate from the same region as the caller process instead of the BASE
865 // region.
827 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE; 866 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE;
828 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem) 867 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem)
829 region = Kernel::g_current_process->flags.memory_region; 868 region = Kernel::g_current_process->flags.memory_region;
830 869
831 shared_memory = SharedMemory::Create(Kernel::g_current_process, size, 870 shared_memory = SharedMemory::Create(
832 static_cast<MemoryPermission>(my_permission), static_cast<MemoryPermission>(other_permission), addr, region); 871 Kernel::g_current_process, size, static_cast<MemoryPermission>(my_permission),
872 static_cast<MemoryPermission>(other_permission), addr, region);
833 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 873 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
834 874
835 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr); 875 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr);
836 return RESULT_SUCCESS; 876 return RESULT_SUCCESS;
837} 877}
838 878
839static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, u32 max_sessions) { 879static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name,
880 u32 max_sessions) {
840 // TODO(Subv): Implement named ports. 881 // TODO(Subv): Implement named ports.
841 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); 882 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented");
842 883
@@ -845,9 +886,12 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, const cha
845 using Kernel::SharedPtr; 886 using Kernel::SharedPtr;
846 887
847 auto ports = ServerPort::CreatePortPair(max_sessions); 888 auto ports = ServerPort::CreatePortPair(max_sessions);
848 CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); 889 CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(
849 // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be created. 890 std::move(std::get<SharedPtr<ClientPort>>(ports))));
850 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); 891 // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
892 // created.
893 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(
894 std::move(std::get<SharedPtr<ServerPort>>(ports))));
851 895
852 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions); 896 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions);
853 return RESULT_SUCCESS; 897 return RESULT_SUCCESS;
@@ -862,9 +906,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
862 case SystemInfoType::REGION_MEMORY_USAGE: 906 case SystemInfoType::REGION_MEMORY_USAGE:
863 switch ((SystemInfoMemUsageRegion)param) { 907 switch ((SystemInfoMemUsageRegion)param) {
864 case SystemInfoMemUsageRegion::ALL: 908 case SystemInfoMemUsageRegion::ALL:
865 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used 909 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used +
866 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used 910 Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used +
867 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; 911 Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used;
868 break; 912 break;
869 case SystemInfoMemUsageRegion::APPLICATION: 913 case SystemInfoMemUsageRegion::APPLICATION:
870 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used; 914 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used;
@@ -912,7 +956,7 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
912 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure 956 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
913 // what's the difference between them. 957 // what's the difference between them.
914 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; 958 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
915 if(*out % Memory::PAGE_SIZE != 0) { 959 if (*out % Memory::PAGE_SIZE != 0) {
916 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); 960 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned");
917 return ERR_MISALIGNED_SIZE; 961 return ERR_MISALIGNED_SIZE;
918 } 962 }
@@ -935,12 +979,12 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
935 979
936 if (type >= 21 && type <= 23) { 980 if (type >= 21 && type <= 23) {
937 return ResultCode( // 0xE0E01BF4 981 return ResultCode( // 0xE0E01BF4
938 ErrorDescription::NotImplemented, ErrorModule::OS, 982 ErrorDescription::NotImplemented, ErrorModule::OS, ErrorSummary::InvalidArgument,
939 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 983 ErrorLevel::Usage);
940 } else { 984 } else {
941 return ResultCode( // 0xD8E007ED 985 return ResultCode( // 0xD8E007ED
942 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, 986 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
943 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 987 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
944 } 988 }
945 break; 989 break;
946 } 990 }
@@ -949,142 +993,142 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
949} 993}
950 994
951namespace { 995namespace {
952 struct FunctionDef { 996struct FunctionDef {
953 using Func = void(); 997 using Func = void();
954 998
955 u32 id; 999 u32 id;
956 Func* func; 1000 Func* func;
957 const char* name; 1001 const char* name;
958 }; 1002};
959} 1003}
960 1004
961static const FunctionDef SVC_Table[] = { 1005static const FunctionDef SVC_Table[] = {
962 {0x00, nullptr, "Unknown"}, 1006 {0x00, nullptr, "Unknown"},
963 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, 1007 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"},
964 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, 1008 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"},
965 {0x03, nullptr, "ExitProcess"}, 1009 {0x03, nullptr, "ExitProcess"},
966 {0x04, nullptr, "GetProcessAffinityMask"}, 1010 {0x04, nullptr, "GetProcessAffinityMask"},
967 {0x05, nullptr, "SetProcessAffinityMask"}, 1011 {0x05, nullptr, "SetProcessAffinityMask"},
968 {0x06, nullptr, "GetProcessIdealProcessor"}, 1012 {0x06, nullptr, "GetProcessIdealProcessor"},
969 {0x07, nullptr, "SetProcessIdealProcessor"}, 1013 {0x07, nullptr, "SetProcessIdealProcessor"},
970 {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, 1014 {0x08, HLE::Wrap<CreateThread>, "CreateThread"},
971 {0x09, ExitThread, "ExitThread"}, 1015 {0x09, ExitThread, "ExitThread"},
972 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, 1016 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"},
973 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, 1017 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"},
974 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, 1018 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"},
975 {0x0D, nullptr, "GetThreadAffinityMask"}, 1019 {0x0D, nullptr, "GetThreadAffinityMask"},
976 {0x0E, nullptr, "SetThreadAffinityMask"}, 1020 {0x0E, nullptr, "SetThreadAffinityMask"},
977 {0x0F, nullptr, "GetThreadIdealProcessor"}, 1021 {0x0F, nullptr, "GetThreadIdealProcessor"},
978 {0x10, nullptr, "SetThreadIdealProcessor"}, 1022 {0x10, nullptr, "SetThreadIdealProcessor"},
979 {0x11, nullptr, "GetCurrentProcessorNumber"}, 1023 {0x11, nullptr, "GetCurrentProcessorNumber"},
980 {0x12, nullptr, "Run"}, 1024 {0x12, nullptr, "Run"},
981 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 1025 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
982 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 1026 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
983 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, 1027 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
984 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"}, 1028 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
985 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 1029 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
986 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 1030 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
987 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 1031 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},
988 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"}, 1032 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"},
989 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"}, 1033 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"},
990 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"}, 1034 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"},
991 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"}, 1035 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"},
992 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"}, 1036 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"},
993 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, 1037 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"},
994 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"}, 1038 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"},
995 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"}, 1039 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"},
996 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"}, 1040 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"},
997 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"}, 1041 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"},
998 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"}, 1042 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"},
999 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"}, 1043 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"},
1000 {0x26, nullptr, "SignalAndWait"}, 1044 {0x26, nullptr, "SignalAndWait"},
1001 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"}, 1045 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"},
1002 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, 1046 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"},
1003 {0x29, nullptr, "GetHandleInfo"}, 1047 {0x29, nullptr, "GetHandleInfo"},
1004 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"}, 1048 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"},
1005 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"}, 1049 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"},
1006 {0x2C, nullptr, "GetThreadInfo"}, 1050 {0x2C, nullptr, "GetThreadInfo"},
1007 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, 1051 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"},
1008 {0x2E, nullptr, "SendSyncRequest1"}, 1052 {0x2E, nullptr, "SendSyncRequest1"},
1009 {0x2F, nullptr, "SendSyncRequest2"}, 1053 {0x2F, nullptr, "SendSyncRequest2"},
1010 {0x30, nullptr, "SendSyncRequest3"}, 1054 {0x30, nullptr, "SendSyncRequest3"},
1011 {0x31, nullptr, "SendSyncRequest4"}, 1055 {0x31, nullptr, "SendSyncRequest4"},
1012 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, 1056 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"},
1013 {0x33, nullptr, "OpenProcess"}, 1057 {0x33, nullptr, "OpenProcess"},
1014 {0x34, nullptr, "OpenThread"}, 1058 {0x34, nullptr, "OpenThread"},
1015 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"}, 1059 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"},
1016 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, 1060 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"},
1017 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, 1061 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"},
1018 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, 1062 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"},
1019 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, 1063 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"},
1020 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, 1064 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"},
1021 {0x3B, nullptr, "GetThreadContext"}, 1065 {0x3B, nullptr, "GetThreadContext"},
1022 {0x3C, HLE::Wrap<Break>, "Break"}, 1066 {0x3C, HLE::Wrap<Break>, "Break"},
1023 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"}, 1067 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"},
1024 {0x3E, nullptr, "ControlPerformanceCounter"}, 1068 {0x3E, nullptr, "ControlPerformanceCounter"},
1025 {0x3F, nullptr, "Unknown"}, 1069 {0x3F, nullptr, "Unknown"},
1026 {0x40, nullptr, "Unknown"}, 1070 {0x40, nullptr, "Unknown"},
1027 {0x41, nullptr, "Unknown"}, 1071 {0x41, nullptr, "Unknown"},
1028 {0x42, nullptr, "Unknown"}, 1072 {0x42, nullptr, "Unknown"},
1029 {0x43, nullptr, "Unknown"}, 1073 {0x43, nullptr, "Unknown"},
1030 {0x44, nullptr, "Unknown"}, 1074 {0x44, nullptr, "Unknown"},
1031 {0x45, nullptr, "Unknown"}, 1075 {0x45, nullptr, "Unknown"},
1032 {0x46, nullptr, "Unknown"}, 1076 {0x46, nullptr, "Unknown"},
1033 {0x47, HLE::Wrap<CreatePort>, "CreatePort"}, 1077 {0x47, HLE::Wrap<CreatePort>, "CreatePort"},
1034 {0x48, nullptr, "CreateSessionToPort"}, 1078 {0x48, nullptr, "CreateSessionToPort"},
1035 {0x49, nullptr, "CreateSession"}, 1079 {0x49, nullptr, "CreateSession"},
1036 {0x4A, nullptr, "AcceptSession"}, 1080 {0x4A, nullptr, "AcceptSession"},
1037 {0x4B, nullptr, "ReplyAndReceive1"}, 1081 {0x4B, nullptr, "ReplyAndReceive1"},
1038 {0x4C, nullptr, "ReplyAndReceive2"}, 1082 {0x4C, nullptr, "ReplyAndReceive2"},
1039 {0x4D, nullptr, "ReplyAndReceive3"}, 1083 {0x4D, nullptr, "ReplyAndReceive3"},
1040 {0x4E, nullptr, "ReplyAndReceive4"}, 1084 {0x4E, nullptr, "ReplyAndReceive4"},
1041 {0x4F, nullptr, "ReplyAndReceive"}, 1085 {0x4F, nullptr, "ReplyAndReceive"},
1042 {0x50, nullptr, "BindInterrupt"}, 1086 {0x50, nullptr, "BindInterrupt"},
1043 {0x51, nullptr, "UnbindInterrupt"}, 1087 {0x51, nullptr, "UnbindInterrupt"},
1044 {0x52, nullptr, "InvalidateProcessDataCache"}, 1088 {0x52, nullptr, "InvalidateProcessDataCache"},
1045 {0x53, nullptr, "StoreProcessDataCache"}, 1089 {0x53, nullptr, "StoreProcessDataCache"},
1046 {0x54, nullptr, "FlushProcessDataCache"}, 1090 {0x54, nullptr, "FlushProcessDataCache"},
1047 {0x55, nullptr, "StartInterProcessDma"}, 1091 {0x55, nullptr, "StartInterProcessDma"},
1048 {0x56, nullptr, "StopDma"}, 1092 {0x56, nullptr, "StopDma"},
1049 {0x57, nullptr, "GetDmaState"}, 1093 {0x57, nullptr, "GetDmaState"},
1050 {0x58, nullptr, "RestartDma"}, 1094 {0x58, nullptr, "RestartDma"},
1051 {0x59, nullptr, "Unknown"}, 1095 {0x59, nullptr, "Unknown"},
1052 {0x5A, nullptr, "Unknown"}, 1096 {0x5A, nullptr, "Unknown"},
1053 {0x5B, nullptr, "Unknown"}, 1097 {0x5B, nullptr, "Unknown"},
1054 {0x5C, nullptr, "Unknown"}, 1098 {0x5C, nullptr, "Unknown"},
1055 {0x5D, nullptr, "Unknown"}, 1099 {0x5D, nullptr, "Unknown"},
1056 {0x5E, nullptr, "Unknown"}, 1100 {0x5E, nullptr, "Unknown"},
1057 {0x5F, nullptr, "Unknown"}, 1101 {0x5F, nullptr, "Unknown"},
1058 {0x60, nullptr, "DebugActiveProcess"}, 1102 {0x60, nullptr, "DebugActiveProcess"},
1059 {0x61, nullptr, "BreakDebugProcess"}, 1103 {0x61, nullptr, "BreakDebugProcess"},
1060 {0x62, nullptr, "TerminateDebugProcess"}, 1104 {0x62, nullptr, "TerminateDebugProcess"},
1061 {0x63, nullptr, "GetProcessDebugEvent"}, 1105 {0x63, nullptr, "GetProcessDebugEvent"},
1062 {0x64, nullptr, "ContinueDebugEvent"}, 1106 {0x64, nullptr, "ContinueDebugEvent"},
1063 {0x65, nullptr, "GetProcessList"}, 1107 {0x65, nullptr, "GetProcessList"},
1064 {0x66, nullptr, "GetThreadList"}, 1108 {0x66, nullptr, "GetThreadList"},
1065 {0x67, nullptr, "GetDebugThreadContext"}, 1109 {0x67, nullptr, "GetDebugThreadContext"},
1066 {0x68, nullptr, "SetDebugThreadContext"}, 1110 {0x68, nullptr, "SetDebugThreadContext"},
1067 {0x69, nullptr, "QueryDebugProcessMemory"}, 1111 {0x69, nullptr, "QueryDebugProcessMemory"},
1068 {0x6A, nullptr, "ReadProcessMemory"}, 1112 {0x6A, nullptr, "ReadProcessMemory"},
1069 {0x6B, nullptr, "WriteProcessMemory"}, 1113 {0x6B, nullptr, "WriteProcessMemory"},
1070 {0x6C, nullptr, "SetHardwareBreakPoint"}, 1114 {0x6C, nullptr, "SetHardwareBreakPoint"},
1071 {0x6D, nullptr, "GetDebugThreadParam"}, 1115 {0x6D, nullptr, "GetDebugThreadParam"},
1072 {0x6E, nullptr, "Unknown"}, 1116 {0x6E, nullptr, "Unknown"},
1073 {0x6F, nullptr, "Unknown"}, 1117 {0x6F, nullptr, "Unknown"},
1074 {0x70, nullptr, "ControlProcessMemory"}, 1118 {0x70, nullptr, "ControlProcessMemory"},
1075 {0x71, nullptr, "MapProcessMemory"}, 1119 {0x71, nullptr, "MapProcessMemory"},
1076 {0x72, nullptr, "UnmapProcessMemory"}, 1120 {0x72, nullptr, "UnmapProcessMemory"},
1077 {0x73, nullptr, "CreateCodeSet"}, 1121 {0x73, nullptr, "CreateCodeSet"},
1078 {0x74, nullptr, "RandomStub"}, 1122 {0x74, nullptr, "RandomStub"},
1079 {0x75, nullptr, "CreateProcess"}, 1123 {0x75, nullptr, "CreateProcess"},
1080 {0x76, nullptr, "TerminateProcess"}, 1124 {0x76, nullptr, "TerminateProcess"},
1081 {0x77, nullptr, "SetProcessResourceLimits"}, 1125 {0x77, nullptr, "SetProcessResourceLimits"},
1082 {0x78, nullptr, "CreateResourceLimit"}, 1126 {0x78, nullptr, "CreateResourceLimit"},
1083 {0x79, nullptr, "SetResourceLimitValues"}, 1127 {0x79, nullptr, "SetResourceLimitValues"},
1084 {0x7A, nullptr, "AddCodeSegment"}, 1128 {0x7A, nullptr, "AddCodeSegment"},
1085 {0x7B, nullptr, "Backdoor"}, 1129 {0x7B, nullptr, "Backdoor"},
1086 {0x7C, nullptr, "KernelSetState"}, 1130 {0x7C, nullptr, "KernelSetState"},
1087 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"}, 1131 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"},
1088}; 1132};
1089 1133
1090static const FunctionDef* GetSVCInfo(u32 func_num) { 1134static const FunctionDef* GetSVCInfo(u32 func_num) {