diff options
Diffstat (limited to 'src/core/hle/service')
| -rw-r--r-- | src/core/hle/service/apt.cpp | 191 | ||||
| -rw-r--r-- | src/core/hle/service/apt.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/gsp.cpp | 149 | ||||
| -rw-r--r-- | src/core/hle/service/gsp.h | 19 | ||||
| -rw-r--r-- | src/core/hle/service/hid.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/hid.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/ndm.cpp | 32 | ||||
| -rw-r--r-- | src/core/hle/service/ndm.h | 33 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/service/service.h | 106 | ||||
| -rw-r--r-- | src/core/hle/service/srv.cpp | 37 | ||||
| -rw-r--r-- | src/core/hle/service/srv.h | 8 |
12 files changed, 390 insertions, 237 deletions
diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 709ac5493..a0012b5dd 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -3,9 +3,11 @@ // Refer to the license.txt file included. -#include "common/log.h" +#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" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -14,93 +16,120 @@ namespace APT_U { void Initialize(Service::Interface* self) { - NOTICE_LOG(OSHLE, "APT_U::Sync - Initialize"); + u32* cmd_buff = Service::GetCommandBuffer(); + DEBUG_LOG(KERNEL, "called"); + + 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 + + cmd_buff[1] = 0; // No error } 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(bunnei): Figure out the purpose of the flag field + cmd_buff[1] = 0; // No error + cmd_buff[5] = Kernel::CreateMutex(false, "APT_U:Lock"); + 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) 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) called app_id=0x%08X", app_id); } const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetLockHandle, "GetLockHandle"}, - {0x00020080, Initialize, "Initialize"}, - {0x00030040, NULL, "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, nullptr, "Finalize"}, + {0x00050040, nullptr, "GetAppletManInfo"}, + {0x00060040, nullptr, "GetAppletInfo"}, + {0x00070000, nullptr, "GetLastSignaledAppletId"}, + {0x00080000, nullptr, "CountRegisteredApplet"}, + {0x00090040, nullptr, "IsRegistered"}, + {0x000A0040, nullptr, "GetAttribute"}, + {0x000B0040, InquireNotification, "InquireNotification"}, + {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/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.cpp b/src/core/hle/service/gsp.cpp index 12c7dabcd..f75ba75c2 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -8,27 +8,32 @@ #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" +#include "core/hw/gpu.h" + +#include "video_core/gpu_debugger.h" //////////////////////////////////////////////////////////////////////////////////////////////////// +// Main graphics debugger object - TODO: Here is probably not the best place for this +GraphicsDebugger g_debugger; + /// GSP shared memory GX command buffer header union GX_CmdBufferHeader { u32 hex; - // Current command index. This index is updated by GSP module after loading the command data, - // right before the command is processed. When this index is updated by GSP module, the total + // Current command index. This index is updated by GSP module after loading the command data, + // right before the command is processed. When this index is updated by GSP module, the total // commands field is decreased by one as well. BitField<0,8,u32> index; - + // Total commands to process, must not be value 0 when GSP module handles commands. This must be - // <=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 + // <=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; }; /// Gets the address of the start (header) of a command buffer in GSP shared memory @@ -44,7 +49,11 @@ static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) { /// Finishes execution of a GSP command void GX_FinishCommand(u32 thread_id) { GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(thread_id); + + g_debugger.GXCommandProcessed(GX_GetCmdBufferPointer(thread_id, 0x20 + (header->index * 0x20))); + header->number_commands = header->number_commands - 1; + // TODO: Increment header->index? } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -52,27 +61,24 @@ void GX_FinishCommand(u32 thread_id) { namespace GSP_GPU { +Handle g_event_handle = 0; u32 g_thread_id = 0; enum { - CMD_GX_REQUEST_DMA = 0x00000000, -}; - -enum { REG_FRAMEBUFFER_1 = 0x00400468, REG_FRAMEBUFFER_2 = 0x00400494, }; /// Read a GSP GPU hardware register void ReadHWRegs(Service::Interface* self) { - static const u32 framebuffer_1[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME1, LCD::PADDR_VRAM_TOP_RIGHT_FRAME1}; - static const u32 framebuffer_2[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME2, LCD::PADDR_VRAM_TOP_RIGHT_FRAME2}; + static const u32 framebuffer_1[] = {GPU::PADDR_VRAM_TOP_LEFT_FRAME1, GPU::PADDR_VRAM_TOP_RIGHT_FRAME1}; + static const u32 framebuffer_2[] = {GPU::PADDR_VRAM_TOP_LEFT_FRAME2, GPU::PADDR_VRAM_TOP_RIGHT_FRAME2}; u32* cmd_buff = Service::GetCommandBuffer(); u32 reg_addr = cmd_buff[1]; u32 size = cmd_buff[2]; u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); - + switch (reg_addr) { // NOTE: Calling SetFramebufferLocation here is a hack... Not sure the correct way yet to set @@ -81,18 +87,18 @@ void ReadHWRegs(Service::Interface* self) { // Top framebuffer 1 addresses case REG_FRAMEBUFFER_1: - LCD::SetFramebufferLocation(LCD::FRAMEBUFFER_LOCATION_VRAM); + GPU::SetFramebufferLocation(GPU::FRAMEBUFFER_LOCATION_VRAM); memcpy(dst, framebuffer_1, size); break; // Top framebuffer 2 addresses case REG_FRAMEBUFFER_2: - LCD::SetFramebufferLocation(LCD::FRAMEBUFFER_LOCATION_VRAM); + GPU::SetFramebufferLocation(GPU::FRAMEBUFFER_LOCATION_VRAM); memcpy(dst, framebuffer_2, size); 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); } } @@ -100,62 +106,101 @@ 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 != 0), "called, but event is nullptr!"); + + 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 - cmd_buff[4] = self->NewHandle(); } + /// This triggers handling of the GX command written to the command buffer in shared memory. void TriggerCmdReqQueue(Service::Interface* self) { GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(g_thread_id); u32* cmd_buff = (u32*)GX_GetCmdBufferPointer(g_thread_id, 0x20 + (header->index * 0x20)); - switch (cmd_buff[0]) { + switch (static_cast<GXCommandId>(cmd_buff[0])) { // GX request DMA - typically used for copying memory from GSP heap to VRAM - case CMD_GX_REQUEST_DMA: + case GXCommandId::REQUEST_DMA: memcpy(Memory::GetPointer(cmd_buff[2]), Memory::GetPointer(cmd_buff[1]), cmd_buff[3]); break; + case GXCommandId::SET_COMMAND_LIST_LAST: + GPU::Write<u32>(GPU::Registers::CommandListAddress, cmd_buff[1] >> 3); + GPU::Write<u32>(GPU::Registers::CommandListSize, cmd_buff[2] >> 3); + GPU::Write<u32>(GPU::Registers::ProcessCommandList, 1); // TODO: Not sure if we are supposed to always write this + + // TODO: Move this to GPU + // TODO: Not sure what units the size is measured in + g_debugger.CommandListCalled(cmd_buff[1], (u32*)Memory::GetPointer(cmd_buff[1]), cmd_buff[2]); + break; + + case GXCommandId::SET_MEMORY_FILL: + break; + + case GXCommandId::SET_DISPLAY_TRANSFER: + break; + + case GXCommandId::SET_TEXTURE_COPY: + break; + + case GXCommandId::SET_COMMAND_LIST_FIRST: + { + //u32* buf0_data = (u32*)Memory::GetPointer(cmd_buff[1]); + //u32* buf1_data = (u32*)Memory::GetPointer(cmd_buff[3]); + //u32* buf2_data = (u32*)Memory::GetPointer(cmd_buff[5]); + 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); } 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/gsp.h b/src/core/hle/service/gsp.h index 5ba09ab70..214de140f 100644 --- a/src/core/hle/service/gsp.h +++ b/src/core/hle/service/gsp.h @@ -11,6 +11,23 @@ namespace GSP_GPU { +enum class GXCommandId : u32 { + REQUEST_DMA = 0x00000000, + SET_COMMAND_LIST_LAST = 0x00000001, + SET_MEMORY_FILL = 0x00000002, // TODO: Confirm? (lictru uses 0x01000102) + SET_DISPLAY_TRANSFER = 0x00000003, + SET_TEXTURE_COPY = 0x00000004, + SET_COMMAND_LIST_FIRST = 0x00000005, +}; + +union GXCommand { + struct { + GXCommandId id; + }; + + u32 data[0x20]; +}; + /// Interface to "srv:" service class Interface : public Service::Interface { public: @@ -23,7 +40,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.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/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/ndm.cpp b/src/core/hle/service/ndm.cpp new file mode 100644 index 000000000..48755b6a7 --- /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, nullptr, "SuspendDaemons"}, + {0x00080040, nullptr, "DisableWifiUsage"}, + {0x00090000, nullptr, "EnableWifiUsage"}, + {0x00140040, nullptr, "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 diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index e6605a398..4a1ac857e 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -7,15 +7,19 @@ #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/ndm.h" #include "core/hle/service/srv.h" +#include "core/hle/kernel/kernel.h" + namespace Service { -Manager* g_manager = NULL; ///< Service manager +Manager* g_manager = nullptr; ///< Service manager //////////////////////////////////////////////////////////////////////////////////////////////////// // Service Manager class @@ -31,41 +35,30 @@ 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); - + m_port_map[service->GetPortName()] = Kernel::g_object_pool.Create(service); m_services.push_back(service); - - m_port_map[service->GetPortName()] = new_uid; - service->m_uid = new_uid; } /// 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)); + 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 UID -Interface* Manager::FetchFromUID(u32 uid) { - int index = GetIndexFromUID(uid); - if (index < (int)m_services.size()) { - return m_services[index]; - } - return NULL; +/// Get a Service Interface from its Handle +Interface* Manager::FetchFromHandle(Handle handle) { + return Kernel::g_object_pool.GetFast<Interface>(handle); } /// Get a Service Interface from its port 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 FetchFromUID(itr->second); + return FetchFromHandle(itr->second); } @@ -80,14 +73,15 @@ 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); - 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/service.h b/src/core/hle/service/service.h index b260a290a..dcd525727 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -4,22 +4,22 @@ #pragma once +#include <algorithm> #include <vector> #include <map> #include <string> #include "common/common.h" -#include "common/common_types.h" #include "core/mem_map.h" -#include "core/hle/syscall.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/svc.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace Service 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 @@ -35,15 +35,15 @@ inline static u32* GetCommandBuffer(const int offset=0) { class Manager; /// Interface to a CTROS service -class Interface : NonCopyable { +class Interface : public Kernel::Object { friend class Manager; public: + + const char *GetName() const { return GetPortName(); } + const char *GetTypeName() const { return GetPortName(); } - Interface() { - } - - virtual ~Interface() { - } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; } + Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Service; } typedef void (*Function)(Interface*); @@ -54,55 +54,53 @@ public: }; /** - * Gets the UID for the serice - * @return UID of service in native format - */ - NativeUID GetUID() const { - return (NativeUID)m_uid; - } - - /** * 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 - Syscall::Handle NewHandle() { - Syscall::Handle handle = (m_handles.size() << 16) | m_uid; + Handle CreateHandle(Kernel::Object *obj) { + Handle handle = Kernel::g_object_pool.Create(obj); m_handles.push_back(handle); return handle; } /// Frees a handle from the service - void DeleteHandle(Syscall::Handle handle) { - for(auto iter = m_handles.begin(); iter != m_handles.end(); ++iter) { - if(*iter == handle) { - m_handles.erase(iter); - break; - } - } + template <class T> + void DeleteHandle(const Handle handle) { + Kernel::g_object_pool.Destroy<T>(handle); + m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); } /** - * 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 */ - Syscall::Result Sync() { + Result SyncRequest(bool* wait) { u32* cmd_buff = GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); if (itr == m_functions.end()) { - ERROR_LOG(OSHLE, "Unknown/unimplemented function: port = %s, command = 0x%08X!", - GetPortName().c_str(), cmd_buff[0]); - return -1; + ERROR_LOG(OSHLE, "unknown/unimplemented function: port=%s, command=0x%08X", + GetPortName(), cmd_buff[0]); + + // 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().c_str(), itr->second.name.c_str()); - return -1; + if (itr->second.func == nullptr) { + ERROR_LOG(OSHLE, "unimplemented function: port=%s, name=%s", + GetPortName(), itr->second.name.c_str()); + + // TODO(bunnei): Hack - ignore error + u32* cmd_buff = Service::GetCommandBuffer(); + cmd_buff[1] = 0; + return 0; } itr->second.func(this); @@ -110,6 +108,17 @@ 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 + ERROR_LOG(OSHLE, "unimplemented function"); + return 0; + } + protected: /** @@ -122,10 +131,10 @@ protected: } private: - u32 m_uid; - - std::vector<Syscall::Handle> m_handles; - std::map<u32, FunctionInfo> m_functions; + + std::vector<Handle> m_handles; + std::map<u32, FunctionInfo> m_functions; + }; /// Simple class to manage accessing services from ports and UID handles @@ -143,25 +152,16 @@ 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); private: - /// Convert an index into m_services vector into a UID - static u32 GetUIDFromIndex(const int index) { - return index | 0x10000000; - } - - /// Convert a UID into an index into m_services - static int GetIndexFromUID(const u32 uid) { - return uid & 0x0FFFFFFF; - } - std::vector<Interface*> m_services; std::map<std::string, u32> m_port_map; + }; /// Initialize ServiceManager diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 071741444..f45c0efc2 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -5,43 +5,52 @@ #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, "called"); + if (!g_mutex) { + g_mutex = Kernel::CreateMutex(true, "SRV:Lock"); + } +} + +void GetProcSemaphore(Service::Interface* self) { + DEBUG_LOG(OSHLE, "called"); + // Get process semaphore? + u32* cmd_buff = Service::GetCommandBuffer(); + cmd_buff[1] = 0; // No error + cmd_buff[3] = g_mutex; // Return something... 0 == nullptr, raises an exception } 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); 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()); - - if (NULL != service) { - cmd_buff[3] = service->GetUID(); + 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 { - 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[] = { {0x00010002, Initialize, "Initialize"}, - {0x00020000, NULL, "GetProcSemaphore"}, - {0x00030100, NULL, "RegisterService"}, - {0x000400C0, NULL, "UnregisterService"}, + {0x00020000, GetProcSemaphore, "GetProcSemaphore"}, + {0x00030100, nullptr, "RegisterService"}, + {0x000400C0, nullptr, "UnregisterService"}, {0x00050100, GetServiceHandle, "GetServiceHandle"}, }; diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h index 760c976b4..81109a2a8 100644 --- a/src/core/hle/service/srv.h +++ b/src/core/hle/service/srv.h @@ -22,16 +22,10 @@ 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:"; } - /** - * Called when svcSendSyncRequest is called, loads command buffer and executes comand - * @return Return result of svcSendSyncRequest passed back to user app - */ - Syscall::Result Sync(); - }; } // namespace |
