From 540a693eae210d090b87426ead8cfac5893a9ef8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 16 May 2014 23:23:56 -0400 Subject: updated APT_U::GetLockHandle to return a valid handle --- src/core/hle/service/apt.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 709ac5493..ddb975607 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -19,7 +19,11 @@ void Initialize(Service::Interface* self) { void GetLockHandle(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); - cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle + u32 flags = cmd_buff[1]; + + // TODO: This should be an actual mutex handle. Games will check that this is not non-zero + // (NULL), and fail if such. A faked non-zero value will at least enable further booting. + cmd_buff[5] = 0xDEADBEEF; } const Interface::FunctionInfo FunctionTable[] = { -- cgit v1.2.3 From 39ee75fc8d2a3291195448696f6a9bda8b1d58ad Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 16 May 2014 23:25:16 -0400 Subject: added stubbed GetProcSemaphore - does nothing but avoids an exception --- src/core/hle/service/srv.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 071741444..303a943d4 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -16,6 +16,12 @@ void Initialize(Service::Interface* self) { NOTICE_LOG(OSHLE, "SRV::Sync - Initialize"); } +void GetProcSemaphore(Service::Interface* self) { + // Get process semaphore? + u32* cmd_buff = Service::GetCommandBuffer(); + cmd_buff[3] = 0xDEADBEEF; // Return something... 0 == NULL, raises an exception +} + void GetServiceHandle(Service::Interface* self) { Syscall::Result res = 0; u32* cmd_buff = Service::GetCommandBuffer(); @@ -39,7 +45,7 @@ void GetServiceHandle(Service::Interface* self) { const Interface::FunctionInfo FunctionTable[] = { {0x00010002, Initialize, "Initialize"}, - {0x00020000, NULL, "GetProcSemaphore"}, + {0x00020000, GetProcSemaphore, "GetProcSemaphore"}, {0x00030100, NULL, "RegisterService"}, {0x000400C0, NULL, "UnregisterService"}, {0x00050100, GetServiceHandle, "GetServiceHandle"}, -- cgit v1.2.3 From 772abad77803809d8ee857efc0d7e29c36c6b2cb Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 May 2014 18:12:29 -0400 Subject: - moved Handle/Result definitions to kernel.h - added ResetType enum --- src/core/hle/kernel/kernel.h | 3 ++- src/core/hle/kernel/thread.cpp | 2 -- src/core/hle/service/service.h | 12 +++++++----- src/core/hle/service/srv.cpp | 2 +- src/core/hle/service/srv.h | 2 +- src/core/hle/syscall.h | 12 ++++++++---- 6 files changed, 19 insertions(+), 14 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 2608eecc9..d4bb28c72 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -6,7 +6,8 @@ #include "common/common_types.h" -typedef s32 Handle; +typedef u32 Handle; +typedef s32 Result; enum KernelIDType { KERNEL_ID_TYPE_THREAD = 1, diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d0bc9c8d8..634218e8b 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -42,8 +42,6 @@ enum WaitType { WAITTYPE_SYNCH, }; -typedef s32 Handle; - class Thread : public KernelObject { public: diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index b260a290a..026e3d5de 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -11,6 +11,8 @@ #include "common/common.h" #include "common/common_types.h" #include "core/mem_map.h" + +#include "core/hle/kernel/kernel.h" #include "core/hle/syscall.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -70,14 +72,14 @@ public: } /// Allocates a new handle for the service - Syscall::Handle NewHandle() { - Syscall::Handle handle = (m_handles.size() << 16) | m_uid; + Handle NewHandle() { + Handle handle = (m_handles.size() << 16) | m_uid; m_handles.push_back(handle); return handle; } /// Frees a handle from the service - void DeleteHandle(Syscall::Handle handle) { + void DeleteHandle(Handle handle) { for(auto iter = m_handles.begin(); iter != m_handles.end(); ++iter) { if(*iter == handle) { m_handles.erase(iter); @@ -90,7 +92,7 @@ public: * Called when svcSendSyncRequest is called, loads command buffer and executes comand * @return Return result of svcSendSyncRequest passed back to user app */ - Syscall::Result Sync() { + Result Sync() { u32* cmd_buff = GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); @@ -124,7 +126,7 @@ protected: private: u32 m_uid; - std::vector m_handles; + std::vector m_handles; std::map m_functions; }; diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 303a943d4..a3d041176 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -23,7 +23,7 @@ void GetProcSemaphore(Service::Interface* self) { } void GetServiceHandle(Service::Interface* self) { - Syscall::Result res = 0; + Result res = 0; u32* cmd_buff = Service::GetCommandBuffer(); std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h index 760c976b4..f465ebc06 100644 --- a/src/core/hle/service/srv.h +++ b/src/core/hle/service/srv.h @@ -30,7 +30,7 @@ public: * Called when svcSendSyncRequest is called, loads command buffer and executes comand * @return Return result of svcSendSyncRequest passed back to user app */ - Syscall::Result Sync(); + Result Sync(); }; diff --git a/src/core/hle/syscall.h b/src/core/hle/syscall.h index 17f190266..3da349ed5 100644 --- a/src/core/hle/syscall.h +++ b/src/core/hle/syscall.h @@ -7,7 +7,7 @@ #include "common/common_types.h" //////////////////////////////////////////////////////////////////////////////////////////////////// -// SVC structures +// SVC types struct MemoryInfo { u32 base_address; @@ -31,14 +31,18 @@ struct ThreadContext { u32 fpexc; }; +enum ResetType { + RESETTYPE_ONESHOT, + RESETTYPE_STICKY, + RESETTYPE_PULSE, + RESETTYPE_MAX_BIT = (1u << 31), +}; + //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace Syscall namespace Syscall { -typedef u32 Handle; -typedef s32 Result; - void Register(); } // namespace -- cgit v1.2.3 From 725d240bf7b9cb48de7a66f8696695ef7aabc889 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 May 2014 18:24:24 -0400 Subject: renamed "UID" to "Handle" where appropriate --- src/core/hle/service/service.cpp | 16 ++++++++-------- src/core/hle/service/service.h | 22 ++++++++++------------ src/core/hle/service/srv.cpp | 4 ++-- src/core/hle/syscall.cpp | 4 ++-- 4 files changed, 22 insertions(+), 24 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index e6605a398..5601e59a1 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -32,27 +32,27 @@ Manager::~Manager() { /// Add a service to the manager (does not create it though) void Manager::AddService(Interface* service) { int index = m_services.size(); - u32 new_uid = GetUIDFromIndex(index); + Handle handle = GetHandleFromIndex(index); m_services.push_back(service); - m_port_map[service->GetPortName()] = new_uid; - service->m_uid = new_uid; + m_port_map[service->GetPortName()] = handle; + service->m_handle = handle; } /// Removes a service from the manager, also frees memory void Manager::DeleteService(std::string port_name) { auto service = FetchFromPortName(port_name); - m_services.erase(m_services.begin() + GetIndexFromUID(service->m_uid)); + m_services.erase(m_services.begin() + GetIndexFromHandle(service->m_handle)); m_port_map.erase(port_name); delete service; } -/// Get a Service Interface from its UID -Interface* Manager::FetchFromUID(u32 uid) { - int index = GetIndexFromUID(uid); +/// Get a Service Interface from its Handle +Interface* Manager::FetchFromHandle(Handle handle) { + int index = GetIndexFromHandle(handle); if (index < (int)m_services.size()) { return m_services[index]; } @@ -65,7 +65,7 @@ Interface* Manager::FetchFromPortName(std::string port_name) { if (itr == m_port_map.end()) { return NULL; } - return FetchFromUID(itr->second); + return FetchFromHandle(itr->second); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 026e3d5de..c3dbd202f 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -20,8 +20,6 @@ namespace Service { -typedef s32 NativeUID; ///< Native handle for a service - static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters) static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header @@ -56,11 +54,11 @@ public: }; /** - * Gets the UID for the serice - * @return UID of service in native format + * Gets the Handle for the serice + * @return Handle of service in native format */ - NativeUID GetUID() const { - return (NativeUID)m_uid; + Handle GetHandle() const { + return m_handle; } /** @@ -73,7 +71,7 @@ public: /// Allocates a new handle for the service Handle NewHandle() { - Handle handle = (m_handles.size() << 16) | m_uid; + Handle handle = (m_handles.size() << 16) | m_handle; m_handles.push_back(handle); return handle; } @@ -124,7 +122,7 @@ protected: } private: - u32 m_uid; + u32 m_handle; std::vector m_handles; std::map m_functions; @@ -145,7 +143,7 @@ public: void DeleteService(std::string port_name); /// Get a Service Interface from its UID - Interface* FetchFromUID(u32 uid); + Interface* FetchFromHandle(u32 uid); /// Get a Service Interface from its port Interface* FetchFromPortName(std::string port_name); @@ -153,13 +151,13 @@ public: private: /// Convert an index into m_services vector into a UID - static u32 GetUIDFromIndex(const int index) { + static Handle GetHandleFromIndex(const int index) { return index | 0x10000000; } /// Convert a UID into an index into m_services - static int GetIndexFromUID(const u32 uid) { - return uid & 0x0FFFFFFF; + static int GetIndexFromHandle(const Handle handle) { + return handle & 0x0FFFFFFF; } std::vector m_services; diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index a3d041176..ff6da8f1c 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -30,10 +30,10 @@ void GetServiceHandle(Service::Interface* self) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); NOTICE_LOG(OSHLE, "SRV::Sync - GetHandle - port: %s, handle: 0x%08X", port_name.c_str(), - service->GetUID()); + service->GetHandle()); if (NULL != service) { - cmd_buff[3] = service->GetUID(); + cmd_buff[3] = service->GetHandle(); } else { ERROR_LOG(OSHLE, "Service %s does not exist", port_name.c_str()); res = -1; diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp index 047d8c40f..1d7daf95c 100644 --- a/src/core/hle/syscall.cpp +++ b/src/core/hle/syscall.cpp @@ -83,7 +83,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) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); - Core::g_app_core->SetReg(1, service->GetUID()); + Core::g_app_core->SetReg(1, service->GetHandle()); DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); return 0; } @@ -91,7 +91,7 @@ Result ConnectToPort(void* out, const char* port_name) { /// Synchronize to an OS service Result SendSyncRequest(Handle session) { DEBUG_LOG(SVC, "SendSyncRequest called session=0x%08X"); - Service::Interface* service = Service::g_manager->FetchFromUID(session); + Service::Interface* service = Service::g_manager->FetchFromHandle(session); service->Sync(); return 0; } -- cgit v1.2.3 From eab6fd01d7d2e9b7434a8c5654d424cb563c3784 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 May 2014 21:43:29 -0400 Subject: - updated service(s) to be KernelObject's - various cleanups --- src/core/hle/kernel/kernel.h | 9 +++---- src/core/hle/service/apt.h | 2 +- src/core/hle/service/gsp.h | 2 +- src/core/hle/service/hid.h | 2 +- src/core/hle/service/service.cpp | 22 ++++++----------- src/core/hle/service/service.h | 51 ++++++++++++---------------------------- src/core/hle/service/srv.h | 2 +- 7 files changed, 31 insertions(+), 59 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d4bb28c72..8f2b7b36d 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -10,10 +10,11 @@ typedef u32 Handle; typedef s32 Result; enum KernelIDType { - KERNEL_ID_TYPE_THREAD = 1, - KERNEL_ID_TYPE_SEMAPHORE = 2, - KERNEL_ID_TYPE_MUTEX = 3, - KERNEL_ID_TYPE_EVENT = 4, + KERNEL_ID_TYPE_THREAD, + KERNEL_ID_TYPE_SEMAPHORE, + KERNEL_ID_TYPE_MUTEX, + KERNEL_ID_TYPE_EVENT, + KERNEL_ID_TYPE_SERVICE, }; enum { diff --git a/src/core/hle/service/apt.h b/src/core/hle/service/apt.h index 4c7dd07e7..dca3097ed 100644 --- a/src/core/hle/service/apt.h +++ b/src/core/hle/service/apt.h @@ -29,7 +29,7 @@ public: * Gets the string port name used by CTROS for the service * @return Port name of service */ - std::string GetPortName() const { + const char *GetPortName() const { return "APT:U"; } }; diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp.h index 5ba09ab70..eb5786cd1 100644 --- a/src/core/hle/service/gsp.h +++ b/src/core/hle/service/gsp.h @@ -23,7 +23,7 @@ public: * Gets the string port name used by CTROS for the service * @return Port name of service */ - std::string GetPortName() const { + const char *GetPortName() const { return "gsp::Gpu"; } diff --git a/src/core/hle/service/hid.h b/src/core/hle/service/hid.h index b17fcfa86..81c29eb2e 100644 --- a/src/core/hle/service/hid.h +++ b/src/core/hle/service/hid.h @@ -25,7 +25,7 @@ public: * Gets the string port name used by CTROS for the service * @return Port name of service */ - std::string GetPortName() const { + const char *GetPortName() const { return "hid:USER"; } diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5601e59a1..b3e414e0f 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -7,12 +7,15 @@ #include "common/string_util.h" #include "core/hle/hle.h" + #include "core/hle/service/service.h" #include "core/hle/service/apt.h" #include "core/hle/service/gsp.h" #include "core/hle/service/hid.h" #include "core/hle/service/srv.h" +#include "core/hle/kernel/kernel.h" + namespace Service { Manager* g_manager = NULL; ///< Service manager @@ -31,32 +34,21 @@ Manager::~Manager() { /// Add a service to the manager (does not create it though) void Manager::AddService(Interface* service) { - int index = m_services.size(); - Handle handle = GetHandleFromIndex(index); - + m_port_map[service->GetPortName()] = g_kernel_objects.Create(service); m_services.push_back(service); - - m_port_map[service->GetPortName()] = handle; - service->m_handle = handle; } /// Removes a service from the manager, also frees memory void Manager::DeleteService(std::string port_name) { - auto service = FetchFromPortName(port_name); - - m_services.erase(m_services.begin() + GetIndexFromHandle(service->m_handle)); + Interface* service = FetchFromPortName(port_name); + m_services.erase(std::remove(m_services.begin(), m_services.end(), service), m_services.end()); m_port_map.erase(port_name); - delete service; } /// Get a Service Interface from its Handle Interface* Manager::FetchFromHandle(Handle handle) { - int index = GetIndexFromHandle(handle); - if (index < (int)m_services.size()) { - return m_services[index]; - } - return NULL; + return g_kernel_objects.GetFast(handle); } /// Get a Service Interface from its port diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index c3dbd202f..35735a00b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -35,15 +36,15 @@ inline static u32* GetCommandBuffer(const int offset=0) { class Manager; /// Interface to a CTROS service -class Interface : NonCopyable { +class Interface : public KernelObject { friend class Manager; public: + + const char *GetName() { return GetPortName(); } + const char *GetTypeName() { return GetPortName(); } - Interface() { - } - - virtual ~Interface() { - } + static KernelIDType GetStaticIDType() { return KERNEL_ID_TYPE_THREAD; } + KernelIDType GetIDType() const { return KERNEL_ID_TYPE_THREAD; } typedef void (*Function)(Interface*); @@ -53,37 +54,24 @@ public: std::string name; }; - /** - * Gets the Handle for the serice - * @return Handle of service in native format - */ - Handle GetHandle() const { - return m_handle; - } - /** * Gets the string name used by CTROS for a service * @return Port name of service */ - virtual std::string GetPortName() const { + virtual const char *GetPortName() const { return "[UNKNOWN SERVICE PORT]"; } /// Allocates a new handle for the service Handle NewHandle() { - Handle handle = (m_handles.size() << 16) | m_handle; + Handle handle = (m_handles.size() << 16) | 0;//m_handle; m_handles.push_back(handle); return handle; } /// Frees a handle from the service void DeleteHandle(Handle handle) { - for(auto iter = m_handles.begin(); iter != m_handles.end(); ++iter) { - if(*iter == handle) { - m_handles.erase(iter); - break; - } - } + m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); } /** @@ -96,12 +84,12 @@ public: if (itr == m_functions.end()) { ERROR_LOG(OSHLE, "Unknown/unimplemented function: port = %s, command = 0x%08X!", - GetPortName().c_str(), cmd_buff[0]); + GetPortName(), cmd_buff[0]); return -1; } if (itr->second.func == NULL) { ERROR_LOG(OSHLE, "Unimplemented function: port = %s, name = %s!", - GetPortName().c_str(), itr->second.name.c_str()); + GetPortName(), itr->second.name.c_str()); return -1; } @@ -122,10 +110,10 @@ protected: } private: - u32 m_handle; - + std::vector m_handles; std::map m_functions; + }; /// Simple class to manage accessing services from ports and UID handles @@ -150,18 +138,9 @@ public: private: - /// Convert an index into m_services vector into a UID - static Handle GetHandleFromIndex(const int index) { - return index | 0x10000000; - } - - /// Convert a UID into an index into m_services - static int GetIndexFromHandle(const Handle handle) { - return handle & 0x0FFFFFFF; - } - std::vector m_services; std::map m_port_map; + }; /// Initialize ServiceManager diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h index f465ebc06..1e35032ba 100644 --- a/src/core/hle/service/srv.h +++ b/src/core/hle/service/srv.h @@ -22,7 +22,7 @@ public: * Gets the string name used by CTROS for the service * @return Port name of service */ - std::string GetPortName() const { + const char *GetPortName() const { return "srv:"; } -- cgit v1.2.3 From 112904b832210d7b8d165988643acae2f68793e7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 May 2014 22:09:08 -0400 Subject: - renamed NewHandle to CreateHandle - updated CreateHandle/DeleteHandle to use KernelObject's --- src/core/hle/service/gsp.cpp | 4 +--- src/core/hle/service/service.h | 12 +++++++----- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 12c7dabcd..50cee2c41 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -27,7 +27,7 @@ union GX_CmdBufferHeader { // <=15 when writing a command to shared memory. This is incremented by the application when // writing a command to shared memory, after increasing this value TriggerCmdReqQueue is only // used if this field is value 1. - BitField<8,8,u32> number_commands; + BitField<8,8,u32> number_commands; }; @@ -101,9 +101,7 @@ 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 - cmd_buff[2] = g_thread_id; // ThreadID - cmd_buff[4] = self->NewHandle(); } /// This triggers handling of the GX command written to the command buffer in shared memory. diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 35735a00b..450a439fe 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -63,14 +63,16 @@ public: } /// Allocates a new handle for the service - Handle NewHandle() { - Handle handle = (m_handles.size() << 16) | 0;//m_handle; + Handle CreateHandle(KernelObject *obj) { + Handle handle = g_kernel_objects.Create(obj); m_handles.push_back(handle); return handle; } /// Frees a handle from the service - void DeleteHandle(Handle handle) { + template + void DeleteHandle(const Handle handle) { + g_kernel_objects.Destroy(handle); m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); } @@ -111,8 +113,8 @@ protected: private: - std::vector m_handles; - std::map m_functions; + std::vector m_handles; + std::map m_functions; }; -- cgit v1.2.3 From 0886dc70ed3eb3c30fcbe0039d53a5c780a6c4b9 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 19 May 2014 22:21:17 -0400 Subject: apt: changed stubbed handle to be something other than 0xDEADBEEF (used as a magic value in other places) so that I can track how it propagates through the app code --- src/core/hle/service/apt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index ddb975607..1f6a70eab 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -23,7 +23,7 @@ void GetLockHandle(Service::Interface* self) { // TODO: This should be an actual mutex handle. Games will check that this is not non-zero // (NULL), and fail if such. A faked non-zero value will at least enable further booting. - cmd_buff[5] = 0xDEADBEEF; + cmd_buff[5] = 0x12345678; } const Interface::FunctionInfo FunctionTable[] = { -- cgit v1.2.3 From 44336329eddd7dbe1f76144e9a1e95e5f76ed372 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 18:13:25 -0400 Subject: - created a Kernel namespace - cleaned up Kernel code a bit (moved stuff into namespace, fixed whitespace issues) - added handle types for all different CTROS handles --- src/core/hle/kernel/kernel.cpp | 49 +++++++++++++------------- src/core/hle/kernel/kernel.h | 75 +++++++++++++++++++++++----------------- src/core/hle/kernel/thread.cpp | 18 +++++----- src/core/hle/kernel/thread.h | 4 +-- src/core/hle/service/service.cpp | 4 +-- src/core/hle/service/service.h | 12 +++---- 6 files changed, 87 insertions(+), 75 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f7145ddd8..b1fdffde5 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -12,22 +12,16 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" -KernelObjectPool g_kernel_objects; +namespace Kernel { -void __KernelInit() { - __KernelThreadingInit(); -} - -void __KernelShutdown() { - __KernelThreadingShutdown(); -} +ObjectPool g_object_pool; -KernelObjectPool::KernelObjectPool() { +ObjectPool::ObjectPool() { memset(occupied, 0, sizeof(bool) * MAX_COUNT); next_id = INITIAL_NEXT_ID; } -Handle KernelObjectPool::Create(KernelObject *obj, int range_bottom, int range_top) { +Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) { if (range_top > MAX_COUNT) { range_top = MAX_COUNT; } @@ -46,8 +40,7 @@ Handle KernelObjectPool::Create(KernelObject *obj, int range_bottom, int range_t return 0; } -bool KernelObjectPool::IsValid(Handle handle) -{ +bool ObjectPool::IsValid(Handle handle) { int index = handle - HANDLE_OFFSET; if (index < 0) return false; @@ -57,26 +50,24 @@ bool KernelObjectPool::IsValid(Handle handle) return occupied[index]; } -void KernelObjectPool::Clear() -{ - for (int i = 0; i < MAX_COUNT; i++) - { +void ObjectPool::Clear() { + for (int i = 0; i < MAX_COUNT; i++) { //brutally clear everything, no validation if (occupied[i]) delete pool[i]; occupied[i] = false; } - memset(pool, 0, sizeof(KernelObject*)*MAX_COUNT); + memset(pool, 0, sizeof(Object*)*MAX_COUNT); next_id = INITIAL_NEXT_ID; } -KernelObject *&KernelObjectPool::operator [](Handle handle) +Object* &ObjectPool::operator [](Handle handle) { _dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); return pool[handle - HANDLE_OFFSET]; } -void KernelObjectPool::List() { +void ObjectPool::List() { for (int i = 0; i < MAX_COUNT; i++) { if (occupied[i]) { if (pool[i]) { @@ -87,18 +78,16 @@ void KernelObjectPool::List() { } } -int KernelObjectPool::GetCount() -{ +int ObjectPool::GetCount() { int count = 0; - for (int i = 0; i < MAX_COUNT; i++) - { + for (int i = 0; i < MAX_COUNT; i++) { if (occupied[i]) count++; } return count; } -KernelObject *KernelObjectPool::CreateByIDType(int type) { +Object* ObjectPool::CreateByIDType(int type) { // Used for save states. This is ugly, but what other way is there? switch (type) { //case SCE_KERNEL_TMID_Alarm: @@ -142,8 +131,18 @@ KernelObject *KernelObjectPool::CreateByIDType(int type) { } } +void Init() { + __KernelThreadingInit(); +} + +void Shutdown() { + __KernelThreadingShutdown(); +} + +} // namespace + bool __KernelLoadExec(u32 entry_point) { - __KernelInit(); + Kernel::Init(); Core::g_app_core->SetPC(entry_point); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 8f2b7b36d..19edb7b57 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -9,41 +9,50 @@ typedef u32 Handle; typedef s32 Result; -enum KernelIDType { - KERNEL_ID_TYPE_THREAD, - KERNEL_ID_TYPE_SEMAPHORE, - KERNEL_ID_TYPE_MUTEX, - KERNEL_ID_TYPE_EVENT, - KERNEL_ID_TYPE_SERVICE, +namespace Kernel { + +enum class HandleType : u32 { + Unknown = 0, + Port = 1, + Service = 2, + Event = 3, + Mutex = 4, + SharedMemory = 5, + Redirection = 6, + Thread = 7, + Process = 8, + Arbiter = 9, + File = 10, + Semaphore = 11, }; - + enum { - KERNEL_MAX_NAME_LENGTH = 0x100, - KERNEL_DEFAULT_STACK_SIZE = 0x4000, + MAX_NAME_LENGTH = 0x100, + DEFAULT_STACK_SIZE = 0x4000, }; -class KernelObjectPool; +class ObjectPool; -class KernelObject { - friend class KernelObjectPool; +class Object : NonCopyable { + friend class ObjectPool; u32 handle; public: - virtual ~KernelObject() {} + 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 KernelIDType GetIDType() const = 0; + virtual Kernel::HandleType GetHandleType() const = 0; }; -class KernelObjectPool { +class ObjectPool : NonCopyable { public: - KernelObjectPool(); - ~KernelObjectPool() {} + ObjectPool(); + ~ObjectPool() {} // Allocates a handle within the range and inserts the object into the map. - Handle Create(KernelObject *obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF); + Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF); - static KernelObject *CreateByIDType(int type); + static Object* CreateByIDType(int type); template u32 Destroy(Handle handle) { @@ -71,7 +80,7 @@ public: // it just acted as a static case and everything worked. This means that we will never // see the Wrong type object error below, but we'll just have to live with that danger. T* t = static_cast(pool[handle - HANDLE_OFFSET]); - if (t == 0 || t->GetIDType() != T::GetStaticIDType()) { + if (t == 0 || t->GetHandleType() != T::GetStaticHandleType()) { WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle); outError = 0;//T::GetMissingErrorCode(); return 0; @@ -86,17 +95,17 @@ public: T *GetFast(Handle handle) { const Handle realHandle = handle - HANDLE_OFFSET; _dbg_assert_(KERNEL, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); - return static_cast(pool[realHandle]); + return static_cast(pool[realHandle]); } template - void Iterate(bool func(T *, ArgT), ArgT arg) { + void Iterate(bool func(T*, ArgT), ArgT arg) { int type = T::GetStaticIDType(); for (int i = 0; i < MAX_COUNT; i++) { if (!occupied[i]) continue; - T *t = static_cast(pool[i]); + T* t = static_cast(pool[i]); if (t->GetIDType() == type) { if (!func(t, arg)) break; @@ -104,33 +113,37 @@ public: } } - bool GetIDType(Handle handle, int *type) const { + bool GetIDType(Handle handle, HandleType* type) const { if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) || !occupied[handle - HANDLE_OFFSET]) { ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); return false; } - KernelObject *t = pool[handle - HANDLE_OFFSET]; - *type = t->GetIDType(); + Object* t = pool[handle - HANDLE_OFFSET]; + *type = t->GetHandleType(); return true; } - KernelObject *&operator [](Handle handle); + Object* &operator [](Handle handle); void List(); void Clear(); int GetCount(); private: + enum { MAX_COUNT = 0x1000, HANDLE_OFFSET = 0x100, INITIAL_NEXT_ID = 0x10, }; - KernelObject *pool[MAX_COUNT]; - bool occupied[MAX_COUNT]; - int next_id; + + Object* pool[MAX_COUNT]; + bool occupied[MAX_COUNT]; + int next_id; }; -extern KernelObjectPool g_kernel_objects; +extern ObjectPool g_object_pool; + +} // namespace bool __KernelLoadExec(u32 entry_point); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 634218e8b..2955d6f5b 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -42,14 +42,14 @@ enum WaitType { WAITTYPE_SYNCH, }; -class Thread : public KernelObject { +class Thread : public Kernel::Object { public: const char *GetName() { return name; } const char *GetTypeName() { return "Thread"; } - static KernelIDType GetStaticIDType() { return KERNEL_ID_TYPE_THREAD; } - KernelIDType GetIDType() const { return KERNEL_ID_TYPE_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; } inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } @@ -71,7 +71,7 @@ public: WaitType wait_type; - char name[KERNEL_MAX_NAME_LENGTH+1]; + char name[Kernel::MAX_NAME_LENGTH + 1]; }; // Lists all thread ids that aren't deleted/etc. @@ -201,7 +201,7 @@ Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, Thread *t = new Thread; - handle = g_kernel_objects.Create(t); + handle = Kernel::g_object_pool.Create(t); g_thread_queue.push_back(handle); g_thread_ready_queue.prepare(priority); @@ -214,8 +214,8 @@ Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, t->processor_id = processor_id; t->wait_type = WAITTYPE_NONE; - strncpy(t->name, name, KERNEL_MAX_NAME_LENGTH); - t->name[KERNEL_MAX_NAME_LENGTH] = '\0'; + strncpy(t->name, name, Kernel::MAX_NAME_LENGTH); + t->name[Kernel::MAX_NAME_LENGTH] = '\0'; return t; } @@ -296,7 +296,7 @@ Thread *__KernelNextThread() { if (next < 0) { return NULL; } - return g_kernel_objects.GetFast(next); + return Kernel::g_object_pool.GetFast(next); } /// Sets up the primary application thread @@ -326,7 +326,7 @@ Handle __KernelSetupMainThread(s32 priority, int stack_size) { /// Resumes a thread from waiting by marking it as "ready" void __KernelResumeThreadFromWait(Handle handle) { u32 error; - Thread *t = g_kernel_objects.Get(handle, 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))) { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index eca84c718..207a5227b 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -23,10 +23,10 @@ enum ThreadProcessorId { /// Creates a new thread - wrapper for external user Handle __KernelCreateThread(const char *name, u32 entry_point, s32 priority, - s32 processor_id, u32 stack_top, int stack_size=KERNEL_DEFAULT_STACK_SIZE); + s32 processor_id, u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); /// Sets up the primary application thread -Handle __KernelSetupMainThread(s32 priority, int stack_size=KERNEL_DEFAULT_STACK_SIZE); +Handle __KernelSetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); /// Reschedules to the next available thread (call after current thread is suspended) void __KernelReschedule(const char *reason); diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index b3e414e0f..08d0c43ff 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -34,7 +34,7 @@ Manager::~Manager() { /// Add a service to the manager (does not create it though) void Manager::AddService(Interface* service) { - m_port_map[service->GetPortName()] = g_kernel_objects.Create(service); + m_port_map[service->GetPortName()] = Kernel::g_object_pool.Create(service); m_services.push_back(service); } @@ -48,7 +48,7 @@ void Manager::DeleteService(std::string port_name) { /// Get a Service Interface from its Handle Interface* Manager::FetchFromHandle(Handle handle) { - return g_kernel_objects.GetFast(handle); + return Kernel::g_object_pool.GetFast(handle); } /// Get a Service Interface from its port diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 450a439fe..f334dbcb8 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -36,15 +36,15 @@ inline static u32* GetCommandBuffer(const int offset=0) { class Manager; /// Interface to a CTROS service -class Interface : public KernelObject { +class Interface : public Kernel::Object { friend class Manager; public: const char *GetName() { return GetPortName(); } const char *GetTypeName() { return GetPortName(); } - static KernelIDType GetStaticIDType() { return KERNEL_ID_TYPE_THREAD; } - KernelIDType GetIDType() const { return KERNEL_ID_TYPE_THREAD; } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; } + Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; } typedef void (*Function)(Interface*); @@ -63,8 +63,8 @@ public: } /// Allocates a new handle for the service - Handle CreateHandle(KernelObject *obj) { - Handle handle = g_kernel_objects.Create(obj); + Handle CreateHandle(Kernel::Object *obj) { + Handle handle = Kernel::g_object_pool.Create(obj); m_handles.push_back(handle); return handle; } @@ -72,7 +72,7 @@ public: /// Frees a handle from the service template void DeleteHandle(const Handle handle) { - g_kernel_objects.Destroy(handle); + g_object_pool.Destroy(handle); m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); } -- cgit v1.2.3 From 143bba20453036f0a4bcc74dad10d99605a84732 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 18:28:38 -0400 Subject: renamed "syscall" module to "svc" (more accurate naming) --- src/core/CMakeLists.txt | 2 +- src/core/core.vcxproj | 4 +- src/core/core.vcxproj.filters | 12 +- src/core/hle/hle.cpp | 14 +- src/core/hle/hle.h | 2 +- src/core/hle/kernel/thread.cpp | 2 +- src/core/hle/service/service.h | 2 +- src/core/hle/svc.cpp | 350 +++++++++++++++++++++++++++++++++++++++++ src/core/hle/svc.h | 48 ++++++ src/core/hle/syscall.cpp | 348 ---------------------------------------- src/core/hle/syscall.h | 48 ------ 11 files changed, 417 insertions(+), 415 deletions(-) create mode 100644 src/core/hle/svc.cpp create mode 100644 src/core/hle/svc.h delete mode 100644 src/core/hle/syscall.cpp delete mode 100644 src/core/hle/syscall.h (limited to 'src/core/hle/service') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b0597db38..e006502da 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -33,7 +33,7 @@ set(SRCS core.cpp hle/hle.cpp hle/config_mem.cpp hle/coprocessor.cpp - hle/syscall.cpp + hle/svc.cpp hle/kernel/kernel.cpp hle/kernel/thread.cpp hle/service/apt.cpp diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index f077154ee..6eb58a636 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -175,7 +175,7 @@ - + @@ -223,7 +223,7 @@ - + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 6aedeb54b..fc4e35edb 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -84,9 +84,6 @@ hle - - hle - hle\service @@ -162,6 +159,9 @@ hle\kernel + + hle + @@ -226,9 +226,6 @@ hle\service - - hle - hle\service @@ -289,6 +286,9 @@ hle\kernel + + hle + diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 452384571..080c36abf 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -6,7 +6,7 @@ #include "core/mem_map.h" #include "core/hle/hle.h" -#include "core/hle/syscall.h" +#include "core/hle/svc.h" #include "core/hle/service/service.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -15,17 +15,17 @@ namespace HLE { static std::vector g_module_db; -const FunctionDef* GetSyscallInfo(u32 opcode) { +const FunctionDef* GetSVCInfo(u32 opcode) { u32 func_num = opcode & 0xFFFFFF; // 8 bits if (func_num > 0xFF) { - ERROR_LOG(HLE,"Unknown syscall: 0x%02X", func_num); + ERROR_LOG(HLE,"Unknown SVC: 0x%02X", func_num); return NULL; } return &g_module_db[0].func_table[func_num]; } -void CallSyscall(u32 opcode) { - const FunctionDef *info = GetSyscallInfo(opcode); +void CallSVC(u32 opcode) { + const FunctionDef *info = GetSVCInfo(opcode); if (!info) { return; @@ -33,7 +33,7 @@ void CallSyscall(u32 opcode) { if (info->func) { info->func(); } else { - ERROR_LOG(HLE, "Unimplemented SysCall function %s(..)", info->name.c_str()); + ERROR_LOG(HLE, "Unimplemented SVC function %s(..)", info->name.c_str()); } } @@ -54,7 +54,7 @@ void RegisterModule(std::string name, int num_functions, const FunctionDef* func } void RegisterAllModules() { - Syscall::Register(); + SVC::Register(); } void Init() { diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 452546e1f..c075147c3 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -34,7 +34,7 @@ struct ModuleDef { void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table); -void CallSyscall(u32 opcode); +void CallSVC(u32 opcode); void EatCycles(u32 cycles); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index cfc5327a3..136fff021 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -15,7 +15,7 @@ #include "core/core.h" #include "core/mem_map.h" #include "core/hle/hle.h" -#include "core/hle/syscall.h" +#include "core/hle/svc.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index f334dbcb8..eba730efb 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -14,7 +14,7 @@ #include "core/mem_map.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/syscall.h" +#include "core/hle/svc.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace Service diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp new file mode 100644 index 000000000..a9141699c --- /dev/null +++ b/src/core/hle/svc.cpp @@ -0,0 +1,350 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "common/symbols.h" + +#include "core/mem_map.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/thread.h" + +#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 + +namespace SVC { + +enum ControlMemoryOperation { + MEMORY_OPERATION_HEAP = 0x00000003, + MEMORY_OPERATION_GSP_HEAP = 0x00010003, +}; + +enum MapMemoryPermission { + MEMORY_PERMISSION_UNMAP = 0x00000000, + MEMORY_PERMISSION_NORMAL = 0x00000001, +}; + +/// 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", + operation, addr0, addr1, size, permissions); + + switch (operation) { + + // Map normal heap memory + case MEMORY_OPERATION_HEAP: + virtual_address = Memory::MapBlock_Heap(size, operation, permissions); + break; + + // Map GSP heap memory + case MEMORY_OPERATION_GSP_HEAP: + virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions); + break; + + // Unknown ControlMemory operation + 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; +} + +/// 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", + memblock, addr, mypermissions, otherpermission); + switch (mypermissions) { + case MEMORY_PERMISSION_NORMAL: + case MEMORY_PERMISSION_NORMAL + 1: + case MEMORY_PERMISSION_NORMAL + 2: + Memory::MapBlock_Shared(memblock, addr, mypermissions); + break; + default: + ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions); + } + return 0; +} + +/// 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); + Core::g_app_core->SetReg(1, service->GetHandle()); + DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); + return 0; +} + +/// 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(); + return 0; +} + +/// Close a handle +Result CloseHandle(Handle handle) { + // ImplementMe + DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); + return 0; +} + +/// Wait for a handle to synchronize, timeout after the specified nanoseconds +Result WaitSynchronization1(Handle handle, s64 nano_seconds) { + // ImplementMe + DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", + handle, nano_seconds); + return 0; +} + +/// 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) { + s32* out = (s32*)_out; + Handle* handles = (Handle*)_handles; + // ImplementMe + + DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronizationN called handle_count=%d, wait_all=%s, nanoseconds=%d %s", + handle_count, (wait_all ? "true" : "false"), nano_seconds); + + for (u32 i = 0; i < handle_count; i++) { + DEBUG_LOG(SVC, "\thandle[%d]=0x%08X", i, handles[i]); + } + __KernelReschedule("WaitSynchronizationN"); + + 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; +} + +/// 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); +} + +/// Get resource limit +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); + 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) { + //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 + return 0; +} + +Result CreateThread(void* thread, u32 priority, u32 entry_point, u32 arg, u32 stack_top, + u32 processor_id) { + std::string name; + if (Symbols::HasSymbol(entry_point)) { + TSymbol symbol = Symbols::GetSymbol(entry_point); + name = symbol.name; + } else { + char buff[100]; + sprintf(buff, "%s", "unknown-%08X", entry_point); + name = buff; + } + DEBUG_LOG(SVC, "CreateThread called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " + "threadpriority=0x%08X, processorid=0x%08X", entry_point, name.c_str(), arg, stack_top, + priority, processor_id); + + Handle handle = __KernelCreateThread(name.c_str(), entry_point, priority, processor_id, + stack_top); + Core::g_app_core->SetReg(1, 0xFEEDDEAF); + + return 0; +} + +Result CreateMutex(void* _mutex, u32 initial_locked) { + Handle* mutex = (Handle*)_mutex; + DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateMutex called initial_locked=%s", + initial_locked ? "true" : "false"); + Core::g_app_core->SetReg(1, 0xF00D0BAD); + return 0; +} + +Result ReleaseMutex(Handle handle) { + DEBUG_LOG(SVC, "(UNIMPLEMENTED) ReleaseMutex called handle=0x%08X", handle); + return 0; +} + +Result GetThreadId(void* thread_id, u32 thread) { + DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetThreadId called thread=0x%08X", thread); + return 0; +} + +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; +} + +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); + return 0; +} + +const HLE::FunctionDef SVC_Table[] = { + {0x00, NULL, "Unknown"}, + {0x01, WrapI_VUUUUU, "ControlMemory"}, + {0x02, WrapI_VVU, "QueryMemory"}, + {0x03, NULL, "ExitProcess"}, + {0x04, NULL, "GetProcessAffinityMask"}, + {0x05, NULL, "SetProcessAffinityMask"}, + {0x06, NULL, "GetProcessIdealProcessor"}, + {0x07, NULL, "SetProcessIdealProcessor"}, + {0x08, WrapI_VUUUUU, "CreateThread"}, + {0x09, NULL, "ExitThread"}, + {0x0A, NULL, "SleepThread"}, + {0x0B, NULL, "GetThreadPriority"}, + {0x0C, NULL, "SetThreadPriority"}, + {0x0D, NULL, "GetThreadAffinityMask"}, + {0x0E, NULL, "SetThreadAffinityMask"}, + {0x0F, NULL, "GetThreadIdealProcessor"}, + {0x10, NULL, "SetThreadIdealProcessor"}, + {0x11, NULL, "GetCurrentProcessorNumber"}, + {0x12, NULL, "Run"}, + {0x13, WrapI_VU, "CreateMutex"}, + {0x14, WrapI_U, "ReleaseMutex"}, + {0x15, NULL, "CreateSemaphore"}, + {0x16, NULL, "ReleaseSemaphore"}, + {0x17, WrapI_VU, "CreateEvent"}, + {0x18, NULL, "SignalEvent"}, + {0x19, NULL, "ClearEvent"}, + {0x1A, NULL, "CreateTimer"}, + {0x1B, NULL, "SetTimer"}, + {0x1C, NULL, "CancelTimer"}, + {0x1D, NULL, "ClearTimer"}, + {0x1E, NULL, "CreateMemoryBlock"}, + {0x1F, WrapI_UUUU, "MapMemoryBlock"}, + {0x20, NULL, "UnmapMemoryBlock"}, + {0x21, WrapI_V, "CreateAddressArbiter"}, + {0x22, NULL, "ArbitrateAddress"}, + {0x23, WrapI_U, "CloseHandle"}, + {0x24, WrapI_US64, "WaitSynchronization1"}, + {0x25, WrapI_VVUUS64, "WaitSynchronizationN"}, + {0x26, NULL, "SignalAndWait"}, + {0x27, NULL, "DuplicateHandle"}, + {0x28, NULL, "GetSystemTick"}, + {0x29, NULL, "GetHandleInfo"}, + {0x2A, NULL, "GetSystemInfo"}, + {0x2B, NULL, "GetProcessInfo"}, + {0x2C, NULL, "GetThreadInfo"}, + {0x2D, WrapI_VC, "ConnectToPort"}, + {0x2E, NULL, "SendSyncRequest1"}, + {0x2F, NULL, "SendSyncRequest2"}, + {0x30, NULL, "SendSyncRequest3"}, + {0x31, NULL, "SendSyncRequest4"}, + {0x32, WrapI_U, "SendSyncRequest"}, + {0x33, NULL, "OpenProcess"}, + {0x34, NULL, "OpenThread"}, + {0x35, NULL, "GetProcessId"}, + {0x36, NULL, "GetProcessIdOfThread"}, + {0x37, WrapI_VU, "GetThreadId"}, + {0x38, WrapI_VU, "GetResourceLimit"}, + {0x39, NULL, "GetResourceLimitLimitValues"}, + {0x3A, WrapI_VUVI, "GetResourceLimitCurrentValues"}, + {0x3B, NULL, "GetThreadContext"}, + {0x3C, NULL, "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"}, +}; + +void Register() { + HLE::RegisterModule("SVC_Table", ARRAY_SIZE(SVC_Table), SVC_Table); +} + +} // namespace diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h new file mode 100644 index 000000000..5c35977d1 --- /dev/null +++ b/src/core/hle/svc.h @@ -0,0 +1,48 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SVC types + +struct MemoryInfo { + u32 base_address; + u32 size; + u32 permission; + u32 state; +}; + +struct PageInfo { + u32 flags; +}; + +struct ThreadContext { + u32 cpu_registers[13]; + u32 sp; + u32 lr; + u32 pc; + u32 cpsr; + u32 fpu_registers[32]; + u32 fpscr; + u32 fpexc; +}; + +enum ResetType { + RESETTYPE_ONESHOT, + RESETTYPE_STICKY, + RESETTYPE_PULSE, + RESETTYPE_MAX_BIT = (1u << 31), +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace SVC + +namespace SVC { + +void Register(); + +} // namespace diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp deleted file mode 100644 index 9a1235246..000000000 --- a/src/core/hle/syscall.cpp +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include -#include - -#include "common/symbols.h" - -#include "core/mem_map.h" - -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/thread.h" - -#include "core/hle/function_wrappers.h" -#include "core/hle/syscall.h" -#include "core/hle/service/service.h" -#include "core/hle/kernel/thread.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Namespace Syscall - -namespace Syscall { - -enum ControlMemoryOperation { - MEMORY_OPERATION_HEAP = 0x00000003, - MEMORY_OPERATION_GSP_HEAP = 0x00010003, -}; - -enum MapMemoryPermission { - MEMORY_PERMISSION_UNMAP = 0x00000000, - MEMORY_PERMISSION_NORMAL = 0x00000001, -}; - -/// 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", - operation, addr0, addr1, size, permissions); - - switch (operation) { - - // Map normal heap memory - case MEMORY_OPERATION_HEAP: - virtual_address = Memory::MapBlock_Heap(size, operation, permissions); - break; - - // Map GSP heap memory - case MEMORY_OPERATION_GSP_HEAP: - virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions); - break; - - // Unknown ControlMemory operation - 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; -} - -/// 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", - memblock, addr, mypermissions, otherpermission); - switch (mypermissions) { - case MEMORY_PERMISSION_NORMAL: - case MEMORY_PERMISSION_NORMAL + 1: - case MEMORY_PERMISSION_NORMAL + 2: - Memory::MapBlock_Shared(memblock, addr, mypermissions); - break; - default: - ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions); - } - return 0; -} - -/// 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); - Core::g_app_core->SetReg(1, service->GetHandle()); - DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); - return 0; -} - -/// 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(); - return 0; -} - -/// Close a handle -Result CloseHandle(Handle handle) { - // ImplementMe - DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); - return 0; -} - -/// Wait for a handle to synchronize, timeout after the specified nanoseconds -Result WaitSynchronization1(Handle handle, s64 nano_seconds) { - // ImplementMe - DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", - handle, nano_seconds); - return 0; -} - -/// 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) { - s32* out = (s32*)_out; - Handle* handles = (Handle*)_handles; - // ImplementMe - - DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronizationN called handle_count=%d, wait_all=%s, nanoseconds=%d %s", - handle_count, (wait_all ? "true" : "false"), nano_seconds); - - for (u32 i = 0; i < handle_count; i++) { - DEBUG_LOG(SVC, "\thandle[%d]=0x%08X", i, handles[i]); - } - 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; -} - -/// 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); -} - -/// Get resource limit -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); - 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) { - //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 - return 0; -} - -Result CreateThread(void* thread, u32 priority, u32 entry_point, u32 arg, u32 stack_top, - u32 processor_id) { - std::string name; - if (Symbols::HasSymbol(entry_point)) { - TSymbol symbol = Symbols::GetSymbol(entry_point); - name = symbol.name; - } else { - char buff[100]; - sprintf(buff, "%s", "unknown-%08X", entry_point); - name = buff; - } - DEBUG_LOG(SVC, "CreateThread called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " - "threadpriority=0x%08X, processorid=0x%08X", entry_point, name.c_str(), arg, stack_top, - priority, processor_id); - - Handle handle = __KernelCreateThread(name.c_str(), entry_point, priority, processor_id, - stack_top); - Core::g_app_core->SetReg(1, 0xFEEDDEAF); - - return 0; -} - -Result CreateMutex(void* _mutex, u32 initial_locked) { - Handle* mutex = (Handle*)_mutex; - DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateMutex called initial_locked=%s", - initial_locked ? "true" : "false"); - Core::g_app_core->SetReg(1, 0xF00D0BAD); - return 0; -} - -Result ReleaseMutex(Handle handle) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) ReleaseMutex called handle=0x%08X", handle); - return 0; -} - -Result GetThreadId(void* thread_id, u32 thread) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetThreadId called thread=0x%08X", thread); - return 0; -} - -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; -} - -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); - return 0; -} - -const HLE::FunctionDef Syscall_Table[] = { - {0x00, NULL, "Unknown"}, - {0x01, WrapI_VUUUUU, "ControlMemory"}, - {0x02, WrapI_VVU, "QueryMemory"}, - {0x03, NULL, "ExitProcess"}, - {0x04, NULL, "GetProcessAffinityMask"}, - {0x05, NULL, "SetProcessAffinityMask"}, - {0x06, NULL, "GetProcessIdealProcessor"}, - {0x07, NULL, "SetProcessIdealProcessor"}, - {0x08, WrapI_VUUUUU, "CreateThread"}, - {0x09, NULL, "ExitThread"}, - {0x0A, NULL, "SleepThread"}, - {0x0B, NULL, "GetThreadPriority"}, - {0x0C, NULL, "SetThreadPriority"}, - {0x0D, NULL, "GetThreadAffinityMask"}, - {0x0E, NULL, "SetThreadAffinityMask"}, - {0x0F, NULL, "GetThreadIdealProcessor"}, - {0x10, NULL, "SetThreadIdealProcessor"}, - {0x11, NULL, "GetCurrentProcessorNumber"}, - {0x12, NULL, "Run"}, - {0x13, WrapI_VU, "CreateMutex"}, - {0x14, WrapI_U, "ReleaseMutex"}, - {0x15, NULL, "CreateSemaphore"}, - {0x16, NULL, "ReleaseSemaphore"}, - {0x17, WrapI_VU, "CreateEvent"}, - {0x18, NULL, "SignalEvent"}, - {0x19, NULL, "ClearEvent"}, - {0x1A, NULL, "CreateTimer"}, - {0x1B, NULL, "SetTimer"}, - {0x1C, NULL, "CancelTimer"}, - {0x1D, NULL, "ClearTimer"}, - {0x1E, NULL, "CreateMemoryBlock"}, - {0x1F, WrapI_UUUU, "MapMemoryBlock"}, - {0x20, NULL, "UnmapMemoryBlock"}, - {0x21, WrapI_V, "CreateAddressArbiter"}, - {0x22, NULL, "ArbitrateAddress"}, - {0x23, WrapI_U, "CloseHandle"}, - {0x24, WrapI_US64, "WaitSynchronization1"}, - {0x25, WrapI_VVUUS64, "WaitSynchronizationN"}, - {0x26, NULL, "SignalAndWait"}, - {0x27, NULL, "DuplicateHandle"}, - {0x28, NULL, "GetSystemTick"}, - {0x29, NULL, "GetHandleInfo"}, - {0x2A, NULL, "GetSystemInfo"}, - {0x2B, NULL, "GetProcessInfo"}, - {0x2C, NULL, "GetThreadInfo"}, - {0x2D, WrapI_VC, "ConnectToPort"}, - {0x2E, NULL, "SendSyncRequest1"}, - {0x2F, NULL, "SendSyncRequest2"}, - {0x30, NULL, "SendSyncRequest3"}, - {0x31, NULL, "SendSyncRequest4"}, - {0x32, WrapI_U, "SendSyncRequest"}, - {0x33, NULL, "OpenProcess"}, - {0x34, NULL, "OpenThread"}, - {0x35, NULL, "GetProcessId"}, - {0x36, NULL, "GetProcessIdOfThread"}, - {0x37, WrapI_VU, "GetThreadId"}, - {0x38, WrapI_VU, "GetResourceLimit"}, - {0x39, NULL, "GetResourceLimitLimitValues"}, - {0x3A, WrapI_VUVI, "GetResourceLimitCurrentValues"}, - {0x3B, NULL, "GetThreadContext"}, - {0x3C, NULL, "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"}, -}; - -void Register() { - HLE::RegisterModule("SyscallTable", ARRAY_SIZE(Syscall_Table), Syscall_Table); -} - -} // namespace diff --git a/src/core/hle/syscall.h b/src/core/hle/syscall.h deleted file mode 100644 index 3da349ed5..000000000 --- a/src/core/hle/syscall.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// SVC types - -struct MemoryInfo { - u32 base_address; - u32 size; - u32 permission; - u32 state; -}; - -struct PageInfo { - u32 flags; -}; - -struct ThreadContext { - u32 cpu_registers[13]; - u32 sp; - u32 lr; - u32 pc; - u32 cpsr; - u32 fpu_registers[32]; - u32 fpscr; - u32 fpexc; -}; - -enum ResetType { - RESETTYPE_ONESHOT, - RESETTYPE_STICKY, - RESETTYPE_PULSE, - RESETTYPE_MAX_BIT = (1u << 31), -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Namespace Syscall - -namespace Syscall { - -void Register(); - -} // namespace -- cgit v1.2.3 From 9bf7ce535a604d5523bfc14ea8057477ce1a4e0f Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 22:27:12 -0400 Subject: service: removed redundant include of common_types.h --- src/core/hle/service/service.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index eba730efb..716669bed 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -10,7 +10,6 @@ #include #include "common/common.h" -#include "common/common_types.h" #include "core/mem_map.h" #include "core/hle/kernel/kernel.h" -- cgit v1.2.3 From 978e1d4653cd12a68d6bfa05af57edb1645da0f5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 23:03:45 -0400 Subject: mutex: initial commit of HLE module --- src/core/CMakeLists.txt | 1 + src/core/core.vcxproj | 2 + src/core/core.vcxproj.filters | 6 +++ src/core/hle/kernel/mutex.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++ src/core/hle/kernel/mutex.h | 26 +++++++++ src/core/hle/service/apt.cpp | 10 ++-- src/core/hle/svc.cpp | 9 ++-- 7 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 src/core/hle/kernel/mutex.cpp create mode 100644 src/core/hle/kernel/mutex.h (limited to 'src/core/hle/service') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e006502da..6ad308798 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -35,6 +35,7 @@ set(SRCS core.cpp hle/coprocessor.cpp hle/svc.cpp hle/kernel/kernel.cpp + hle/kernel/mutex.cpp hle/kernel/thread.cpp hle/service/apt.cpp hle/service/gsp.cpp diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 6eb58a636..f271d336e 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -169,6 +169,7 @@ + @@ -217,6 +218,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index fc4e35edb..f664debec 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -162,6 +162,9 @@ hle + + hle\kernel + @@ -289,6 +292,9 @@ hle + + hle\kernel + diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp new file mode 100644 index 000000000..2b2cff4ea --- /dev/null +++ b/src/core/hle/kernel/mutex.cpp @@ -0,0 +1,122 @@ +// 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/thread.h" + +namespace Kernel { + +class Mutex : public Object { +public: + const char* GetTypeName() { return "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 + 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 +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef std::multimap MutexMap; +static MutexMap g_mutex_held_locks; + +void __MutexAcquireLock(Mutex* mutex, Handle thread) { + g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); + mutex->lock_thread = thread; +} + +void __MutexAcquireLock(Mutex* mutex) { + Handle thread = GetCurrentThread(); + __MutexAcquireLock(mutex, thread); +} + +void __MutexEraseLock(Mutex* mutex) { + Handle handle = mutex->GetHandle(); + auto locked = g_mutex_held_locks.equal_range(mutex->lock_thread); + for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { + if ((*iter).second == handle) { + g_mutex_held_locks.erase(iter); + break; + } + } + mutex->lock_thread = -1; +} + +bool __LockMutex(Mutex* mutex) { + // Mutex alread locked? + if (mutex->locked) { + return false; + } + __MutexAcquireLock(mutex); + return true; +} + +bool __ReleaseMutexForThread(Mutex* mutex, Handle thread) { + __MutexAcquireLock(mutex, thread); + Kernel::ResumeThreadFromWait(thread); + return true; +} + +bool __ReleaseMutex(Mutex* mutex) { + __MutexEraseLock(mutex); + bool woke_threads = false; + auto iter = mutex->waiting_threads.begin(); + + // Find the next waiting thread for the mutex... + while (!woke_threads && !mutex->waiting_threads.empty()) { + woke_threads |= __ReleaseMutexForThread(mutex, *iter); + mutex->waiting_threads.erase(iter); + } + // Reset mutex lock thread handle, nothing is waiting + if (!woke_threads) { + mutex->locked = false; + mutex->lock_thread = -1; + } + return woke_threads; +} + +/** + * Releases a mutex + * @param handle Handle to mutex to release + */ +Result ReleaseMutex(Handle handle) { + Mutex* mutex = Kernel::g_object_pool.GetFast(handle); + if (!__ReleaseMutex(mutex)) { + return -1; + } + return 0; +} + +/** + * Creates a mutex + * @param handle Reference to handle for the newly created mutex + * @param initial_locked Specifies if the mutex should be locked initially + */ +Result CreateMutex(Handle& handle, bool initial_locked) { + Mutex* mutex = new Mutex; + handle = Kernel::g_object_pool.Create(mutex); + + mutex->locked = mutex->initial_locked = initial_locked; + + // Acquire mutex with current thread if initialized as locked... + if (mutex->locked) { + __MutexAcquireLock(mutex); + + // Otherwise, reset lock thread handle + } else { + mutex->lock_thread = -1; + } + return 0; +} + +} // namespace diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h new file mode 100644 index 000000000..1f843e979 --- /dev/null +++ b/src/core/hle/kernel/mutex.h @@ -0,0 +1,26 @@ +// 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" + +namespace Kernel { + +/** + * Releases a mutex + * @param handle Handle to mutex to release + */ +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 + */ +Result CreateMutex(Handle& handle, bool initial_locked); + +} // namespace diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 1f6a70eab..ecec4da00 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -3,9 +3,10 @@ // Refer to the license.txt file included. -#include "common/log.h" +#include "common/common.h" #include "core/hle/hle.h" +#include "core/hle/kernel/mutex.h" #include "core/hle/service/apt.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -19,11 +20,8 @@ void Initialize(Service::Interface* self) { void GetLockHandle(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); - u32 flags = cmd_buff[1]; - - // TODO: This should be an actual mutex handle. Games will check that this is not non-zero - // (NULL), and fail if such. A faked non-zero value will at least enable further booting. - cmd_buff[5] = 0x12345678; + u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field + cmd_buff[1] = Kernel::CreateMutex(cmd_buff[5], false); } const Interface::FunctionInfo FunctionTable[] = { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 3674a08c5..73ab073f5 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -187,15 +187,16 @@ Result CreateThread(void* thread, u32 priority, u32 entry_point, u32 arg, u32 st /// Create a mutex Result CreateMutex(void* _mutex, u32 initial_locked) { Handle* mutex = (Handle*)_mutex; - DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateMutex called initial_locked=%s", - initial_locked ? "true" : "false"); - Core::g_app_core->SetReg(1, 0xF00D0BAD); + DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s", initial_locked ? "true" : "false"); + Kernel::CreateMutex(*mutex, (bool)initial_locked); + Core::g_app_core->SetReg(1, *mutex); return 0; } /// Release a mutex Result ReleaseMutex(Handle handle) { - DEBUG_LOG(SVC, "(UNIMPLEMENTED) ReleaseMutex called handle=0x%08X", handle); + DEBUG_LOG(SVC, "ReleaseMutex called handle=0x%08X", handle); + Kernel::ReleaseMutex(handle); return 0; } -- cgit v1.2.3 From eb537c560a33db9955413a96afd3b98203a729fe Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 23:23:58 -0400 Subject: mutex: refactored the interface to code to return a Mutex* handle --- src/core/hle/kernel/mutex.cpp | 14 ++++++++++++-- src/core/hle/kernel/mutex.h | 2 +- src/core/hle/service/apt.cpp | 3 ++- src/core/hle/svc.cpp | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 2b2cff4ea..7cf3439e9 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -102,7 +102,7 @@ Result ReleaseMutex(Handle handle) { * @param handle Reference to handle for the newly created mutex * @param initial_locked Specifies if the mutex should be locked initially */ -Result CreateMutex(Handle& handle, bool initial_locked) { +Mutex* CreateMutex(Handle& handle, bool initial_locked) { Mutex* mutex = new Mutex; handle = Kernel::g_object_pool.Create(mutex); @@ -116,7 +116,17 @@ Result CreateMutex(Handle& handle, bool initial_locked) { } else { mutex->lock_thread = -1; } - return 0; + return mutex; +} + +/** + * Creates a mutex + * @param initial_locked Specifies if the mutex should be locked initially + */ +Handle CreateMutex(bool initial_locked) { + Handle handle; + Mutex* mutex = CreateMutex(handle, initial_locked); + return handle; } } // namespace diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 1f843e979..871e2e562 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -21,6 +21,6 @@ Result ReleaseMutex(Handle handle); * @param handle Reference to handle for the newly created mutex * @param initial_locked Specifies if the mutex should be locked initially */ -Result CreateMutex(Handle& handle, bool initial_locked); +Handle CreateMutex(bool initial_locked); } // namespace diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index ecec4da00..b01f35ac5 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -21,7 +21,8 @@ void Initialize(Service::Interface* self) { 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] = Kernel::CreateMutex(cmd_buff[5], false); + cmd_buff[1] = 0; // No error + cmd_buff[5] = Kernel::CreateMutex(false); } const Interface::FunctionInfo FunctionTable[] = { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 73ab073f5..ffacdfb86 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -188,7 +188,7 @@ Result CreateThread(void* thread, u32 priority, u32 entry_point, u32 arg, u32 st Result CreateMutex(void* _mutex, u32 initial_locked) { Handle* mutex = (Handle*)_mutex; DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s", initial_locked ? "true" : "false"); - Kernel::CreateMutex(*mutex, (bool)initial_locked); + *mutex = Kernel::CreateMutex((initial_locked != 0)); Core::g_app_core->SetReg(1, *mutex); return 0; } -- cgit v1.2.3 From 9fddba68435f6e276bfb40c793f1ca0f8b984ec9 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 22 May 2014 18:48:14 -0400 Subject: APT_U: added a debug log on calling GetLockHandle --- src/core/hle/service/apt.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index b01f35ac5..32759a087 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -23,6 +23,7 @@ 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]); } const Interface::FunctionInfo FunctionTable[] = { -- cgit v1.2.3