From 15d2ab1b33e8ef579d15bb6f20e6c625a58fb166 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 20:55:48 -0400 Subject: [PATCH 01/84] svc: added stub for DuplicateHandle SVC call --- src/core/hle/svc.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 90c05cb74..0c647b86f 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -226,6 +226,13 @@ Result CreateEvent(void* _event, u32 reset_type) { return 0; } +/// Duplicates a kernel handle +Result DuplicateHandle(void* _out, Handle handle) { + Handle* out = (Handle*)_out; + DEBUG_LOG(SVC, "(UNIMPLEMENTED) DuplicateHandle called handle=0x%08X", handle); + return 0; +} + const HLE::FunctionDef SVC_Table[] = { {0x00, NULL, "Unknown"}, {0x01, WrapI_VUUUUU, "ControlMemory"}, @@ -266,7 +273,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x24, WrapI_US64, "WaitSynchronization1"}, {0x25, WrapI_VVUUS64, "WaitSynchronizationN"}, {0x26, NULL, "SignalAndWait"}, - {0x27, NULL, "DuplicateHandle"}, + {0x27, WrapI_VU, "DuplicateHandle"}, {0x28, NULL, "GetSystemTick"}, {0x29, NULL, "GetHandleInfo"}, {0x2A, NULL, "GetSystemInfo"}, From d73d782ba7ea6f3f2dd9c4f70d34c1004397dacb Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:01:27 -0400 Subject: [PATCH 02/84] kernel: add a SyncRequest method to KernelObject for use with svcSendSyncRequest --- src/core/hle/kernel/kernel.h | 1 + src/core/hle/kernel/mutex.cpp | 5 +++++ src/core/hle/kernel/thread.cpp | 5 +++++ src/core/hle/service/srv.h | 6 ------ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 7cd79c2c4..046d583cb 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -42,6 +42,7 @@ public: virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; + virtual Result SyncRequest() = 0; }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 019efbc78..fa924404d 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -23,6 +23,11 @@ public: bool locked; ///< Current locked state Handle lock_thread; ///< Handle to thread that currently has mutex std::vector waiting_threads; ///< Threads that are waiting for the mutex + + /// Synchronize kernel object + Result SyncRequest() { + return 0; + } }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index bf4c8353c..b9dd9fac4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -36,6 +36,11 @@ public: inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } + /// Synchronize kernel object + Result SyncRequest() { + return 0; + } + ThreadContext context; u32 status; diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h index 1e35032ba..81109a2a8 100644 --- a/src/core/hle/service/srv.h +++ b/src/core/hle/service/srv.h @@ -26,12 +26,6 @@ public: return "srv:"; } - /** - * Called when svcSendSyncRequest is called, loads command buffer and executes comand - * @return Return result of svcSendSyncRequest passed back to user app - */ - Result Sync(); - }; } // namespace From 9f7ed2d027462b6f2f9e1cb96eb586419f5351a8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:17:10 -0400 Subject: [PATCH 03/84] svc: changed SendSyncRequest to use Kernel::Object SyncRequest (instead of just service Interface class) --- src/core/hle/svc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 0c647b86f..ac016a966 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -96,8 +96,8 @@ Result ConnectToPort(void* out, const char* port_name) { /// Synchronize to an OS service Result SendSyncRequest(Handle handle) { DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X"); - Service::Interface* service = Service::g_manager->FetchFromHandle(handle); - service->Sync(); + Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); + object->SyncRequest(); return 0; } From 96b21055249ade8a36f8117e4e22ea2a8a10707b Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:55:55 -0400 Subject: [PATCH 04/84] srv: added a real mutex for GetProcSemaphore (instead of stubbed) --- src/core/hle/service/srv.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index ff6da8f1c..7bbc03bf6 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -5,21 +5,28 @@ #include "core/hle/hle.h" #include "core/hle/service/srv.h" #include "core/hle/service/service.h" - +#include "core/hle/kernel/mutex.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SRV namespace SRV { +Handle g_mutex = 0; + void Initialize(Service::Interface* self) { - NOTICE_LOG(OSHLE, "SRV::Sync - Initialize"); + DEBUG_LOG(OSHLE, "SRV::Initialize called"); + if (!g_mutex) { + g_mutex = Kernel::CreateMutex(false); + } } void GetProcSemaphore(Service::Interface* self) { + DEBUG_LOG(OSHLE, "SRV::GetProcSemaphore called"); // Get process semaphore? u32* cmd_buff = Service::GetCommandBuffer(); - cmd_buff[3] = 0xDEADBEEF; // Return something... 0 == NULL, raises an exception + cmd_buff[1] = 0; // No error + cmd_buff[3] = g_mutex; // Return something... 0 == NULL, raises an exception } void GetServiceHandle(Service::Interface* self) { From 3d7693f75f4a599d0da4a23dea0ec1a0578da0e1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:56:23 -0400 Subject: [PATCH 05/84] kernel: added enum for known CurrentThread and CurrentProcess handles --- src/core/hle/kernel/kernel.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 046d583cb..786d3abf3 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -11,6 +11,11 @@ typedef s32 Result; namespace Kernel { +enum KernelHandle { + CurrentThread = 0xFFFF8000, + CurrentProcess = 0xFFFF8001, +}; + enum class HandleType : u32 { Unknown = 0, Port = 1, From 16fea415d09e3c1e55667a6affab495e03117f96 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:56:51 -0400 Subject: [PATCH 06/84] service: Renamed Sync to SyncRequest --- src/core/hle/service/service.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 716669bed..c970ace4b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -79,7 +79,7 @@ public: * Called when svcSendSyncRequest is called, loads command buffer and executes comand * @return Return result of svcSendSyncRequest passed back to user app */ - Result Sync() { + Result SyncRequest() { u32* cmd_buff = GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); From 6e51c56fe41c3ff38db3a13e8773a9e9b2103377 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:57:10 -0400 Subject: [PATCH 07/84] svc: added some assertions --- src/core/hle/svc.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index ac016a966..6f72a6eb7 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -84,19 +84,17 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper /// Connect to an OS service given the port name, returns the handle to the port to out Result ConnectToPort(void* out, const char* port_name) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); - if (service) { - Core::g_app_core->SetReg(1, service->GetHandle()); - } else { - PanicYesNo("ConnectToPort called port_name=%s, but it is not implemented!", port_name); - } DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); + _assert_msg_(KERNEL, service, "ConnectToPort called, but service is not implemented!"); + Core::g_app_core->SetReg(1, service->GetHandle()); return 0; } /// Synchronize to an OS service Result SendSyncRequest(Handle handle) { - DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X"); Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); + DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X"); + _assert_msg_(KERNEL, object, "SendSyncRequest called, but kernel object is NULL!"); object->SyncRequest(); return 0; } From 58a3adcdd2eed9d31cd441186af872a0a8924e73 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:12:46 -0400 Subject: [PATCH 08/84] kernel: updated SyncRequest to take boolean thread wait result as a parameter --- src/core/hle/kernel/kernel.h | 9 ++++++++- src/core/hle/kernel/mutex.cpp | 8 ++++++-- src/core/hle/kernel/thread.cpp | 8 ++++++-- src/core/hle/service/service.h | 7 ++++--- src/core/hle/svc.cpp | 11 +++++++++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 786d3abf3..4acc9f220 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -47,7 +47,14 @@ public: virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; - virtual Result SyncRequest() = 0; + + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + virtual Result SyncRequest(bool* wait) = 0; + }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index fa924404d..5465b7a3c 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -24,8 +24,12 @@ public: Handle lock_thread; ///< Handle to thread that currently has mutex std::vector waiting_threads; ///< Threads that are waiting for the mutex - /// Synchronize kernel object - Result SyncRequest() { + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { return 0; } }; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index b9dd9fac4..56c7755cf 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -36,8 +36,12 @@ public: inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } - /// Synchronize kernel object - Result SyncRequest() { + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { return 0; } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index c970ace4b..12ef51b91 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -76,10 +76,11 @@ public: } /** - * Called when svcSendSyncRequest is called, loads command buffer and executes comand - * @return Return result of svcSendSyncRequest passed back to user app + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code */ - Result SyncRequest() { + Result SyncRequest(bool* wait) { u32* cmd_buff = GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 6f72a6eb7..e566036e5 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -92,11 +92,18 @@ Result ConnectToPort(void* out, const char* port_name) { /// Synchronize to an OS service Result SendSyncRequest(Handle handle) { + bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); + DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X"); _assert_msg_(KERNEL, object, "SendSyncRequest called, but kernel object is NULL!"); - object->SyncRequest(); - return 0; + + Result res = object->SyncRequest(&wait); + if (wait) { + Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? + } + + return res; } /// Close a handle From a432dc8f39a866b7b523235d6d94531f93bb4aa1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:17:49 -0400 Subject: [PATCH 09/84] kernel: added WaitSynchronization method to Kernel::Object --- src/core/hle/kernel/kernel.h | 7 +++++++ src/core/hle/kernel/mutex.cpp | 11 +++++++++++ src/core/hle/kernel/thread.cpp | 11 +++++++++++ src/core/hle/service/service.h | 10 ++++++++++ 4 files changed, 39 insertions(+) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 4acc9f220..620cd2d73 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -55,6 +55,13 @@ public: */ virtual Result SyncRequest(bool* wait) = 0; + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + virtual Result WaitSynchronization(bool* wait) = 0; + }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 5465b7a3c..17fd40acd 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -30,6 +30,17 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result SyncRequest(bool* wait) { + // TODO(bunnei): ImplementMe + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe return 0; } }; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 56c7755cf..6e8b53eb1 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -42,6 +42,17 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result SyncRequest(bool* wait) { + // TODO(bunnei): ImplementMe + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe return 0; } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 12ef51b91..4671d4528 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -100,6 +100,16 @@ public: return 0; // TODO: Implement return from actual function } + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe + return 0; + } + protected: /** From 93cd5a069122e86605ce2c15347e9498ceda2cc4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:47:47 -0400 Subject: [PATCH 10/84] mutex: added additional docstrings --- src/core/hle/kernel/mutex.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 871e2e562..8a9309069 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -13,6 +13,7 @@ namespace Kernel { /** * Releases a mutex * @param handle Handle to mutex to release + * @return Result of operation, 0 on success, otherwise error code */ Result ReleaseMutex(Handle handle); @@ -20,6 +21,7 @@ Result ReleaseMutex(Handle handle); * Creates a mutex * @param handle Reference to handle for the newly created mutex * @param initial_locked Specifies if the mutex should be locked initially + * @return Handle to newly created object */ Handle CreateMutex(bool initial_locked); From d493d725acfc431fcbed729bb28d9b8a19250f96 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:49:11 -0400 Subject: [PATCH 11/84] mutex: removed docstring comment that is no longer relevant --- src/core/hle/kernel/mutex.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 8a9309069..4cd266725 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -19,7 +19,6 @@ Result ReleaseMutex(Handle handle); /** * Creates a mutex - * @param handle Reference to handle for the newly created mutex * @param initial_locked Specifies if the mutex should be locked initially * @return Handle to newly created object */ From fd69fd03259b71be521aeb69d3f73761b598be8a Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 20:16:13 -0400 Subject: [PATCH 12/84] kernel: added event module to support creation of CTR "Event" objects --- src/core/core.vcxproj | 2 + src/core/core.vcxproj.filters | 6 +++ src/core/hle/kernel/event.cpp | 91 +++++++++++++++++++++++++++++++++++ src/core/hle/kernel/event.h | 28 +++++++++++ 4 files changed, 127 insertions(+) create mode 100644 src/core/hle/kernel/event.cpp create mode 100644 src/core/hle/kernel/event.h diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index f271d336e..efcd30d77 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -168,6 +168,7 @@ + @@ -217,6 +218,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index b6c1d5b93..135e4c89c 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -165,6 +165,9 @@ arm\interpreter + + hle\kernel + @@ -295,6 +298,9 @@ hle\kernel + + hle\kernel + diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp new file mode 100644 index 000000000..cc15ba9bc --- /dev/null +++ b/src/core/hle/kernel/event.cpp @@ -0,0 +1,91 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "common/common.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/event.h" + +namespace Kernel { + +class Event : public Object { +public: + const char* GetTypeName() { return "Event"; } + + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } + Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } + + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType + + bool locked; ///< Current locked state + + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { + // TODO(bunnei): ImplementMe + ERROR_LOG(KERNEL, "Unimplemented function Event::SyncRequest"); + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe + *wait = locked; + if (reset_type != RESETTYPE_STICKY) { + locked = true; + } + return 0; + } +}; + +/** + * Clears an event + * @param handle Handle to event to clear + * @return Result of operation, 0 on success, otherwise error code + */ +Result ClearEvent(Handle handle) { + ERROR_LOG(KERNEL, "Unimplemented function ClearEvent"); + return 0; +} + +/** + * Creates an event + * @param handle Reference to handle for the newly created mutex + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Event* CreateEvent(Handle& handle, const ResetType reset_type) { + Event* evt = new Event; + + handle = Kernel::g_object_pool.Create(evt); + + evt->reset_type = evt->intitial_reset_type = reset_type; + evt->locked = false; + + return evt; +} + +/** + * Creates an event + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Handle CreateEvent(const ResetType reset_type) { + Handle handle; + Event* evt = CreateEvent(handle, reset_type); + return handle; +} + +} // namespace diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h new file mode 100644 index 000000000..2ef1bd65b --- /dev/null +++ b/src/core/hle/kernel/event.h @@ -0,0 +1,28 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/svc.h" + +namespace Kernel { + +/** + * Clears an event + * @param handle Handle to event to clear + * @return Result of operation, 0 on success, otherwise error code + */ +Result ClearEvent(Handle handle); + +/** + * Creates an event + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Handle CreateEvent(const ResetType reset_type); + +} // namespace From beea6f054ae0bd40d1a564aa586735b81f2bf662 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:14:00 -0400 Subject: [PATCH 13/84] event: added SetEventLocked method to change status an events lock --- src/core/hle/kernel/event.cpp | 11 +++++++++++ src/core/hle/kernel/event.h | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index cc15ba9bc..e85f39f0d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -50,6 +50,17 @@ public: } }; +/** + * Changes whether an event is locked or not + * @param handle Handle to event to change + * @param locked Boolean locked value to set event + */ +void SetEventLocked(const Handle handle, const bool locked) { + Event* evt = g_object_pool.GetFast(handle); + evt->locked = locked; + return; +} + /** * Clears an event * @param handle Handle to event to clear diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 2ef1bd65b..0bcfe00b7 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -11,6 +11,13 @@ namespace Kernel { +/** + * Changes whether an event is locked or not + * @param handle Handle to event to change + * @param locked Boolean locked value to set event + */ +void SetEventLocked(const Handle handle, const bool locked) + /** * Clears an event * @param handle Handle to event to clear From ea8627d5360eedaa10c979854ad9b4dd3b85f800 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:14:38 -0400 Subject: [PATCH 14/84] event: fixed typos and updated CMakeLists --- src/core/CMakeLists.txt | 1 + src/core/hle/kernel/event.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6ad308798..468e6a631 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -34,6 +34,7 @@ set(SRCS core.cpp hle/config_mem.cpp hle/coprocessor.cpp hle/svc.cpp + hle/kernel/event.cpp hle/kernel/kernel.cpp hle/kernel/mutex.cpp hle/kernel/thread.cpp diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 0bcfe00b7..c1842cb88 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -16,7 +16,7 @@ namespace Kernel { * @param handle Handle to event to change * @param locked Boolean locked value to set event */ -void SetEventLocked(const Handle handle, const bool locked) +void SetEventLocked(const Handle handle, const bool locked); /** * Clears an event From 94b30e8a3875346888fb7d0d36b9145cbed34836 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:29:11 -0400 Subject: [PATCH 15/84] APT_U: added event creation to Initialize method --- src/core/hle/service/apt.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 32759a087..67c53529a 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -6,6 +6,7 @@ #include "common/common.h" #include "core/hle/hle.h" +#include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" #include "core/hle/service/apt.h" @@ -15,7 +16,16 @@ namespace APT_U { void Initialize(Service::Interface* self) { - NOTICE_LOG(OSHLE, "APT_U::Sync - Initialize"); + u32* cmd_buff = Service::GetCommandBuffer(); + DEBUG_LOG(KERNEL, "APT_U::Sync - Initialize"); + + cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT menu event handle + cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT pause event handle + + Kernel::SetEventLocked(cmd_buff[3], true); + Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event + + cmd_buff[1] = 0; // No error } void GetLockHandle(Service::Interface* self) { From 47e781e80a4bc0f37eb431a89aa36b27224185e7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:41:09 -0400 Subject: [PATCH 16/84] svc: implemented WaitSynchronization1, WaitSynchronizationN, and CreateEvent --- src/core/hle/svc.cpp | 68 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index e566036e5..8468c4fab 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -9,6 +9,7 @@ #include "core/mem_map.h" +#include "core/hle/kernel/event.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/thread.h" @@ -16,7 +17,6 @@ #include "core/hle/function_wrappers.h" #include "core/hle/svc.h" #include "core/hle/service/service.h" -#include "core/hle/kernel/thread.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SVC @@ -95,7 +95,7 @@ Result SendSyncRequest(Handle handle) { bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); - DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X"); + DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X", handle); _assert_msg_(KERNEL, object, "SendSyncRequest called, but kernel object is NULL!"); Result res = object->SyncRequest(&wait); @@ -115,24 +115,62 @@ Result CloseHandle(Handle handle) { /// Wait for a handle to synchronize, timeout after the specified nanoseconds Result WaitSynchronization1(Handle handle, s64 nano_seconds) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", - handle, nano_seconds); - Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? - return 0; + // TODO(bunnei): Do something with nano_seconds, currently ignoring this + bool wait = false; + + Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); + + DEBUG_LOG(SVC, "WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", handle, + nano_seconds); + _assert_msg_(KERNEL, object, "WaitSynchronization1 called, but kernel object is NULL!"); + + Result res = object->WaitSynchronization(&wait); + + if (wait) { + Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? + } + + return res; } /// Wait for the given handles to synchronize, timeout after the specified nanoseconds -Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wait_all, s64 nano_seconds) { +Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wait_all, + s64 nano_seconds) { + // TODO(bunnei): Do something with nano_seconds, currently ignoring this + s32* out = (s32*)_out; Handle* handles = (Handle*)_handles; + bool unlock_all = true; - DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronizationN called handle_count=%d, wait_all=%s, nanoseconds=%d %s", + DEBUG_LOG(SVC, "WaitSynchronizationN called handle_count=%d, wait_all=%s, nanoseconds=%d", handle_count, (wait_all ? "true" : "false"), nano_seconds); + // Iterate through each handle, synchronize kernel object for (u32 i = 0; i < handle_count; i++) { - DEBUG_LOG(SVC, "\thandle[%d]=0x%08X", i, handles[i]); + bool wait = false; + Kernel::Object* object = Kernel::g_object_pool.GetFast(handles[i]); // 0 handle + + _assert_msg_(KERNEL, object, "WaitSynchronizationN called handle=0x%08X, but kernel object " + "is NULL!", handles[i]); + + Result res = object->WaitSynchronization(&wait); + + if (!wait && !wait_all) { + Core::g_app_core->SetReg(1, i); + return 0; + } else { + unlock_all = false; + } } + + if (wait_all && unlock_all) { + Core::g_app_core->SetReg(1, handle_count); + return 0; + } + + // Set current thread to wait state if not all handles were unlocked Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? + return 0; } @@ -195,16 +233,17 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p /// Create a mutex Result CreateMutex(void* _mutex, u32 initial_locked) { Handle* mutex = (Handle*)_mutex; - *mutex = Kernel::CreateMutex((initial_locked != 0)); - Core::g_app_core->SetReg(1, *mutex); DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s : created handle 0x%08X", initial_locked ? "true" : "false", *mutex); + *mutex = Kernel::CreateMutex((initial_locked != 0)); + Core::g_app_core->SetReg(1, *mutex); return 0; } /// Release a mutex Result ReleaseMutex(Handle handle) { DEBUG_LOG(SVC, "ReleaseMutex called handle=0x%08X", handle); + _assert_msg_(KERNEL, handle, "ReleaseMutex called, but handle is NULL!"); Kernel::ReleaseMutex(handle); return 0; } @@ -225,9 +264,10 @@ Result QueryMemory(void *_info, void *_out, u32 addr) { /// Create an event Result CreateEvent(void* _event, u32 reset_type) { - Handle* event = (Handle*)_event; - DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateEvent called reset_type=0x%08X", reset_type); - Core::g_app_core->SetReg(1, 0xBADC0DE0); + Handle* evt = (Handle*)_event; + DEBUG_LOG(SVC, "CreateEvent called reset_type=0x%08X", reset_type); + *evt = Kernel::CreateEvent((ResetType)reset_type); + Core::g_app_core->SetReg(1, *evt); return 0; } From 2ed6652f100fdbc5ad7d72a0602dc2c99ef79cce Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:42:16 -0400 Subject: [PATCH 17/84] mutex: added preliminary SyncRequest/WaitSynchronization, added some comments/assertions --- src/core/hle/kernel/mutex.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 17fd40acd..23c064571 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -31,6 +31,7 @@ public: */ Result SyncRequest(bool* wait) { // TODO(bunnei): ImplementMe + locked = true; return 0; } @@ -41,6 +42,7 @@ public: */ Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe + *wait = locked; return 0; } }; @@ -111,6 +113,9 @@ bool ReleaseMutex(Mutex* mutex) { */ Result ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_object_pool.GetFast(handle); + + _assert_msg_(KERNEL, mutex, "ReleaseMutex tried to release a NULL mutex!"); + if (!ReleaseMutex(mutex)) { return -1; } @@ -121,6 +126,7 @@ Result ReleaseMutex(Handle handle) { * Creates a mutex * @param handle Reference to handle for the newly created mutex * @param initial_locked Specifies if the mutex should be locked initially + * @return Pointer to new Mutex object */ Mutex* CreateMutex(Handle& handle, bool initial_locked) { Mutex* mutex = new Mutex; From 3972d4ca8ba82a1e344e1255b0c113751d4b9f59 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 23:56:08 -0400 Subject: [PATCH 18/84] APT_U: added stubbed function for APT_U::Enable, fixed some log messages to be more consistent --- src/core/hle/service/apt.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 67c53529a..ae040562c 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -17,7 +17,7 @@ namespace APT_U { void Initialize(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); - DEBUG_LOG(KERNEL, "APT_U::Sync - Initialize"); + DEBUG_LOG(KERNEL, "APT_U::Initialize called"); cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT menu event handle cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT pause event handle @@ -33,13 +33,20 @@ void GetLockHandle(Service::Interface* self) { u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field cmd_buff[1] = 0; // No error cmd_buff[5] = Kernel::CreateMutex(false); - DEBUG_LOG(KERNEL, "APT_U::GetLockHandle called : created handle 0x%08X", cmd_buff[5]); + DEBUG_LOG(KERNEL, "APT_U::GetLockHandle called handle=0x%08X", cmd_buff[5]); +} + +void Enable(Service::Interface* self) { + u32* cmd_buff = Service::GetCommandBuffer(); + u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for? + cmd_buff[1] = 0; // No error + ERROR_LOG(KERNEL, "(UNIMPEMENTED) APT_U::Enable called unk=0x%08X", unk); } const Interface::FunctionInfo FunctionTable[] = { {0x00010040, GetLockHandle, "GetLockHandle"}, {0x00020080, Initialize, "Initialize"}, - {0x00030040, NULL, "Enable"}, + {0x00030040, Enable, "Enable"}, {0x00040040, NULL, "Finalize"}, {0x00050040, NULL, "GetAppletManInfo"}, {0x00060040, NULL, "GetAppletInfo"}, From 70af9d620b8c1ebbc203c3601aad7c746fddff76 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 28 May 2014 18:39:28 -0400 Subject: [PATCH 19/84] service: changed interface to return 0 (no error) when a service method is unimplemented - hack to make apps boot further --- src/core/hle/service/service.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 4671d4528..4a3d4c68a 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -87,12 +87,12 @@ public: if (itr == m_functions.end()) { ERROR_LOG(OSHLE, "Unknown/unimplemented function: port = %s, command = 0x%08X!", GetPortName(), cmd_buff[0]); - return -1; + return 0; // TODO(bunnei): Hack - ignore error } if (itr->second.func == NULL) { ERROR_LOG(OSHLE, "Unimplemented function: port = %s, name = %s!", GetPortName(), itr->second.name.c_str()); - return -1; + return 0; // TODO(bunnei): Hack - ignore error } itr->second.func(this); From 46aef01d0431253a4aa17b31b85cb35603a036ec Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 28 May 2014 21:19:13 -0400 Subject: [PATCH 20/84] lcd: moved kFrameTicks to lcd.h for use in other modules --- src/core/hw/lcd.cpp | 2 -- src/core/hw/lcd.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp index b57563a73..6cbce14ed 100644 --- a/src/core/hw/lcd.cpp +++ b/src/core/hw/lcd.cpp @@ -17,8 +17,6 @@ namespace LCD { Registers g_regs; -static const u32 kFrameTicks = 268123480 / 60; ///< 268MHz / 60 frames per second - u64 g_last_ticks = 0; ///< Last CPU ticks /** diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h index 2dd3b4adc..41baa51d0 100644 --- a/src/core/hw/lcd.h +++ b/src/core/hw/lcd.h @@ -8,6 +8,8 @@ namespace LCD { +static const u32 kFrameTicks = 268123480 / 60; ///< 268MHz / 60 frames per second + struct Registers { u32 framebuffer_top_left_1; u32 framebuffer_top_left_2; From 9fd5d6c7d81053e05b3b4218bdee2575cd1f3fd0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 28 May 2014 21:20:00 -0400 Subject: [PATCH 21/84] hle: removed PARAM64 macro (this was incorrect), made several bug fixes accordingly for decoding U64 function parameters --- src/core/hle/function_wrappers.h | 4 ++-- src/core/hle/hle.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 24cc74fc6..d31fab298 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -750,11 +750,11 @@ template void WrapI_VUUUUU(){ } template void WrapI_US64() { - int retval = func(PARAM(0), PARAM64(1)); + int retval = func(PARAM(0), ((PARAM(3) << 32) | PARAM(2))); RETURN(retval); } template void WrapI_VVUUS64() { - int retval = func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), PARAM(4)); + int retval = func(Memory::GetPointer(PARAM(5)), Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), ((PARAM(4) << 32) | PARAM(0))); RETURN(retval); } diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index c075147c3..c31e273b5 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -10,7 +10,6 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #define PARAM(n) Core::g_app_core->GetReg(n) -#define PARAM64(n) (Core::g_app_core->GetReg(n) | ((u64)Core::g_app_core->GetReg(n + 1) << 32)) #define RETURN(n) Core::g_app_core->SetReg(0, n) //////////////////////////////////////////////////////////////////////////////////////////////////// From c4b5168b453ed2738bac61e05810fd4f5b95217d Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 28 May 2014 22:03:10 -0400 Subject: [PATCH 22/84] hle: properly cast 64-bit function wrapper parameters to (u64) --- src/core/hle/function_wrappers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index d31fab298..7b07d8ca8 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -750,11 +750,11 @@ template void WrapI_VUUUUU(){ } template void WrapI_US64() { - int retval = func(PARAM(0), ((PARAM(3) << 32) | PARAM(2))); + int retval = func(PARAM(0), (((u64)PARAM(3) << 32) | PARAM(2))); RETURN(retval); } template void WrapI_VVUUS64() { - int retval = func(Memory::GetPointer(PARAM(5)), Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), ((PARAM(4) << 32) | PARAM(0))); + int retval = func(Memory::GetPointer(PARAM(5)), Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); RETURN(retval); } From 4b4a6de1d810c9e274eb1f9978f5fb006c9346f9 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 28 May 2014 23:33:24 -0400 Subject: [PATCH 23/84] apt: added stubbed function for InquireNotification --- src/core/hle/service/apt.cpp | 164 ++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 78 deletions(-) diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index ae040562c..f2118ba03 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -43,85 +43,93 @@ void Enable(Service::Interface* self) { ERROR_LOG(KERNEL, "(UNIMPEMENTED) APT_U::Enable called unk=0x%08X", unk); } +void InquireNotification(Service::Interface* self) { + u32* cmd_buff = Service::GetCommandBuffer(); + u32 app_id = cmd_buff[2]; + cmd_buff[1] = 0; // No error + cmd_buff[3] = 0; // Signal type + ERROR_LOG(KERNEL, "(UNIMPEMENTED) APT_U::InquireNotification called app_id=0x%08X", app_id); +} + const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetLockHandle, "GetLockHandle"}, - {0x00020080, Initialize, "Initialize"}, - {0x00030040, Enable, "Enable"}, - {0x00040040, NULL, "Finalize"}, - {0x00050040, NULL, "GetAppletManInfo"}, - {0x00060040, NULL, "GetAppletInfo"}, - {0x00070000, NULL, "GetLastSignaledAppletId"}, - {0x00080000, NULL, "CountRegisteredApplet"}, - {0x00090040, NULL, "IsRegistered"}, - {0x000A0040, NULL, "GetAttribute"}, - {0x000B0040, NULL, "InquireNotification"}, - {0x000C0104, NULL, "SendParameter"}, - {0x000D0080, NULL, "ReceiveParameter"}, - {0x000E0080, NULL, "GlanceParameter"}, - {0x000F0100, NULL, "CancelParameter"}, - {0x001000C2, NULL, "DebugFunc"}, - {0x001100C0, NULL, "MapProgramIdForDebug"}, - {0x00120040, NULL, "SetHomeMenuAppletIdForDebug"}, - {0x00130000, NULL, "GetPreparationState"}, - {0x00140040, NULL, "SetPreparationState"}, - {0x00150140, NULL, "PrepareToStartApplication"}, - {0x00160040, NULL, "PreloadLibraryApplet"}, - {0x00170040, NULL, "FinishPreloadingLibraryApplet"}, - {0x00180040, NULL, "PrepareToStartLibraryApplet"}, - {0x00190040, NULL, "PrepareToStartSystemApplet"}, - {0x001A0000, NULL, "PrepareToStartNewestHomeMenu"}, - {0x001B00C4, NULL, "StartApplication"}, - {0x001C0000, NULL, "WakeupApplication"}, - {0x001D0000, NULL, "CancelApplication"}, - {0x001E0084, NULL, "StartLibraryApplet"}, - {0x001F0084, NULL, "StartSystemApplet"}, - {0x00200044, NULL, "StartNewestHomeMenu"}, - {0x00210000, NULL, "OrderToCloseApplication"}, - {0x00220040, NULL, "PrepareToCloseApplication"}, - {0x00230040, NULL, "PrepareToJumpToApplication"}, - {0x00240044, NULL, "JumpToApplication"}, - {0x002500C0, NULL, "PrepareToCloseLibraryApplet"}, - {0x00260000, NULL, "PrepareToCloseSystemApplet"}, - {0x00270044, NULL, "CloseApplication"}, - {0x00280044, NULL, "CloseLibraryApplet"}, - {0x00290044, NULL, "CloseSystemApplet"}, - {0x002A0000, NULL, "OrderToCloseSystemApplet"}, - {0x002B0000, NULL, "PrepareToJumpToHomeMenu"}, - {0x002C0044, NULL, "JumpToHomeMenu"}, - {0x002D0000, NULL, "PrepareToLeaveHomeMenu"}, - {0x002E0044, NULL, "LeaveHomeMenu"}, - {0x002F0040, NULL, "PrepareToLeaveResidentApplet"}, - {0x00300044, NULL, "LeaveResidentApplet"}, - {0x00310100, NULL, "PrepareToDoApplicationJump"}, - {0x00320084, NULL, "DoApplicationJump"}, - {0x00330000, NULL, "GetProgramIdOnApplicationJump"}, - {0x00340084, NULL, "SendDeliverArg"}, - {0x00350080, NULL, "ReceiveDeliverArg"}, - {0x00360040, NULL, "LoadSysMenuArg"}, - {0x00370042, NULL, "StoreSysMenuArg"}, - {0x00380040, NULL, "PreloadResidentApplet"}, - {0x00390040, NULL, "PrepareToStartResidentApplet"}, - {0x003A0044, NULL, "StartResidentApplet"}, - {0x003B0040, NULL, "CancelLibraryApplet"}, - {0x003C0042, NULL, "SendDspSleep"}, - {0x003D0042, NULL, "SendDspWakeUp"}, - {0x003E0080, NULL, "ReplySleepQuery"}, - {0x003F0040, NULL, "ReplySleepNotificationComplete"}, - {0x00400042, NULL, "SendCaptureBufferInfo"}, - {0x00410040, NULL, "ReceiveCaptureBufferInfo"}, - {0x00420080, NULL, "SleepSystem"}, - {0x00430040, NULL, "NotifyToWait"}, - {0x00440000, NULL, "GetSharedFont"}, - {0x00450040, NULL, "GetWirelessRebootInfo"}, - {0x00460104, NULL, "Wrap"}, - {0x00470104, NULL, "Unwrap"}, - {0x00480100, NULL, "GetProgramInfo"}, - {0x00490180, NULL, "Reboot"}, - {0x004A0040, NULL, "GetCaptureInfo"}, - {0x004B00C2, NULL, "AppletUtility"}, - {0x004C0000, NULL, "SetFatalErrDispMode"}, - {0x004D0080, NULL, "GetAppletProgramInfo"}, - {0x004E0000, NULL, "HardwareResetAsync"}, + {0x00010040, GetLockHandle, "GetLockHandle"}, + {0x00020080, Initialize, "Initialize"}, + {0x00030040, Enable, "Enable"}, + {0x00040040, NULL, "Finalize"}, + {0x00050040, NULL, "GetAppletManInfo"}, + {0x00060040, NULL, "GetAppletInfo"}, + {0x00070000, NULL, "GetLastSignaledAppletId"}, + {0x00080000, NULL, "CountRegisteredApplet"}, + {0x00090040, NULL, "IsRegistered"}, + {0x000A0040, NULL, "GetAttribute"}, + {0x000B0040, InquireNotification, "InquireNotification"}, + {0x000C0104, NULL, "SendParameter"}, + {0x000D0080, NULL, "ReceiveParameter"}, + {0x000E0080, NULL, "GlanceParameter"}, + {0x000F0100, NULL, "CancelParameter"}, + {0x001000C2, NULL, "DebugFunc"}, + {0x001100C0, NULL, "MapProgramIdForDebug"}, + {0x00120040, NULL, "SetHomeMenuAppletIdForDebug"}, + {0x00130000, NULL, "GetPreparationState"}, + {0x00140040, NULL, "SetPreparationState"}, + {0x00150140, NULL, "PrepareToStartApplication"}, + {0x00160040, NULL, "PreloadLibraryApplet"}, + {0x00170040, NULL, "FinishPreloadingLibraryApplet"}, + {0x00180040, NULL, "PrepareToStartLibraryApplet"}, + {0x00190040, NULL, "PrepareToStartSystemApplet"}, + {0x001A0000, NULL, "PrepareToStartNewestHomeMenu"}, + {0x001B00C4, NULL, "StartApplication"}, + {0x001C0000, NULL, "WakeupApplication"}, + {0x001D0000, NULL, "CancelApplication"}, + {0x001E0084, NULL, "StartLibraryApplet"}, + {0x001F0084, NULL, "StartSystemApplet"}, + {0x00200044, NULL, "StartNewestHomeMenu"}, + {0x00210000, NULL, "OrderToCloseApplication"}, + {0x00220040, NULL, "PrepareToCloseApplication"}, + {0x00230040, NULL, "PrepareToJumpToApplication"}, + {0x00240044, NULL, "JumpToApplication"}, + {0x002500C0, NULL, "PrepareToCloseLibraryApplet"}, + {0x00260000, NULL, "PrepareToCloseSystemApplet"}, + {0x00270044, NULL, "CloseApplication"}, + {0x00280044, NULL, "CloseLibraryApplet"}, + {0x00290044, NULL, "CloseSystemApplet"}, + {0x002A0000, NULL, "OrderToCloseSystemApplet"}, + {0x002B0000, NULL, "PrepareToJumpToHomeMenu"}, + {0x002C0044, NULL, "JumpToHomeMenu"}, + {0x002D0000, NULL, "PrepareToLeaveHomeMenu"}, + {0x002E0044, NULL, "LeaveHomeMenu"}, + {0x002F0040, NULL, "PrepareToLeaveResidentApplet"}, + {0x00300044, NULL, "LeaveResidentApplet"}, + {0x00310100, NULL, "PrepareToDoApplicationJump"}, + {0x00320084, NULL, "DoApplicationJump"}, + {0x00330000, NULL, "GetProgramIdOnApplicationJump"}, + {0x00340084, NULL, "SendDeliverArg"}, + {0x00350080, NULL, "ReceiveDeliverArg"}, + {0x00360040, NULL, "LoadSysMenuArg"}, + {0x00370042, NULL, "StoreSysMenuArg"}, + {0x00380040, NULL, "PreloadResidentApplet"}, + {0x00390040, NULL, "PrepareToStartResidentApplet"}, + {0x003A0044, NULL, "StartResidentApplet"}, + {0x003B0040, NULL, "CancelLibraryApplet"}, + {0x003C0042, NULL, "SendDspSleep"}, + {0x003D0042, NULL, "SendDspWakeUp"}, + {0x003E0080, NULL, "ReplySleepQuery"}, + {0x003F0040, NULL, "ReplySleepNotificationComplete"}, + {0x00400042, NULL, "SendCaptureBufferInfo"}, + {0x00410040, NULL, "ReceiveCaptureBufferInfo"}, + {0x00420080, NULL, "SleepSystem"}, + {0x00430040, NULL, "NotifyToWait"}, + {0x00440000, NULL, "GetSharedFont"}, + {0x00450040, NULL, "GetWirelessRebootInfo"}, + {0x00460104, NULL, "Wrap"}, + {0x00470104, NULL, "Unwrap"}, + {0x00480100, NULL, "GetProgramInfo"}, + {0x00490180, NULL, "Reboot"}, + {0x004A0040, NULL, "GetCaptureInfo"}, + {0x004B00C2, NULL, "AppletUtility"}, + {0x004C0000, NULL, "SetFatalErrDispMode"}, + {0x004D0080, NULL, "GetAppletProgramInfo"}, + {0x004E0000, NULL, "HardwareResetAsync"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// From e7202e5b2d086c4eaa8a324a54b878aa4689d4e4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 18:52:57 -0400 Subject: [PATCH 24/84] svc: added ArbitrationType enumeration --- src/core/hle/svc.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index 5c35977d1..c5170aab7 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h @@ -38,6 +38,15 @@ enum ResetType { RESETTYPE_MAX_BIT = (1u << 31), }; +enum ArbitrationType { + ARBITRATIONTYPE_SIGNAL, + ARBITRATIONTYPE_WAIT_IF_LESS_THAN, + ARBITRATIONTYPE_DECREMENT_AND_WAIT_IF_LESS_THAN, + ARBITRATIONTYPE_WAIT_IF_LESS_THAN_WITH_TIMEOUT, + ARBITRATIONTYPE_DECREMENT_AND_WAIT_IF_LESS_THAN_WITH_TIMEOUT, + ARBITRATIONTYPE_MAX_BIT = (1u << 31) +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SVC From b08b3c154fd5c2cdb12ab88597863f736c156123 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 18:53:45 -0400 Subject: [PATCH 25/84] srv: changed a NOTICE_LOG to DEBUG_LOG --- src/core/hle/service/srv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 7bbc03bf6..97e7fc8fa 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -36,7 +36,7 @@ void GetServiceHandle(Service::Interface* self) { std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); - NOTICE_LOG(OSHLE, "SRV::Sync - GetHandle - port: %s, handle: 0x%08X", port_name.c_str(), + DEBUG_LOG(OSHLE, "SRV::Sync - GetHandle - port: %s, handle: 0x%08X", port_name.c_str(), service->GetHandle()); if (NULL != service) { From 545e6919ce33a815761aef0f32e8e052858a60b3 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 18:54:59 -0400 Subject: [PATCH 26/84] service: added additional hack to return success on unimplemented service calls --- src/core/hle/service/service.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 4a3d4c68a..8f8d4d552 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -87,12 +87,20 @@ public: if (itr == m_functions.end()) { ERROR_LOG(OSHLE, "Unknown/unimplemented function: port = %s, command = 0x%08X!", GetPortName(), cmd_buff[0]); - return 0; // TODO(bunnei): Hack - ignore error + + // TODO(bunnei): Hack - ignore error + u32* cmd_buff = Service::GetCommandBuffer(); + cmd_buff[1] = 0; + return 0; } if (itr->second.func == NULL) { ERROR_LOG(OSHLE, "Unimplemented function: port = %s, name = %s!", GetPortName(), itr->second.name.c_str()); - return 0; // TODO(bunnei): Hack - ignore error + + // TODO(bunnei): Hack - ignore error + u32* cmd_buff = Service::GetCommandBuffer(); + cmd_buff[1] = 0; + return 0; } itr->second.func(this); From d51c84dde22549c7413e52a682158e6da3ff1fdc Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 20:00:44 -0400 Subject: [PATCH 27/84] event: added support for ClearEvent, fixed a bug with CreateEvent, fixed some comments --- src/core/hle/kernel/event.cpp | 18 +++++++++++------- src/core/hle/kernel/event.h | 5 +++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e85f39f0d..7cb8c5142 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -54,11 +54,16 @@ public: * Changes whether an event is locked or not * @param handle Handle to event to change * @param locked Boolean locked value to set event + * @return Result of operation, 0 on success, otherwise error code */ -void SetEventLocked(const Handle handle, const bool locked) { +Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "SetEventLocked called with unknown handle=0x%08X", handle); + return -1; + } evt->locked = locked; - return; + return 0; } /** @@ -67,23 +72,22 @@ void SetEventLocked(const Handle handle, const bool locked) { * @return Result of operation, 0 on success, otherwise error code */ Result ClearEvent(Handle handle) { - ERROR_LOG(KERNEL, "Unimplemented function ClearEvent"); - return 0; + return SetEventLocked(handle, true); } /** * Creates an event * @param handle Reference to handle for the newly created mutex * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Newly created Event object */ Event* CreateEvent(Handle& handle, const ResetType reset_type) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); + evt->locked = true; evt->reset_type = evt->intitial_reset_type = reset_type; - evt->locked = false; return evt; } @@ -91,7 +95,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { /** * Creates an event * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Handle to newly created Event object */ Handle CreateEvent(const ResetType reset_type) { Handle handle; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index c1842cb88..b1d2c6ad1 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -15,8 +15,9 @@ namespace Kernel { * Changes whether an event is locked or not * @param handle Handle to event to change * @param locked Boolean locked value to set event + * @return Result of operation, 0 on success, otherwise error code */ -void SetEventLocked(const Handle handle, const bool locked); +Result SetEventLocked(const Handle handle, const bool locked); /** * Clears an event @@ -28,7 +29,7 @@ Result ClearEvent(Handle handle); /** * Creates an event * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Handle to newly created Event object */ Handle CreateEvent(const ResetType reset_type); From 58af0da792adab4bfd77699f9431050290a75b7c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 20:24:51 -0400 Subject: [PATCH 28/84] svc: added svcClearEvent, stubbed function for svcArbitrateAddress, and various fixes - force kernel reschedule after svcWaitSynchronization - fixed some bugs with passing in pointer arguments - cleaned up some comments and log messages --- src/core/hle/function_wrappers.h | 6 ++++ src/core/hle/svc.cpp | 54 +++++++++++++++++++------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 7b07d8ca8..43f0d15e0 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -758,3 +758,9 @@ template void WrapI_VVUUS64() { int retval = func(Memory::GetPointer(PARAM(5)), Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); RETURN(retval); } + +// TODO(bunne): Is this correct? Probably not +template void WrapI_UUUUS64() { + int retval = func(PARAM(5), PARAM(1), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); + RETURN(retval); +} diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 8468c4fab..8ef894e68 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -35,7 +35,6 @@ enum MapMemoryPermission { /// Map application or GSP heap memory Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { - u32* outaddr = (u32*)_outaddr; u32 virtual_address = 0x00000000; DEBUG_LOG(SVC, "ControlMemory called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", @@ -57,9 +56,7 @@ Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 si default: ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation); } - if (NULL != outaddr) { - *outaddr = virtual_address; - } + Core::g_app_core->SetReg(1, virtual_address); return 0; @@ -82,7 +79,7 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper } /// Connect to an OS service given the port name, returns the handle to the port to out -Result ConnectToPort(void* out, const char* port_name) { +Result ConnectToPort(void* _out, const char* port_name) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); _assert_msg_(KERNEL, service, "ConnectToPort called, but service is not implemented!"); @@ -128,6 +125,7 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { if (wait) { Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? + Kernel::Reschedule(); } return res; @@ -138,7 +136,6 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa s64 nano_seconds) { // TODO(bunnei): Do something with nano_seconds, currently ignoring this - s32* out = (s32*)_out; Handle* handles = (Handle*)_handles; bool unlock_all = true; @@ -153,6 +150,8 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa _assert_msg_(KERNEL, object, "WaitSynchronizationN called handle=0x%08X, but kernel object " "is NULL!", handles[i]); + DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X", i, handles[i]); + Result res = object->WaitSynchronization(&wait); if (!wait && !wait_all) { @@ -170,18 +169,26 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa // Set current thread to wait state if not all handles were unlocked Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? + Kernel::Reschedule(); return 0; } /// Create an address arbiter (to allocate access to shared resources) Result CreateAddressArbiter(void* arbiter) { - // ImplementMe DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called"); Core::g_app_core->SetReg(1, 0xFABBDADD); return 0; } +/// Arbitrate address +Result ArbitrateAddress(Handle arbiter, u32 addr, u32 _type, u32 value, s64 nanoseconds) { + DEBUG_LOG(SVC, "(UNIMPLEMENTED) ArbitrateAddress called"); + ArbitrationType type = (ArbitrationType)_type; + Memory::Write32(addr, type); + return 0; +} + /// Used to output a message on a debug hardware unit - does nothing on a retail unit void OutputDebugString(const char* string) { NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string); @@ -199,7 +206,6 @@ Result GetResourceLimit(void* resource_limit, Handle process) { /// Get resource limit current values Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) { - //s64* values = (s64*)_values; DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d", resource_limit, names, name_count); Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now @@ -224,7 +230,7 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p Core::g_app_core->SetReg(1, thread); DEBUG_LOG(SVC, "CreateThread called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " - "threadpriority=0x%08X, processorid=0x%08X : created handle 0x%08X", entry_point, + "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, name.c_str(), arg, stack_top, priority, processor_id, thread); return 0; @@ -232,11 +238,10 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p /// Create a mutex Result CreateMutex(void* _mutex, u32 initial_locked) { - Handle* mutex = (Handle*)_mutex; - DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s : created handle 0x%08X", - initial_locked ? "true" : "false", *mutex); - *mutex = Kernel::CreateMutex((initial_locked != 0)); - Core::g_app_core->SetReg(1, *mutex); + Handle mutex = Kernel::CreateMutex((initial_locked != 0)); + Core::g_app_core->SetReg(1, mutex); + DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s : created handle=0x%08X", + initial_locked ? "true" : "false", mutex); return 0; } @@ -256,18 +261,16 @@ Result GetThreadId(void* thread_id, u32 thread) { /// Query memory Result QueryMemory(void *_info, void *_out, u32 addr) { - MemoryInfo* info = (MemoryInfo*) _info; - PageInfo* out = (PageInfo*) _out; DEBUG_LOG(SVC, "(UNIMPLEMENTED) QueryMemory called addr=0x%08X", addr); return 0; } /// Create an event Result CreateEvent(void* _event, u32 reset_type) { - Handle* evt = (Handle*)_event; - DEBUG_LOG(SVC, "CreateEvent called reset_type=0x%08X", reset_type); - *evt = Kernel::CreateEvent((ResetType)reset_type); - Core::g_app_core->SetReg(1, *evt); + Handle evt = Kernel::CreateEvent((ResetType)reset_type); + Core::g_app_core->SetReg(1, evt); + DEBUG_LOG(SVC, "CreateEvent called reset_type=0x%08X : created handle=0x%08X", + reset_type, evt); return 0; } @@ -278,6 +281,13 @@ Result DuplicateHandle(void* _out, Handle handle) { return 0; } +/// Clears an event +Result ClearEvent(Handle evt) { + Result res = Kernel::ClearEvent(evt); + DEBUG_LOG(SVC, "ClearEvent called event=0x%08X", evt); + return res; +} + const HLE::FunctionDef SVC_Table[] = { {0x00, NULL, "Unknown"}, {0x01, WrapI_VUUUUU, "ControlMemory"}, @@ -304,7 +314,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x16, NULL, "ReleaseSemaphore"}, {0x17, WrapI_VU, "CreateEvent"}, {0x18, NULL, "SignalEvent"}, - {0x19, NULL, "ClearEvent"}, + {0x19, WrapI_U, "ClearEvent"}, {0x1A, NULL, "CreateTimer"}, {0x1B, NULL, "SetTimer"}, {0x1C, NULL, "CancelTimer"}, @@ -313,7 +323,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x1F, WrapI_UUUU, "MapMemoryBlock"}, {0x20, NULL, "UnmapMemoryBlock"}, {0x21, WrapI_V, "CreateAddressArbiter"}, - {0x22, NULL, "ArbitrateAddress"}, + {0x22, WrapI_UUUUS64, "ArbitrateAddress"}, {0x23, WrapI_U, "CloseHandle"}, {0x24, WrapI_US64, "WaitSynchronization1"}, {0x25, WrapI_VVUUS64, "WaitSynchronizationN"}, From 6d267142ad42ed09e475742cab463b55d9176c29 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 20:26:27 -0400 Subject: [PATCH 29/84] svc: changed unimplemented SVC log messages from "debug" messages to "error" messages --- src/core/hle/svc.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 8ef894e68..6df0309e6 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -106,7 +106,7 @@ Result SendSyncRequest(Handle handle) { /// Close a handle Result CloseHandle(Handle handle) { // ImplementMe - DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); + ERROR_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); return 0; } @@ -176,14 +176,14 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa /// Create an address arbiter (to allocate access to shared resources) Result CreateAddressArbiter(void* arbiter) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called"); + ERROR_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called"); Core::g_app_core->SetReg(1, 0xFABBDADD); return 0; } /// Arbitrate address Result ArbitrateAddress(Handle arbiter, u32 addr, u32 _type, u32 value, s64 nanoseconds) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) ArbitrateAddress called"); + ERROR_LOG(SVC, "(UNIMPLEMENTED) ArbitrateAddress called"); ArbitrationType type = (ArbitrationType)_type; Memory::Write32(addr, type); return 0; @@ -199,14 +199,14 @@ Result GetResourceLimit(void* resource_limit, Handle process) { // With regards to proceess values: // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for // the current KThread. - DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process); + ERROR_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process); Core::g_app_core->SetReg(1, 0xDEADBEEF); return 0; } /// Get resource limit current values Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d", + ERROR_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d", resource_limit, names, name_count); Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now return 0; @@ -255,13 +255,13 @@ Result ReleaseMutex(Handle handle) { /// Get current thread ID Result GetThreadId(void* thread_id, u32 thread) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetThreadId called thread=0x%08X", thread); + ERROR_LOG(SVC, "(UNIMPLEMENTED) GetThreadId called thread=0x%08X", thread); return 0; } /// Query memory Result QueryMemory(void *_info, void *_out, u32 addr) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) QueryMemory called addr=0x%08X", addr); + ERROR_LOG(SVC, "(UNIMPLEMENTED) QueryMemory called addr=0x%08X", addr); return 0; } @@ -277,7 +277,7 @@ Result CreateEvent(void* _event, u32 reset_type) { /// Duplicates a kernel handle Result DuplicateHandle(void* _out, Handle handle) { Handle* out = (Handle*)_out; - DEBUG_LOG(SVC, "(UNIMPLEMENTED) DuplicateHandle called handle=0x%08X", handle); + ERROR_LOG(SVC, "(UNIMPLEMENTED) DuplicateHandle called handle=0x%08X", handle); return 0; } From 9839f3b6cd9ea0d62730edee7db027dde86f6239 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 20:30:17 -0400 Subject: [PATCH 30/84] core: changed time delay before kernel reschedule to "approximate" a screen refresh --- src/core/core.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index f88bcd704..070f92ed5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -9,6 +9,7 @@ #include "core/core.h" #include "core/mem_map.h" #include "core/hw/hw.h" +#include "core/hw/lcd.h" #include "core/arm/disassembler/arm_disasm.h" #include "core/arm/interpreter/arm_interpreter.h" @@ -23,7 +24,7 @@ ARM_Interface* g_sys_core = NULL; ///< ARM11 system (OS) core /// Run the core CPU loop void RunLoop() { for (;;){ - g_app_core->Run(100); + g_app_core->Run(LCD::kFrameTicks / 2); HW::Update(); Kernel::Reschedule(); } @@ -31,9 +32,17 @@ void RunLoop() { /// Step the CPU one instruction void SingleStep() { + static int ticks = 0; + g_app_core->Step(); - HW::Update(); - Kernel::Reschedule(); + + if (ticks >= LCD::kFrameTicks / 2) { + HW::Update(); + Kernel::Reschedule(); + ticks = 0; + } else { + ticks++; + } } /// Halt the core From 6fc62f8c93bd81f6207fcbdfe332b4e56c2aa2be Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 23:03:03 -0400 Subject: [PATCH 31/84] log: fixed to not print twice, enabled coloring, added OS print logging as its own type --- src/common/console_listener.cpp | 16 ++++++---------- src/common/log.h | 31 +++++++++++++++++++------------ src/common/log_manager.cpp | 28 +++++++++++++++------------- src/common/log_manager.h | 4 ++-- 4 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/common/console_listener.cpp b/src/common/console_listener.cpp index b5f32d1bd..db48abbf6 100644 --- a/src/common/console_listener.cpp +++ b/src/common/console_listener.cpp @@ -259,14 +259,17 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) switch (Level) { + case OS_LEVEL: // light yellow + Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + break; case NOTICE_LEVEL: // light green Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; case ERROR_LEVEL: // light red Color = FOREGROUND_RED | FOREGROUND_INTENSITY; break; - case WARNING_LEVEL: // light yellow - Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + case WARNING_LEVEL: // light purple + Color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break; case INFO_LEVEL: // cyan Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; @@ -278,15 +281,8 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; } - if (strlen(Text) > 10) - { - // First 10 chars white - SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); - WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL); - Text += 10; - } SetConsoleTextAttribute(hConsole, Color); - WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL); + printf(Text); #else char ColorAttr[16] = ""; char ResetAttr[16] = ""; diff --git a/src/common/log.h b/src/common/log.h index 8b39b03a1..2543b51a8 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -7,11 +7,14 @@ #define LOGGING -#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports. -#define ERROR_LEVEL 2 // Critical errors -#define WARNING_LEVEL 3 // Something is suspicious. -#define INFO_LEVEL 4 // General information. -#define DEBUG_LEVEL 5 // Detailed debugging - might make things slow. +enum { + OS_LEVEL, // Printed by the emulated operating system + NOTICE_LEVEL, // VERY important information that is NOT errors. Like startup and OSReports. + ERROR_LEVEL, // Critical errors + WARNING_LEVEL, // Something is suspicious. + INFO_LEVEL, // General information. + DEBUG_LEVEL, // Detailed debugging - might make things slow. +}; namespace LogTypes { @@ -70,6 +73,7 @@ enum LOG_TYPE { // FIXME: should this be removed? enum LOG_LEVELS { + LOS = OS_LEVEL, LNOTICE = NOTICE_LEVEL, LERROR = ERROR_LEVEL, LWARNING = WARNING_LEVEL, @@ -82,8 +86,8 @@ enum LOG_LEVELS { } // namespace -void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, - const char *file, int line, const char *fmt, ...) +void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line, + const char* function, const char* fmt, ...) #ifdef __GNUC__ __attribute__((format(printf, 5, 6))) #endif @@ -97,16 +101,19 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, #endif // loglevel #endif // logging -#ifdef GEKKO -#define GENERIC_LOG(t, v, ...) -#else +#ifdef _WIN32 +#ifndef __func__ +#define __func__ __FUNCTION__ +#endif +#endif + // Let the compiler optimize this out #define GENERIC_LOG(t, v, ...) { \ if (v <= MAX_LOGLEVEL) \ - GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \ + GenericLog(v, t, __FILE__, __LINE__, __func__, __VA_ARGS__); \ } -#endif +#define OS_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LOS, __VA_ARGS__) } while (0) #define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0) #define WARN_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LWARNING, __VA_ARGS__) } while (0) #define NOTICE_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LNOTICE, __VA_ARGS__) } while (0) diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index 146472888..d026fca56 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp @@ -10,14 +10,16 @@ #include "common/thread.h" #include "common/file_util.h" -void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, - const char *file, int line, const char* fmt, ...) +void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, + const char* function, const char* fmt, ...) { va_list args; va_start(args, fmt); - if (LogManager::GetInstance()) + + if (LogManager::GetInstance()) { LogManager::GetInstance()->Log(level, type, - file, line, fmt, args); + file, line, function, fmt, args); + } va_end(args); } @@ -88,6 +90,8 @@ LogManager::LogManager() m_Log[i]->AddListener(m_debuggerLog); #endif } + + m_consoleLog->Open(); } LogManager::~LogManager() @@ -107,8 +111,8 @@ LogManager::~LogManager() delete m_debuggerLog; } -void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, - const char *file, int line, const char *format, va_list args) +void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, + int line, const char* function, const char *fmt, va_list args) { char temp[MAX_MSGLEN]; char msg[MAX_MSGLEN * 2]; @@ -117,17 +121,15 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners()) return; - CharArrayFromFormatV(temp, MAX_MSGLEN, format, args); + CharArrayFromFormatV(temp, MAX_MSGLEN, fmt, args); - static const char level_to_char[7] = "-NEWID"; - sprintf(msg, "%s %s:%u %c[%s]: %s\n", - Common::Timer::GetTimeFormatted().c_str(), - file, line, level_to_char[(int)level], - log->GetShortName(), temp); + static const char level_to_char[7] = "ONEWID"; + sprintf(msg, "%s %s:%u %c[%s] %s: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line, + level_to_char[(int)level], log->GetShortName(), function, temp); + #ifdef ANDROID Host_SysMessage(msg); #endif - printf(msg); // TODO(ShizZy): RemoveMe when I no longer need this log->Trigger(level, msg); } diff --git a/src/common/log_manager.h b/src/common/log_manager.h index 580860b4d..3e238dfa7 100644 --- a/src/common/log_manager.h +++ b/src/common/log_manager.h @@ -99,8 +99,8 @@ public: static u32 GetMaxLevel() { return MAX_LOGLEVEL; } - void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, - const char *file, int line, const char *fmt, va_list args); + void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, + const char* function, const char *fmt, va_list args); void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level) { From 55a540eb0209b58a03c6a095b3b475892af150a9 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 23:03:47 -0400 Subject: [PATCH 32/84] arm: removed unnecessary code when calling SVC from skyeye --- src/core/arm/interpreter/armemu.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index e5dc7bd44..1e22cda9d 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -4533,23 +4533,7 @@ ARMul_Emulate26 (ARMul_State * state) case 0xfd: case 0xfe: case 0xff: - if (instr == ARMul_ABORTWORD - && state->AbortAddr == pc) { - /* A prefetch abort. */ - XScale_set_fsr_far (state, - ARMul_CP15_R5_MMU_EXCPT, - pc); - ARMul_Abort (state, - ARMul_PrefetchAbortV); - break; - } - //sky_pref_t* pref = get_skyeye_pref(); - //if(pref->user_mode_sim){ - // ARMul_OSHandleSWI (state, BITS (0, 23)); - // break; - //} HLE::CallSVC(instr); - ARMul_Abort (state, ARMul_SWIV); break; } } From b0bad47c0e25717bb1c69bc9a286e57f39064238 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 23:04:18 -0400 Subject: [PATCH 33/84] svc: updated OutputDebugString to use OS_LOG --- src/core/hle/svc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 6df0309e6..27f2b2315 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -191,7 +191,7 @@ Result ArbitrateAddress(Handle arbiter, u32 addr, u32 _type, u32 value, s64 nano /// Used to output a message on a debug hardware unit - does nothing on a retail unit void OutputDebugString(const char* string) { - NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string); + OS_LOG(SVC, "%s", string); } /// Get resource limit From c404d22036e16d20d91fca0cf29d56785656c0f5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 23:26:58 -0400 Subject: [PATCH 34/84] hle: cleaned up log messages --- src/core/hle/config_mem.cpp | 2 +- src/core/hle/hle.cpp | 6 ++-- src/core/hle/service/apt.cpp | 8 ++--- src/core/hle/service/gsp.cpp | 4 +-- src/core/hle/service/service.cpp | 8 +++-- src/core/hle/service/srv.cpp | 6 ++-- src/core/hle/svc.cpp | 55 ++++++++++++++++---------------- src/core/mem_map_funcs.cpp | 5 ++- 8 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index 48aa878cc..8c898b265 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp @@ -55,7 +55,7 @@ inline void Read(T &var, const u32 addr) { break; default: - ERROR_LOG(HLE, "unknown ConfigMem::Read%d @ 0x%08X", sizeof(var) * 8, addr); + ERROR_LOG(HLE, "unknown addr=0x%08X", addr); } } diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 080c36abf..f703da44e 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -18,7 +18,7 @@ static std::vector g_module_db; const FunctionDef* GetSVCInfo(u32 opcode) { u32 func_num = opcode & 0xFFFFFF; // 8 bits if (func_num > 0xFF) { - ERROR_LOG(HLE,"Unknown SVC: 0x%02X", func_num); + ERROR_LOG(HLE,"unknown svc=0x%02X", func_num); return NULL; } return &g_module_db[0].func_table[func_num]; @@ -33,7 +33,7 @@ void CallSVC(u32 opcode) { if (info->func) { info->func(); } else { - ERROR_LOG(HLE, "Unimplemented SVC function %s(..)", info->name.c_str()); + ERROR_LOG(HLE, "unimplemented SVC function %s(..)", info->name.c_str()); } } @@ -43,7 +43,7 @@ void EatCycles(u32 cycles) { void ReSchedule(const char *reason) { #ifdef _DEBUG - _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "ReSchedule: Invalid or too long reason."); + _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); #endif // TODO: ImplementMe } diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index f2118ba03..10d9a94bd 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -17,7 +17,7 @@ namespace APT_U { void Initialize(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); - DEBUG_LOG(KERNEL, "APT_U::Initialize called"); + DEBUG_LOG(KERNEL, "called"); cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT menu event handle cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT pause event handle @@ -33,14 +33,14 @@ void GetLockHandle(Service::Interface* self) { u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field cmd_buff[1] = 0; // No error cmd_buff[5] = Kernel::CreateMutex(false); - DEBUG_LOG(KERNEL, "APT_U::GetLockHandle called handle=0x%08X", cmd_buff[5]); + DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]); } void Enable(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for? cmd_buff[1] = 0; // No error - ERROR_LOG(KERNEL, "(UNIMPEMENTED) APT_U::Enable called unk=0x%08X", unk); + ERROR_LOG(KERNEL, "(UNIMPEMENTED) called unk=0x%08X", unk); } void InquireNotification(Service::Interface* self) { @@ -48,7 +48,7 @@ void InquireNotification(Service::Interface* self) { u32 app_id = cmd_buff[2]; cmd_buff[1] = 0; // No error cmd_buff[3] = 0; // Signal type - ERROR_LOG(KERNEL, "(UNIMPEMENTED) APT_U::InquireNotification called app_id=0x%08X", app_id); + ERROR_LOG(KERNEL, "(UNIMPEMENTED) called app_id=0x%08X", app_id); } const Interface::FunctionInfo FunctionTable[] = { diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 50cee2c41..575db86c1 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -92,7 +92,7 @@ void ReadHWRegs(Service::Interface* self) { break; default: - ERROR_LOG(GSP, "ReadHWRegs unknown register read at address %08X", reg_addr); + ERROR_LOG(GSP, "unknown register read at address %08X", reg_addr); } } @@ -117,7 +117,7 @@ void TriggerCmdReqQueue(Service::Interface* self) { break; default: - ERROR_LOG(GSP, "TriggerCmdReqQueue unknown command 0x%08X", cmd_buff[0]); + ERROR_LOG(GSP, "unknown command 0x%08X", cmd_buff[0]); } GX_FinishCommand(g_thread_id); diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 08d0c43ff..904670e62 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -12,6 +12,8 @@ #include "core/hle/service/apt.h" #include "core/hle/service/gsp.h" #include "core/hle/service/hid.h" +#include "core/hle/service/ndm.h" +#include "core/hle/service/pt.h" #include "core/hle/service/srv.h" #include "core/hle/kernel/kernel.h" @@ -72,14 +74,16 @@ void Init() { g_manager->AddService(new APT_U::Interface); g_manager->AddService(new GSP_GPU::Interface); g_manager->AddService(new HID_User::Interface); + g_manager->AddService(new NDM_U::Interface); + g_manager->AddService(new PT_A::Interface); - NOTICE_LOG(HLE, "Services initialized OK"); + NOTICE_LOG(HLE, "initialized OK"); } /// Shutdown ServiceManager void Shutdown() { delete g_manager; - NOTICE_LOG(HLE, "Services shutdown OK"); + NOTICE_LOG(HLE, "shutdown OK"); } diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 97e7fc8fa..ac8f398fc 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -15,14 +15,14 @@ namespace SRV { Handle g_mutex = 0; void Initialize(Service::Interface* self) { - DEBUG_LOG(OSHLE, "SRV::Initialize called"); + DEBUG_LOG(OSHLE, "called"); if (!g_mutex) { g_mutex = Kernel::CreateMutex(false); } } void GetProcSemaphore(Service::Interface* self) { - DEBUG_LOG(OSHLE, "SRV::GetProcSemaphore called"); + DEBUG_LOG(OSHLE, "called"); // Get process semaphore? u32* cmd_buff = Service::GetCommandBuffer(); cmd_buff[1] = 0; // No error @@ -36,7 +36,7 @@ void GetServiceHandle(Service::Interface* self) { std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); - DEBUG_LOG(OSHLE, "SRV::Sync - GetHandle - port: %s, handle: 0x%08X", port_name.c_str(), + DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), service->GetHandle()); if (NULL != service) { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 27f2b2315..01fb647e7 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -37,7 +37,7 @@ enum MapMemoryPermission { Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { u32 virtual_address = 0x00000000; - DEBUG_LOG(SVC, "ControlMemory called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", + DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", operation, addr0, addr1, size, permissions); switch (operation) { @@ -54,7 +54,7 @@ Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 si // Unknown ControlMemory operation default: - ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation); + ERROR_LOG(SVC, "unknown operation=0x%08X", operation); } Core::g_app_core->SetReg(1, virtual_address); @@ -64,7 +64,7 @@ Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 si /// Maps a memory block to specified address Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) { - DEBUG_LOG(SVC, "MapMemoryBlock called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", + DEBUG_LOG(SVC, "called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", memblock, addr, mypermissions, otherpermission); switch (mypermissions) { case MEMORY_PERMISSION_NORMAL: @@ -73,7 +73,7 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper Memory::MapBlock_Shared(memblock, addr, mypermissions); break; default: - ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions); + ERROR_LOG(OSHLE, "unknown permissions=0x%08X", mypermissions); } return 0; } @@ -81,8 +81,8 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper /// Connect to an OS service given the port name, returns the handle to the port to out Result ConnectToPort(void* _out, const char* port_name) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); - DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); - _assert_msg_(KERNEL, service, "ConnectToPort called, but service is not implemented!"); + DEBUG_LOG(SVC, "called port_name=%s", port_name); + _assert_msg_(KERNEL, service, "called, but service is not implemented!"); Core::g_app_core->SetReg(1, service->GetHandle()); return 0; } @@ -92,8 +92,8 @@ Result SendSyncRequest(Handle handle) { bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); - DEBUG_LOG(SVC, "SendSyncRequest called handle=0x%08X", handle); - _assert_msg_(KERNEL, object, "SendSyncRequest called, but kernel object is NULL!"); + DEBUG_LOG(SVC, "called handle=0x%08X", handle); + _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); Result res = object->SyncRequest(&wait); if (wait) { @@ -106,7 +106,7 @@ Result SendSyncRequest(Handle handle) { /// Close a handle Result CloseHandle(Handle handle) { // ImplementMe - ERROR_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); + ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); return 0; } @@ -117,9 +117,9 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); - DEBUG_LOG(SVC, "WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", handle, + DEBUG_LOG(SVC, "called handle=0x%08X, nanoseconds=%d", handle, nano_seconds); - _assert_msg_(KERNEL, object, "WaitSynchronization1 called, but kernel object is NULL!"); + _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); Result res = object->WaitSynchronization(&wait); @@ -139,7 +139,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa Handle* handles = (Handle*)_handles; bool unlock_all = true; - DEBUG_LOG(SVC, "WaitSynchronizationN called handle_count=%d, wait_all=%s, nanoseconds=%d", + DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%d", handle_count, (wait_all ? "true" : "false"), nano_seconds); // Iterate through each handle, synchronize kernel object @@ -147,7 +147,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handles[i]); // 0 handle - _assert_msg_(KERNEL, object, "WaitSynchronizationN called handle=0x%08X, but kernel object " + _assert_msg_(KERNEL, object, "called handle=0x%08X, but kernel object " "is NULL!", handles[i]); DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X", i, handles[i]); @@ -176,14 +176,14 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa /// Create an address arbiter (to allocate access to shared resources) Result CreateAddressArbiter(void* arbiter) { - ERROR_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called"); + ERROR_LOG(SVC, "(UNIMPLEMENTED) called"); Core::g_app_core->SetReg(1, 0xFABBDADD); return 0; } /// Arbitrate address Result ArbitrateAddress(Handle arbiter, u32 addr, u32 _type, u32 value, s64 nanoseconds) { - ERROR_LOG(SVC, "(UNIMPLEMENTED) ArbitrateAddress called"); + ERROR_LOG(SVC, "(UNIMPLEMENTED) called"); ArbitrationType type = (ArbitrationType)_type; Memory::Write32(addr, type); return 0; @@ -199,14 +199,15 @@ Result GetResourceLimit(void* resource_limit, Handle process) { // With regards to proceess values: // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for // the current KThread. - ERROR_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process); + ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); Core::g_app_core->SetReg(1, 0xDEADBEEF); return 0; } /// Get resource limit current values -Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) { - ERROR_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d", +Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, + s32 name_count) { + ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", resource_limit, names, name_count); Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now return 0; @@ -229,7 +230,7 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p Core::g_app_core->SetReg(1, thread); - DEBUG_LOG(SVC, "CreateThread called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " + DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, name.c_str(), arg, stack_top, priority, processor_id, thread); @@ -240,28 +241,28 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p Result CreateMutex(void* _mutex, u32 initial_locked) { Handle mutex = Kernel::CreateMutex((initial_locked != 0)); Core::g_app_core->SetReg(1, mutex); - DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s : created handle=0x%08X", + DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", initial_locked ? "true" : "false", mutex); return 0; } /// Release a mutex Result ReleaseMutex(Handle handle) { - DEBUG_LOG(SVC, "ReleaseMutex called handle=0x%08X", handle); - _assert_msg_(KERNEL, handle, "ReleaseMutex called, but handle is NULL!"); + DEBUG_LOG(SVC, "called handle=0x%08X", handle); + _assert_msg_(KERNEL, handle, "called, but handle is NULL!"); Kernel::ReleaseMutex(handle); return 0; } /// Get current thread ID Result GetThreadId(void* thread_id, u32 thread) { - ERROR_LOG(SVC, "(UNIMPLEMENTED) GetThreadId called thread=0x%08X", thread); + ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); return 0; } /// Query memory Result QueryMemory(void *_info, void *_out, u32 addr) { - ERROR_LOG(SVC, "(UNIMPLEMENTED) QueryMemory called addr=0x%08X", addr); + ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); return 0; } @@ -269,7 +270,7 @@ Result QueryMemory(void *_info, void *_out, u32 addr) { Result CreateEvent(void* _event, u32 reset_type) { Handle evt = Kernel::CreateEvent((ResetType)reset_type); Core::g_app_core->SetReg(1, evt); - DEBUG_LOG(SVC, "CreateEvent called reset_type=0x%08X : created handle=0x%08X", + DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, evt); return 0; } @@ -277,14 +278,14 @@ Result CreateEvent(void* _event, u32 reset_type) { /// Duplicates a kernel handle Result DuplicateHandle(void* _out, Handle handle) { Handle* out = (Handle*)_out; - ERROR_LOG(SVC, "(UNIMPLEMENTED) DuplicateHandle called handle=0x%08X", handle); + ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); return 0; } /// Clears an event Result ClearEvent(Handle evt) { Result res = Kernel::ClearEvent(evt); - DEBUG_LOG(SVC, "ClearEvent called event=0x%08X", evt); + DEBUG_LOG(SVC, "called event=0x%08X", evt); return res; } diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp index 86e9eaa20..ab014a596 100644 --- a/src/core/mem_map_funcs.cpp +++ b/src/core/mem_map_funcs.cpp @@ -86,7 +86,7 @@ inline void _Read(T &var, const u32 addr) { var = *((const T*)&g_vram[vaddr & VRAM_MASK]); } else { - //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr); + ERROR_LOG(MEMMAP, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr); } } @@ -136,8 +136,7 @@ inline void _Write(u32 addr, const T data) { // Error out... } else { - _assert_msg_(MEMMAP, false, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, - data, vaddr); + ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr); } } From d8a2c8c6579b78d9c61abe544cfaea651238130c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 23:31:01 -0400 Subject: [PATCH 35/84] mutex: fixed typo in ReleaseMutex --- src/core/hle/kernel/mutex.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 23c064571..5ac88cd85 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -8,6 +8,7 @@ #include "common/common.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/mutex.h" #include "core/hle/kernel/thread.h" namespace Kernel { @@ -92,10 +93,11 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { bool ReleaseMutex(Mutex* mutex) { MutexEraseLock(mutex); bool woke_threads = false; - auto iter = mutex->waiting_threads.begin(); + std::vector::iterator iter; // Find the next waiting thread for the mutex... while (!woke_threads && !mutex->waiting_threads.empty()) { + iter = mutex->waiting_threads.begin(); woke_threads |= ReleaseMutexForThread(mutex, *iter); mutex->waiting_threads.erase(iter); } From 007b7edada86bf97e1499625c3c8fda25132bbac Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 23:54:09 -0400 Subject: [PATCH 36/84] srv: fix to log unimplemented service (instead of crash) --- src/core/hle/service/srv.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index ac8f398fc..f1940e6f5 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -36,18 +36,14 @@ void GetServiceHandle(Service::Interface* self) { std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); - DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), - service->GetHandle()); - if (NULL != service) { cmd_buff[3] = service->GetHandle(); + DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); } else { - ERROR_LOG(OSHLE, "Service %s does not exist", port_name.c_str()); + ERROR_LOG(OSHLE, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); res = -1; } cmd_buff[1] = res; - - //return res; } const Interface::FunctionInfo FunctionTable[] = { From 2482be13df81eaae17b721e080249bd6c4de759e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 30 May 2014 00:22:25 -0400 Subject: [PATCH 37/84] service: removed PT_A from, as this was just an alias for APT_U --- src/core/hle/service/service.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 904670e62..781b41fb0 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -13,7 +13,6 @@ #include "core/hle/service/gsp.h" #include "core/hle/service/hid.h" #include "core/hle/service/ndm.h" -#include "core/hle/service/pt.h" #include "core/hle/service/srv.h" #include "core/hle/kernel/kernel.h" @@ -75,7 +74,6 @@ void Init() { g_manager->AddService(new GSP_GPU::Interface); g_manager->AddService(new HID_User::Interface); g_manager->AddService(new NDM_U::Interface); - g_manager->AddService(new PT_A::Interface); NOTICE_LOG(HLE, "initialized OK"); } From c451ad28355b48f9d55a9b1a939e913fbf875953 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 30 May 2014 00:22:39 -0400 Subject: [PATCH 38/84] service: cleaned up log messages --- src/core/hle/service/service.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 8f8d4d552..c3e9dd313 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -85,7 +85,7 @@ public: auto itr = m_functions.find(cmd_buff[0]); if (itr == m_functions.end()) { - ERROR_LOG(OSHLE, "Unknown/unimplemented function: port = %s, command = 0x%08X!", + ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X", GetPortName(), cmd_buff[0]); // TODO(bunnei): Hack - ignore error @@ -94,7 +94,7 @@ public: return 0; } if (itr->second.func == NULL) { - ERROR_LOG(OSHLE, "Unimplemented function: port = %s, name = %s!", + ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s", GetPortName(), itr->second.name.c_str()); // TODO(bunnei): Hack - ignore error From 55325dea4c85e1a91c6d37282322b466ef40ffac Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 30 May 2014 00:24:04 -0400 Subject: [PATCH 39/84] hle: added stubbed service for ndm_u --- src/core/CMakeLists.txt | 1 + src/core/core.vcxproj | 2 ++ src/core/core.vcxproj.filters | 6 ++++++ src/core/hle/service/ndm.cpp | 32 ++++++++++++++++++++++++++++++++ src/core/hle/service/ndm.h | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 src/core/hle/service/ndm.cpp create mode 100644 src/core/hle/service/ndm.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 468e6a631..7236033c4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRCS core.cpp hle/service/apt.cpp hle/service/gsp.cpp hle/service/hid.cpp + hle/service/ndm.cpp hle/service/service.cpp hle/service/srv.cpp hw/hw.cpp diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index efcd30d77..6fec75d79 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -175,6 +175,7 @@ + @@ -225,6 +226,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 135e4c89c..8e5966d73 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -168,6 +168,9 @@ hle\kernel + + hle\service + @@ -301,6 +304,9 @@ hle\kernel + + hle\service + diff --git a/src/core/hle/service/ndm.cpp b/src/core/hle/service/ndm.cpp new file mode 100644 index 000000000..671e9d4bd --- /dev/null +++ b/src/core/hle/service/ndm.cpp @@ -0,0 +1,32 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "common/log.h" + +#include "core/hle/hle.h" +#include "core/hle/service/ndm.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace NDM_U + +namespace NDM_U { + +const Interface::FunctionInfo FunctionTable[] = { + {0x00060040, NULL, "SuspendDaemons"}, + {0x00080040, NULL, "DisableWifiUsage"}, + {0x00090000, NULL, "EnableWifiUsage"}, + {0x00140040, NULL, "OverrideDefaultDaemons"}, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Interface class + +Interface::Interface() { + Register(FunctionTable, ARRAY_SIZE(FunctionTable)); +} + +Interface::~Interface() { +} + +} // namespace diff --git a/src/core/hle/service/ndm.h b/src/core/hle/service/ndm.h new file mode 100644 index 000000000..fbe88fb8f --- /dev/null +++ b/src/core/hle/service/ndm.h @@ -0,0 +1,33 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace NDM + +// No idea what this is + +namespace NDM_U { + +class Interface : public Service::Interface { +public: + + Interface(); + + ~Interface(); + + /** + * Gets the string port name used by CTROS for the service + * @return Port name of service + */ + const char *GetPortName() const { + return "ndm:u"; + } + +}; + +} // namespace From f7cececc5ca82f97a9fb1ab50c62fd9e3a49ccdc Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:33:55 -0400 Subject: [PATCH 40/84] event: added a hackish ability to set an event as "locked" to its current state, cleaned up some comments --- src/core/hle/kernel/event.cpp | 28 ++++++++++++++++++++++++---- src/core/hle/kernel/event.h | 8 ++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 7cb8c5142..e84d0b49e 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -23,6 +23,7 @@ public: ResetType reset_type; ///< Current ResetType bool locked; ///< Current locked state + bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) /** * Synchronize kernel object @@ -31,7 +32,7 @@ public: */ Result SyncRequest(bool* wait) { // TODO(bunnei): ImplementMe - ERROR_LOG(KERNEL, "Unimplemented function Event::SyncRequest"); + ERROR_LOG(KERNEL, "(UMIMPLEMENTED) call"); return 0; } @@ -43,7 +44,7 @@ public: Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe *wait = locked; - if (reset_type != RESETTYPE_STICKY) { + if (reset_type != RESETTYPE_STICKY && !permanent_locked) { locked = true; } return 0; @@ -59,10 +60,28 @@ public: Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); if (!evt) { - ERROR_LOG(KERNEL, "SetEventLocked called with unknown handle=0x%08X", handle); + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); return -1; } - evt->locked = locked; + if (!evt->permanent_locked) { + evt->locked = locked; + } + return 0; +} + +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked) { + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + evt->permanent_locked = permanent_locked; return 0; } @@ -87,6 +106,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { handle = Kernel::g_object_pool.Create(evt); evt->locked = true; + evt->permanent_locked = false; evt->reset_type = evt->intitial_reset_type = reset_type; return evt; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index b1d2c6ad1..f91a72c1c 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -19,6 +19,14 @@ namespace Kernel { */ Result SetEventLocked(const Handle handle, const bool locked); +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked); + /** * Clears an event * @param handle Handle to event to clear From ba98e25e979b1aedaa9b917a7db8f710c83c073c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:35:42 -0400 Subject: [PATCH 41/84] thread: updated Reschedule to sit at a synchronization barrier when no other threads are ready for execution --- src/core/hle/kernel/thread.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6e8b53eb1..d1e13c949 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -323,11 +323,29 @@ void Reschedule() { Thread* prev = GetCurrentThread(); Thread* next = NextThread(); if (next > 0) { + INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); + SwitchContext(next); // Hack - automatically change previous thread (which would have been in "wait" state) to // "ready" state, so that we can immediately resume to it when new thread yields. FixMe to // actually wait for whatever event it is supposed to be waiting on. + + ChangeReadyState(prev, true); + } else { + INFO_LOG(KERNEL, "no ready threads, staying on 0x%08X", prev->GetHandle()); + + // Hack - no other threads are available, so decrement current PC to the last instruction, + // and then resume current thread. This should always be called on a blocking instruction + // (e.g. svcWaitSynchronization), and the result should be that the instruction is repeated + // until it no longer blocks. + + // TODO(bunnei): A better solution: Have the CPU switch to an idle thread + + ThreadContext ctx; + SaveContext(ctx); + ctx.pc -= 4; + LoadContext(ctx); ChangeReadyState(prev, true); } } From f2f638492b1585739d193b400e34ede91c256462 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:37:19 -0400 Subject: [PATCH 42/84] svc: updated waitSychronization to not overwrite handle on return, added stub for SleepThread (does nothing) --- src/core/hle/svc.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 01fb647e7..5ba42973a 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -126,6 +126,14 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { if (wait) { Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? Kernel::Reschedule(); + + // Context switch - Function blocked, is not actually returning (will be "called" again) + + // TODO(bunnei): This saves handle to R0 so that it's correctly reloaded on context switch + // (otherwise R0 will be set to whatever is returned, and handle will be invalid when this + // thread is resumed). There is probably a better way of keeping track of state so that we + // don't necessarily have to do this. + return (Result)PARAM(0); } return res; @@ -171,7 +179,13 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? Kernel::Reschedule(); - return 0; + // Context switch - Function blocked, is not actually returning (will be "called" again) + + // TODO(bunnei): This saves handle to R0 so that it's correctly reloaded on context switch + // (otherwise R0 will be set to whatever is returned, and handle will be invalid when this + // thread is resumed). There is probably a better way of keeping track of state so that we + // don't necessarily have to do this. + return (Result)PARAM(0); } /// Create an address arbiter (to allocate access to shared resources) @@ -289,6 +303,11 @@ Result ClearEvent(Handle evt) { return res; } +/// Sleep the current thread +void SleepThread(s64 nanoseconds) { + DEBUG_LOG(SVC, "called nanoseconds=%d", nanoseconds); +} + const HLE::FunctionDef SVC_Table[] = { {0x00, NULL, "Unknown"}, {0x01, WrapI_VUUUUU, "ControlMemory"}, @@ -300,7 +319,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x07, NULL, "SetProcessIdealProcessor"}, {0x08, WrapI_UUUUU, "CreateThread"}, {0x09, NULL, "ExitThread"}, - {0x0A, NULL, "SleepThread"}, + {0x0A, WrapV_S64, "SleepThread"}, {0x0B, NULL, "GetThreadPriority"}, {0x0C, NULL, "SetThreadPriority"}, {0x0D, NULL, "GetThreadAffinityMask"}, From 7dd18a8df97f7497447ff121d8ad07c5a708a5c5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:41:23 -0400 Subject: [PATCH 43/84] gsp: always pass through synchronization barrier for commands --- src/core/hle/service/gsp.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 575db86c1..2635a2eb8 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -8,6 +8,7 @@ #include "core/mem_map.h" #include "core/hle/hle.h" +#include "core/hle/kernel/event.h" #include "core/hle/service/gsp.h" #include "core/hw/lcd.h" @@ -52,6 +53,7 @@ void GX_FinishCommand(u32 thread_id) { namespace GSP_GPU { +Handle g_event_handle = 0; u32 g_thread_id = 0; enum { @@ -100,7 +102,20 @@ void ReadHWRegs(Service::Interface* self) { void RegisterInterruptRelayQueue(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); u32 flags = cmd_buff[1]; - u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling + u32 event_handle = cmd_buff[3]; + + _assert_msg_(GSP, event_handle, "called, but event is NULL!"); + + g_event_handle = event_handle; + + Kernel::SetEventLocked(event_handle, false); + + // Hack - This function will permanently set the state of the GSP event such that GPU command + // synchronization barriers always passthrough. Correct solution would be to set this after the + // GPU as processed all queued up commands, but due to the emulator being single-threaded they + // will always be ready. + Kernel::SetPermanentLock(event_handle, true); + cmd_buff[2] = g_thread_id; // ThreadID } From 2f55c9e55bb8b505dd2faefb74cad5a8306b7a2a Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:41:41 -0400 Subject: [PATCH 44/84] svc: added missing function wrapper for SleepThread --- src/core/hle/function_wrappers.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 43f0d15e0..7eb62fc48 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -642,6 +642,10 @@ template void WrapV_C() { func(Memory::GetCharPointer(PARAM(0))); } +template void WrapV_S64() { + func(((s64)PARAM(1) << 32) | PARAM(0)); +} + template void WrapV_CI() { func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); } From 5cd922d1514e629f1aa0d7083272e51decb61175 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:57:45 -0400 Subject: [PATCH 45/84] log: updated GenericLog __attribute__ for newly added parameter --- src/common/log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/log.h b/src/common/log.h index 2543b51a8..3518d4e1d 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -89,7 +89,7 @@ enum LOG_LEVELS { void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int line, const char* function, const char* fmt, ...) #ifdef __GNUC__ - __attribute__((format(printf, 5, 6))) + __attribute__((format(printf, 6, 7))) #endif ; From 00adbc7817194183dbea95ddfdb8678a5571c799 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 11:49:58 -0400 Subject: [PATCH 46/84] log: updated MAX_LOGLEVEL to use correct log level enum type --- src/common/log.h | 6 +++--- src/common/log_manager.cpp | 2 +- src/common/log_manager.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/log.h b/src/common/log.h index 3518d4e1d..a3c8bdde6 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -94,10 +94,10 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int ; #if defined LOGGING || defined _DEBUG || defined DEBUGFAST -#define MAX_LOGLEVEL DEBUG_LEVEL +#define MAX_LOGLEVEL LDEBUG #else #ifndef MAX_LOGLEVEL -#define MAX_LOGLEVEL WARNING_LEVEL +#define MAX_LOGLEVEL LWARNING #endif // loglevel #endif // logging @@ -109,7 +109,7 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, const char*file, int // Let the compiler optimize this out #define GENERIC_LOG(t, v, ...) { \ - if (v <= MAX_LOGLEVEL) \ + if (v <= LogTypes::MAX_LOGLEVEL) \ GenericLog(v, t, __FILE__, __LINE__, __func__, __VA_ARGS__); \ } diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index d026fca56..b6caba3bf 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp @@ -149,7 +149,7 @@ LogContainer::LogContainer(const char* shortName, const char* fullName, bool ena { strncpy(m_fullName, fullName, 128); strncpy(m_shortName, shortName, 32); - m_level = (LogTypes::LOG_LEVELS)MAX_LOGLEVEL; + m_level = LogTypes::MAX_LOGLEVEL; } // LogContainer diff --git a/src/common/log_manager.h b/src/common/log_manager.h index 3e238dfa7..6d3d7c7ff 100644 --- a/src/common/log_manager.h +++ b/src/common/log_manager.h @@ -97,7 +97,7 @@ private: ~LogManager(); public: - static u32 GetMaxLevel() { return MAX_LOGLEVEL; } + static u32 GetMaxLevel() { return LogTypes::MAX_LOGLEVEL; } void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line, const char* function, const char *fmt, va_list args); From 15c7d8170669cadce685471fea48c215687d6622 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 20:48:29 -0400 Subject: [PATCH 47/84] svc: cleaned up function_wrappers, updated various SVCs to make use of pointer arguments --- src/core/hle/function_wrappers.h | 37 +++++++++++++++++++------------- src/core/hle/svc.cpp | 34 +++++++++++++++-------------- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 7eb62fc48..65e3164c4 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -33,7 +33,9 @@ template void WrapU_V() { } template void WrapI_VC() { - u32 retval = func(Memory::GetPointer(PARAM(0)), Memory::GetCharPointer(PARAM(1))); + u32 param_1 = 0; + u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))); + Core::g_app_core->SetReg(1, param_1); RETURN(retval); } @@ -48,7 +50,8 @@ template void WrapI_CIIU() { } template void WrapI_ICUVVUI() { - u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)),Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); + u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), + Memory::GetPointer(PARAM(3)),Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6)); RETURN(retval); } @@ -394,8 +397,8 @@ template void WrapU_C() { template void WrapU_CCCU() { u32 retval = func(Memory::GetCharPointer(PARAM(0)), - Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)), - PARAM(3)); + Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)), + PARAM(3)); RETURN(retval); } @@ -431,7 +434,7 @@ template void WrapI_CUU() { template void WrapI_CUUU() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3)); + PARAM(3)); RETURN(retval); } @@ -442,7 +445,7 @@ template void WrapI_CCII() { template void WrapI_CUUIUU() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4), PARAM(5)); + PARAM(3), PARAM(4), PARAM(5)); RETURN(retval); } @@ -454,7 +457,7 @@ template void WrapI_CIIUII() { template void WrapI_CIUUU() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4)); + PARAM(3), PARAM(4)); RETURN(retval); } @@ -554,18 +557,18 @@ template void WrapI_CUIU() { template void WrapV_UCUIU() { func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3), - PARAM(4)); + PARAM(4)); } template void WrapI_UCUIU() { int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), - PARAM(3), PARAM(4)); + PARAM(3), PARAM(4)); RETURN(retval); } template void WrapV_CUIIU() { func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), - PARAM(4)); + PARAM(4)); } template void WrapI_CUIIU() { @@ -689,8 +692,8 @@ template void WrapI_IUU() { } template void WrapU_UUUUUUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); + RETURN(retval); } template void WrapI_UIUU() { @@ -734,7 +737,9 @@ template void WrapI_ICU } template void WrapI_VU(){ - u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1)); + u32 param_1 = 0; + u32 retval = func(¶m_1, PARAM(1)); + Core::g_app_core->SetReg(1, param_1); RETURN(retval); } @@ -749,7 +754,9 @@ template void WrapI_VUVI(){ } template void WrapI_VUUUUU(){ - u32 retval = func(NULL, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + u32 param_1 = 0; + u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + Core::g_app_core->SetReg(1, param_1); RETURN(retval); } @@ -763,7 +770,7 @@ template void WrapI_VVUUS64() { RETURN(retval); } -// TODO(bunne): Is this correct? Probably not +// TODO(bunnei): Is this correct? Probably not template void WrapI_UUUUS64() { int retval = func(PARAM(5), PARAM(1), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); RETURN(retval); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 5ba42973a..11b77e2c5 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -34,8 +34,8 @@ enum MapMemoryPermission { }; /// Map application or GSP heap memory -Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { - u32 virtual_address = 0x00000000; +Result ControlMemory(void* _out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { + u32* out_addr = (u32*)_out_addr; DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", operation, addr0, addr1, size, permissions); @@ -44,21 +44,18 @@ Result ControlMemory(void* _outaddr, u32 operation, u32 addr0, u32 addr1, u32 si // Map normal heap memory case MEMORY_OPERATION_HEAP: - virtual_address = Memory::MapBlock_Heap(size, operation, permissions); + *out_addr = Memory::MapBlock_Heap(size, operation, permissions); break; // Map GSP heap memory case MEMORY_OPERATION_GSP_HEAP: - virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions); + *out_addr = Memory::MapBlock_HeapGSP(size, operation, permissions); break; // Unknown ControlMemory operation default: ERROR_LOG(SVC, "unknown operation=0x%08X", operation); } - - Core::g_app_core->SetReg(1, virtual_address); - return 0; } @@ -80,10 +77,14 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper /// Connect to an OS service given the port name, returns the handle to the port to out Result ConnectToPort(void* _out, const char* port_name) { + Handle* out = (Handle*)_out; Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); + DEBUG_LOG(SVC, "called port_name=%s", port_name); _assert_msg_(KERNEL, service, "called, but service is not implemented!"); - Core::g_app_core->SetReg(1, service->GetHandle()); + + *out = service->GetHandle(); + return 0; } @@ -209,12 +210,13 @@ void OutputDebugString(const char* string) { } /// Get resource limit -Result GetResourceLimit(void* resource_limit, Handle process) { +Result GetResourceLimit(void* _resource_limit, Handle process) { // With regards to proceess values: // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for // the current KThread. + Handle* resource_limit = (Handle*)_resource_limit; + *resource_limit = 0xDEADBEEF; ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); - Core::g_app_core->SetReg(1, 0xDEADBEEF); return 0; } @@ -253,10 +255,10 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p /// Create a mutex Result CreateMutex(void* _mutex, u32 initial_locked) { - Handle mutex = Kernel::CreateMutex((initial_locked != 0)); - Core::g_app_core->SetReg(1, mutex); + Handle* mutex = (Handle*)_mutex; + *mutex = Kernel::CreateMutex((initial_locked != 0)); DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", - initial_locked ? "true" : "false", mutex); + initial_locked ? "true" : "false", *mutex); return 0; } @@ -282,10 +284,10 @@ Result QueryMemory(void *_info, void *_out, u32 addr) { /// Create an event Result CreateEvent(void* _event, u32 reset_type) { - Handle evt = Kernel::CreateEvent((ResetType)reset_type); - Core::g_app_core->SetReg(1, evt); + Handle* evt = (Handle*)_event; + *evt = Kernel::CreateEvent((ResetType)reset_type); DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", - reset_type, evt); + reset_type, *evt); return 0; } From e8a17ee6fdf7ab653be32f52afb10f0dafdf61c1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 21:40:10 -0400 Subject: [PATCH 48/84] arm: added option to prepare CPU core (while mid-instruction) for thread reschedule --- src/core/arm/arm_interface.h | 3 +++ src/core/arm/interpreter/arm_interpreter.cpp | 5 +++++ src/core/arm/interpreter/arm_interpreter.h | 3 +++ 3 files changed, 11 insertions(+) diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index b73786ccd..316b50fbb 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -89,6 +89,9 @@ public: */ virtual void LoadContext(const ThreadContext& ctx) = 0; + /// Prepare core for thread reschedule (if needed to correctly handle state) + virtual void PrepareReschedule() = 0; + /// Getter for num_instructions u64 GetNumInstructions() { return num_instructions; diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp index 17f787b86..2aa100e86 100644 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ b/src/core/arm/interpreter/arm_interpreter.cpp @@ -140,3 +140,8 @@ void ARM_Interpreter::LoadContext(const ThreadContext& ctx) { state->Reg[15] = ctx.pc; state->NextInstr = RESUME; } + +/// Prepare core for thread reschedule (if needed to correctly handle state) +void ARM_Interpreter::PrepareReschedule() { + state->NumInstrsToExecute = 0; +} diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h index 6a531e497..1e82883a2 100644 --- a/src/core/arm/interpreter/arm_interpreter.h +++ b/src/core/arm/interpreter/arm_interpreter.h @@ -72,6 +72,9 @@ public: */ void LoadContext(const ThreadContext& ctx); + /// Prepare core for thread reschedule (if needed to correctly handle state) + void PrepareReschedule(); + protected: /** From 10447d1f4831b495d7bef7711681ddd548f847a6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 21:42:50 -0400 Subject: [PATCH 49/84] kernel: changed main thread priority to default, updated Kernel::Reschedule to use PrepareReschedule --- src/core/hle/hle.cpp | 5 +++-- src/core/hle/hle.h | 2 +- src/core/hle/kernel/kernel.cpp | 3 ++- src/core/hle/kernel/kernel.h | 1 + src/core/hle/kernel/thread.cpp | 6 +++--- src/core/hle/svc.cpp | 9 +++++++-- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index f703da44e..08b0685c9 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -7,6 +7,7 @@ #include "core/mem_map.h" #include "core/hle/hle.h" #include "core/hle/svc.h" +#include "core/hle/kernel/thread.h" #include "core/hle/service/service.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -41,11 +42,11 @@ void EatCycles(u32 cycles) { // TODO: ImplementMe } -void ReSchedule(const char *reason) { +void Reschedule(const char *reason) { #ifdef _DEBUG _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); #endif - // TODO: ImplementMe + Core::g_app_core->PrepareReschedule(); } void RegisterModule(std::string name, int num_functions, const FunctionDef* func_table) { diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index c31e273b5..9bc4bfd2c 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -37,7 +37,7 @@ void CallSVC(u32 opcode); void EatCycles(u32 cycles); -void ReSchedule(const char *reason); +void Reschedule(const char *reason); void Init(); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index de80de893..c0c0fa177 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -14,6 +14,7 @@ namespace Kernel { +Handle g_main_thread = 0; ObjectPool g_object_pool; ObjectPool::ObjectPool() { @@ -150,7 +151,7 @@ bool LoadExec(u32 entry_point) { Core::g_app_core->SetPC(entry_point); // 0x30 is the typical main thread priority I've seen used so far - Handle thread = Kernel::SetupMainThread(0x30); + g_main_thread = Kernel::SetupMainThread(THREADPRIO_DEFAULT); return true; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 620cd2d73..2192df16f 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -163,6 +163,7 @@ private: }; extern ObjectPool g_object_pool; +extern Handle g_main_thread; /** * Loads executable stored at specified address diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d1e13c949..f2094f7a7 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -285,11 +285,11 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 HLE::EatCycles(32000); + CallThread(t); + // This won't schedule to the new thread, but it may to one woken from eating cycles. // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. - HLE::ReSchedule("thread created"); - - CallThread(t); + //HLE::Reschedule("thread created"); return handle; } diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 11b77e2c5..0c2412a65 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -125,8 +125,11 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { Result res = object->WaitSynchronization(&wait); if (wait) { + // Set current thread to wait state if handle was not unlocked Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? - Kernel::Reschedule(); + + // Check for next thread to schedule + HLE::Reschedule(__func__); // Context switch - Function blocked, is not actually returning (will be "called" again) @@ -178,7 +181,9 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa // Set current thread to wait state if not all handles were unlocked Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? - Kernel::Reschedule(); + + // Check for next thread to schedule + HLE::Reschedule(__func__); // Context switch - Function blocked, is not actually returning (will be "called" again) From 3fb31fbc57fd1d537db79af898ef26c92b0e0867 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 22:12:54 -0400 Subject: [PATCH 50/84] svc: added GetThreadPriority and SetThreadPriority, added (incomplete) DuplicateHandle support --- src/core/hle/kernel/thread.cpp | 45 ++++++++++++++++++++++++++++++++++ src/core/hle/kernel/thread.h | 6 +++++ src/core/hle/svc.cpp | 29 +++++++++++++++++++--- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f2094f7a7..c84fdf91d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -294,6 +294,51 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 return handle; } +/// Get the priority of the thread specified by handle +u32 GetThreadPriority(const Handle handle) { + Thread* thread = g_object_pool.GetFast(handle); + _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + return thread->current_priority; +} + +/// Set the priority of the thread specified by handle +Result SetThreadPriority(Handle handle, s32 priority) { + Thread* thread = NULL; + if (!handle) { + thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? + } else { + thread = g_object_pool.GetFast(handle); + } + _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + + // If priority is invalid, clamp to valid range + if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { + s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); + WARN_LOG(KERNEL, "invalid priority=0x%08X, clamping to %08X", priority, new_priority); + // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm + // validity of this + priority = new_priority; + } + + // Change thread priority + s32 old = thread->current_priority; + g_thread_ready_queue.remove(old, handle); + thread->current_priority = priority; + g_thread_ready_queue.prepare(thread->current_priority); + + // Change thread status to "ready" and push to ready queue + if (thread->IsRunning()) { + thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY; + } + if (thread->IsReady()) { + g_thread_ready_queue.push_back(thread->current_priority, handle); + } + + HLE::EatCycles(450); + + return 0; +} + /// Sets up the primary application thread Handle SetupMainThread(s32 priority, int stack_size) { Handle handle; diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 9628f165d..094c8d43e 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -65,6 +65,12 @@ Handle GetCurrentThreadHandle(); /// Put current thread in a wait state - on WaitSynchronization void WaitThread_Synchronization(); +/// Get the priority of the thread specified by handle +u32 GetThreadPriority(const Handle handle); + +/// Set the priority of the thread specified by handle +Result SetThreadPriority(Handle handle, s32 priority); + /// Initialize threading void ThreadingInit(); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 0c2412a65..2384b7936 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -258,6 +258,18 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p return 0; } +/// Gets the priority for the specified thread +Result GetThreadPriority(void* _priority, Handle handle) { + s32* priority = (s32*)_priority; + *priority = Kernel::GetThreadPriority(handle); + return 0; +} + +/// Sets the priority for the specified thread +Result SetThreadPriority(Handle handle, s32 priority) { + return Kernel::SetThreadPriority(handle, priority); +} + /// Create a mutex Result CreateMutex(void* _mutex, u32 initial_locked) { Handle* mutex = (Handle*)_mutex; @@ -299,7 +311,18 @@ Result CreateEvent(void* _event, u32 reset_type) { /// Duplicates a kernel handle Result DuplicateHandle(void* _out, Handle handle) { Handle* out = (Handle*)_out; - ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); + ERROR_LOG(SVC, "called handle=0x%08X", handle); + + // Translate kernel handles -> real handles + if (handle == Kernel::CurrentThread) { + handle = Kernel::GetCurrentThreadHandle(); + } + _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), + "(UNIMPLEMENTED) process handle duplication!"); + + // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate. + *out = handle; + return 0; } @@ -327,8 +350,8 @@ const HLE::FunctionDef SVC_Table[] = { {0x08, WrapI_UUUUU, "CreateThread"}, {0x09, NULL, "ExitThread"}, {0x0A, WrapV_S64, "SleepThread"}, - {0x0B, NULL, "GetThreadPriority"}, - {0x0C, NULL, "SetThreadPriority"}, + {0x0B, WrapI_VU, "GetThreadPriority"}, + {0x0C, WrapI_UI, "SetThreadPriority"}, {0x0D, NULL, "GetThreadAffinityMask"}, {0x0E, NULL, "SetThreadAffinityMask"}, {0x0F, NULL, "GetThreadIdealProcessor"}, From 4819e9a60f36ac4ec1a7cb3d30008353ab03bf14 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 22:33:53 -0400 Subject: [PATCH 51/84] svc: changed DuplicateHandle log message from "error" to "debug" --- src/core/hle/svc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 2384b7936..1f36c7ac5 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -311,7 +311,7 @@ Result CreateEvent(void* _event, u32 reset_type) { /// Duplicates a kernel handle Result DuplicateHandle(void* _out, Handle handle) { Handle* out = (Handle*)_out; - ERROR_LOG(SVC, "called handle=0x%08X", handle); + DEBUG_LOG(SVC, "called handle=0x%08X", handle); // Translate kernel handles -> real handles if (handle == Kernel::CurrentThread) { From 477b0caca4f0db084ab2d2dfb866fd81e5839228 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 2 Jun 2014 17:54:07 -0400 Subject: [PATCH 52/84] svc: updated WaitSynchronizationN to properly use first pointer argument --- src/core/hle/function_wrappers.h | 4 +++- src/core/hle/svc.cpp | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 65e3164c4..2d0dcf476 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -766,7 +766,9 @@ template void WrapI_US64() { } template void WrapI_VVUUS64() { - int retval = func(Memory::GetPointer(PARAM(5)), Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); + u32 param_1 = 0; + int retval = func(¶m_1, Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); + Core::g_app_core->SetReg(1, param_1); RETURN(retval); } diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 1f36c7ac5..c8eb8ea80 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -147,7 +147,7 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wait_all, s64 nano_seconds) { // TODO(bunnei): Do something with nano_seconds, currently ignoring this - + s32* out = (s32*)_out; Handle* handles = (Handle*)_handles; bool unlock_all = true; @@ -167,7 +167,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa Result res = object->WaitSynchronization(&wait); if (!wait && !wait_all) { - Core::g_app_core->SetReg(1, i); + *out = i; return 0; } else { unlock_all = false; @@ -175,7 +175,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa } if (wait_all && unlock_all) { - Core::g_app_core->SetReg(1, handle_count); + *out = handle_count; return 0; } From 2773360f84f60b739290aa549f87c2c10adc7fb4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 2 Jun 2014 20:36:34 -0400 Subject: [PATCH 53/84] coprocessor: reenabled debug log --- src/core/hle/coprocessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp index 39674ee64..9a5b0deda 100644 --- a/src/core/hle/coprocessor.cpp +++ b/src/core/hle/coprocessor.cpp @@ -25,7 +25,7 @@ s32 CallMRC(u32 instruction) { return GetThreadCommandBuffer(); default: - //DEBUG_LOG(OSHLE, "unknown MRC call 0x%08X", instruction); + DEBUG_LOG(OSHLE, "unknown MRC call 0x%08X", instruction); break; } return -1; From 8c0f02a70cfb3eb9a7a334f3f93345bc64e383b6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 2 Jun 2014 20:36:58 -0400 Subject: [PATCH 54/84] kernel: moved position of * for GetTypeName and GetName --- src/core/hle/kernel/kernel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 2192df16f..c26071276 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -44,8 +44,8 @@ class Object : NonCopyable { public: virtual ~Object() {} Handle GetHandle() const { return handle; } - virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } - virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; } + virtual const char* GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } + virtual const char* GetName() { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; /** From b78aff85857a3a356fdf11e1dbc4e5f52490676e Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 2 Jun 2014 20:38:34 -0400 Subject: [PATCH 55/84] svc: added optional name field to Event and Mutex (used for debugging) --- src/core/hle/kernel/event.cpp | 11 ++++++++--- src/core/hle/kernel/event.h | 3 ++- src/core/hle/kernel/mutex.cpp | 12 +++++++++--- src/core/hle/kernel/mutex.h | 3 ++- src/core/hle/service/apt.cpp | 6 +++--- src/core/hle/service/srv.cpp | 2 +- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e84d0b49e..70e50115d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -15,6 +15,7 @@ namespace Kernel { class Event : public Object { public: const char* GetTypeName() { return "Event"; } + const char* GetName() { return name.c_str(); } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } @@ -24,6 +25,7 @@ public: bool locked; ///< Current locked state bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) + std::string name; ///< Name of event (optional) /** * Synchronize kernel object @@ -98,9 +100,10 @@ Result ClearEvent(Handle handle) { * Creates an event * @param handle Reference to handle for the newly created mutex * @param reset_type ResetType describing how to create event + * @param name Optional name of event * @return Newly created Event object */ -Event* CreateEvent(Handle& handle, const ResetType reset_type) { +Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string name) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); @@ -108,6 +111,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { evt->locked = true; evt->permanent_locked = false; evt->reset_type = evt->intitial_reset_type = reset_type; + evt->name = name; return evt; } @@ -115,11 +119,12 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { /** * Creates an event * @param reset_type ResetType describing how to create event + * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type) { +Handle CreateEvent(const ResetType reset_type, const std::string name) { Handle handle; - Event* evt = CreateEvent(handle, reset_type); + Event* evt = CreateEvent(handle, reset_type, name); return handle; } diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index f91a72c1c..eed09f0e3 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -37,8 +37,9 @@ Result ClearEvent(Handle handle); /** * Creates an event * @param reset_type ResetType describing how to create event + * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type); +Handle CreateEvent(const ResetType reset_type, const std::string name="Unknown"); } // namespace diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 5ac88cd85..7e60fbfe0 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -16,6 +16,7 @@ namespace Kernel { class Mutex : public Object { public: const char* GetTypeName() { return "Mutex"; } + const char* GetName() { return name.c_str(); } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; } @@ -24,6 +25,7 @@ public: bool locked; ///< Current locked state Handle lock_thread; ///< Handle to thread that currently has mutex std::vector waiting_threads; ///< Threads that are waiting for the mutex + std::string name; ///< Name of mutex (optional) /** * Synchronize kernel object @@ -128,13 +130,15 @@ Result ReleaseMutex(Handle handle) { * Creates a mutex * @param handle Reference to handle for the newly created mutex * @param initial_locked Specifies if the mutex should be locked initially + * @param name Optional name of mutex * @return Pointer to new Mutex object */ -Mutex* CreateMutex(Handle& handle, bool initial_locked) { +Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string name) { Mutex* mutex = new Mutex; handle = Kernel::g_object_pool.Create(mutex); mutex->locked = mutex->initial_locked = initial_locked; + mutex->name = name; // Acquire mutex with current thread if initialized as locked... if (mutex->locked) { @@ -150,10 +154,12 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked) { /** * Creates a mutex * @param initial_locked Specifies if the mutex should be locked initially + * @param name Optional name of mutex + * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked) { +Handle CreateMutex(bool initial_locked, std::string name) { Handle handle; - Mutex* mutex = CreateMutex(handle, initial_locked); + Mutex* mutex = CreateMutex(handle, initial_locked, name); return handle; } diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 4cd266725..fde5549fa 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -20,8 +20,9 @@ Result ReleaseMutex(Handle handle); /** * Creates a mutex * @param initial_locked Specifies if the mutex should be locked initially + * @param name Optional name of mutex * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked); +Handle CreateMutex(bool initial_locked, const std::string name="Unknown"); } // namespace diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 10d9a94bd..33ee1ec8f 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -19,8 +19,8 @@ void Initialize(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); DEBUG_LOG(KERNEL, "called"); - cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT menu event handle - cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT); // APT pause event handle + cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu"); // APT menu event handle + cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle Kernel::SetEventLocked(cmd_buff[3], true); Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event @@ -32,7 +32,7 @@ void GetLockHandle(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field cmd_buff[1] = 0; // No error - cmd_buff[5] = Kernel::CreateMutex(false); + cmd_buff[5] = Kernel::CreateMutex(false, "APT_U:Lock"); DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]); } diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index f1940e6f5..07e2009a0 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -17,7 +17,7 @@ Handle g_mutex = 0; void Initialize(Service::Interface* self) { DEBUG_LOG(OSHLE, "called"); if (!g_mutex) { - g_mutex = Kernel::CreateMutex(false); + g_mutex = Kernel::CreateMutex(true, "SRV:Lock"); } } From c330a0a1d66f916fc19cf92160522530baf1aad1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 4 Jun 2014 18:41:44 -0400 Subject: [PATCH 56/84] arm: reverting a change made with cb0663de - this has to have been a typo! --- src/core/arm/interpreter/armemu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index 1e22cda9d..f3c14e608 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -4456,6 +4456,7 @@ ARMul_Emulate26 (ARMul_State * state) } /* Drop through. */ + case 0xe0: case 0xe4: case 0xe6: case 0xe8: @@ -4489,7 +4490,6 @@ ARMul_Emulate26 (ARMul_State * state) /* Co-Processor Register Transfers (MRC) and Data Ops. */ - case 0xe0: case 0xe1: case 0xe3: case 0xe5: From 870c6146e727e3537536f162e76ee8e20d56622f Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 4 Jun 2014 18:50:50 -0400 Subject: [PATCH 57/84] service: added a error log messages for unimplemented WaitSynchronization --- src/core/hle/service/service.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index c3e9dd313..8699ad305 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -115,6 +115,7 @@ public: */ Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe + ERROR_LOG(OSHLE, "unimplemented function"); return 0; } From 9ece9da50d7c7827b9eb3bb9cfb007fb4af07061 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 00:20:11 -0400 Subject: [PATCH 58/84] arm: fixed bug in how thread context switch occurs with SkyEye --- src/core/arm/interpreter/arm_interpreter.cpp | 7 +++++-- src/core/hle/svc.h | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp index 2aa100e86..8030ec56a 100644 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ b/src/core/arm/interpreter/arm_interpreter.cpp @@ -118,6 +118,9 @@ void ARM_Interpreter::SaveContext(ThreadContext& ctx) { ctx.fpscr = state->VFP[1]; ctx.fpexc = state->VFP[2]; + + ctx.reg_15 = state->Reg[15]; + ctx.mode = state->NextInstr; } /** @@ -137,8 +140,8 @@ void ARM_Interpreter::LoadContext(const ThreadContext& ctx) { state->VFP[1] = ctx.fpscr; state->VFP[2] = ctx.fpexc; - state->Reg[15] = ctx.pc; - state->NextInstr = RESUME; + state->Reg[15] = ctx.reg_15; + state->NextInstr = ctx.mode; } /// Prepare core for thread reschedule (if needed to correctly handle state) diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index c5170aab7..1d125faf6 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h @@ -29,6 +29,10 @@ struct ThreadContext { u32 fpu_registers[32]; u32 fpscr; u32 fpexc; + + // These are not part of native ThreadContext, but needed by emu + u32 reg_15; + u32 mode; }; enum ResetType { From ce1c56127886fa746b2bda95bf162bf67878e482 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 00:20:58 -0400 Subject: [PATCH 59/84] kernel: changed current default thread priority back to 0x30 - I think this is more correct --- src/core/hle/kernel/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index c0c0fa177..9d5991c37 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -151,7 +151,7 @@ bool LoadExec(u32 entry_point) { Core::g_app_core->SetPC(entry_point); // 0x30 is the typical main thread priority I've seen used so far - g_main_thread = Kernel::SetupMainThread(THREADPRIO_DEFAULT); + g_main_thread = Kernel::SetupMainThread(0x30); return true; } From 6cdad8390c20aed5c526916816388831d71213a2 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 00:25:32 -0400 Subject: [PATCH 60/84] arm: fixed a bug where ARM_Interpreter::ExecuteInstructions was actually executing one more instruction than expected --- src/core/arm/interpreter/arm_interpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp index 8030ec56a..0e893f182 100644 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ b/src/core/arm/interpreter/arm_interpreter.cpp @@ -98,7 +98,7 @@ u64 ARM_Interpreter::GetTicks() const { * @param num_instructions Number of instructions to executes */ void ARM_Interpreter::ExecuteInstructions(int num_instructions) { - state->NumInstrsToExecute = num_instructions; + state->NumInstrsToExecute = num_instructions - 1; ARMul_Emulate32(state); } From 174cc9a0ed023ca89420fbc999ed82337cc94b8b Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 00:26:48 -0400 Subject: [PATCH 61/84] hle: added a hokey way to force a thread reschedule during CPU single step mode (as used by the debugger) --- src/core/core.cpp | 3 ++- src/core/hle/hle.cpp | 3 +++ src/core/hle/hle.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 070f92ed5..0500394b3 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -13,6 +13,7 @@ #include "core/arm/disassembler/arm_disasm.h" #include "core/arm/interpreter/arm_interpreter.h" +#include "core/hle/hle.h" #include "core/hle/kernel/thread.h" namespace Core { @@ -36,7 +37,7 @@ void SingleStep() { g_app_core->Step(); - if (ticks >= LCD::kFrameTicks / 2) { + if ((ticks >= LCD::kFrameTicks / 2) || HLE::g_reschedule) { HW::Update(); Kernel::Reschedule(); ticks = 0; diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 08b0685c9..e49395f56 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -16,6 +16,8 @@ namespace HLE { static std::vector g_module_db; +bool g_reschedule = false; ///< If true, immediately reschedules the CPU to a new thread + const FunctionDef* GetSVCInfo(u32 opcode) { u32 func_num = opcode & 0xFFFFFF; // 8 bits if (func_num > 0xFF) { @@ -47,6 +49,7 @@ void Reschedule(const char *reason) { _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); #endif Core::g_app_core->PrepareReschedule(); + g_reschedule = true; } void RegisterModule(std::string name, int num_functions, const FunctionDef* func_table) { diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 9bc4bfd2c..8a59020c2 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -16,6 +16,8 @@ namespace HLE { +extern bool g_reschedule; ///< If true, immediately reschedules the CPU to a new thread + typedef u32 Addr; typedef void (*Func)(); From a002abf1711a53430d3002e81de8221ea24766ee Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 01:08:54 -0400 Subject: [PATCH 62/84] qt: updated disassembler to show 2X as many instructions --- src/citra_qt/debugger/disassembler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index ccc83abf2..4e8f841f4 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp @@ -48,7 +48,7 @@ void DisassemblerWidget::Init() unsigned int curInstAddr = base_addr; char result[255]; - for (int i = 0; i < 10000; i++) // fixed for now + for (int i = 0; i < 20000; i++) // fixed for now { disasm->disasm(curInstAddr, Memory::Read32(curInstAddr), result); model->setItem(i, 0, new QStandardItem(QString("0x%1").arg((uint)(curInstAddr), 8, 16, QLatin1Char('0')))); From f5c7c1543434e25a215286e6db5e71c055ba48cf Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 22:35:36 -0400 Subject: [PATCH 63/84] Kernel: Added real support for thread and event blocking - SVC: Added ExitThread support - SVC: Added SignalEvent support - Thread: Added WAITTYPE_EVENT for waiting threads for event signals - Thread: Added support for blocking on other threads to finish (e.g. Thread::Join) - Thread: Added debug function for printing current threads ready for execution - Thread: Removed hack/broken thread ready state code from Kernel::Reschedule - Mutex: Moved WaitCurrentThread from SVC to Mutex::WaitSynchronization - Event: Added support for blocking threads on event signalling Kernel: Added missing algorithm #include for use of std::find on non-Windows platforms. --- src/core/hle/kernel/event.cpp | 71 +++++++++++++++---- src/core/hle/kernel/event.h | 7 ++ src/core/hle/kernel/mutex.cpp | 5 ++ src/core/hle/kernel/thread.cpp | 121 ++++++++++++++++++++++++--------- src/core/hle/kernel/thread.h | 9 ++- src/core/hle/svc.cpp | 59 ++++++++-------- 6 files changed, 196 insertions(+), 76 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 70e50115d..787e9f5fd 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -3,12 +3,14 @@ // Refer to the license.txt file included. #include +#include #include #include "common/common.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/event.h" +#include "core/hle/kernel/thread.h" namespace Kernel { @@ -20,12 +22,13 @@ public: static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } - ResetType intitial_reset_type; ///< ResetType specified at Event initialization - ResetType reset_type; ///< Current ResetType + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType - bool locked; ///< Current locked state - bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) - std::string name; ///< Name of event (optional) + bool locked; ///< Event signal wait + bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) + std::vector waiting_threads; ///< Threads that are waiting for the event + std::string name; ///< Name of event (optional) /** * Synchronize kernel object @@ -44,8 +47,14 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result WaitSynchronization(bool* wait) { - // TODO(bunnei): ImplementMe *wait = locked; + if (locked) { + Handle thread = GetCurrentThreadHandle(); + if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { + waiting_threads.push_back(thread); + } + Kernel::WaitCurrentThread(WAITTYPE_EVENT); + } if (reset_type != RESETTYPE_STICKY && !permanent_locked) { locked = true; } @@ -53,6 +62,22 @@ public: } }; +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked) { + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + evt->permanent_locked = permanent_locked; + return 0; +} + /** * Changes whether an event is locked or not * @param handle Handle to event to change @@ -72,18 +97,32 @@ Result SetEventLocked(const Handle handle, const bool locked) { } /** - * Hackish function to set an events permanent lock state, used to pass through synch blocks - * @param handle Handle to event to change - * @param permanent_locked Boolean permanent locked value to set event + * Signals an event + * @param handle Handle to event to signal * @return Result of operation, 0 on success, otherwise error code */ -Result SetPermanentLock(Handle handle, const bool permanent_locked) { +Result SignalEvent(const Handle handle) { Event* evt = g_object_pool.GetFast(handle); if (!evt) { ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); return -1; } - evt->permanent_locked = permanent_locked; + // Resume threads waiting for event to signal + bool event_caught = false; + for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { + ResumeThreadFromWait( evt->waiting_threads[i]); + + // If any thread is signalled awake by this event, assume the event was "caught" and reset + // the event. This will result in the next thread waiting on the event to block. Otherwise, + // the event will not be reset, and the next thread to call WaitSynchronization on it will + // not block. Not sure if this is correct behavior, but it seems to work. + event_caught = true; + } + evt->waiting_threads.clear(); + + if (!evt->permanent_locked) { + evt->locked = event_caught; + } return 0; } @@ -93,7 +132,15 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { * @return Result of operation, 0 on success, otherwise error code */ Result ClearEvent(Handle handle) { - return SetEventLocked(handle, true); + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + if (!evt->permanent_locked) { + evt->locked = true; + } + return 0; } /** diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index eed09f0e3..3527b01fd 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -27,6 +27,13 @@ Result SetEventLocked(const Handle handle, const bool locked); */ Result SetPermanentLock(Handle handle, const bool permanent_locked); +/** + * Signals an event + * @param handle Handle to event to signal + * @return Result of operation, 0 on success, otherwise error code + */ +Result SignalEvent(const Handle handle); + /** * Clears an event * @param handle Handle to event to clear diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 7e60fbfe0..133c43079 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -46,6 +46,11 @@ public: Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe *wait = locked; + + if (locked) { + Kernel::WaitCurrentThread(WAITTYPE_MUTEX); + } + return 0; } }; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index c84fdf91d..d372df709 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -52,7 +53,14 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result WaitSynchronization(bool* wait) { - // TODO(bunnei): ImplementMe + if (status != THREADSTATUS_DORMANT) { + Handle thread = GetCurrentThreadHandle(); + if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { + waiting_threads.push_back(thread); + } + WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); + *wait = true; + } return 0; } @@ -69,6 +77,9 @@ public: s32 processor_id; WaitType wait_type; + Handle wait_handle; + + std::vector waiting_threads; char name[Kernel::MAX_NAME_LENGTH + 1]; }; @@ -82,7 +93,6 @@ Common::ThreadQueueList g_thread_ready_queue; Handle g_current_thread_handle; Thread* g_current_thread; - /// Gets the current thread inline Thread* GetCurrentThread() { return g_current_thread; @@ -114,15 +124,15 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { memset(&t->context, 0, sizeof(ThreadContext)); t->context.cpu_registers[0] = arg; - t->context.pc = t->entry_point; + t->context.pc = t->context.cpu_registers[15] = t->entry_point; t->context.sp = t->stack_top; t->context.cpsr = 0x1F; // Usermode if (t->current_priority < lowest_priority) { t->current_priority = t->initial_priority; } - t->wait_type = WAITTYPE_NONE; + t->wait_handle = 0; } /// Change a thread to "ready" state @@ -142,6 +152,43 @@ void ChangeReadyState(Thread* t, bool ready) { } } +/// Verify that a thread has not been released from waiting +inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { + Handle wait_id = 0; + Thread *t = g_object_pool.GetFast(thread); + if (t) { + if (type == t->wait_type && handle == t->wait_handle) { + return true; + } + } else { + ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); + } + return false; +} + +/// Stops the current thread +void StopThread(Handle thread, const char* reason) { + u32 error; + Thread *t = g_object_pool.Get(thread, error); + if (t) { + ChangeReadyState(t, false); + t->status = THREADSTATUS_DORMANT; + for (size_t i = 0; i < t->waiting_threads.size(); ++i) { + const Handle waiting_thread = t->waiting_threads[i]; + if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, thread)) { + ResumeThreadFromWait(waiting_thread); + } + } + t->waiting_threads.clear(); + + // Stopped threads are never waiting. + t->wait_type = WAITTYPE_NONE; + t->wait_handle = 0; + } else { + ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); + } +} + /// Changes a threads state void ChangeThreadState(Thread* t, ThreadStatus new_status) { if (!t || t->status == new_status) { @@ -152,7 +199,7 @@ void ChangeThreadState(Thread* t, ThreadStatus new_status) { if (new_status == THREADSTATUS_WAIT) { if (t->wait_type == WAITTYPE_NONE) { - printf("ERROR: Waittype none not allowed here\n"); + ERROR_LOG(KERNEL, "Waittype none not allowed"); } } } @@ -207,9 +254,10 @@ Thread* NextThread() { } /// Puts the current thread in the wait state for the given type -void WaitCurrentThread(WaitType wait_type) { +void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { Thread* t = GetCurrentThread(); t->wait_type = wait_type; + t->wait_handle = wait_handle; ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); } @@ -225,6 +273,22 @@ void ResumeThreadFromWait(Handle handle) { } } +/// Prints the thread queue for debugging purposes +void DebugThreadQueue() { + Thread* thread = GetCurrentThread(); + if (!thread) { + return; + } + INFO_LOG(KERNEL, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThreadHandle()); + for (u32 i = 0; i < g_thread_queue.size(); i++) { + Handle handle = g_thread_queue[i]; + s32 priority = g_thread_ready_queue.contains(handle); + if (priority != -1) { + INFO_LOG(KERNEL, "0x%02X 0x%08X", priority, handle); + } + } +} + /// Creates a new thread Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, s32 processor_id, u32 stack_top, int stack_size) { @@ -233,12 +297,12 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio "CreateThread priority=%d, outside of allowable range!", priority) Thread* t = new Thread; - + handle = Kernel::g_object_pool.Create(t); - + g_thread_queue.push_back(handle); g_thread_ready_queue.prepare(priority); - + t->status = THREADSTATUS_DORMANT; t->entry_point = entry_point; t->stack_top = stack_top; @@ -246,16 +310,18 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio t->initial_priority = t->current_priority = priority; t->processor_id = processor_id; t->wait_type = WAITTYPE_NONE; - + t->wait_handle = 0; + strncpy(t->name, name, Kernel::MAX_NAME_LENGTH); t->name[Kernel::MAX_NAME_LENGTH] = '\0'; - + return t; } /// Creates a new thread - wrapper for external user Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, u32 stack_top, int stack_size) { + if (name == NULL) { ERROR_LOG(KERNEL, "CreateThread(): NULL name"); return -1; @@ -289,7 +355,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 // This won't schedule to the new thread, but it may to one woken from eating cycles. // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. - //HLE::Reschedule("thread created"); + //HLE::Reschedule(__func__); return handle; } @@ -363,35 +429,24 @@ Handle SetupMainThread(s32 priority, int stack_size) { return handle; } + /// Reschedules to the next available thread (call after current thread is suspended) void Reschedule() { Thread* prev = GetCurrentThread(); Thread* next = NextThread(); + HLE::g_reschedule = false; if (next > 0) { INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); - + SwitchContext(next); - // Hack - automatically change previous thread (which would have been in "wait" state) to - // "ready" state, so that we can immediately resume to it when new thread yields. FixMe to - // actually wait for whatever event it is supposed to be waiting on. - - ChangeReadyState(prev, true); - } else { - INFO_LOG(KERNEL, "no ready threads, staying on 0x%08X", prev->GetHandle()); - - // Hack - no other threads are available, so decrement current PC to the last instruction, - // and then resume current thread. This should always be called on a blocking instruction - // (e.g. svcWaitSynchronization), and the result should be that the instruction is repeated - // until it no longer blocks. - - // TODO(bunnei): A better solution: Have the CPU switch to an idle thread - - ThreadContext ctx; - SaveContext(ctx); - ctx.pc -= 4; - LoadContext(ctx); - ChangeReadyState(prev, true); + // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep + // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again. + // This results in the current thread yielding on a VBLANK once, and then it will be + // immediately placed back in the queue for execution. + if (prev->wait_type == WAITTYPE_VBLANK) { + ResumeThreadFromWait(prev->GetHandle()); + } } } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 094c8d43e..04914ba90 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -34,7 +34,7 @@ enum WaitType { WAITTYPE_NONE, WAITTYPE_SLEEP, WAITTYPE_SEMA, - WAITTYPE_EVENTFLAG, + WAITTYPE_EVENT, WAITTYPE_THREADEND, WAITTYPE_VBLANK, WAITTYPE_MUTEX, @@ -53,8 +53,8 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); /// Reschedules to the next available thread (call after current thread is suspended) void Reschedule(); -/// Puts the current thread in the wait state for the given type -void WaitCurrentThread(WaitType wait_type); +/// Stops the current thread +void StopThread(Handle thread, const char* reason); /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle); @@ -62,6 +62,9 @@ void ResumeThreadFromWait(Handle handle); /// Gets the current thread handle Handle GetCurrentThreadHandle(); +/// Puts the current thread in the wait state for the given type +void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle()); + /// Put current thread in a wait state - on WaitSynchronization void WaitThread_Synchronization(); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index c8eb8ea80..0ce831103 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -93,8 +93,8 @@ Result SendSyncRequest(Handle handle) { bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); - DEBUG_LOG(SVC, "called handle=0x%08X", handle); _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); + DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName()); Result res = object->SyncRequest(&wait); if (wait) { @@ -115,29 +115,21 @@ Result CloseHandle(Handle handle) { Result WaitSynchronization1(Handle handle, s64 nano_seconds) { // TODO(bunnei): Do something with nano_seconds, currently ignoring this bool wait = false; + bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); - DEBUG_LOG(SVC, "called handle=0x%08X, nanoseconds=%d", handle, - nano_seconds); + DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%d", handle, object->GetTypeName(), + object->GetName(), nano_seconds); + _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); Result res = object->WaitSynchronization(&wait); + // Check for next thread to schedule if (wait) { - // Set current thread to wait state if handle was not unlocked - Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? - - // Check for next thread to schedule HLE::Reschedule(__func__); - - // Context switch - Function blocked, is not actually returning (will be "called" again) - - // TODO(bunnei): This saves handle to R0 so that it's correctly reloaded on context switch - // (otherwise R0 will be set to whatever is returned, and handle will be invalid when this - // thread is resumed). There is probably a better way of keeping track of state so that we - // don't necessarily have to do this. - return (Result)PARAM(0); + return 0; } return res; @@ -150,6 +142,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa s32* out = (s32*)_out; Handle* handles = (Handle*)_handles; bool unlock_all = true; + bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%d", handle_count, (wait_all ? "true" : "false"), nano_seconds); @@ -162,7 +155,8 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa _assert_msg_(KERNEL, object, "called handle=0x%08X, but kernel object " "is NULL!", handles[i]); - DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X", i, handles[i]); + DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName(), + object->GetName()); Result res = object->WaitSynchronization(&wait); @@ -179,19 +173,10 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa return 0; } - // Set current thread to wait state if not all handles were unlocked - Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? - // Check for next thread to schedule HLE::Reschedule(__func__); - // Context switch - Function blocked, is not actually returning (will be "called" again) - - // TODO(bunnei): This saves handle to R0 so that it's correctly reloaded on context switch - // (otherwise R0 will be set to whatever is returned, and handle will be invalid when this - // thread is resumed). There is probably a better way of keeping track of state so that we - // don't necessarily have to do this. - return (Result)PARAM(0); + return 0; } /// Create an address arbiter (to allocate access to shared resources) @@ -258,6 +243,17 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p return 0; } +/// Called when a thread exits +u32 ExitThread() { + Handle thread = Kernel::GetCurrentThreadHandle(); + + DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C + + Kernel::StopThread(thread, __func__); + HLE::Reschedule(__func__); + return 0; +} + /// Gets the priority for the specified thread Result GetThreadPriority(void* _priority, Handle handle) { s32* priority = (s32*)_priority; @@ -326,6 +322,13 @@ Result DuplicateHandle(void* _out, Handle handle) { return 0; } +/// Signals an event +Result SignalEvent(Handle evt) { + Result res = Kernel::SignalEvent(evt); + DEBUG_LOG(SVC, "called event=0x%08X", evt); + return res; +} + /// Clears an event Result ClearEvent(Handle evt) { Result res = Kernel::ClearEvent(evt); @@ -348,7 +351,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x06, NULL, "GetProcessIdealProcessor"}, {0x07, NULL, "SetProcessIdealProcessor"}, {0x08, WrapI_UUUUU, "CreateThread"}, - {0x09, NULL, "ExitThread"}, + {0x09, WrapU_V, "ExitThread"}, {0x0A, WrapV_S64, "SleepThread"}, {0x0B, WrapI_VU, "GetThreadPriority"}, {0x0C, WrapI_UI, "SetThreadPriority"}, @@ -363,7 +366,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x15, NULL, "CreateSemaphore"}, {0x16, NULL, "ReleaseSemaphore"}, {0x17, WrapI_VU, "CreateEvent"}, - {0x18, NULL, "SignalEvent"}, + {0x18, WrapI_U, "SignalEvent"}, {0x19, WrapI_U, "ClearEvent"}, {0x1A, NULL, "CreateTimer"}, {0x1B, NULL, "SetTimer"}, From aae9fcf4a4071a408af10ca1c72180cdc04687b8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 23:13:28 -0400 Subject: [PATCH 64/84] Kernel: Made SyncRequest not pure virtual, with a default implementation of error (as this is not required for all kernel objects) --- src/core/hle/kernel/event.cpp | 11 ----------- src/core/hle/kernel/kernel.h | 6 ++++-- src/core/hle/kernel/thread.cpp | 10 ---------- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 787e9f5fd..36c7dcbc8 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -30,17 +30,6 @@ public: std::vector waiting_threads; ///< Threads that are waiting for the event std::string name; ///< Name of event (optional) - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) { - // TODO(bunnei): ImplementMe - ERROR_LOG(KERNEL, "(UMIMPLEMENTED) call"); - return 0; - } - /** * Wait for kernel object to synchronize * @param wait Boolean wait set if current thread should wait as a result of sync operation diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index c26071276..f1bb78801 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -53,7 +53,10 @@ public: * @param wait Boolean wait set if current thread should wait as a result of sync operation * @return Result of operation, 0 on success, otherwise error code */ - virtual Result SyncRequest(bool* wait) = 0; + virtual Result SyncRequest(bool* wait) { + ERROR_LOG(KERNEL, "(UNIMPLEMENTED)"); + return -1; + } /** * Wait for kernel object to synchronize @@ -61,7 +64,6 @@ public: * @return Result of operation, 0 on success, otherwise error code */ virtual Result WaitSynchronization(bool* wait) = 0; - }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d372df709..180c14928 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -37,16 +37,6 @@ public: inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) { - // TODO(bunnei): ImplementMe - return 0; - } - /** * Wait for kernel object to synchronize * @param wait Boolean wait set if current thread should wait as a result of sync operation From b774b8b04e50ad709381506a80e881a1a1471b0f Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 23:19:55 -0400 Subject: [PATCH 65/84] Thread: Fixed bug with ResetThread where cpu_registers[15] was being incorrectly set --- src/core/hle/kernel/thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 180c14928..6196c352c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -114,7 +114,7 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { memset(&t->context, 0, sizeof(ThreadContext)); t->context.cpu_registers[0] = arg; - t->context.pc = t->context.cpu_registers[15] = t->entry_point; + t->context.pc = t->context.reg_15 = t->entry_point; t->context.sp = t->stack_top; t->context.cpsr = 0x1F; // Usermode From 3449aaa35066b9a4bd784fe86a303666713076bf Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 23:32:02 -0400 Subject: [PATCH 66/84] Core: Changed HW update/thread reschedule to occur more frequently (assume each instruction is ~3 cycles) --- src/core/core.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 0500394b3..6ec25fdd4 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -25,7 +25,7 @@ ARM_Interface* g_sys_core = NULL; ///< ARM11 system (OS) core /// Run the core CPU loop void RunLoop() { for (;;){ - g_app_core->Run(LCD::kFrameTicks / 2); + g_app_core->Run(LCD::kFrameTicks / 3); HW::Update(); Kernel::Reschedule(); } @@ -37,7 +37,7 @@ void SingleStep() { g_app_core->Step(); - if ((ticks >= LCD::kFrameTicks / 2) || HLE::g_reschedule) { + if ((ticks >= LCD::kFrameTicks / 3) || HLE::g_reschedule) { HW::Update(); Kernel::Reschedule(); ticks = 0; From 0deeda54eefb18aaf6a62b8ec139cfe9bd21769c Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:06:33 -0400 Subject: [PATCH 67/84] Core: Cleaned up SingleStep(), updated default LCD refresh to assume each instruction is ~3 cycles --- src/core/core.cpp | 23 ++++++++++++----------- src/core/hw/lcd.h | 3 ++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 6ec25fdd4..26d52f7be 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -18,14 +18,15 @@ namespace Core { -ARM_Disasm* g_disasm = NULL; ///< ARM disassembler -ARM_Interface* g_app_core = NULL; ///< ARM11 application core -ARM_Interface* g_sys_core = NULL; ///< ARM11 system (OS) core +u64 g_last_ticks = 0; ///< Last CPU ticks +ARM_Disasm* g_disasm = NULL; ///< ARM disassembler +ARM_Interface* g_app_core = NULL; ///< ARM11 application core +ARM_Interface* g_sys_core = NULL; ///< ARM11 system (OS) core /// Run the core CPU loop void RunLoop() { for (;;){ - g_app_core->Run(LCD::kFrameTicks / 3); + g_app_core->Run(LCD::kFrameTicks); HW::Update(); Kernel::Reschedule(); } @@ -33,16 +34,14 @@ void RunLoop() { /// Step the CPU one instruction void SingleStep() { - static int ticks = 0; - g_app_core->Step(); - - if ((ticks >= LCD::kFrameTicks / 3) || HLE::g_reschedule) { + + // Update and reschedule after approx. 1 frame + u64 current_ticks = Core::g_app_core->GetTicks(); + if ((current_ticks - g_last_ticks) >= LCD::kFrameTicks || HLE::g_reschedule) { + g_last_ticks = current_ticks; HW::Update(); Kernel::Reschedule(); - ticks = 0; - } else { - ticks++; } } @@ -64,6 +63,8 @@ int Init() { g_app_core = new ARM_Interpreter(); g_sys_core = new ARM_Interpreter(); + g_last_ticks = Core::g_app_core->GetTicks(); + return 0; } diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h index 41baa51d0..7484f8f66 100644 --- a/src/core/hw/lcd.h +++ b/src/core/hw/lcd.h @@ -8,7 +8,8 @@ namespace LCD { -static const u32 kFrameTicks = 268123480 / 60; ///< 268MHz / 60 frames per second +static const u32 kFrameCycles = 268123480 / 60; ///< 268MHz / 60 frames per second +static const u32 kFrameTicks = kFrameCycles / 3; ///< Approximate number of instructions/frame struct Registers { u32 framebuffer_top_left_1; From 8cac527c943253a9471849d17b1520f4762fbb5c Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:10:50 -0400 Subject: [PATCH 68/84] Kernel: Updated several member functions to be const --- src/core/hle/kernel/event.cpp | 6 +++--- src/core/hle/kernel/kernel.h | 4 ++-- src/core/hle/kernel/mutex.cpp | 6 +++--- src/core/hle/kernel/thread.cpp | 6 +++--- src/core/hle/service/service.h | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 36c7dcbc8..72a190f8c 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -16,10 +16,10 @@ namespace Kernel { class Event : public Object { public: - const char* GetTypeName() { return "Event"; } - const char* GetName() { return name.c_str(); } + const char* GetTypeName() const { return "Event"; } + const char* GetName() const { return name.c_str(); } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } ResetType intitial_reset_type; ///< ResetType specified at Event initialization diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index f1bb78801..d2d624f6d 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -44,8 +44,8 @@ class Object : NonCopyable { public: virtual ~Object() {} Handle GetHandle() const { return handle; } - virtual const char* GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } - virtual const char* GetName() { return "[UNKNOWN KERNEL OBJECT]"; } + virtual const char* GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } + virtual const char* GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; /** diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 133c43079..9d909ea01 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -15,10 +15,10 @@ namespace Kernel { class Mutex : public Object { public: - const char* GetTypeName() { return "Mutex"; } - const char* GetName() { return name.c_str(); } + const char* GetTypeName() const { return "Mutex"; } + const char* GetName() const { return name.c_str(); } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; } bool initial_locked; ///< Initial lock state when mutex was created diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6196c352c..da93e006c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -25,10 +25,10 @@ namespace Kernel { class Thread : public Kernel::Object { public: - const char* GetName() { return name; } - const char* GetTypeName() { return "Thread"; } + const char* GetName() const { return name; } + const char* GetTypeName() const { return "Thread"; } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Thread; } inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 8699ad305..4b5c5b3c8 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -39,8 +39,8 @@ class Interface : public Kernel::Object { friend class Manager; public: - const char *GetName() { return GetPortName(); } - const char *GetTypeName() { return GetPortName(); } + const char *GetName() const { return GetPortName(); } + const char *GetTypeName() const { return GetPortName(); } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; } From 780a443b08454b4bf0eb7f5416e361ce95cc7584 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:13:50 -0400 Subject: [PATCH 69/84] Mutex: Moved ReleaseMutex iterator declaration to be inside while loop. --- src/core/hle/kernel/mutex.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 9d909ea01..eee7c4935 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -100,11 +100,10 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { bool ReleaseMutex(Mutex* mutex) { MutexEraseLock(mutex); bool woke_threads = false; - std::vector::iterator iter; // Find the next waiting thread for the mutex... while (!woke_threads && !mutex->waiting_threads.empty()) { - iter = mutex->waiting_threads.begin(); + std::vector::iterator iter = mutex->waiting_threads.begin(); woke_threads |= ReleaseMutexForThread(mutex, *iter); mutex->waiting_threads.erase(iter); } From d7363322c79d6e7598e0d80cf1af9c05b652cecb Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:19:40 -0400 Subject: [PATCH 70/84] HLE: Updated various handle debug assertions to be more clear. --- src/core/hle/kernel/mutex.cpp | 2 +- src/core/hle/kernel/thread.cpp | 4 ++-- src/core/hle/service/gsp.cpp | 2 +- src/core/hle/svc.cpp | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index eee7c4935..ee7507edf 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -122,7 +122,7 @@ bool ReleaseMutex(Mutex* mutex) { Result ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, mutex, "ReleaseMutex tried to release a NULL mutex!"); + _assert_msg_(KERNEL, (mutex != NULL), "ReleaseMutex tried to release a NULL mutex!"); if (!ReleaseMutex(mutex)) { return -1; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index da93e006c..5fdb4fbe6 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -353,7 +353,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 /// Get the priority of the thread specified by handle u32 GetThreadPriority(const Handle handle) { Thread* thread = g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); return thread->current_priority; } @@ -365,7 +365,7 @@ Result SetThreadPriority(Handle handle, s32 priority) { } else { thread = g_object_pool.GetFast(handle); } - _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); // If priority is invalid, clamp to valid range if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 2635a2eb8..c181e296f 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -104,7 +104,7 @@ void RegisterInterruptRelayQueue(Service::Interface* self) { u32 flags = cmd_buff[1]; u32 event_handle = cmd_buff[3]; - _assert_msg_(GSP, event_handle, "called, but event is NULL!"); + _assert_msg_(GSP, (event_handle != 0), "called, but event is NULL!"); g_event_handle = event_handle; diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 0ce831103..c389bbaac 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -81,7 +81,7 @@ Result ConnectToPort(void* _out, const char* port_name) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); DEBUG_LOG(SVC, "called port_name=%s", port_name); - _assert_msg_(KERNEL, service, "called, but service is not implemented!"); + _assert_msg_(KERNEL, (service != NULL), "called, but service is not implemented!"); *out = service->GetHandle(); @@ -93,7 +93,7 @@ Result SendSyncRequest(Handle handle) { bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); + _assert_msg_(KERNEL, (object != NULL), "called, but kernel object is NULL!"); DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName()); Result res = object->SyncRequest(&wait); @@ -122,7 +122,7 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%d", handle, object->GetTypeName(), object->GetName(), nano_seconds); - _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); + _assert_msg_(KERNEL, (object != NULL), "called, but kernel object is NULL!"); Result res = object->WaitSynchronization(&wait); @@ -150,9 +150,9 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa // Iterate through each handle, synchronize kernel object for (u32 i = 0; i < handle_count; i++) { bool wait = false; - Kernel::Object* object = Kernel::g_object_pool.GetFast(handles[i]); // 0 handle + Kernel::Object* object = Kernel::g_object_pool.GetFast(handles[i]); - _assert_msg_(KERNEL, object, "called handle=0x%08X, but kernel object " + _assert_msg_(KERNEL, (object != NULL), "called handle=0x%08X, but kernel object " "is NULL!", handles[i]); DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName(), @@ -278,7 +278,7 @@ Result CreateMutex(void* _mutex, u32 initial_locked) { /// Release a mutex Result ReleaseMutex(Handle handle) { DEBUG_LOG(SVC, "called handle=0x%08X", handle); - _assert_msg_(KERNEL, handle, "called, but handle is NULL!"); + _assert_msg_(KERNEL, (handle != 0), "called, but handle is NULL!"); Kernel::ReleaseMutex(handle); return 0; } From 5365ca157d5cb81c5cba3922036839f3c58e85ba Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:23:33 -0400 Subject: [PATCH 71/84] Kernel: Updated various kernel function "name" arguments to be const references. --- src/core/hle/kernel/event.cpp | 4 ++-- src/core/hle/kernel/event.h | 2 +- src/core/hle/kernel/mutex.cpp | 4 ++-- src/core/hle/kernel/mutex.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 72a190f8c..3a522c190 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -139,7 +139,7 @@ Result ClearEvent(Handle handle) { * @param name Optional name of event * @return Newly created Event object */ -Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string name) { +Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); @@ -158,7 +158,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type, const std::string name) { +Handle CreateEvent(const ResetType reset_type, const std::string& name) { Handle handle; Event* evt = CreateEvent(handle, reset_type, name); return handle; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 3527b01fd..c39b33180 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -47,6 +47,6 @@ Result ClearEvent(Handle handle); * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type, const std::string name="Unknown"); +Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown"); } // namespace diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index ee7507edf..a76c8de03 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -137,7 +137,7 @@ Result ReleaseMutex(Handle handle) { * @param name Optional name of mutex * @return Pointer to new Mutex object */ -Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string name) { +Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { Mutex* mutex = new Mutex; handle = Kernel::g_object_pool.Create(mutex); @@ -161,7 +161,7 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string name) * @param name Optional name of mutex * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked, std::string name) { +Handle CreateMutex(bool initial_locked, const std::string& name) { Handle handle; Mutex* mutex = CreateMutex(handle, initial_locked, name); return handle; diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index fde5549fa..7d7b5137e 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -23,6 +23,6 @@ Result ReleaseMutex(Handle handle); * @param name Optional name of mutex * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked, const std::string name="Unknown"); +Handle CreateMutex(bool initial_locked, const std::string& name="Unknown"); } // namespace From c95972275e276abe3afcac79d956ea29a0879c8e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:35:49 -0400 Subject: [PATCH 72/84] HLE: Updated all uses of NULL to nullptr (to be C++11 compliant) --- src/core/core.cpp | 8 +- src/core/hle/hle.cpp | 2 +- src/core/hle/kernel/kernel.cpp | 2 +- src/core/hle/kernel/mutex.cpp | 2 +- src/core/hle/kernel/thread.cpp | 14 +- src/core/hle/service/apt.cpp | 148 ++++++++++----------- src/core/hle/service/gsp.cpp | 56 ++++---- src/core/hle/service/hid.cpp | 10 +- src/core/hle/service/ndm.cpp | 8 +- src/core/hle/service/service.cpp | 4 +- src/core/hle/service/service.h | 2 +- src/core/hle/service/srv.cpp | 8 +- src/core/hle/svc.cpp | 214 +++++++++++++++---------------- 13 files changed, 239 insertions(+), 239 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 26d52f7be..d366498a5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -18,10 +18,10 @@ namespace Core { -u64 g_last_ticks = 0; ///< Last CPU ticks -ARM_Disasm* g_disasm = NULL; ///< ARM disassembler -ARM_Interface* g_app_core = NULL; ///< ARM11 application core -ARM_Interface* g_sys_core = NULL; ///< ARM11 system (OS) core +u64 g_last_ticks = 0; ///< Last CPU ticks +ARM_Disasm* g_disasm = nullptr; ///< ARM disassembler +ARM_Interface* g_app_core = nullptr; ///< ARM11 application core +ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core /// Run the core CPU loop void RunLoop() { diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index e49395f56..dde6d0f40 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -22,7 +22,7 @@ const FunctionDef* GetSVCInfo(u32 opcode) { u32 func_num = opcode & 0xFFFFFF; // 8 bits if (func_num > 0xFF) { ERROR_LOG(HLE,"unknown svc=0x%02X", func_num); - return NULL; + return nullptr; } return &g_module_db[0].func_table[func_num]; } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 9d5991c37..e51a9d45a 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -128,7 +128,7 @@ Object* ObjectPool::CreateByIDType(int type) { default: ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type); - return NULL; + return nullptr; } } diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index a76c8de03..1ccf1eb73 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -122,7 +122,7 @@ bool ReleaseMutex(Mutex* mutex) { Result ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, (mutex != NULL), "ReleaseMutex tried to release a NULL mutex!"); + _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!"); if (!ReleaseMutex(mutex)) { return -1; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 5fdb4fbe6..700f4ea7c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -223,7 +223,7 @@ void SwitchContext(Thread* t) { t->wait_type = WAITTYPE_NONE; LoadContext(t->context); } else { - SetCurrentThread(NULL); + SetCurrentThread(nullptr); } } @@ -238,7 +238,7 @@ Thread* NextThread() { next = g_thread_ready_queue.pop_first(); } if (next == 0) { - return NULL; + return nullptr; } return Kernel::g_object_pool.GetFast(next); } @@ -312,8 +312,8 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, u32 stack_top, int stack_size) { - if (name == NULL) { - ERROR_LOG(KERNEL, "CreateThread(): NULL name"); + if (name == nullptr) { + ERROR_LOG(KERNEL, "CreateThread(): nullptr name"); return -1; } if ((u32)stack_size < 0x200) { @@ -353,19 +353,19 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 /// Get the priority of the thread specified by handle u32 GetThreadPriority(const Handle handle) { Thread* thread = g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); return thread->current_priority; } /// Set the priority of the thread specified by handle Result SetThreadPriority(Handle handle, s32 priority) { - Thread* thread = NULL; + Thread* thread = nullptr; if (!handle) { thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? } else { thread = g_object_pool.GetFast(handle); } - _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); // If priority is invalid, clamp to valid range if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 33ee1ec8f..a0012b5dd 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -55,81 +55,81 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00010040, GetLockHandle, "GetLockHandle"}, {0x00020080, Initialize, "Initialize"}, {0x00030040, Enable, "Enable"}, - {0x00040040, NULL, "Finalize"}, - {0x00050040, NULL, "GetAppletManInfo"}, - {0x00060040, NULL, "GetAppletInfo"}, - {0x00070000, NULL, "GetLastSignaledAppletId"}, - {0x00080000, NULL, "CountRegisteredApplet"}, - {0x00090040, NULL, "IsRegistered"}, - {0x000A0040, NULL, "GetAttribute"}, + {0x00040040, nullptr, "Finalize"}, + {0x00050040, nullptr, "GetAppletManInfo"}, + {0x00060040, nullptr, "GetAppletInfo"}, + {0x00070000, nullptr, "GetLastSignaledAppletId"}, + {0x00080000, nullptr, "CountRegisteredApplet"}, + {0x00090040, nullptr, "IsRegistered"}, + {0x000A0040, nullptr, "GetAttribute"}, {0x000B0040, InquireNotification, "InquireNotification"}, - {0x000C0104, NULL, "SendParameter"}, - {0x000D0080, NULL, "ReceiveParameter"}, - {0x000E0080, NULL, "GlanceParameter"}, - {0x000F0100, NULL, "CancelParameter"}, - {0x001000C2, NULL, "DebugFunc"}, - {0x001100C0, NULL, "MapProgramIdForDebug"}, - {0x00120040, NULL, "SetHomeMenuAppletIdForDebug"}, - {0x00130000, NULL, "GetPreparationState"}, - {0x00140040, NULL, "SetPreparationState"}, - {0x00150140, NULL, "PrepareToStartApplication"}, - {0x00160040, NULL, "PreloadLibraryApplet"}, - {0x00170040, NULL, "FinishPreloadingLibraryApplet"}, - {0x00180040, NULL, "PrepareToStartLibraryApplet"}, - {0x00190040, NULL, "PrepareToStartSystemApplet"}, - {0x001A0000, NULL, "PrepareToStartNewestHomeMenu"}, - {0x001B00C4, NULL, "StartApplication"}, - {0x001C0000, NULL, "WakeupApplication"}, - {0x001D0000, NULL, "CancelApplication"}, - {0x001E0084, NULL, "StartLibraryApplet"}, - {0x001F0084, NULL, "StartSystemApplet"}, - {0x00200044, NULL, "StartNewestHomeMenu"}, - {0x00210000, NULL, "OrderToCloseApplication"}, - {0x00220040, NULL, "PrepareToCloseApplication"}, - {0x00230040, NULL, "PrepareToJumpToApplication"}, - {0x00240044, NULL, "JumpToApplication"}, - {0x002500C0, NULL, "PrepareToCloseLibraryApplet"}, - {0x00260000, NULL, "PrepareToCloseSystemApplet"}, - {0x00270044, NULL, "CloseApplication"}, - {0x00280044, NULL, "CloseLibraryApplet"}, - {0x00290044, NULL, "CloseSystemApplet"}, - {0x002A0000, NULL, "OrderToCloseSystemApplet"}, - {0x002B0000, NULL, "PrepareToJumpToHomeMenu"}, - {0x002C0044, NULL, "JumpToHomeMenu"}, - {0x002D0000, NULL, "PrepareToLeaveHomeMenu"}, - {0x002E0044, NULL, "LeaveHomeMenu"}, - {0x002F0040, NULL, "PrepareToLeaveResidentApplet"}, - {0x00300044, NULL, "LeaveResidentApplet"}, - {0x00310100, NULL, "PrepareToDoApplicationJump"}, - {0x00320084, NULL, "DoApplicationJump"}, - {0x00330000, NULL, "GetProgramIdOnApplicationJump"}, - {0x00340084, NULL, "SendDeliverArg"}, - {0x00350080, NULL, "ReceiveDeliverArg"}, - {0x00360040, NULL, "LoadSysMenuArg"}, - {0x00370042, NULL, "StoreSysMenuArg"}, - {0x00380040, NULL, "PreloadResidentApplet"}, - {0x00390040, NULL, "PrepareToStartResidentApplet"}, - {0x003A0044, NULL, "StartResidentApplet"}, - {0x003B0040, NULL, "CancelLibraryApplet"}, - {0x003C0042, NULL, "SendDspSleep"}, - {0x003D0042, NULL, "SendDspWakeUp"}, - {0x003E0080, NULL, "ReplySleepQuery"}, - {0x003F0040, NULL, "ReplySleepNotificationComplete"}, - {0x00400042, NULL, "SendCaptureBufferInfo"}, - {0x00410040, NULL, "ReceiveCaptureBufferInfo"}, - {0x00420080, NULL, "SleepSystem"}, - {0x00430040, NULL, "NotifyToWait"}, - {0x00440000, NULL, "GetSharedFont"}, - {0x00450040, NULL, "GetWirelessRebootInfo"}, - {0x00460104, NULL, "Wrap"}, - {0x00470104, NULL, "Unwrap"}, - {0x00480100, NULL, "GetProgramInfo"}, - {0x00490180, NULL, "Reboot"}, - {0x004A0040, NULL, "GetCaptureInfo"}, - {0x004B00C2, NULL, "AppletUtility"}, - {0x004C0000, NULL, "SetFatalErrDispMode"}, - {0x004D0080, NULL, "GetAppletProgramInfo"}, - {0x004E0000, NULL, "HardwareResetAsync"}, + {0x000C0104, nullptr, "SendParameter"}, + {0x000D0080, nullptr, "ReceiveParameter"}, + {0x000E0080, nullptr, "GlanceParameter"}, + {0x000F0100, nullptr, "CancelParameter"}, + {0x001000C2, nullptr, "DebugFunc"}, + {0x001100C0, nullptr, "MapProgramIdForDebug"}, + {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, + {0x00130000, nullptr, "GetPreparationState"}, + {0x00140040, nullptr, "SetPreparationState"}, + {0x00150140, nullptr, "PrepareToStartApplication"}, + {0x00160040, nullptr, "PreloadLibraryApplet"}, + {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, + {0x00180040, nullptr, "PrepareToStartLibraryApplet"}, + {0x00190040, nullptr, "PrepareToStartSystemApplet"}, + {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, + {0x001B00C4, nullptr, "StartApplication"}, + {0x001C0000, nullptr, "WakeupApplication"}, + {0x001D0000, nullptr, "CancelApplication"}, + {0x001E0084, nullptr, "StartLibraryApplet"}, + {0x001F0084, nullptr, "StartSystemApplet"}, + {0x00200044, nullptr, "StartNewestHomeMenu"}, + {0x00210000, nullptr, "OrderToCloseApplication"}, + {0x00220040, nullptr, "PrepareToCloseApplication"}, + {0x00230040, nullptr, "PrepareToJumpToApplication"}, + {0x00240044, nullptr, "JumpToApplication"}, + {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, + {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, + {0x00270044, nullptr, "CloseApplication"}, + {0x00280044, nullptr, "CloseLibraryApplet"}, + {0x00290044, nullptr, "CloseSystemApplet"}, + {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, + {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, + {0x002C0044, nullptr, "JumpToHomeMenu"}, + {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, + {0x002E0044, nullptr, "LeaveHomeMenu"}, + {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, + {0x00300044, nullptr, "LeaveResidentApplet"}, + {0x00310100, nullptr, "PrepareToDoApplicationJump"}, + {0x00320084, nullptr, "DoApplicationJump"}, + {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, + {0x00340084, nullptr, "SendDeliverArg"}, + {0x00350080, nullptr, "ReceiveDeliverArg"}, + {0x00360040, nullptr, "LoadSysMenuArg"}, + {0x00370042, nullptr, "StoreSysMenuArg"}, + {0x00380040, nullptr, "PreloadResidentApplet"}, + {0x00390040, nullptr, "PrepareToStartResidentApplet"}, + {0x003A0044, nullptr, "StartResidentApplet"}, + {0x003B0040, nullptr, "CancelLibraryApplet"}, + {0x003C0042, nullptr, "SendDspSleep"}, + {0x003D0042, nullptr, "SendDspWakeUp"}, + {0x003E0080, nullptr, "ReplySleepQuery"}, + {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, + {0x00400042, nullptr, "SendCaptureBufferInfo"}, + {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, + {0x00420080, nullptr, "SleepSystem"}, + {0x00430040, nullptr, "NotifyToWait"}, + {0x00440000, nullptr, "GetSharedFont"}, + {0x00450040, nullptr, "GetWirelessRebootInfo"}, + {0x00460104, nullptr, "Wrap"}, + {0x00470104, nullptr, "Unwrap"}, + {0x00480100, nullptr, "GetProgramInfo"}, + {0x00490180, nullptr, "Reboot"}, + {0x004A0040, nullptr, "GetCaptureInfo"}, + {0x004B00C2, nullptr, "AppletUtility"}, + {0x004C0000, nullptr, "SetFatalErrDispMode"}, + {0x004D0080, nullptr, "GetAppletProgramInfo"}, + {0x004E0000, nullptr, "HardwareResetAsync"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index c181e296f..f31e7d86d 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -104,7 +104,7 @@ void RegisterInterruptRelayQueue(Service::Interface* self) { u32 flags = cmd_buff[1]; u32 event_handle = cmd_buff[3]; - _assert_msg_(GSP, (event_handle != 0), "called, but event is NULL!"); + _assert_msg_(GSP, (event_handle != 0), "called, but event is nullptr!"); g_event_handle = event_handle; @@ -139,36 +139,36 @@ void TriggerCmdReqQueue(Service::Interface* self) { } const Interface::FunctionInfo FunctionTable[] = { - {0x00010082, NULL, "WriteHWRegs"}, - {0x00020084, NULL, "WriteHWRegsWithMask"}, - {0x00030082, NULL, "WriteHWRegRepeat"}, + {0x00010082, nullptr, "WriteHWRegs"}, + {0x00020084, nullptr, "WriteHWRegsWithMask"}, + {0x00030082, nullptr, "WriteHWRegRepeat"}, {0x00040080, ReadHWRegs, "ReadHWRegs"}, - {0x00050200, NULL, "SetBufferSwap"}, - {0x00060082, NULL, "SetCommandList"}, - {0x000700C2, NULL, "RequestDma"}, - {0x00080082, NULL, "FlushDataCache"}, - {0x00090082, NULL, "InvalidateDataCache"}, - {0x000A0044, NULL, "RegisterInterruptEvents"}, - {0x000B0040, NULL, "SetLcdForceBlack"}, + {0x00050200, nullptr, "SetBufferSwap"}, + {0x00060082, nullptr, "SetCommandList"}, + {0x000700C2, nullptr, "RequestDma"}, + {0x00080082, nullptr, "FlushDataCache"}, + {0x00090082, nullptr, "InvalidateDataCache"}, + {0x000A0044, nullptr, "RegisterInterruptEvents"}, + {0x000B0040, nullptr, "SetLcdForceBlack"}, {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, - {0x000D0140, NULL, "SetDisplayTransfer"}, - {0x000E0180, NULL, "SetTextureCopy"}, - {0x000F0200, NULL, "SetMemoryFill"}, - {0x00100040, NULL, "SetAxiConfigQoSMode"}, - {0x00110040, NULL, "SetPerfLogMode"}, - {0x00120000, NULL, "GetPerfLog"}, + {0x000D0140, nullptr, "SetDisplayTransfer"}, + {0x000E0180, nullptr, "SetTextureCopy"}, + {0x000F0200, nullptr, "SetMemoryFill"}, + {0x00100040, nullptr, "SetAxiConfigQoSMode"}, + {0x00110040, nullptr, "SetPerfLogMode"}, + {0x00120000, nullptr, "GetPerfLog"}, {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, - {0x00140000, NULL, "UnregisterInterruptRelayQueue"}, - {0x00150002, NULL, "TryAcquireRight"}, - {0x00160042, NULL, "AcquireRight"}, - {0x00170000, NULL, "ReleaseRight"}, - {0x00180000, NULL, "ImportDisplayCaptureInfo"}, - {0x00190000, NULL, "SaveVramSysArea"}, - {0x001A0000, NULL, "RestoreVramSysArea"}, - {0x001B0000, NULL, "ResetGpuCore"}, - {0x001C0040, NULL, "SetLedForceOff"}, - {0x001D0040, NULL, "SetTestCommand"}, - {0x001E0080, NULL, "SetInternalPriorities"}, + {0x00140000, nullptr, "UnregisterInterruptRelayQueue"}, + {0x00150002, nullptr, "TryAcquireRight"}, + {0x00160042, nullptr, "AcquireRight"}, + {0x00170000, nullptr, "ReleaseRight"}, + {0x00180000, nullptr, "ImportDisplayCaptureInfo"}, + {0x00190000, nullptr, "SaveVramSysArea"}, + {0x001A0000, nullptr, "RestoreVramSysArea"}, + {0x001B0000, nullptr, "ResetGpuCore"}, + {0x001C0040, nullptr, "SetLedForceOff"}, + {0x001D0040, nullptr, "SetTestCommand"}, + {0x001E0080, nullptr, "SetInternalPriorities"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/hid.cpp b/src/core/hle/service/hid.cpp index 5542e5bf2..ab78f47d7 100644 --- a/src/core/hle/service/hid.cpp +++ b/src/core/hle/service/hid.cpp @@ -13,11 +13,11 @@ namespace HID_User { const Interface::FunctionInfo FunctionTable[] = { - {0x000A0000, NULL, "GetIPCHandles"}, - {0x00110000, NULL, "EnableAccelerometer"}, - {0x00130000, NULL, "EnableGyroscopeLow"}, - {0x00150000, NULL, "GetGyroscopeLowRawToDpsCoefficient"}, - {0x00160000, NULL, "GetGyroscopeLowCalibrateParam"}, + {0x000A0000, nullptr, "GetIPCHandles"}, + {0x00110000, nullptr, "EnableAccelerometer"}, + {0x00130000, nullptr, "EnableGyroscopeLow"}, + {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"}, + {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/ndm.cpp b/src/core/hle/service/ndm.cpp index 671e9d4bd..48755b6a7 100644 --- a/src/core/hle/service/ndm.cpp +++ b/src/core/hle/service/ndm.cpp @@ -13,10 +13,10 @@ namespace NDM_U { const Interface::FunctionInfo FunctionTable[] = { - {0x00060040, NULL, "SuspendDaemons"}, - {0x00080040, NULL, "DisableWifiUsage"}, - {0x00090000, NULL, "EnableWifiUsage"}, - {0x00140040, NULL, "OverrideDefaultDaemons"}, + {0x00060040, nullptr, "SuspendDaemons"}, + {0x00080040, nullptr, "DisableWifiUsage"}, + {0x00090000, nullptr, "EnableWifiUsage"}, + {0x00140040, nullptr, "OverrideDefaultDaemons"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 781b41fb0..4a1ac857e 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -19,7 +19,7 @@ namespace Service { -Manager* g_manager = NULL; ///< Service manager +Manager* g_manager = nullptr; ///< Service manager //////////////////////////////////////////////////////////////////////////////////////////////////// // Service Manager class @@ -56,7 +56,7 @@ Interface* Manager::FetchFromHandle(Handle handle) { Interface* Manager::FetchFromPortName(std::string port_name) { auto itr = m_port_map.find(port_name); if (itr == m_port_map.end()) { - return NULL; + return nullptr; } return FetchFromHandle(itr->second); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 4b5c5b3c8..166d13038 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -93,7 +93,7 @@ public: cmd_buff[1] = 0; return 0; } - if (itr->second.func == NULL) { + if (itr->second.func == nullptr) { ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s", GetPortName(), itr->second.name.c_str()); diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 07e2009a0..f45c0efc2 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -26,7 +26,7 @@ void GetProcSemaphore(Service::Interface* self) { // Get process semaphore? u32* cmd_buff = Service::GetCommandBuffer(); cmd_buff[1] = 0; // No error - cmd_buff[3] = g_mutex; // Return something... 0 == NULL, raises an exception + cmd_buff[3] = g_mutex; // Return something... 0 == nullptr, raises an exception } void GetServiceHandle(Service::Interface* self) { @@ -36,7 +36,7 @@ void GetServiceHandle(Service::Interface* self) { std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); - if (NULL != service) { + if (nullptr != service) { cmd_buff[3] = service->GetHandle(); DEBUG_LOG(OSHLE, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); } else { @@ -49,8 +49,8 @@ void GetServiceHandle(Service::Interface* self) { const Interface::FunctionInfo FunctionTable[] = { {0x00010002, Initialize, "Initialize"}, {0x00020000, GetProcSemaphore, "GetProcSemaphore"}, - {0x00030100, NULL, "RegisterService"}, - {0x000400C0, NULL, "UnregisterService"}, + {0x00030100, nullptr, "RegisterService"}, + {0x000400C0, nullptr, "UnregisterService"}, {0x00050100, GetServiceHandle, "GetServiceHandle"}, }; diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index c389bbaac..01fc056a1 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -81,7 +81,7 @@ Result ConnectToPort(void* _out, const char* port_name) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); DEBUG_LOG(SVC, "called port_name=%s", port_name); - _assert_msg_(KERNEL, (service != NULL), "called, but service is not implemented!"); + _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); *out = service->GetHandle(); @@ -93,7 +93,7 @@ Result SendSyncRequest(Handle handle) { bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, (object != NULL), "called, but kernel object is NULL!"); + _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName()); Result res = object->SyncRequest(&wait); @@ -122,7 +122,7 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%d", handle, object->GetTypeName(), object->GetName(), nano_seconds); - _assert_msg_(KERNEL, (object != NULL), "called, but kernel object is NULL!"); + _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); Result res = object->WaitSynchronization(&wait); @@ -152,8 +152,8 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handles[i]); - _assert_msg_(KERNEL, (object != NULL), "called handle=0x%08X, but kernel object " - "is NULL!", handles[i]); + _assert_msg_(KERNEL, (object != nullptr), "called handle=0x%08X, but kernel object " + "is nullptr!", handles[i]); DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName(), object->GetName()); @@ -278,7 +278,7 @@ Result CreateMutex(void* _mutex, u32 initial_locked) { /// Release a mutex Result ReleaseMutex(Handle handle) { DEBUG_LOG(SVC, "called handle=0x%08X", handle); - _assert_msg_(KERNEL, (handle != 0), "called, but handle is NULL!"); + _assert_msg_(KERNEL, (handle != 0), "called, but handle is nullptr!"); Kernel::ReleaseMutex(handle); return 0; } @@ -342,132 +342,132 @@ void SleepThread(s64 nanoseconds) { } const HLE::FunctionDef SVC_Table[] = { - {0x00, NULL, "Unknown"}, + {0x00, nullptr, "Unknown"}, {0x01, WrapI_VUUUUU, "ControlMemory"}, {0x02, WrapI_VVU, "QueryMemory"}, - {0x03, NULL, "ExitProcess"}, - {0x04, NULL, "GetProcessAffinityMask"}, - {0x05, NULL, "SetProcessAffinityMask"}, - {0x06, NULL, "GetProcessIdealProcessor"}, - {0x07, NULL, "SetProcessIdealProcessor"}, + {0x03, nullptr, "ExitProcess"}, + {0x04, nullptr, "GetProcessAffinityMask"}, + {0x05, nullptr, "SetProcessAffinityMask"}, + {0x06, nullptr, "GetProcessIdealProcessor"}, + {0x07, nullptr, "SetProcessIdealProcessor"}, {0x08, WrapI_UUUUU, "CreateThread"}, {0x09, WrapU_V, "ExitThread"}, {0x0A, WrapV_S64, "SleepThread"}, {0x0B, WrapI_VU, "GetThreadPriority"}, {0x0C, WrapI_UI, "SetThreadPriority"}, - {0x0D, NULL, "GetThreadAffinityMask"}, - {0x0E, NULL, "SetThreadAffinityMask"}, - {0x0F, NULL, "GetThreadIdealProcessor"}, - {0x10, NULL, "SetThreadIdealProcessor"}, - {0x11, NULL, "GetCurrentProcessorNumber"}, - {0x12, NULL, "Run"}, + {0x0D, nullptr, "GetThreadAffinityMask"}, + {0x0E, nullptr, "SetThreadAffinityMask"}, + {0x0F, nullptr, "GetThreadIdealProcessor"}, + {0x10, nullptr, "SetThreadIdealProcessor"}, + {0x11, nullptr, "GetCurrentProcessorNumber"}, + {0x12, nullptr, "Run"}, {0x13, WrapI_VU, "CreateMutex"}, {0x14, WrapI_U, "ReleaseMutex"}, - {0x15, NULL, "CreateSemaphore"}, - {0x16, NULL, "ReleaseSemaphore"}, + {0x15, nullptr, "CreateSemaphore"}, + {0x16, nullptr, "ReleaseSemaphore"}, {0x17, WrapI_VU, "CreateEvent"}, {0x18, WrapI_U, "SignalEvent"}, {0x19, WrapI_U, "ClearEvent"}, - {0x1A, NULL, "CreateTimer"}, - {0x1B, NULL, "SetTimer"}, - {0x1C, NULL, "CancelTimer"}, - {0x1D, NULL, "ClearTimer"}, - {0x1E, NULL, "CreateMemoryBlock"}, + {0x1A, nullptr, "CreateTimer"}, + {0x1B, nullptr, "SetTimer"}, + {0x1C, nullptr, "CancelTimer"}, + {0x1D, nullptr, "ClearTimer"}, + {0x1E, nullptr, "CreateMemoryBlock"}, {0x1F, WrapI_UUUU, "MapMemoryBlock"}, - {0x20, NULL, "UnmapMemoryBlock"}, + {0x20, nullptr, "UnmapMemoryBlock"}, {0x21, WrapI_V, "CreateAddressArbiter"}, {0x22, WrapI_UUUUS64, "ArbitrateAddress"}, {0x23, WrapI_U, "CloseHandle"}, {0x24, WrapI_US64, "WaitSynchronization1"}, {0x25, WrapI_VVUUS64, "WaitSynchronizationN"}, - {0x26, NULL, "SignalAndWait"}, + {0x26, nullptr, "SignalAndWait"}, {0x27, WrapI_VU, "DuplicateHandle"}, - {0x28, NULL, "GetSystemTick"}, - {0x29, NULL, "GetHandleInfo"}, - {0x2A, NULL, "GetSystemInfo"}, - {0x2B, NULL, "GetProcessInfo"}, - {0x2C, NULL, "GetThreadInfo"}, + {0x28, nullptr, "GetSystemTick"}, + {0x29, nullptr, "GetHandleInfo"}, + {0x2A, nullptr, "GetSystemInfo"}, + {0x2B, nullptr, "GetProcessInfo"}, + {0x2C, nullptr, "GetThreadInfo"}, {0x2D, WrapI_VC, "ConnectToPort"}, - {0x2E, NULL, "SendSyncRequest1"}, - {0x2F, NULL, "SendSyncRequest2"}, - {0x30, NULL, "SendSyncRequest3"}, - {0x31, NULL, "SendSyncRequest4"}, + {0x2E, nullptr, "SendSyncRequest1"}, + {0x2F, nullptr, "SendSyncRequest2"}, + {0x30, nullptr, "SendSyncRequest3"}, + {0x31, nullptr, "SendSyncRequest4"}, {0x32, WrapI_U, "SendSyncRequest"}, - {0x33, NULL, "OpenProcess"}, - {0x34, NULL, "OpenThread"}, - {0x35, NULL, "GetProcessId"}, - {0x36, NULL, "GetProcessIdOfThread"}, + {0x33, nullptr, "OpenProcess"}, + {0x34, nullptr, "OpenThread"}, + {0x35, nullptr, "GetProcessId"}, + {0x36, nullptr, "GetProcessIdOfThread"}, {0x37, WrapI_VU, "GetThreadId"}, {0x38, WrapI_VU, "GetResourceLimit"}, - {0x39, NULL, "GetResourceLimitLimitValues"}, + {0x39, nullptr, "GetResourceLimitLimitValues"}, {0x3A, WrapI_VUVI, "GetResourceLimitCurrentValues"}, - {0x3B, NULL, "GetThreadContext"}, - {0x3C, NULL, "Break"}, + {0x3B, nullptr, "GetThreadContext"}, + {0x3C, nullptr, "Break"}, {0x3D, WrapV_C, "OutputDebugString"}, - {0x3E, NULL, "ControlPerformanceCounter"}, - {0x3F, NULL, "Unknown"}, - {0x40, NULL, "Unknown"}, - {0x41, NULL, "Unknown"}, - {0x42, NULL, "Unknown"}, - {0x43, NULL, "Unknown"}, - {0x44, NULL, "Unknown"}, - {0x45, NULL, "Unknown"}, - {0x46, NULL, "Unknown"}, - {0x47, NULL, "CreatePort"}, - {0x48, NULL, "CreateSessionToPort"}, - {0x49, NULL, "CreateSession"}, - {0x4A, NULL, "AcceptSession"}, - {0x4B, NULL, "ReplyAndReceive1"}, - {0x4C, NULL, "ReplyAndReceive2"}, - {0x4D, NULL, "ReplyAndReceive3"}, - {0x4E, NULL, "ReplyAndReceive4"}, - {0x4F, NULL, "ReplyAndReceive"}, - {0x50, NULL, "BindInterrupt"}, - {0x51, NULL, "UnbindInterrupt"}, - {0x52, NULL, "InvalidateProcessDataCache"}, - {0x53, NULL, "StoreProcessDataCache"}, - {0x54, NULL, "FlushProcessDataCache"}, - {0x55, NULL, "StartInterProcessDma"}, - {0x56, NULL, "StopDma"}, - {0x57, NULL, "GetDmaState"}, - {0x58, NULL, "RestartDma"}, - {0x59, NULL, "Unknown"}, - {0x5A, NULL, "Unknown"}, - {0x5B, NULL, "Unknown"}, - {0x5C, NULL, "Unknown"}, - {0x5D, NULL, "Unknown"}, - {0x5E, NULL, "Unknown"}, - {0x5F, NULL, "Unknown"}, - {0x60, NULL, "DebugActiveProcess"}, - {0x61, NULL, "BreakDebugProcess"}, - {0x62, NULL, "TerminateDebugProcess"}, - {0x63, NULL, "GetProcessDebugEvent"}, - {0x64, NULL, "ContinueDebugEvent"}, - {0x65, NULL, "GetProcessList"}, - {0x66, NULL, "GetThreadList"}, - {0x67, NULL, "GetDebugThreadContext"}, - {0x68, NULL, "SetDebugThreadContext"}, - {0x69, NULL, "QueryDebugProcessMemory"}, - {0x6A, NULL, "ReadProcessMemory"}, - {0x6B, NULL, "WriteProcessMemory"}, - {0x6C, NULL, "SetHardwareBreakPoint"}, - {0x6D, NULL, "GetDebugThreadParam"}, - {0x6E, NULL, "Unknown"}, - {0x6F, NULL, "Unknown"}, - {0x70, NULL, "ControlProcessMemory"}, - {0x71, NULL, "MapProcessMemory"}, - {0x72, NULL, "UnmapProcessMemory"}, - {0x73, NULL, "Unknown"}, - {0x74, NULL, "Unknown"}, - {0x75, NULL, "Unknown"}, - {0x76, NULL, "TerminateProcess"}, - {0x77, NULL, "Unknown"}, - {0x78, NULL, "CreateResourceLimit"}, - {0x79, NULL, "Unknown"}, - {0x7A, NULL, "Unknown"}, - {0x7B, NULL, "Unknown"}, - {0x7C, NULL, "KernelSetState"}, - {0x7D, NULL, "QueryProcessMemory"}, + {0x3E, nullptr, "ControlPerformanceCounter"}, + {0x3F, nullptr, "Unknown"}, + {0x40, nullptr, "Unknown"}, + {0x41, nullptr, "Unknown"}, + {0x42, nullptr, "Unknown"}, + {0x43, nullptr, "Unknown"}, + {0x44, nullptr, "Unknown"}, + {0x45, nullptr, "Unknown"}, + {0x46, nullptr, "Unknown"}, + {0x47, nullptr, "CreatePort"}, + {0x48, nullptr, "CreateSessionToPort"}, + {0x49, nullptr, "CreateSession"}, + {0x4A, nullptr, "AcceptSession"}, + {0x4B, nullptr, "ReplyAndReceive1"}, + {0x4C, nullptr, "ReplyAndReceive2"}, + {0x4D, nullptr, "ReplyAndReceive3"}, + {0x4E, nullptr, "ReplyAndReceive4"}, + {0x4F, nullptr, "ReplyAndReceive"}, + {0x50, nullptr, "BindInterrupt"}, + {0x51, nullptr, "UnbindInterrupt"}, + {0x52, nullptr, "InvalidateProcessDataCache"}, + {0x53, nullptr, "StoreProcessDataCache"}, + {0x54, nullptr, "FlushProcessDataCache"}, + {0x55, nullptr, "StartInterProcessDma"}, + {0x56, nullptr, "StopDma"}, + {0x57, nullptr, "GetDmaState"}, + {0x58, nullptr, "RestartDma"}, + {0x59, nullptr, "Unknown"}, + {0x5A, nullptr, "Unknown"}, + {0x5B, nullptr, "Unknown"}, + {0x5C, nullptr, "Unknown"}, + {0x5D, nullptr, "Unknown"}, + {0x5E, nullptr, "Unknown"}, + {0x5F, nullptr, "Unknown"}, + {0x60, nullptr, "DebugActiveProcess"}, + {0x61, nullptr, "BreakDebugProcess"}, + {0x62, nullptr, "TerminateDebugProcess"}, + {0x63, nullptr, "GetProcessDebugEvent"}, + {0x64, nullptr, "ContinueDebugEvent"}, + {0x65, nullptr, "GetProcessList"}, + {0x66, nullptr, "GetThreadList"}, + {0x67, nullptr, "GetDebugThreadContext"}, + {0x68, nullptr, "SetDebugThreadContext"}, + {0x69, nullptr, "QueryDebugProcessMemory"}, + {0x6A, nullptr, "ReadProcessMemory"}, + {0x6B, nullptr, "WriteProcessMemory"}, + {0x6C, nullptr, "SetHardwareBreakPoint"}, + {0x6D, nullptr, "GetDebugThreadParam"}, + {0x6E, nullptr, "Unknown"}, + {0x6F, nullptr, "Unknown"}, + {0x70, nullptr, "ControlProcessMemory"}, + {0x71, nullptr, "MapProcessMemory"}, + {0x72, nullptr, "UnmapProcessMemory"}, + {0x73, nullptr, "Unknown"}, + {0x74, nullptr, "Unknown"}, + {0x75, nullptr, "Unknown"}, + {0x76, nullptr, "TerminateProcess"}, + {0x77, nullptr, "Unknown"}, + {0x78, nullptr, "CreateResourceLimit"}, + {0x79, nullptr, "Unknown"}, + {0x7A, nullptr, "Unknown"}, + {0x7B, nullptr, "Unknown"}, + {0x7C, nullptr, "KernelSetState"}, + {0x7D, nullptr, "QueryProcessMemory"}, }; void Register() { From 4d6c96b7d8d77b87fcc137aa03cd6a4e4313bdc7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:44:44 -0400 Subject: [PATCH 73/84] SVC: Moved declaration of "wait" variable in SendSyncRequest for improved readability. --- src/core/hle/svc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 01fc056a1..76c6a0771 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -90,12 +90,12 @@ Result ConnectToPort(void* _out, const char* port_name) { /// Synchronize to an OS service Result SendSyncRequest(Handle handle) { - bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handle); _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName()); + bool wait = false; Result res = object->SyncRequest(&wait); if (wait) { Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? From 12e2a59565520382e76c641896b594fdafebd244 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 17:57:52 -0400 Subject: [PATCH 74/84] Thread: Updated VerifyWait to be more readable (but functionally the same). --- src/core/hle/kernel/thread.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 700f4ea7c..0385a64fd 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -146,12 +146,11 @@ void ChangeReadyState(Thread* t, bool ready) { inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { Handle wait_id = 0; Thread *t = g_object_pool.GetFast(thread); - if (t) { - if (type == t->wait_type && handle == t->wait_handle) { - return true; - } + if (t != nullptr && type == t->wait_type && handle == t->wait_handle) { + return true; } else { ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); + return false; } return false; } From bfdd874b1f3a7af9ec540105ed1d52edc0d72472 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 20:05:16 -0400 Subject: [PATCH 75/84] Thread: Moved position of * in arguments. --- src/core/hle/kernel/thread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 0385a64fd..cb5b89379 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -145,7 +145,7 @@ void ChangeReadyState(Thread* t, bool ready) { /// Verify that a thread has not been released from waiting inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { Handle wait_id = 0; - Thread *t = g_object_pool.GetFast(thread); + Thread* t = g_object_pool.GetFast(thread); if (t != nullptr && type == t->wait_type && handle == t->wait_handle) { return true; } else { @@ -158,7 +158,7 @@ inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { /// Stops the current thread void StopThread(Handle thread, const char* reason) { u32 error; - Thread *t = g_object_pool.Get(thread, error); + Thread* t = g_object_pool.Get(thread, error); if (t) { ChangeReadyState(t, false); t->status = THREADSTATUS_DORMANT; From 862db811f02f8d28c4537a6be7b6a8f6c8fec812 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 23:31:29 -0400 Subject: [PATCH 76/84] SVC: Cleaned up function wrappers to pass in correct argument types. --- src/core/hle/function_wrappers.h | 847 ++++--------------------------- src/core/hle/svc.cpp | 286 +++++------ 2 files changed, 232 insertions(+), 901 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 2d0dcf476..e8afa90d6 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -1,19 +1,6 @@ -// Copyright (c) 2012- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. #pragma once @@ -21,759 +8,113 @@ #include "core/mem_map.h" #include "core/hle/hle.h" -// For easy parameter parsing and return value processing. +namespace Wrap { -//32bit wrappers -template void WrapV_V() { - func(); -} - -template void WrapU_V() { - RETURN(func()); -} - -template void WrapI_VC() { - u32 param_1 = 0; - u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))); - Core::g_app_core->SetReg(1, param_1); - RETURN(retval); -} - -template void WrapU_IVI() { - u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), PARAM(2)); - RETURN(retval); -} - -template void WrapI_CIIU() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_ICUVVUI() { - u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), - Memory::GetPointer(PARAM(3)),Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6)); - RETURN(retval); -} - -// Hm, do so many params get passed in registers? -template void WrapI_CICIIIII() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), Memory::GetCharPointer(PARAM(2)), - PARAM(3), PARAM(4), PARAM(5), PARAM(6), PARAM(7)); - RETURN(retval); -} - -// Hm, do so many params get passed in registers? -template void WrapI_CIIIIII() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); -} - -// Hm, do so many params get passed in registers? -template void WrapI_IIIIIIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); -} - -// Hm, do so many params get passed in registers? -template void WrapI_IIIIIIIIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6), PARAM(7), PARAM(8)); - RETURN(retval); -} - -template void WrapU_IV() { - u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1))); - RETURN(retval); -} - -template void WrapF_V() { - RETURNF(func()); -} - -// TODO: Not sure about the floating point parameter passing -template void WrapF_IFU() { - RETURNF(func(PARAM(0), PARAMF(0), PARAM(1))); -} - -template void WrapU_U() { - u32 retval = func(PARAM(0)); - RETURN(retval); -} - -template void WrapU_UI() { - u32 retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapI_U() { - int retval = func(PARAM(0)); - RETURN(retval); -} - -template void WrapI_UI() { - int retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapI_UIIU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_IUI() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_UU() { - int retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapI_UFF() { - // Not sure about the float arguments. - int retval = func(PARAM(0), PARAMF(0), PARAMF(1)); - RETURN(retval); -} - -template void WrapI_UUU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_UUUI() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_UUUIIII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); -} - -template void WrapI_UUUU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_UUUUU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_V() { - u32 retval = func(Memory::GetPointer(PARAM(0))); - RETURN(retval); -} - -template void WrapU_I() { - u32 retval = func(PARAM(0)); - RETURN(retval); -} - -template void WrapU_IIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_I() { - int retval = func(PARAM(0)); - RETURN(retval); -} - -template void WrapV_U() { - func(PARAM(0)); -} - -template void WrapV_I() { - func(PARAM(0)); -} - -template void WrapV_UU() { - func(PARAM(0), PARAM(1)); -} - -template void WrapV_II() { - func(PARAM(0), PARAM(1)); -} - -template void WrapV_UC() { - func(PARAM(0), Memory::GetCharPointer(PARAM(1))); -} - -template void WrapI_UC() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1))); - RETURN(retval); -} - -template void WrapI_UCI() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2)); - RETURN(retval); -} - -template void WrapU_UIIIII() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); -} - -template void WrapU_UIIIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapU_UIIIIII() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); -} - -template void WrapU_UU() { - u32 retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapU_UUI() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapU_UUII() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_CUUU() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapV_UIUII() { - func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); -} - -template void WrapU_UIUII() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_UIUII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapU_UIUI() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_UIUI() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_UIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapU_UIUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_UII() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapU_UIIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_UIIUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_UUII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_UUIII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapV_UIII() { - func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); -} - -template void WrapV_UIIIII() { - func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); -} - -template void WrapV_UII() { - func(PARAM(0), PARAM(1), PARAM(2)); -} - -template void WrapU_IU() { - int retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapI_IU() { - int retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapI_UUI() { - int retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_UUIU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_II() { - int retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapI_III() { - int retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_IUI() { - int retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_IIII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_UIII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_IIIUI() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_IUUII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_ICIUU() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_IIU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Function wrappers that return type s32 -template void WrapV_IU() { - func(PARAM(0), PARAM(1)); -} - -template void WrapV_UI() { - func(PARAM(0), PARAM(1)); -} - -template void WrapU_C() { - u32 retval = func(Memory::GetCharPointer(PARAM(0))); - RETURN(retval); -} - -template void WrapU_CCCU() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), - Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)), - PARAM(3)); - RETURN(retval); -} - -template void WrapI_C() { - int retval = func(Memory::GetCharPointer(PARAM(0))); - RETURN(retval); -} - -template void WrapI_CU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); - RETURN(retval); -} - -template void WrapI_CUI() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_ICIU() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_CIU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_CUU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_CUUU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3)); - RETURN(retval); -} - -template void WrapI_CCII() { - int retval = func(Memory::GetCharPointer(PARAM(0)), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_CUUIUU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); -} - -template void WrapI_CIIUII() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); -} - -template void WrapI_CIUUU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_CUUUUU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); -} - -template void WrapU_CU() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); - RETURN((u32) retval); -} - -template void WrapU_UC() { - u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1))); - RETURN(retval); -} - -template void WrapU_CUU() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); - RETURN((u32) retval); -} - -template void WrapU_III() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapU_II() { - u32 retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - -template void WrapU_IIII() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_IUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapU_IUUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_IUUUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapU_UUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapV_IUU() { - func(PARAM(0), PARAM(1), PARAM(2)); -} - -template void WrapV_IIU() { - func(PARAM(0), PARAM(1), PARAM(2)); -} - -template void WrapV_UIU() { - func(PARAM(0), PARAM(1), PARAM(2)); -} - -template void WrapI_UIU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapV_IUUUU() { - func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); -} - -template void WrapV_UUU() { - func(PARAM(0), PARAM(1), PARAM(2)); -} - -template void WrapV_UUUU() { - func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); -} - -template void WrapV_CUIU() { - func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); -} - -template void WrapI_CUIU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapV_UCUIU() { - func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3), - PARAM(4)); -} - -template void WrapI_UCUIU() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), - PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapV_CUIIU() { - func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), - PARAM(4)); -} - -template void WrapI_CUIIU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapU_UUUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_UCUU() { - u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_UUUI() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_UUUIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapU_UUUIUI() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); -} - -template void WrapU_UUIU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapU_UIII() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_IUUUU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_IUUUUU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); -} - -template void WrapI_IUII() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} -template void WrapU_UUUUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapV_UUUUU() { - func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); -} - -template void WrapU_CC() { - int retval = func(Memory::GetCharPointer(PARAM(0)), - Memory::GetCharPointer(PARAM(1))); - RETURN(retval); -} - -template void WrapV_C() { - func(Memory::GetCharPointer(PARAM(0))); -} - -template void WrapV_S64() { - func(((s64)PARAM(1) << 32) | PARAM(0)); -} - -template void WrapV_CI() { - func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); -} - -template void WrapU_CI() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); - RETURN(retval); -} - -template void WrapU_CII() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapU_CIUIU() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapU_CIUIUI() { - u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), - PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); -} - -template void WrapU_UUUUUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), - PARAM(5)); - RETURN(retval); -} - -template void WrapI_IUUU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_IUU() { - int retval = func(PARAM(0), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapU_UUUUUUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); -} - -template void WrapI_UIUU() { - u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); - RETURN(retval); -} - -template void WrapI_IC() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1))); - RETURN(retval); -} - -template void WrapI_ICCUI() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)), PARAM(3), PARAM(4)); - RETURN(retval); -} - -template void WrapI_ICCI() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), Memory::GetCharPointer(PARAM(2)), PARAM(3)); - RETURN(retval); -} - -template void WrapI_CII() { - int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); - RETURN(retval); -} - -template void WrapI_ICI() { - int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2)); - RETURN(retval); -} - -template void WrapI_IVVVVUI(){ - u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); - RETURN(retval); -} - -template void WrapI_ICUVIII(){ - u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); -} - -template void WrapI_VU(){ - u32 param_1 = 0; - u32 retval = func(¶m_1, PARAM(1)); - Core::g_app_core->SetReg(1, param_1); - RETURN(retval); -} +namespace S32 { -template void WrapI_VVU(){ - u32 retval = func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2)); - RETURN(retval); +template void U32_U32_U32_U32() { + RETURN(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3))); } -template void WrapI_VUVI(){ - u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), PARAM(3)); - RETURN(retval); +template void U32_U32_U32_U32_U32() { + RETURN(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4))); } -template void WrapI_VUUUUU(){ +template void U32P_U32_U32_U32_U32_U32(){ u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); Core::g_app_core->SetReg(1, param_1); RETURN(retval); } -template void WrapI_US64() { - int retval = func(PARAM(0), (((u64)PARAM(3) << 32) | PARAM(2))); - RETURN(retval); -} - -template void WrapI_VVUUS64() { - u32 param_1 = 0; - int retval = func(¶m_1, Memory::GetPointer(PARAM(1)), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); - Core::g_app_core->SetReg(1, param_1); +template void S32P_U32P_S32_Bool_S64() { + s32 param_1 = 0; + s32 retval = func(¶m_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), + (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))); + Core::g_app_core->SetReg(1, (u32)param_1); RETURN(retval); } // TODO(bunnei): Is this correct? Probably not -template void WrapI_UUUUS64() { - int retval = func(PARAM(5), PARAM(1), PARAM(2), PARAM(3), (((u64)PARAM(4) << 32) | PARAM(0))); +template void U32_U32_U32_U32_S64() { + RETURN(func(PARAM(5), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(4) << 32) | PARAM(0)))); +} + +template void U32_S64() { + RETURN(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2)))); +} + +template void VoidP_VoidP_U32(){ + RETURN(func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2))); +} + +template void S32P_U32(){ + s32 param_1 = 0; + u32 retval = func(¶m_1, PARAM(1)); + Core::g_app_core->SetReg(1, param_1); RETURN(retval); } + +template void U32_S32() { + RETURN(func(PARAM(0), (s32)PARAM(1))); +} + +template void U32P_U32(){ + u32 param_1 = 0; + u32 retval = func(¶m_1, PARAM(1)); + Core::g_app_core->SetReg(1, param_1); + RETURN(retval); +} + +template void U32() { + RETURN(func(PARAM(0))); +} + +template void U32P() { + RETURN(func(Memory::GetPointer(PARAM(0)))); +} + +template void S64P_U32_VoidP_S32(){ + RETURN(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), + (s32)PARAM(3))); +} + +template void U32P_CharP() { + u32 param_1 = 0; + u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))); + Core::g_app_core->SetReg(1, param_1); + RETURN(retval); +} + +} // namespace S32 + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Function wrappers that return type u32 + +namespace U32 { + +template void Void() { + RETURN(func()); +} + +} // namespace U32 + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// Function wrappers that return type void + +namespace Void { + +template void S64() { + func(((s64)PARAM(1) << 32) | PARAM(0)); +} + +template void CharP() { + func(Memory::GetCharPointer(PARAM(0))); +} + +} // namespace Void + +} // namespace Wrap diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 76c6a0771..d964d062e 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -34,9 +34,7 @@ enum MapMemoryPermission { }; /// Map application or GSP heap memory -Result ControlMemory(void* _out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { - u32* out_addr = (u32*)_out_addr; - +Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", operation, addr0, addr1, size, permissions); @@ -76,8 +74,7 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper } /// Connect to an OS service given the port name, returns the handle to the port to out -Result ConnectToPort(void* _out, const char* port_name) { - Handle* out = (Handle*)_out; +Result ConnectToPort(Handle* out, const char* port_name) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); DEBUG_LOG(SVC, "called port_name=%s", port_name); @@ -136,11 +133,9 @@ Result WaitSynchronization1(Handle handle, s64 nano_seconds) { } /// Wait for the given handles to synchronize, timeout after the specified nanoseconds -Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wait_all, +Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { // TODO(bunnei): Do something with nano_seconds, currently ignoring this - s32* out = (s32*)_out; - Handle* handles = (Handle*)_handles; bool unlock_all = true; bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated @@ -148,7 +143,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa handle_count, (wait_all ? "true" : "false"), nano_seconds); // Iterate through each handle, synchronize kernel object - for (u32 i = 0; i < handle_count; i++) { + for (s32 i = 0; i < handle_count; i++) { bool wait = false; Kernel::Object* object = Kernel::g_object_pool.GetFast(handles[i]); @@ -200,18 +195,17 @@ void OutputDebugString(const char* string) { } /// Get resource limit -Result GetResourceLimit(void* _resource_limit, Handle process) { +Result GetResourceLimit(Handle* resource_limit, Handle process) { // With regards to proceess values: // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for // the current KThread. - Handle* resource_limit = (Handle*)_resource_limit; *resource_limit = 0xDEADBEEF; ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); return 0; } /// Get resource limit current values -Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, +Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, s32 name_count) { ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", resource_limit, names, name_count); @@ -255,8 +249,7 @@ u32 ExitThread() { } /// Gets the priority for the specified thread -Result GetThreadPriority(void* _priority, Handle handle) { - s32* priority = (s32*)_priority; +Result GetThreadPriority(s32* priority, Handle handle) { *priority = Kernel::GetThreadPriority(handle); return 0; } @@ -267,8 +260,7 @@ Result SetThreadPriority(Handle handle, s32 priority) { } /// Create a mutex -Result CreateMutex(void* _mutex, u32 initial_locked) { - Handle* mutex = (Handle*)_mutex; +Result CreateMutex(Handle* mutex, u32 initial_locked) { *mutex = Kernel::CreateMutex((initial_locked != 0)); DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", initial_locked ? "true" : "false", *mutex); @@ -284,20 +276,19 @@ Result ReleaseMutex(Handle handle) { } /// Get current thread ID -Result GetThreadId(void* thread_id, u32 thread) { +Result GetThreadId(u32* thread_id, Handle thread) { ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); return 0; } /// Query memory -Result QueryMemory(void *_info, void *_out, u32 addr) { +Result QueryMemory(void* info, void* out, u32 addr) { ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); return 0; } /// Create an event -Result CreateEvent(void* _event, u32 reset_type) { - Handle* evt = (Handle*)_event; +Result CreateEvent(Handle* evt, u32 reset_type) { *evt = Kernel::CreateEvent((ResetType)reset_type); DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *evt); @@ -305,8 +296,7 @@ Result CreateEvent(void* _event, u32 reset_type) { } /// Duplicates a kernel handle -Result DuplicateHandle(void* _out, Handle handle) { - Handle* out = (Handle*)_out; +Result DuplicateHandle(Handle* out, Handle handle) { DEBUG_LOG(SVC, "called handle=0x%08X", handle); // Translate kernel handles -> real handles @@ -342,132 +332,132 @@ void SleepThread(s64 nanoseconds) { } const HLE::FunctionDef SVC_Table[] = { - {0x00, nullptr, "Unknown"}, - {0x01, WrapI_VUUUUU, "ControlMemory"}, - {0x02, WrapI_VVU, "QueryMemory"}, - {0x03, nullptr, "ExitProcess"}, - {0x04, nullptr, "GetProcessAffinityMask"}, - {0x05, nullptr, "SetProcessAffinityMask"}, - {0x06, nullptr, "GetProcessIdealProcessor"}, - {0x07, nullptr, "SetProcessIdealProcessor"}, - {0x08, WrapI_UUUUU, "CreateThread"}, - {0x09, WrapU_V, "ExitThread"}, - {0x0A, WrapV_S64, "SleepThread"}, - {0x0B, WrapI_VU, "GetThreadPriority"}, - {0x0C, WrapI_UI, "SetThreadPriority"}, - {0x0D, nullptr, "GetThreadAffinityMask"}, - {0x0E, nullptr, "SetThreadAffinityMask"}, - {0x0F, nullptr, "GetThreadIdealProcessor"}, - {0x10, nullptr, "SetThreadIdealProcessor"}, - {0x11, nullptr, "GetCurrentProcessorNumber"}, - {0x12, nullptr, "Run"}, - {0x13, WrapI_VU, "CreateMutex"}, - {0x14, WrapI_U, "ReleaseMutex"}, - {0x15, nullptr, "CreateSemaphore"}, - {0x16, nullptr, "ReleaseSemaphore"}, - {0x17, WrapI_VU, "CreateEvent"}, - {0x18, WrapI_U, "SignalEvent"}, - {0x19, WrapI_U, "ClearEvent"}, - {0x1A, nullptr, "CreateTimer"}, - {0x1B, nullptr, "SetTimer"}, - {0x1C, nullptr, "CancelTimer"}, - {0x1D, nullptr, "ClearTimer"}, - {0x1E, nullptr, "CreateMemoryBlock"}, - {0x1F, WrapI_UUUU, "MapMemoryBlock"}, - {0x20, nullptr, "UnmapMemoryBlock"}, - {0x21, WrapI_V, "CreateAddressArbiter"}, - {0x22, WrapI_UUUUS64, "ArbitrateAddress"}, - {0x23, WrapI_U, "CloseHandle"}, - {0x24, WrapI_US64, "WaitSynchronization1"}, - {0x25, WrapI_VVUUS64, "WaitSynchronizationN"}, - {0x26, nullptr, "SignalAndWait"}, - {0x27, WrapI_VU, "DuplicateHandle"}, - {0x28, nullptr, "GetSystemTick"}, - {0x29, nullptr, "GetHandleInfo"}, - {0x2A, nullptr, "GetSystemInfo"}, - {0x2B, nullptr, "GetProcessInfo"}, - {0x2C, nullptr, "GetThreadInfo"}, - {0x2D, WrapI_VC, "ConnectToPort"}, - {0x2E, nullptr, "SendSyncRequest1"}, - {0x2F, nullptr, "SendSyncRequest2"}, - {0x30, nullptr, "SendSyncRequest3"}, - {0x31, nullptr, "SendSyncRequest4"}, - {0x32, WrapI_U, "SendSyncRequest"}, - {0x33, nullptr, "OpenProcess"}, - {0x34, nullptr, "OpenThread"}, - {0x35, nullptr, "GetProcessId"}, - {0x36, nullptr, "GetProcessIdOfThread"}, - {0x37, WrapI_VU, "GetThreadId"}, - {0x38, WrapI_VU, "GetResourceLimit"}, - {0x39, nullptr, "GetResourceLimitLimitValues"}, - {0x3A, WrapI_VUVI, "GetResourceLimitCurrentValues"}, - {0x3B, nullptr, "GetThreadContext"}, - {0x3C, nullptr, "Break"}, - {0x3D, WrapV_C, "OutputDebugString"}, - {0x3E, nullptr, "ControlPerformanceCounter"}, - {0x3F, nullptr, "Unknown"}, - {0x40, nullptr, "Unknown"}, - {0x41, nullptr, "Unknown"}, - {0x42, nullptr, "Unknown"}, - {0x43, nullptr, "Unknown"}, - {0x44, nullptr, "Unknown"}, - {0x45, nullptr, "Unknown"}, - {0x46, nullptr, "Unknown"}, - {0x47, nullptr, "CreatePort"}, - {0x48, nullptr, "CreateSessionToPort"}, - {0x49, nullptr, "CreateSession"}, - {0x4A, nullptr, "AcceptSession"}, - {0x4B, nullptr, "ReplyAndReceive1"}, - {0x4C, nullptr, "ReplyAndReceive2"}, - {0x4D, nullptr, "ReplyAndReceive3"}, - {0x4E, nullptr, "ReplyAndReceive4"}, - {0x4F, nullptr, "ReplyAndReceive"}, - {0x50, nullptr, "BindInterrupt"}, - {0x51, nullptr, "UnbindInterrupt"}, - {0x52, nullptr, "InvalidateProcessDataCache"}, - {0x53, nullptr, "StoreProcessDataCache"}, - {0x54, nullptr, "FlushProcessDataCache"}, - {0x55, nullptr, "StartInterProcessDma"}, - {0x56, nullptr, "StopDma"}, - {0x57, nullptr, "GetDmaState"}, - {0x58, nullptr, "RestartDma"}, - {0x59, nullptr, "Unknown"}, - {0x5A, nullptr, "Unknown"}, - {0x5B, nullptr, "Unknown"}, - {0x5C, nullptr, "Unknown"}, - {0x5D, nullptr, "Unknown"}, - {0x5E, nullptr, "Unknown"}, - {0x5F, nullptr, "Unknown"}, - {0x60, nullptr, "DebugActiveProcess"}, - {0x61, nullptr, "BreakDebugProcess"}, - {0x62, nullptr, "TerminateDebugProcess"}, - {0x63, nullptr, "GetProcessDebugEvent"}, - {0x64, nullptr, "ContinueDebugEvent"}, - {0x65, nullptr, "GetProcessList"}, - {0x66, nullptr, "GetThreadList"}, - {0x67, nullptr, "GetDebugThreadContext"}, - {0x68, nullptr, "SetDebugThreadContext"}, - {0x69, nullptr, "QueryDebugProcessMemory"}, - {0x6A, nullptr, "ReadProcessMemory"}, - {0x6B, nullptr, "WriteProcessMemory"}, - {0x6C, nullptr, "SetHardwareBreakPoint"}, - {0x6D, nullptr, "GetDebugThreadParam"}, - {0x6E, nullptr, "Unknown"}, - {0x6F, nullptr, "Unknown"}, - {0x70, nullptr, "ControlProcessMemory"}, - {0x71, nullptr, "MapProcessMemory"}, - {0x72, nullptr, "UnmapProcessMemory"}, - {0x73, nullptr, "Unknown"}, - {0x74, nullptr, "Unknown"}, - {0x75, nullptr, "Unknown"}, - {0x76, nullptr, "TerminateProcess"}, - {0x77, nullptr, "Unknown"}, - {0x78, nullptr, "CreateResourceLimit"}, - {0x79, nullptr, "Unknown"}, - {0x7A, nullptr, "Unknown"}, - {0x7B, nullptr, "Unknown"}, - {0x7C, nullptr, "KernelSetState"}, - {0x7D, nullptr, "QueryProcessMemory"}, + {0x00, nullptr, "Unknown"}, + {0x01, Wrap::S32::U32P_U32_U32_U32_U32_U32, "ControlMemory"}, + {0x02, Wrap::S32::VoidP_VoidP_U32, "QueryMemory"}, + {0x03, nullptr, "ExitProcess"}, + {0x04, nullptr, "GetProcessAffinityMask"}, + {0x05, nullptr, "SetProcessAffinityMask"}, + {0x06, nullptr, "GetProcessIdealProcessor"}, + {0x07, nullptr, "SetProcessIdealProcessor"}, + {0x08, Wrap::S32::U32_U32_U32_U32_U32, "CreateThread"}, + {0x09, Wrap::U32::Void, "ExitThread"}, + {0x0A, Wrap::Void::S64, "SleepThread"}, + {0x0B, Wrap::S32::S32P_U32, "GetThreadPriority"}, + {0x0C, Wrap::S32::U32_S32, "SetThreadPriority"}, + {0x0D, nullptr, "GetThreadAffinityMask"}, + {0x0E, nullptr, "SetThreadAffinityMask"}, + {0x0F, nullptr, "GetThreadIdealProcessor"}, + {0x10, nullptr, "SetThreadIdealProcessor"}, + {0x11, nullptr, "GetCurrentProcessorNumber"}, + {0x12, nullptr, "Run"}, + {0x13, Wrap::S32::U32P_U32, "CreateMutex"}, + {0x14, Wrap::S32::U32, "ReleaseMutex"}, + {0x15, nullptr, "CreateSemaphore"}, + {0x16, nullptr, "ReleaseSemaphore"}, + {0x17, Wrap::S32::U32P_U32, "CreateEvent"}, + {0x18, Wrap::S32::U32, "SignalEvent"}, + {0x19, Wrap::S32::U32, "ClearEvent"}, + {0x1A, nullptr, "CreateTimer"}, + {0x1B, nullptr, "SetTimer"}, + {0x1C, nullptr, "CancelTimer"}, + {0x1D, nullptr, "ClearTimer"}, + {0x1E, nullptr, "CreateMemoryBlock"}, + {0x1F, Wrap::S32::U32_U32_U32_U32, "MapMemoryBlock"}, + {0x20, nullptr, "UnmapMemoryBlock"}, + {0x21, Wrap::S32::U32P, "CreateAddressArbiter"}, + {0x22, Wrap::S32::U32_U32_U32_U32_S64, "ArbitrateAddress"}, + {0x23, Wrap::S32::U32, "CloseHandle"}, + {0x24, Wrap::S32::U32_S64, "WaitSynchronization1"}, + {0x25, Wrap::S32::S32P_U32P_S32_Bool_S64, "WaitSynchronizationN"}, + {0x26, nullptr, "SignalAndWait"}, + {0x27, Wrap::S32::U32P_U32, "DuplicateHandle"}, + {0x28, nullptr, "GetSystemTick"}, + {0x29, nullptr, "GetHandleInfo"}, + {0x2A, nullptr, "GetSystemInfo"}, + {0x2B, nullptr, "GetProcessInfo"}, + {0x2C, nullptr, "GetThreadInfo"}, + {0x2D, Wrap::S32::U32P_CharP, "ConnectToPort"}, + {0x2E, nullptr, "SendSyncRequest1"}, + {0x2F, nullptr, "SendSyncRequest2"}, + {0x30, nullptr, "SendSyncRequest3"}, + {0x31, nullptr, "SendSyncRequest4"}, + {0x32, Wrap::S32::U32, "SendSyncRequest"}, + {0x33, nullptr, "OpenProcess"}, + {0x34, nullptr, "OpenThread"}, + {0x35, nullptr, "GetProcessId"}, + {0x36, nullptr, "GetProcessIdOfThread"}, + {0x37, Wrap::S32::U32P_U32, "GetThreadId"}, + {0x38, Wrap::S32::U32P_U32, "GetResourceLimit"}, + {0x39, nullptr, "GetResourceLimitLimitValues"}, + {0x3A, Wrap::S32::S64P_U32_VoidP_S32, "GetResourceLimitCurrentValues"}, + {0x3B, nullptr, "GetThreadContext"}, + {0x3C, nullptr, "Break"}, + {0x3D, Wrap::Void::CharP, "OutputDebugString"}, + {0x3E, nullptr, "ControlPerformanceCounter"}, + {0x3F, nullptr, "Unknown"}, + {0x40, nullptr, "Unknown"}, + {0x41, nullptr, "Unknown"}, + {0x42, nullptr, "Unknown"}, + {0x43, nullptr, "Unknown"}, + {0x44, nullptr, "Unknown"}, + {0x45, nullptr, "Unknown"}, + {0x46, nullptr, "Unknown"}, + {0x47, nullptr, "CreatePort"}, + {0x48, nullptr, "CreateSessionToPort"}, + {0x49, nullptr, "CreateSession"}, + {0x4A, nullptr, "AcceptSession"}, + {0x4B, nullptr, "ReplyAndReceive1"}, + {0x4C, nullptr, "ReplyAndReceive2"}, + {0x4D, nullptr, "ReplyAndReceive3"}, + {0x4E, nullptr, "ReplyAndReceive4"}, + {0x4F, nullptr, "ReplyAndReceive"}, + {0x50, nullptr, "BindInterrupt"}, + {0x51, nullptr, "UnbindInterrupt"}, + {0x52, nullptr, "InvalidateProcessDataCache"}, + {0x53, nullptr, "StoreProcessDataCache"}, + {0x54, nullptr, "FlushProcessDataCache"}, + {0x55, nullptr, "StartInterProcessDma"}, + {0x56, nullptr, "StopDma"}, + {0x57, nullptr, "GetDmaState"}, + {0x58, nullptr, "RestartDma"}, + {0x59, nullptr, "Unknown"}, + {0x5A, nullptr, "Unknown"}, + {0x5B, nullptr, "Unknown"}, + {0x5C, nullptr, "Unknown"}, + {0x5D, nullptr, "Unknown"}, + {0x5E, nullptr, "Unknown"}, + {0x5F, nullptr, "Unknown"}, + {0x60, nullptr, "DebugActiveProcess"}, + {0x61, nullptr, "BreakDebugProcess"}, + {0x62, nullptr, "TerminateDebugProcess"}, + {0x63, nullptr, "GetProcessDebugEvent"}, + {0x64, nullptr, "ContinueDebugEvent"}, + {0x65, nullptr, "GetProcessList"}, + {0x66, nullptr, "GetThreadList"}, + {0x67, nullptr, "GetDebugThreadContext"}, + {0x68, nullptr, "SetDebugThreadContext"}, + {0x69, nullptr, "QueryDebugProcessMemory"}, + {0x6A, nullptr, "ReadProcessMemory"}, + {0x6B, nullptr, "WriteProcessMemory"}, + {0x6C, nullptr, "SetHardwareBreakPoint"}, + {0x6D, nullptr, "GetDebugThreadParam"}, + {0x6E, nullptr, "Unknown"}, + {0x6F, nullptr, "Unknown"}, + {0x70, nullptr, "ControlProcessMemory"}, + {0x71, nullptr, "MapProcessMemory"}, + {0x72, nullptr, "UnmapProcessMemory"}, + {0x73, nullptr, "Unknown"}, + {0x74, nullptr, "Unknown"}, + {0x75, nullptr, "Unknown"}, + {0x76, nullptr, "TerminateProcess"}, + {0x77, nullptr, "Unknown"}, + {0x78, nullptr, "CreateResourceLimit"}, + {0x79, nullptr, "Unknown"}, + {0x7A, nullptr, "Unknown"}, + {0x7B, nullptr, "Unknown"}, + {0x7C, nullptr, "KernelSetState"}, + {0x7D, nullptr, "QueryProcessMemory"}, }; void Register() { From 4620e2a741735a18f3a331037f86b3aae0f9fc6d Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 23:34:49 -0400 Subject: [PATCH 77/84] HLE: Removed usnused EatCycles function. --- src/core/hle/hle.cpp | 4 ---- src/core/hle/hle.h | 2 -- src/core/hle/kernel/thread.cpp | 9 --------- 3 files changed, 15 deletions(-) diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index dde6d0f40..53cda4a61 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -40,10 +40,6 @@ void CallSVC(u32 opcode) { } } -void EatCycles(u32 cycles) { - // TODO: ImplementMe -} - void Reschedule(const char *reason) { #ifdef _DEBUG _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 8a59020c2..0397da5d9 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -37,8 +37,6 @@ void RegisterModule(std::string name, int num_functions, const FunctionDef *func void CallSVC(u32 opcode); -void EatCycles(u32 cycles); - void Reschedule(const char *reason); void Init(); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index cb5b89379..ebe308a93 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -337,15 +337,8 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 stack_size); ResetThread(t, arg, 0); - - HLE::EatCycles(32000); - CallThread(t); - // This won't schedule to the new thread, but it may to one woken from eating cycles. - // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. - //HLE::Reschedule(__func__); - return handle; } @@ -389,8 +382,6 @@ Result SetThreadPriority(Handle handle, s32 priority) { g_thread_ready_queue.push_back(thread->current_priority, handle); } - HLE::EatCycles(450); - return 0; } From 5b7cf50a7760ea1d4202ac3890cefc8934ac841f Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:08:49 -0400 Subject: [PATCH 78/84] Thread: Cleaned up VerifyWait, fixed issue where nullptr msg could unnecessarily be logged. --- src/core/hle/kernel/thread.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ebe308a93..baa9687cb 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -143,16 +143,14 @@ void ChangeReadyState(Thread* t, bool ready) { } /// Verify that a thread has not been released from waiting -inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { - Handle wait_id = 0; - Thread* t = g_object_pool.GetFast(thread); - if (t != nullptr && type == t->wait_type && handle == t->wait_handle) { - return true; - } else { - ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); +inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { + Thread* thread = g_object_pool.GetFast(handle); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); + + if (type != thread->wait_type || wait_handle != thread->wait_handle) return false; - } - return false; + + return true; } /// Stops the current thread From b62ef4bbd2f415b6a193ce53e87decb56bacb3e1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:14:03 -0400 Subject: [PATCH 79/84] Thread: Renamed occurrences of "t" to "thread" to improve readability. --- src/core/hle/kernel/thread.cpp | 93 ++++++++++++++++------------------ 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index baa9687cb..ab5a5559e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -154,26 +154,23 @@ inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) } /// Stops the current thread -void StopThread(Handle thread, const char* reason) { - u32 error; - Thread* t = g_object_pool.Get(thread, error); - if (t) { - ChangeReadyState(t, false); - t->status = THREADSTATUS_DORMANT; - for (size_t i = 0; i < t->waiting_threads.size(); ++i) { - const Handle waiting_thread = t->waiting_threads[i]; - if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, thread)) { - ResumeThreadFromWait(waiting_thread); - } +void StopThread(Handle handle, const char* reason) { + Thread* thread = g_object_pool.GetFast(handle); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); + + ChangeReadyState(thread, false); + thread->status = THREADSTATUS_DORMANT; + for (size_t i = 0; i < thread->waiting_threads.size(); ++i) { + const Handle waiting_thread = thread->waiting_threads[i]; + if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { + ResumeThreadFromWait(waiting_thread); } - t->waiting_threads.clear(); - - // Stopped threads are never waiting. - t->wait_type = WAITTYPE_NONE; - t->wait_handle = 0; - } else { - ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); } + thread->waiting_threads.clear(); + + // Stopped threads are never waiting. + thread->wait_type = WAITTYPE_NONE; + thread->wait_handle = 0; } /// Changes a threads state @@ -242,20 +239,20 @@ Thread* NextThread() { /// Puts the current thread in the wait state for the given type void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { - Thread* t = GetCurrentThread(); - t->wait_type = wait_type; - t->wait_handle = wait_handle; - ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); + Thread* thread = GetCurrentThread(); + thread->wait_type = wait_type; + thread->wait_handle = wait_handle; + ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); } /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle) { u32 error; - Thread* t = Kernel::g_object_pool.Get(handle, error); - if (t) { - t->status &= ~THREADSTATUS_WAIT; - if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { - ChangeReadyState(t, true); + Thread* thread = Kernel::g_object_pool.Get(handle, error); + if (thread) { + thread->status &= ~THREADSTATUS_WAIT; + if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { + ChangeReadyState(thread, true); } } } @@ -283,26 +280,26 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST), "CreateThread priority=%d, outside of allowable range!", priority) - Thread* t = new Thread; + Thread* thread = new Thread; - handle = Kernel::g_object_pool.Create(t); + handle = Kernel::g_object_pool.Create(thread); g_thread_queue.push_back(handle); g_thread_ready_queue.prepare(priority); - t->status = THREADSTATUS_DORMANT; - t->entry_point = entry_point; - t->stack_top = stack_top; - t->stack_size = stack_size; - t->initial_priority = t->current_priority = priority; - t->processor_id = processor_id; - t->wait_type = WAITTYPE_NONE; - t->wait_handle = 0; + thread->status = THREADSTATUS_DORMANT; + thread->entry_point = entry_point; + thread->stack_top = stack_top; + thread->stack_size = stack_size; + thread->initial_priority = thread->current_priority = priority; + thread->processor_id = processor_id; + thread->wait_type = WAITTYPE_NONE; + thread->wait_handle = 0; - strncpy(t->name, name, Kernel::MAX_NAME_LENGTH); - t->name[Kernel::MAX_NAME_LENGTH] = '\0'; + strncpy(thread->name, name, Kernel::MAX_NAME_LENGTH); + thread->name[Kernel::MAX_NAME_LENGTH] = '\0'; - return t; + return thread; } /// Creates a new thread - wrapper for external user @@ -331,11 +328,11 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 return -1; } Handle handle; - Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, + Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, stack_size); - ResetThread(t, arg, 0); - CallThread(t); + ResetThread(thread, arg, 0); + CallThread(thread); return handle; } @@ -388,10 +385,10 @@ Handle SetupMainThread(s32 priority, int stack_size) { Handle handle; // Initialize new "main" thread - Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, + Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); - ResetThread(t, 0, 0); + ResetThread(thread, 0, 0); // If running another thread already, set it to "ready" state Thread* cur = GetCurrentThread(); @@ -400,9 +397,9 @@ Handle SetupMainThread(s32 priority, int stack_size) { } // Run new "main" thread - SetCurrentThread(t); - t->status = THREADSTATUS_RUNNING; - LoadContext(t->context); + SetCurrentThread(thread); + thread->status = THREADSTATUS_RUNNING; + LoadContext(thread->context); return handle; } From 8957622d10784d5f04571e9ae01dbae13ed64c3e Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:30:39 -0400 Subject: [PATCH 80/84] SVC: Renamed all function wrapper templates to Wrap, moved to HLE namespace. --- src/core/hle/function_wrappers.h | 50 +++--- src/core/hle/svc.cpp | 252 +++++++++++++++---------------- 2 files changed, 145 insertions(+), 157 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index e8afa90d6..aa5278c8a 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -8,29 +8,27 @@ #include "core/mem_map.h" #include "core/hle/hle.h" -namespace Wrap { +namespace HLE { //////////////////////////////////////////////////////////////////////////////////////////////////// // Function wrappers that return type s32 -namespace S32 { - -template void U32_U32_U32_U32() { +template void Wrap() { RETURN(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3))); } -template void U32_U32_U32_U32_U32() { +template void Wrap() { RETURN(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4))); } -template void U32P_U32_U32_U32_U32_U32(){ +template void Wrap(){ u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); Core::g_app_core->SetReg(1, param_1); RETURN(retval); } -template void S32P_U32P_S32_Bool_S64() { +template void Wrap() { s32 param_1 = 0; s32 retval = func(¶m_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))); @@ -39,82 +37,72 @@ template void S32P_U32P_S32_Bool_S64() { } // TODO(bunnei): Is this correct? Probably not -template void U32_U32_U32_U32_S64() { +template void Wrap() { RETURN(func(PARAM(5), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(4) << 32) | PARAM(0)))); } -template void U32_S64() { +template void Wrap() { RETURN(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2)))); } -template void VoidP_VoidP_U32(){ +template void Wrap(){ RETURN(func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2))); } -template void S32P_U32(){ +template void Wrap(){ s32 param_1 = 0; u32 retval = func(¶m_1, PARAM(1)); Core::g_app_core->SetReg(1, param_1); RETURN(retval); } -template void U32_S32() { +template void Wrap() { RETURN(func(PARAM(0), (s32)PARAM(1))); } -template void U32P_U32(){ +template void Wrap(){ u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(1)); Core::g_app_core->SetReg(1, param_1); RETURN(retval); } -template void U32() { +template void Wrap() { RETURN(func(PARAM(0))); } -template void U32P() { +template void Wrap() { RETURN(func(Memory::GetPointer(PARAM(0)))); } -template void S64P_U32_VoidP_S32(){ +template void Wrap(){ RETURN(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), (s32)PARAM(3))); } -template void U32P_CharP() { +template void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))); Core::g_app_core->SetReg(1, param_1); RETURN(retval); } -} // namespace S32 - //////////////////////////////////////////////////////////////////////////////////////////////////// // Function wrappers that return type u32 -namespace U32 { - -template void Void() { +template void Wrap() { RETURN(func()); } -} // namespace U32 - //////////////////////////////////////////////////////////////////////////////////////////////////// /// Function wrappers that return type void -namespace Void { - -template void S64() { +template void Wrap() { func(((s64)PARAM(1) << 32) | PARAM(0)); } -template void CharP() { +template void Wrap() { func(Memory::GetCharPointer(PARAM(0))); } -} // namespace Void - -} // namespace Wrap +} // namespace HLE diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index d964d062e..441d8ce8d 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -332,132 +332,132 @@ void SleepThread(s64 nanoseconds) { } const HLE::FunctionDef SVC_Table[] = { - {0x00, nullptr, "Unknown"}, - {0x01, Wrap::S32::U32P_U32_U32_U32_U32_U32, "ControlMemory"}, - {0x02, Wrap::S32::VoidP_VoidP_U32, "QueryMemory"}, - {0x03, nullptr, "ExitProcess"}, - {0x04, nullptr, "GetProcessAffinityMask"}, - {0x05, nullptr, "SetProcessAffinityMask"}, - {0x06, nullptr, "GetProcessIdealProcessor"}, - {0x07, nullptr, "SetProcessIdealProcessor"}, - {0x08, Wrap::S32::U32_U32_U32_U32_U32, "CreateThread"}, - {0x09, Wrap::U32::Void, "ExitThread"}, - {0x0A, Wrap::Void::S64, "SleepThread"}, - {0x0B, Wrap::S32::S32P_U32, "GetThreadPriority"}, - {0x0C, Wrap::S32::U32_S32, "SetThreadPriority"}, - {0x0D, nullptr, "GetThreadAffinityMask"}, - {0x0E, nullptr, "SetThreadAffinityMask"}, - {0x0F, nullptr, "GetThreadIdealProcessor"}, - {0x10, nullptr, "SetThreadIdealProcessor"}, - {0x11, nullptr, "GetCurrentProcessorNumber"}, - {0x12, nullptr, "Run"}, - {0x13, Wrap::S32::U32P_U32, "CreateMutex"}, - {0x14, Wrap::S32::U32, "ReleaseMutex"}, - {0x15, nullptr, "CreateSemaphore"}, - {0x16, nullptr, "ReleaseSemaphore"}, - {0x17, Wrap::S32::U32P_U32, "CreateEvent"}, - {0x18, Wrap::S32::U32, "SignalEvent"}, - {0x19, Wrap::S32::U32, "ClearEvent"}, - {0x1A, nullptr, "CreateTimer"}, - {0x1B, nullptr, "SetTimer"}, - {0x1C, nullptr, "CancelTimer"}, - {0x1D, nullptr, "ClearTimer"}, - {0x1E, nullptr, "CreateMemoryBlock"}, - {0x1F, Wrap::S32::U32_U32_U32_U32, "MapMemoryBlock"}, - {0x20, nullptr, "UnmapMemoryBlock"}, - {0x21, Wrap::S32::U32P, "CreateAddressArbiter"}, - {0x22, Wrap::S32::U32_U32_U32_U32_S64, "ArbitrateAddress"}, - {0x23, Wrap::S32::U32, "CloseHandle"}, - {0x24, Wrap::S32::U32_S64, "WaitSynchronization1"}, - {0x25, Wrap::S32::S32P_U32P_S32_Bool_S64, "WaitSynchronizationN"}, - {0x26, nullptr, "SignalAndWait"}, - {0x27, Wrap::S32::U32P_U32, "DuplicateHandle"}, - {0x28, nullptr, "GetSystemTick"}, - {0x29, nullptr, "GetHandleInfo"}, - {0x2A, nullptr, "GetSystemInfo"}, - {0x2B, nullptr, "GetProcessInfo"}, - {0x2C, nullptr, "GetThreadInfo"}, - {0x2D, Wrap::S32::U32P_CharP, "ConnectToPort"}, - {0x2E, nullptr, "SendSyncRequest1"}, - {0x2F, nullptr, "SendSyncRequest2"}, - {0x30, nullptr, "SendSyncRequest3"}, - {0x31, nullptr, "SendSyncRequest4"}, - {0x32, Wrap::S32::U32, "SendSyncRequest"}, - {0x33, nullptr, "OpenProcess"}, - {0x34, nullptr, "OpenThread"}, - {0x35, nullptr, "GetProcessId"}, - {0x36, nullptr, "GetProcessIdOfThread"}, - {0x37, Wrap::S32::U32P_U32, "GetThreadId"}, - {0x38, Wrap::S32::U32P_U32, "GetResourceLimit"}, - {0x39, nullptr, "GetResourceLimitLimitValues"}, - {0x3A, Wrap::S32::S64P_U32_VoidP_S32, "GetResourceLimitCurrentValues"}, - {0x3B, nullptr, "GetThreadContext"}, - {0x3C, nullptr, "Break"}, - {0x3D, Wrap::Void::CharP, "OutputDebugString"}, - {0x3E, nullptr, "ControlPerformanceCounter"}, - {0x3F, nullptr, "Unknown"}, - {0x40, nullptr, "Unknown"}, - {0x41, nullptr, "Unknown"}, - {0x42, nullptr, "Unknown"}, - {0x43, nullptr, "Unknown"}, - {0x44, nullptr, "Unknown"}, - {0x45, nullptr, "Unknown"}, - {0x46, nullptr, "Unknown"}, - {0x47, nullptr, "CreatePort"}, - {0x48, nullptr, "CreateSessionToPort"}, - {0x49, nullptr, "CreateSession"}, - {0x4A, nullptr, "AcceptSession"}, - {0x4B, nullptr, "ReplyAndReceive1"}, - {0x4C, nullptr, "ReplyAndReceive2"}, - {0x4D, nullptr, "ReplyAndReceive3"}, - {0x4E, nullptr, "ReplyAndReceive4"}, - {0x4F, nullptr, "ReplyAndReceive"}, - {0x50, nullptr, "BindInterrupt"}, - {0x51, nullptr, "UnbindInterrupt"}, - {0x52, nullptr, "InvalidateProcessDataCache"}, - {0x53, nullptr, "StoreProcessDataCache"}, - {0x54, nullptr, "FlushProcessDataCache"}, - {0x55, nullptr, "StartInterProcessDma"}, - {0x56, nullptr, "StopDma"}, - {0x57, nullptr, "GetDmaState"}, - {0x58, nullptr, "RestartDma"}, - {0x59, nullptr, "Unknown"}, - {0x5A, nullptr, "Unknown"}, - {0x5B, nullptr, "Unknown"}, - {0x5C, nullptr, "Unknown"}, - {0x5D, nullptr, "Unknown"}, - {0x5E, nullptr, "Unknown"}, - {0x5F, nullptr, "Unknown"}, - {0x60, nullptr, "DebugActiveProcess"}, - {0x61, nullptr, "BreakDebugProcess"}, - {0x62, nullptr, "TerminateDebugProcess"}, - {0x63, nullptr, "GetProcessDebugEvent"}, - {0x64, nullptr, "ContinueDebugEvent"}, - {0x65, nullptr, "GetProcessList"}, - {0x66, nullptr, "GetThreadList"}, - {0x67, nullptr, "GetDebugThreadContext"}, - {0x68, nullptr, "SetDebugThreadContext"}, - {0x69, nullptr, "QueryDebugProcessMemory"}, - {0x6A, nullptr, "ReadProcessMemory"}, - {0x6B, nullptr, "WriteProcessMemory"}, - {0x6C, nullptr, "SetHardwareBreakPoint"}, - {0x6D, nullptr, "GetDebugThreadParam"}, - {0x6E, nullptr, "Unknown"}, - {0x6F, nullptr, "Unknown"}, - {0x70, nullptr, "ControlProcessMemory"}, - {0x71, nullptr, "MapProcessMemory"}, - {0x72, nullptr, "UnmapProcessMemory"}, - {0x73, nullptr, "Unknown"}, - {0x74, nullptr, "Unknown"}, - {0x75, nullptr, "Unknown"}, - {0x76, nullptr, "TerminateProcess"}, - {0x77, nullptr, "Unknown"}, - {0x78, nullptr, "CreateResourceLimit"}, - {0x79, nullptr, "Unknown"}, - {0x7A, nullptr, "Unknown"}, - {0x7B, nullptr, "Unknown"}, - {0x7C, nullptr, "KernelSetState"}, - {0x7D, nullptr, "QueryProcessMemory"}, + {0x00, nullptr, "Unknown"}, + {0x01, HLE::Wrap, "ControlMemory"}, + {0x02, HLE::Wrap, "QueryMemory"}, + {0x03, nullptr, "ExitProcess"}, + {0x04, nullptr, "GetProcessAffinityMask"}, + {0x05, nullptr, "SetProcessAffinityMask"}, + {0x06, nullptr, "GetProcessIdealProcessor"}, + {0x07, nullptr, "SetProcessIdealProcessor"}, + {0x08, HLE::Wrap, "CreateThread"}, + {0x09, HLE::Wrap, "ExitThread"}, + {0x0A, HLE::Wrap, "SleepThread"}, + {0x0B, HLE::Wrap, "GetThreadPriority"}, + {0x0C, HLE::Wrap, "SetThreadPriority"}, + {0x0D, nullptr, "GetThreadAffinityMask"}, + {0x0E, nullptr, "SetThreadAffinityMask"}, + {0x0F, nullptr, "GetThreadIdealProcessor"}, + {0x10, nullptr, "SetThreadIdealProcessor"}, + {0x11, nullptr, "GetCurrentProcessorNumber"}, + {0x12, nullptr, "Run"}, + {0x13, HLE::Wrap, "CreateMutex"}, + {0x14, HLE::Wrap, "ReleaseMutex"}, + {0x15, nullptr, "CreateSemaphore"}, + {0x16, nullptr, "ReleaseSemaphore"}, + {0x17, HLE::Wrap, "CreateEvent"}, + {0x18, HLE::Wrap, "SignalEvent"}, + {0x19, HLE::Wrap, "ClearEvent"}, + {0x1A, nullptr, "CreateTimer"}, + {0x1B, nullptr, "SetTimer"}, + {0x1C, nullptr, "CancelTimer"}, + {0x1D, nullptr, "ClearTimer"}, + {0x1E, nullptr, "CreateMemoryBlock"}, + {0x1F, HLE::Wrap, "MapMemoryBlock"}, + {0x20, nullptr, "UnmapMemoryBlock"}, + {0x21, HLE::Wrap, "CreateAddressArbiter"}, + {0x22, HLE::Wrap, "ArbitrateAddress"}, + {0x23, HLE::Wrap, "CloseHandle"}, + {0x24, HLE::Wrap, "WaitSynchronization1"}, + {0x25, HLE::Wrap, "WaitSynchronizationN"}, + {0x26, nullptr, "SignalAndWait"}, + {0x27, HLE::Wrap, "DuplicateHandle"}, + {0x28, nullptr, "GetSystemTick"}, + {0x29, nullptr, "GetHandleInfo"}, + {0x2A, nullptr, "GetSystemInfo"}, + {0x2B, nullptr, "GetProcessInfo"}, + {0x2C, nullptr, "GetThreadInfo"}, + {0x2D, HLE::Wrap, "ConnectToPort"}, + {0x2E, nullptr, "SendSyncRequest1"}, + {0x2F, nullptr, "SendSyncRequest2"}, + {0x30, nullptr, "SendSyncRequest3"}, + {0x31, nullptr, "SendSyncRequest4"}, + {0x32, HLE::Wrap, "SendSyncRequest"}, + {0x33, nullptr, "OpenProcess"}, + {0x34, nullptr, "OpenThread"}, + {0x35, nullptr, "GetProcessId"}, + {0x36, nullptr, "GetProcessIdOfThread"}, + {0x37, HLE::Wrap, "GetThreadId"}, + {0x38, HLE::Wrap, "GetResourceLimit"}, + {0x39, nullptr, "GetResourceLimitLimitValues"}, + {0x3A, HLE::Wrap, "GetResourceLimitCurrentValues"}, + {0x3B, nullptr, "GetThreadContext"}, + {0x3C, nullptr, "Break"}, + {0x3D, HLE::Wrap, "OutputDebugString"}, + {0x3E, nullptr, "ControlPerformanceCounter"}, + {0x3F, nullptr, "Unknown"}, + {0x40, nullptr, "Unknown"}, + {0x41, nullptr, "Unknown"}, + {0x42, nullptr, "Unknown"}, + {0x43, nullptr, "Unknown"}, + {0x44, nullptr, "Unknown"}, + {0x45, nullptr, "Unknown"}, + {0x46, nullptr, "Unknown"}, + {0x47, nullptr, "CreatePort"}, + {0x48, nullptr, "CreateSessionToPort"}, + {0x49, nullptr, "CreateSession"}, + {0x4A, nullptr, "AcceptSession"}, + {0x4B, nullptr, "ReplyAndReceive1"}, + {0x4C, nullptr, "ReplyAndReceive2"}, + {0x4D, nullptr, "ReplyAndReceive3"}, + {0x4E, nullptr, "ReplyAndReceive4"}, + {0x4F, nullptr, "ReplyAndReceive"}, + {0x50, nullptr, "BindInterrupt"}, + {0x51, nullptr, "UnbindInterrupt"}, + {0x52, nullptr, "InvalidateProcessDataCache"}, + {0x53, nullptr, "StoreProcessDataCache"}, + {0x54, nullptr, "FlushProcessDataCache"}, + {0x55, nullptr, "StartInterProcessDma"}, + {0x56, nullptr, "StopDma"}, + {0x57, nullptr, "GetDmaState"}, + {0x58, nullptr, "RestartDma"}, + {0x59, nullptr, "Unknown"}, + {0x5A, nullptr, "Unknown"}, + {0x5B, nullptr, "Unknown"}, + {0x5C, nullptr, "Unknown"}, + {0x5D, nullptr, "Unknown"}, + {0x5E, nullptr, "Unknown"}, + {0x5F, nullptr, "Unknown"}, + {0x60, nullptr, "DebugActiveProcess"}, + {0x61, nullptr, "BreakDebugProcess"}, + {0x62, nullptr, "TerminateDebugProcess"}, + {0x63, nullptr, "GetProcessDebugEvent"}, + {0x64, nullptr, "ContinueDebugEvent"}, + {0x65, nullptr, "GetProcessList"}, + {0x66, nullptr, "GetThreadList"}, + {0x67, nullptr, "GetDebugThreadContext"}, + {0x68, nullptr, "SetDebugThreadContext"}, + {0x69, nullptr, "QueryDebugProcessMemory"}, + {0x6A, nullptr, "ReadProcessMemory"}, + {0x6B, nullptr, "WriteProcessMemory"}, + {0x6C, nullptr, "SetHardwareBreakPoint"}, + {0x6D, nullptr, "GetDebugThreadParam"}, + {0x6E, nullptr, "Unknown"}, + {0x6F, nullptr, "Unknown"}, + {0x70, nullptr, "ControlProcessMemory"}, + {0x71, nullptr, "MapProcessMemory"}, + {0x72, nullptr, "UnmapProcessMemory"}, + {0x73, nullptr, "Unknown"}, + {0x74, nullptr, "Unknown"}, + {0x75, nullptr, "Unknown"}, + {0x76, nullptr, "TerminateProcess"}, + {0x77, nullptr, "Unknown"}, + {0x78, nullptr, "CreateResourceLimit"}, + {0x79, nullptr, "Unknown"}, + {0x7A, nullptr, "Unknown"}, + {0x7B, nullptr, "Unknown"}, + {0x7C, nullptr, "KernelSetState"}, + {0x7D, nullptr, "QueryProcessMemory"}, }; void Register() { From edaefe9fa6f354b5de45a46adfcdd129f549185b Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:40:52 -0400 Subject: [PATCH 81/84] HLE: Moved "PARAM" and "RETURN" macros to function_wrappers.h (this is only module where they are needed). --- src/core/hle/function_wrappers.h | 6 ++++++ src/core/hle/hle.h | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index aa5278c8a..0bed78653 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -10,6 +10,9 @@ namespace HLE { +#define PARAM(n) Core::g_app_core->GetReg(n) +#define RETURN(n) Core::g_app_core->SetReg(0, n) + //////////////////////////////////////////////////////////////////////////////////////////////////// // Function wrappers that return type s32 @@ -105,4 +108,7 @@ template void Wrap() { func(Memory::GetCharPointer(PARAM(0))); } +#undef PARAM +#undef RETURN + } // namespace HLE diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 0397da5d9..bf4d84575 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -9,11 +9,6 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// -#define PARAM(n) Core::g_app_core->GetReg(n) -#define RETURN(n) Core::g_app_core->SetReg(0, n) - -//////////////////////////////////////////////////////////////////////////////////////////////////// - namespace HLE { extern bool g_reschedule; ///< If true, immediately reschedules the CPU to a new thread From 83a4ad28854f6c90f688e3d4523708c2d06267de Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:46:54 -0400 Subject: [PATCH 82/84] Event: Updated several log messages to be assertions. --- src/core/hle/kernel/event.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 3a522c190..127c0cfc6 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -59,10 +59,8 @@ public: */ Result SetPermanentLock(Handle handle, const bool permanent_locked) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + evt->permanent_locked = permanent_locked; return 0; } @@ -75,10 +73,8 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { */ Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + if (!evt->permanent_locked) { evt->locked = locked; } @@ -92,10 +88,8 @@ Result SetEventLocked(const Handle handle, const bool locked) { */ Result SignalEvent(const Handle handle) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + // Resume threads waiting for event to signal bool event_caught = false; for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { @@ -122,10 +116,8 @@ Result SignalEvent(const Handle handle) { */ Result ClearEvent(Handle handle) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + if (!evt->permanent_locked) { evt->locked = true; } From f49ac3a2d71f06d603b8401817a6dfd9dbc3c4bc Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 10 Jun 2014 22:43:50 -0400 Subject: [PATCH 83/84] Kernel: Added freeing of kernel objects on emulator shutdown. --- src/core/hle/kernel/kernel.cpp | 4 ++++ src/core/hle/kernel/kernel.h | 6 ++++++ src/core/system.cpp | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index e51a9d45a..739ddd4ef 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -132,12 +132,16 @@ Object* ObjectPool::CreateByIDType(int type) { } } +/// Initialize the kernel void Init() { Kernel::ThreadingInit(); } +/// Shutdown the kernel void Shutdown() { Kernel::ThreadingShutdown(); + + g_object_pool.Clear(); // Free all kernel objects } /** diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d2d624f6d..3f15da0ac 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -167,6 +167,12 @@ private: extern ObjectPool g_object_pool; extern Handle g_main_thread; +/// Initialize the kernel +void Init(); + +/// Shutdown the kernel +void Shutdown(); + /** * Loads executable stored at specified address * @entry_point Entry point in memory of loaded executable diff --git a/src/core/system.cpp b/src/core/system.cpp index c77092327..9b1e96888 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -8,6 +8,7 @@ #include "core/system.h" #include "core/hw/hw.h" #include "core/hle/hle.h" +#include "core/hle/kernel/kernel.h" #include "video_core/video_core.h" @@ -26,6 +27,7 @@ void Init(EmuWindow* emu_window) { HLE::Init(); CoreTiming::Init(); VideoCore::Init(emu_window); + Kernel::Init(); } void RunLoopFor(int cycles) { @@ -42,6 +44,7 @@ void Shutdown() { HLE::Shutdown(); CoreTiming::Shutdown(); VideoCore::Shutdown(); + Kernel::Shutdown(); g_ctr_file_system.Shutdown(); } From b45a38f55794e47b0429a8667441a20433e19e42 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 12 Jun 2014 16:57:18 -0400 Subject: [PATCH 84/84] Kernel: Removed unnecessary "#pragma once". --- src/core/hle/kernel/kernel.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 739ddd4ef..cda183add 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#pragma once - #include #include "common/common.h"