diff options
Diffstat (limited to 'src/core/hle/svc.cpp')
| -rw-r--r-- | src/core/hle/svc.cpp | 487 |
1 files changed, 296 insertions, 191 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 90c05cb74..441d8ce8d 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include "core/mem_map.h" | 10 | #include "core/mem_map.h" |
| 11 | 11 | ||
| 12 | #include "core/hle/kernel/event.h" | ||
| 12 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/kernel/mutex.h" | 14 | #include "core/hle/kernel/mutex.h" |
| 14 | #include "core/hle/kernel/thread.h" | 15 | #include "core/hle/kernel/thread.h" |
| @@ -16,7 +17,6 @@ | |||
| 16 | #include "core/hle/function_wrappers.h" | 17 | #include "core/hle/function_wrappers.h" |
| 17 | #include "core/hle/svc.h" | 18 | #include "core/hle/svc.h" |
| 18 | #include "core/hle/service/service.h" | 19 | #include "core/hle/service/service.h" |
| 19 | #include "core/hle/kernel/thread.h" | ||
| 20 | 20 | ||
| 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 22 | // Namespace SVC | 22 | // Namespace SVC |
| @@ -34,40 +34,32 @@ enum MapMemoryPermission { | |||
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | /// Map application or GSP heap memory | 36 | /// Map application or GSP heap memory |
| 37 | Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { | 37 | Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { |
| 38 | u32* outaddr = (u32*)_outaddr; | 38 | DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", |
| 39 | u32 virtual_address = 0x00000000; | ||
| 40 | |||
| 41 | DEBUG_LOG(SVC, "ControlMemory called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", | ||
| 42 | operation, addr0, addr1, size, permissions); | 39 | operation, addr0, addr1, size, permissions); |
| 43 | 40 | ||
| 44 | switch (operation) { | 41 | switch (operation) { |
| 45 | 42 | ||
| 46 | // Map normal heap memory | 43 | // Map normal heap memory |
| 47 | case MEMORY_OPERATION_HEAP: | 44 | case MEMORY_OPERATION_HEAP: |
| 48 | virtual_address = Memory::MapBlock_Heap(size, operation, permissions); | 45 | *out_addr = Memory::MapBlock_Heap(size, operation, permissions); |
| 49 | break; | 46 | break; |
| 50 | 47 | ||
| 51 | // Map GSP heap memory | 48 | // Map GSP heap memory |
| 52 | case MEMORY_OPERATION_GSP_HEAP: | 49 | case MEMORY_OPERATION_GSP_HEAP: |
| 53 | virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions); | 50 | *out_addr = Memory::MapBlock_HeapGSP(size, operation, permissions); |
| 54 | break; | 51 | break; |
| 55 | 52 | ||
| 56 | // Unknown ControlMemory operation | 53 | // Unknown ControlMemory operation |
| 57 | default: | 54 | default: |
| 58 | ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation); | 55 | ERROR_LOG(SVC, "unknown operation=0x%08X", operation); |
| 59 | } | 56 | } |
| 60 | if (NULL != outaddr) { | ||
| 61 | *outaddr = virtual_address; | ||
| 62 | } | ||
| 63 | Core::g_app_core->SetReg(1, virtual_address); | ||
| 64 | |||
| 65 | return 0; | 57 | return 0; |
| 66 | } | 58 | } |
| 67 | 59 | ||
| 68 | /// Maps a memory block to specified address | 60 | /// Maps a memory block to specified address |
| 69 | Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) { | 61 | Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) { |
| 70 | DEBUG_LOG(SVC, "MapMemoryBlock called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", | 62 | DEBUG_LOG(SVC, "called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", |
| 71 | memblock, addr, mypermissions, otherpermission); | 63 | memblock, addr, mypermissions, otherpermission); |
| 72 | switch (mypermissions) { | 64 | switch (mypermissions) { |
| 73 | case MEMORY_PERMISSION_NORMAL: | 65 | case MEMORY_PERMISSION_NORMAL: |
| @@ -76,88 +68,146 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper | |||
| 76 | Memory::MapBlock_Shared(memblock, addr, mypermissions); | 68 | Memory::MapBlock_Shared(memblock, addr, mypermissions); |
| 77 | break; | 69 | break; |
| 78 | default: | 70 | default: |
| 79 | ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions); | 71 | ERROR_LOG(OSHLE, "unknown permissions=0x%08X", mypermissions); |
| 80 | } | 72 | } |
| 81 | return 0; | 73 | return 0; |
| 82 | } | 74 | } |
| 83 | 75 | ||
| 84 | /// Connect to an OS service given the port name, returns the handle to the port to out | 76 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 85 | Result ConnectToPort(void* out, const char* port_name) { | 77 | Result ConnectToPort(Handle* out, const char* port_name) { |
| 86 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | 78 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); |
| 87 | if (service) { | 79 | |
| 88 | Core::g_app_core->SetReg(1, service->GetHandle()); | 80 | DEBUG_LOG(SVC, "called port_name=%s", port_name); |
| 89 | } else { | 81 | _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); |
| 90 | PanicYesNo("ConnectToPort called port_name=%s, but it is not implemented!", port_name); | 82 | |
| 91 | } | 83 | *out = service->GetHandle(); |
| 92 | DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); | 84 | |
| 93 | return 0; | 85 | return 0; |
| 94 | } | 86 | } |
| 95 | 87 | ||
| 96 | /// Synchronize to an OS service | 88 | /// Synchronize to an OS service |
| 97 | Result SendSyncRequest(Handle handle) { | 89 | Result SendSyncRequest(Handle handle) { |
| 98 | DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X"); | 90 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); |
| 99 | Service::Interface* service = Service::g_manager->FetchFromHandle(handle); | 91 | |
| 100 | service->Sync(); | 92 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); |
| 101 | return 0; | 93 | DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName()); |
| 94 | |||
| 95 | bool wait = false; | ||
| 96 | Result res = object->SyncRequest(&wait); | ||
| 97 | if (wait) { | ||
| 98 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? | ||
| 99 | } | ||
| 100 | |||
| 101 | return res; | ||
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | /// Close a handle | 104 | /// Close a handle |
| 105 | Result CloseHandle(Handle handle) { | 105 | Result CloseHandle(Handle handle) { |
| 106 | // ImplementMe | 106 | // ImplementMe |
| 107 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); | 107 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); |
| 108 | return 0; | 108 | return 0; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds | 111 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds |
| 112 | Result WaitSynchronization1(Handle handle, s64 nano_seconds) { | 112 | Result WaitSynchronization1(Handle handle, s64 nano_seconds) { |
| 113 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", | 113 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this |
| 114 | handle, nano_seconds); | 114 | bool wait = false; |
| 115 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? | 115 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated |
| 116 | return 0; | 116 | |
| 117 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | ||
| 118 | |||
| 119 | DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%d", handle, object->GetTypeName(), | ||
| 120 | object->GetName(), nano_seconds); | ||
| 121 | |||
| 122 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); | ||
| 123 | |||
| 124 | Result res = object->WaitSynchronization(&wait); | ||
| 125 | |||
| 126 | // Check for next thread to schedule | ||
| 127 | if (wait) { | ||
| 128 | HLE::Reschedule(__func__); | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | return res; | ||
| 117 | } | 133 | } |
| 118 | 134 | ||
| 119 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 135 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 120 | Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wait_all, s64 nano_seconds) { | 136 | Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, |
| 121 | s32* out = (s32*)_out; | 137 | s64 nano_seconds) { |
| 122 | Handle* handles = (Handle*)_handles; | 138 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this |
| 139 | bool unlock_all = true; | ||
| 140 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated | ||
| 123 | 141 | ||
| 124 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronizationN called handle_count=%d, wait_all=%s, nanoseconds=%d %s", | 142 | DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%d", |
| 125 | handle_count, (wait_all ? "true" : "false"), nano_seconds); | 143 | handle_count, (wait_all ? "true" : "false"), nano_seconds); |
| 126 | 144 | ||
| 127 | for (u32 i = 0; i < handle_count; i++) { | 145 | // Iterate through each handle, synchronize kernel object |
| 128 | DEBUG_LOG(SVC, "\thandle[%d]=0x%08X", i, handles[i]); | 146 | for (s32 i = 0; i < handle_count; i++) { |
| 147 | bool wait = false; | ||
| 148 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]); | ||
| 149 | |||
| 150 | _assert_msg_(KERNEL, (object != nullptr), "called handle=0x%08X, but kernel object " | ||
| 151 | "is nullptr!", handles[i]); | ||
| 152 | |||
| 153 | DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName(), | ||
| 154 | object->GetName()); | ||
| 155 | |||
| 156 | Result res = object->WaitSynchronization(&wait); | ||
| 157 | |||
| 158 | if (!wait && !wait_all) { | ||
| 159 | *out = i; | ||
| 160 | return 0; | ||
| 161 | } else { | ||
| 162 | unlock_all = false; | ||
| 163 | } | ||
| 129 | } | 164 | } |
| 130 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? | 165 | |
| 166 | if (wait_all && unlock_all) { | ||
| 167 | *out = handle_count; | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | // Check for next thread to schedule | ||
| 172 | HLE::Reschedule(__func__); | ||
| 173 | |||
| 131 | return 0; | 174 | return 0; |
| 132 | } | 175 | } |
| 133 | 176 | ||
| 134 | /// Create an address arbiter (to allocate access to shared resources) | 177 | /// Create an address arbiter (to allocate access to shared resources) |
| 135 | Result CreateAddressArbiter(void* arbiter) { | 178 | Result CreateAddressArbiter(void* arbiter) { |
| 136 | // ImplementMe | 179 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called"); |
| 137 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called"); | ||
| 138 | Core::g_app_core->SetReg(1, 0xFABBDADD); | 180 | Core::g_app_core->SetReg(1, 0xFABBDADD); |
| 139 | return 0; | 181 | return 0; |
| 140 | } | 182 | } |
| 141 | 183 | ||
| 184 | /// Arbitrate address | ||
| 185 | Result ArbitrateAddress(Handle arbiter, u32 addr, u32 _type, u32 value, s64 nanoseconds) { | ||
| 186 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called"); | ||
| 187 | ArbitrationType type = (ArbitrationType)_type; | ||
| 188 | Memory::Write32(addr, type); | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 142 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 192 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| 143 | void OutputDebugString(const char* string) { | 193 | void OutputDebugString(const char* string) { |
| 144 | NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string); | 194 | OS_LOG(SVC, "%s", string); |
| 145 | } | 195 | } |
| 146 | 196 | ||
| 147 | /// Get resource limit | 197 | /// Get resource limit |
| 148 | Result GetResourceLimit(void* resource_limit, Handle process) { | 198 | Result GetResourceLimit(Handle* resource_limit, Handle process) { |
| 149 | // With regards to proceess values: | 199 | // With regards to proceess values: |
| 150 | // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for | 200 | // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for |
| 151 | // the current KThread. | 201 | // the current KThread. |
| 152 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process); | 202 | *resource_limit = 0xDEADBEEF; |
| 153 | Core::g_app_core->SetReg(1, 0xDEADBEEF); | 203 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); |
| 154 | return 0; | 204 | return 0; |
| 155 | } | 205 | } |
| 156 | 206 | ||
| 157 | /// Get resource limit current values | 207 | /// Get resource limit current values |
| 158 | Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) { | 208 | Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, |
| 159 | //s64* values = (s64*)_values; | 209 | s32 name_count) { |
| 160 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d", | 210 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", |
| 161 | resource_limit, names, name_count); | 211 | resource_limit, names, name_count); |
| 162 | Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now | 212 | Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now |
| 163 | return 0; | 213 | return 0; |
| @@ -180,179 +230,234 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p | |||
| 180 | 230 | ||
| 181 | Core::g_app_core->SetReg(1, thread); | 231 | Core::g_app_core->SetReg(1, thread); |
| 182 | 232 | ||
| 183 | DEBUG_LOG(SVC, "CreateThread called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | 233 | DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " |
| 184 | "threadpriority=0x%08X, processorid=0x%08X : created handle 0x%08X", entry_point, | 234 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, |
| 185 | name.c_str(), arg, stack_top, priority, processor_id, thread); | 235 | name.c_str(), arg, stack_top, priority, processor_id, thread); |
| 186 | 236 | ||
| 187 | return 0; | 237 | return 0; |
| 188 | } | 238 | } |
| 189 | 239 | ||
| 240 | /// Called when a thread exits | ||
| 241 | u32 ExitThread() { | ||
| 242 | Handle thread = Kernel::GetCurrentThreadHandle(); | ||
| 243 | |||
| 244 | DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C | ||
| 245 | |||
| 246 | Kernel::StopThread(thread, __func__); | ||
| 247 | HLE::Reschedule(__func__); | ||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | |||
| 251 | /// Gets the priority for the specified thread | ||
| 252 | Result GetThreadPriority(s32* priority, Handle handle) { | ||
| 253 | *priority = Kernel::GetThreadPriority(handle); | ||
| 254 | return 0; | ||
| 255 | } | ||
| 256 | |||
| 257 | /// Sets the priority for the specified thread | ||
| 258 | Result SetThreadPriority(Handle handle, s32 priority) { | ||
| 259 | return Kernel::SetThreadPriority(handle, priority); | ||
| 260 | } | ||
| 261 | |||
| 190 | /// Create a mutex | 262 | /// Create a mutex |
| 191 | Result CreateMutex(void* _mutex, u32 initial_locked) { | 263 | Result CreateMutex(Handle* mutex, u32 initial_locked) { |
| 192 | Handle* mutex = (Handle*)_mutex; | ||
| 193 | *mutex = Kernel::CreateMutex((initial_locked != 0)); | 264 | *mutex = Kernel::CreateMutex((initial_locked != 0)); |
| 194 | Core::g_app_core->SetReg(1, *mutex); | 265 | DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", |
| 195 | DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s : created handle 0x%08X", | ||
| 196 | initial_locked ? "true" : "false", *mutex); | 266 | initial_locked ? "true" : "false", *mutex); |
| 197 | return 0; | 267 | return 0; |
| 198 | } | 268 | } |
| 199 | 269 | ||
| 200 | /// Release a mutex | 270 | /// Release a mutex |
| 201 | Result ReleaseMutex(Handle handle) { | 271 | Result ReleaseMutex(Handle handle) { |
| 202 | DEBUG_LOG(SVC, "ReleaseMutex called handle=0x%08X", handle); | 272 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); |
| 273 | _assert_msg_(KERNEL, (handle != 0), "called, but handle is nullptr!"); | ||
| 203 | Kernel::ReleaseMutex(handle); | 274 | Kernel::ReleaseMutex(handle); |
| 204 | return 0; | 275 | return 0; |
| 205 | } | 276 | } |
| 206 | 277 | ||
| 207 | /// Get current thread ID | 278 | /// Get current thread ID |
| 208 | Result GetThreadId(void* thread_id, u32 thread) { | 279 | Result GetThreadId(u32* thread_id, Handle thread) { |
| 209 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetThreadId called thread=0x%08X", thread); | 280 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); |
| 210 | return 0; | 281 | return 0; |
| 211 | } | 282 | } |
| 212 | 283 | ||
| 213 | /// Query memory | 284 | /// Query memory |
| 214 | Result QueryMemory(void *_info, void *_out, u32 addr) { | 285 | Result QueryMemory(void* info, void* out, u32 addr) { |
| 215 | MemoryInfo* info = (MemoryInfo*) _info; | 286 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); |
| 216 | PageInfo* out = (PageInfo*) _out; | ||
| 217 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) QueryMemory called addr=0x%08X", addr); | ||
| 218 | return 0; | 287 | return 0; |
| 219 | } | 288 | } |
| 220 | 289 | ||
| 221 | /// Create an event | 290 | /// Create an event |
| 222 | Result CreateEvent(void* _event, u32 reset_type) { | 291 | Result CreateEvent(Handle* evt, u32 reset_type) { |
| 223 | Handle* event = (Handle*)_event; | 292 | *evt = Kernel::CreateEvent((ResetType)reset_type); |
| 224 | DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateEvent called reset_type=0x%08X", reset_type); | 293 | DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", |
| 225 | Core::g_app_core->SetReg(1, 0xBADC0DE0); | 294 | reset_type, *evt); |
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | /// Duplicates a kernel handle | ||
| 299 | Result DuplicateHandle(Handle* out, Handle handle) { | ||
| 300 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); | ||
| 301 | |||
| 302 | // Translate kernel handles -> real handles | ||
| 303 | if (handle == Kernel::CurrentThread) { | ||
| 304 | handle = Kernel::GetCurrentThreadHandle(); | ||
| 305 | } | ||
| 306 | _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), | ||
| 307 | "(UNIMPLEMENTED) process handle duplication!"); | ||
| 308 | |||
| 309 | // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate. | ||
| 310 | *out = handle; | ||
| 311 | |||
| 226 | return 0; | 312 | return 0; |
| 227 | } | 313 | } |
| 228 | 314 | ||
| 315 | /// Signals an event | ||
| 316 | Result SignalEvent(Handle evt) { | ||
| 317 | Result res = Kernel::SignalEvent(evt); | ||
| 318 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | ||
| 319 | return res; | ||
| 320 | } | ||
| 321 | |||
| 322 | /// Clears an event | ||
| 323 | Result ClearEvent(Handle evt) { | ||
| 324 | Result res = Kernel::ClearEvent(evt); | ||
| 325 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | ||
| 326 | return res; | ||
| 327 | } | ||
| 328 | |||
| 329 | /// Sleep the current thread | ||
| 330 | void SleepThread(s64 nanoseconds) { | ||
| 331 | DEBUG_LOG(SVC, "called nanoseconds=%d", nanoseconds); | ||
| 332 | } | ||
| 333 | |||
| 229 | const HLE::FunctionDef SVC_Table[] = { | 334 | const HLE::FunctionDef SVC_Table[] = { |
| 230 | {0x00, NULL, "Unknown"}, | 335 | {0x00, nullptr, "Unknown"}, |
| 231 | {0x01, WrapI_VUUUUU<ControlMemory>, "ControlMemory"}, | 336 | {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, |
| 232 | {0x02, WrapI_VVU<QueryMemory>, "QueryMemory"}, | 337 | {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, |
| 233 | {0x03, NULL, "ExitProcess"}, | 338 | {0x03, nullptr, "ExitProcess"}, |
| 234 | {0x04, NULL, "GetProcessAffinityMask"}, | 339 | {0x04, nullptr, "GetProcessAffinityMask"}, |
| 235 | {0x05, NULL, "SetProcessAffinityMask"}, | 340 | {0x05, nullptr, "SetProcessAffinityMask"}, |
| 236 | {0x06, NULL, "GetProcessIdealProcessor"}, | 341 | {0x06, nullptr, "GetProcessIdealProcessor"}, |
| 237 | {0x07, NULL, "SetProcessIdealProcessor"}, | 342 | {0x07, nullptr, "SetProcessIdealProcessor"}, |
| 238 | {0x08, WrapI_UUUUU<CreateThread>, "CreateThread"}, | 343 | {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, |
| 239 | {0x09, NULL, "ExitThread"}, | 344 | {0x09, HLE::Wrap<ExitThread>, "ExitThread"}, |
| 240 | {0x0A, NULL, "SleepThread"}, | 345 | {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, |
| 241 | {0x0B, NULL, "GetThreadPriority"}, | 346 | {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, |
| 242 | {0x0C, NULL, "SetThreadPriority"}, | 347 | {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, |
| 243 | {0x0D, NULL, "GetThreadAffinityMask"}, | 348 | {0x0D, nullptr, "GetThreadAffinityMask"}, |
| 244 | {0x0E, NULL, "SetThreadAffinityMask"}, | 349 | {0x0E, nullptr, "SetThreadAffinityMask"}, |
| 245 | {0x0F, NULL, "GetThreadIdealProcessor"}, | 350 | {0x0F, nullptr, "GetThreadIdealProcessor"}, |
| 246 | {0x10, NULL, "SetThreadIdealProcessor"}, | 351 | {0x10, nullptr, "SetThreadIdealProcessor"}, |
| 247 | {0x11, NULL, "GetCurrentProcessorNumber"}, | 352 | {0x11, nullptr, "GetCurrentProcessorNumber"}, |
| 248 | {0x12, NULL, "Run"}, | 353 | {0x12, nullptr, "Run"}, |
| 249 | {0x13, WrapI_VU<CreateMutex>, "CreateMutex"}, | 354 | {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, |
| 250 | {0x14, WrapI_U<ReleaseMutex>, "ReleaseMutex"}, | 355 | {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, |
| 251 | {0x15, NULL, "CreateSemaphore"}, | 356 | {0x15, nullptr, "CreateSemaphore"}, |
| 252 | {0x16, NULL, "ReleaseSemaphore"}, | 357 | {0x16, nullptr, "ReleaseSemaphore"}, |
| 253 | {0x17, WrapI_VU<CreateEvent>, "CreateEvent"}, | 358 | {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, |
| 254 | {0x18, NULL, "SignalEvent"}, | 359 | {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, |
| 255 | {0x19, NULL, "ClearEvent"}, | 360 | {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, |
| 256 | {0x1A, NULL, "CreateTimer"}, | 361 | {0x1A, nullptr, "CreateTimer"}, |
| 257 | {0x1B, NULL, "SetTimer"}, | 362 | {0x1B, nullptr, "SetTimer"}, |
| 258 | {0x1C, NULL, "CancelTimer"}, | 363 | {0x1C, nullptr, "CancelTimer"}, |
| 259 | {0x1D, NULL, "ClearTimer"}, | 364 | {0x1D, nullptr, "ClearTimer"}, |
| 260 | {0x1E, NULL, "CreateMemoryBlock"}, | 365 | {0x1E, nullptr, "CreateMemoryBlock"}, |
| 261 | {0x1F, WrapI_UUUU<MapMemoryBlock>, "MapMemoryBlock"}, | 366 | {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, |
| 262 | {0x20, NULL, "UnmapMemoryBlock"}, | 367 | {0x20, nullptr, "UnmapMemoryBlock"}, |
| 263 | {0x21, WrapI_V<CreateAddressArbiter>, "CreateAddressArbiter"}, | 368 | {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"}, |
| 264 | {0x22, NULL, "ArbitrateAddress"}, | 369 | {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"}, |
| 265 | {0x23, WrapI_U<CloseHandle>, "CloseHandle"}, | 370 | {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"}, |
| 266 | {0x24, WrapI_US64<WaitSynchronization1>, "WaitSynchronization1"}, | 371 | {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"}, |
| 267 | {0x25, WrapI_VVUUS64<WaitSynchronizationN>, "WaitSynchronizationN"}, | 372 | {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"}, |
| 268 | {0x26, NULL, "SignalAndWait"}, | 373 | {0x26, nullptr, "SignalAndWait"}, |
| 269 | {0x27, NULL, "DuplicateHandle"}, | 374 | {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"}, |
| 270 | {0x28, NULL, "GetSystemTick"}, | 375 | {0x28, nullptr, "GetSystemTick"}, |
| 271 | {0x29, NULL, "GetHandleInfo"}, | 376 | {0x29, nullptr, "GetHandleInfo"}, |
| 272 | {0x2A, NULL, "GetSystemInfo"}, | 377 | {0x2A, nullptr, "GetSystemInfo"}, |
| 273 | {0x2B, NULL, "GetProcessInfo"}, | 378 | {0x2B, nullptr, "GetProcessInfo"}, |
| 274 | {0x2C, NULL, "GetThreadInfo"}, | 379 | {0x2C, nullptr, "GetThreadInfo"}, |
| 275 | {0x2D, WrapI_VC<ConnectToPort>, "ConnectToPort"}, | 380 | {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, |
| 276 | {0x2E, NULL, "SendSyncRequest1"}, | 381 | {0x2E, nullptr, "SendSyncRequest1"}, |
| 277 | {0x2F, NULL, "SendSyncRequest2"}, | 382 | {0x2F, nullptr, "SendSyncRequest2"}, |
| 278 | {0x30, NULL, "SendSyncRequest3"}, | 383 | {0x30, nullptr, "SendSyncRequest3"}, |
| 279 | {0x31, NULL, "SendSyncRequest4"}, | 384 | {0x31, nullptr, "SendSyncRequest4"}, |
| 280 | {0x32, WrapI_U<SendSyncRequest>, "SendSyncRequest"}, | 385 | {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, |
| 281 | {0x33, NULL, "OpenProcess"}, | 386 | {0x33, nullptr, "OpenProcess"}, |
| 282 | {0x34, NULL, "OpenThread"}, | 387 | {0x34, nullptr, "OpenThread"}, |
| 283 | {0x35, NULL, "GetProcessId"}, | 388 | {0x35, nullptr, "GetProcessId"}, |
| 284 | {0x36, NULL, "GetProcessIdOfThread"}, | 389 | {0x36, nullptr, "GetProcessIdOfThread"}, |
| 285 | {0x37, WrapI_VU<GetThreadId>, "GetThreadId"}, | 390 | {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, |
| 286 | {0x38, WrapI_VU<GetResourceLimit>, "GetResourceLimit"}, | 391 | {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, |
| 287 | {0x39, NULL, "GetResourceLimitLimitValues"}, | 392 | {0x39, nullptr, "GetResourceLimitLimitValues"}, |
| 288 | {0x3A, WrapI_VUVI<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, | 393 | {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, |
| 289 | {0x3B, NULL, "GetThreadContext"}, | 394 | {0x3B, nullptr, "GetThreadContext"}, |
| 290 | {0x3C, NULL, "Break"}, | 395 | {0x3C, nullptr, "Break"}, |
| 291 | {0x3D, WrapV_C<OutputDebugString>, "OutputDebugString"}, | 396 | {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"}, |
| 292 | {0x3E, NULL, "ControlPerformanceCounter"}, | 397 | {0x3E, nullptr, "ControlPerformanceCounter"}, |
| 293 | {0x3F, NULL, "Unknown"}, | 398 | {0x3F, nullptr, "Unknown"}, |
| 294 | {0x40, NULL, "Unknown"}, | 399 | {0x40, nullptr, "Unknown"}, |
| 295 | {0x41, NULL, "Unknown"}, | 400 | {0x41, nullptr, "Unknown"}, |
| 296 | {0x42, NULL, "Unknown"}, | 401 | {0x42, nullptr, "Unknown"}, |
| 297 | {0x43, NULL, "Unknown"}, | 402 | {0x43, nullptr, "Unknown"}, |
| 298 | {0x44, NULL, "Unknown"}, | 403 | {0x44, nullptr, "Unknown"}, |
| 299 | {0x45, NULL, "Unknown"}, | 404 | {0x45, nullptr, "Unknown"}, |
| 300 | {0x46, NULL, "Unknown"}, | 405 | {0x46, nullptr, "Unknown"}, |
| 301 | {0x47, NULL, "CreatePort"}, | 406 | {0x47, nullptr, "CreatePort"}, |
| 302 | {0x48, NULL, "CreateSessionToPort"}, | 407 | {0x48, nullptr, "CreateSessionToPort"}, |
| 303 | {0x49, NULL, "CreateSession"}, | 408 | {0x49, nullptr, "CreateSession"}, |
| 304 | {0x4A, NULL, "AcceptSession"}, | 409 | {0x4A, nullptr, "AcceptSession"}, |
| 305 | {0x4B, NULL, "ReplyAndReceive1"}, | 410 | {0x4B, nullptr, "ReplyAndReceive1"}, |
| 306 | {0x4C, NULL, "ReplyAndReceive2"}, | 411 | {0x4C, nullptr, "ReplyAndReceive2"}, |
| 307 | {0x4D, NULL, "ReplyAndReceive3"}, | 412 | {0x4D, nullptr, "ReplyAndReceive3"}, |
| 308 | {0x4E, NULL, "ReplyAndReceive4"}, | 413 | {0x4E, nullptr, "ReplyAndReceive4"}, |
| 309 | {0x4F, NULL, "ReplyAndReceive"}, | 414 | {0x4F, nullptr, "ReplyAndReceive"}, |
| 310 | {0x50, NULL, "BindInterrupt"}, | 415 | {0x50, nullptr, "BindInterrupt"}, |
| 311 | {0x51, NULL, "UnbindInterrupt"}, | 416 | {0x51, nullptr, "UnbindInterrupt"}, |
| 312 | {0x52, NULL, "InvalidateProcessDataCache"}, | 417 | {0x52, nullptr, "InvalidateProcessDataCache"}, |
| 313 | {0x53, NULL, "StoreProcessDataCache"}, | 418 | {0x53, nullptr, "StoreProcessDataCache"}, |
| 314 | {0x54, NULL, "FlushProcessDataCache"}, | 419 | {0x54, nullptr, "FlushProcessDataCache"}, |
| 315 | {0x55, NULL, "StartInterProcessDma"}, | 420 | {0x55, nullptr, "StartInterProcessDma"}, |
| 316 | {0x56, NULL, "StopDma"}, | 421 | {0x56, nullptr, "StopDma"}, |
| 317 | {0x57, NULL, "GetDmaState"}, | 422 | {0x57, nullptr, "GetDmaState"}, |
| 318 | {0x58, NULL, "RestartDma"}, | 423 | {0x58, nullptr, "RestartDma"}, |
| 319 | {0x59, NULL, "Unknown"}, | 424 | {0x59, nullptr, "Unknown"}, |
| 320 | {0x5A, NULL, "Unknown"}, | 425 | {0x5A, nullptr, "Unknown"}, |
| 321 | {0x5B, NULL, "Unknown"}, | 426 | {0x5B, nullptr, "Unknown"}, |
| 322 | {0x5C, NULL, "Unknown"}, | 427 | {0x5C, nullptr, "Unknown"}, |
| 323 | {0x5D, NULL, "Unknown"}, | 428 | {0x5D, nullptr, "Unknown"}, |
| 324 | {0x5E, NULL, "Unknown"}, | 429 | {0x5E, nullptr, "Unknown"}, |
| 325 | {0x5F, NULL, "Unknown"}, | 430 | {0x5F, nullptr, "Unknown"}, |
| 326 | {0x60, NULL, "DebugActiveProcess"}, | 431 | {0x60, nullptr, "DebugActiveProcess"}, |
| 327 | {0x61, NULL, "BreakDebugProcess"}, | 432 | {0x61, nullptr, "BreakDebugProcess"}, |
| 328 | {0x62, NULL, "TerminateDebugProcess"}, | 433 | {0x62, nullptr, "TerminateDebugProcess"}, |
| 329 | {0x63, NULL, "GetProcessDebugEvent"}, | 434 | {0x63, nullptr, "GetProcessDebugEvent"}, |
| 330 | {0x64, NULL, "ContinueDebugEvent"}, | 435 | {0x64, nullptr, "ContinueDebugEvent"}, |
| 331 | {0x65, NULL, "GetProcessList"}, | 436 | {0x65, nullptr, "GetProcessList"}, |
| 332 | {0x66, NULL, "GetThreadList"}, | 437 | {0x66, nullptr, "GetThreadList"}, |
| 333 | {0x67, NULL, "GetDebugThreadContext"}, | 438 | {0x67, nullptr, "GetDebugThreadContext"}, |
| 334 | {0x68, NULL, "SetDebugThreadContext"}, | 439 | {0x68, nullptr, "SetDebugThreadContext"}, |
| 335 | {0x69, NULL, "QueryDebugProcessMemory"}, | 440 | {0x69, nullptr, "QueryDebugProcessMemory"}, |
| 336 | {0x6A, NULL, "ReadProcessMemory"}, | 441 | {0x6A, nullptr, "ReadProcessMemory"}, |
| 337 | {0x6B, NULL, "WriteProcessMemory"}, | 442 | {0x6B, nullptr, "WriteProcessMemory"}, |
| 338 | {0x6C, NULL, "SetHardwareBreakPoint"}, | 443 | {0x6C, nullptr, "SetHardwareBreakPoint"}, |
| 339 | {0x6D, NULL, "GetDebugThreadParam"}, | 444 | {0x6D, nullptr, "GetDebugThreadParam"}, |
| 340 | {0x6E, NULL, "Unknown"}, | 445 | {0x6E, nullptr, "Unknown"}, |
| 341 | {0x6F, NULL, "Unknown"}, | 446 | {0x6F, nullptr, "Unknown"}, |
| 342 | {0x70, NULL, "ControlProcessMemory"}, | 447 | {0x70, nullptr, "ControlProcessMemory"}, |
| 343 | {0x71, NULL, "MapProcessMemory"}, | 448 | {0x71, nullptr, "MapProcessMemory"}, |
| 344 | {0x72, NULL, "UnmapProcessMemory"}, | 449 | {0x72, nullptr, "UnmapProcessMemory"}, |
| 345 | {0x73, NULL, "Unknown"}, | 450 | {0x73, nullptr, "Unknown"}, |
| 346 | {0x74, NULL, "Unknown"}, | 451 | {0x74, nullptr, "Unknown"}, |
| 347 | {0x75, NULL, "Unknown"}, | 452 | {0x75, nullptr, "Unknown"}, |
| 348 | {0x76, NULL, "TerminateProcess"}, | 453 | {0x76, nullptr, "TerminateProcess"}, |
| 349 | {0x77, NULL, "Unknown"}, | 454 | {0x77, nullptr, "Unknown"}, |
| 350 | {0x78, NULL, "CreateResourceLimit"}, | 455 | {0x78, nullptr, "CreateResourceLimit"}, |
| 351 | {0x79, NULL, "Unknown"}, | 456 | {0x79, nullptr, "Unknown"}, |
| 352 | {0x7A, NULL, "Unknown"}, | 457 | {0x7A, nullptr, "Unknown"}, |
| 353 | {0x7B, NULL, "Unknown"}, | 458 | {0x7B, nullptr, "Unknown"}, |
| 354 | {0x7C, NULL, "KernelSetState"}, | 459 | {0x7C, nullptr, "KernelSetState"}, |
| 355 | {0x7D, NULL, "QueryProcessMemory"}, | 460 | {0x7D, nullptr, "QueryProcessMemory"}, |
| 356 | }; | 461 | }; |
| 357 | 462 | ||
| 358 | void Register() { | 463 | void Register() { |