aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/apt.cpp191
-rw-r--r--src/core/hle/service/apt.h2
-rw-r--r--src/core/hle/service/gsp.cpp149
-rw-r--r--src/core/hle/service/gsp.h19
-rw-r--r--src/core/hle/service/hid.cpp10
-rw-r--r--src/core/hle/service/hid.h2
-rw-r--r--src/core/hle/service/ndm.cpp32
-rw-r--r--src/core/hle/service/ndm.h33
-rw-r--r--src/core/hle/service/service.cpp38
-rw-r--r--src/core/hle/service/service.h106
-rw-r--r--src/core/hle/service/srv.cpp37
-rw-r--r--src/core/hle/service/srv.h8
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