aboutsummaryrefslogtreecommitdiffhomepage
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/ac_u.cpp2
-rw-r--r--src/core/hle/service/act_u.cpp2
-rw-r--r--src/core/hle/service/am_app.cpp2
-rw-r--r--src/core/hle/service/am_net.cpp2
-rw-r--r--src/core/hle/service/am_sys.cpp24
-rw-r--r--src/core/hle/service/am_sys.h23
-rw-r--r--src/core/hle/service/apt_a.cpp4
-rw-r--r--src/core/hle/service/apt_s.cpp123
-rw-r--r--src/core/hle/service/apt_s.h30
-rw-r--r--src/core/hle/service/apt_u.cpp421
-rw-r--r--src/core/hle/service/boss_p.cpp24
-rw-r--r--src/core/hle/service/boss_p.h23
-rw-r--r--src/core/hle/service/boss_u.cpp2
-rw-r--r--src/core/hle/service/cam_u.cpp24
-rw-r--r--src/core/hle/service/cam_u.h23
-rw-r--r--src/core/hle/service/cecd_s.cpp24
-rw-r--r--src/core/hle/service/cecd_s.h23
-rw-r--r--src/core/hle/service/cecd_u.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg.h2
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg_s.cpp98
-rw-r--r--src/core/hle/service/cfg/cfg_s.h23
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp2
-rw-r--r--src/core/hle/service/csnd_snd.cpp2
-rw-r--r--src/core/hle/service/dsp_dsp.cpp32
-rw-r--r--src/core/hle/service/err_f.cpp2
-rw-r--r--src/core/hle/service/frd_a.cpp24
-rw-r--r--src/core/hle/service/frd_a.h23
-rw-r--r--src/core/hle/service/frd_u.cpp2
-rw-r--r--src/core/hle/service/fs/archive.cpp73
-rw-r--r--src/core/hle/service/fs/archive.h24
-rw-r--r--src/core/hle/service/fs/fs_user.cpp40
-rw-r--r--src/core/hle/service/gsp_gpu.cpp68
-rw-r--r--src/core/hle/service/gsp_gpu.h25
-rw-r--r--src/core/hle/service/gsp_lcd.cpp26
-rw-r--r--src/core/hle/service/gsp_lcd.h24
-rw-r--r--src/core/hle/service/hid/hid.cpp142
-rw-r--r--src/core/hle/service/hid/hid.h (renamed from src/core/hle/service/hid_user.h)42
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp38
-rw-r--r--src/core/hle/service/hid/hid_spvr.h23
-rw-r--r--src/core/hle/service/hid/hid_user.cpp78
-rw-r--r--src/core/hle/service/hid/hid_user.h29
-rw-r--r--src/core/hle/service/hid_user.cpp197
-rw-r--r--src/core/hle/service/http_c.cpp2
-rw-r--r--src/core/hle/service/ir_rst.cpp2
-rw-r--r--src/core/hle/service/ir_u.cpp2
-rw-r--r--src/core/hle/service/ldr_ro.cpp2
-rw-r--r--src/core/hle/service/mic_u.cpp2
-rw-r--r--src/core/hle/service/ndm_u.cpp2
-rw-r--r--src/core/hle/service/news_s.cpp25
-rw-r--r--src/core/hle/service/news_s.h23
-rw-r--r--src/core/hle/service/news_u.cpp2
-rw-r--r--src/core/hle/service/nim_aoc.cpp2
-rw-r--r--src/core/hle/service/ns_s.cpp27
-rw-r--r--src/core/hle/service/ns_s.h24
-rw-r--r--src/core/hle/service/nwm_uds.cpp2
-rw-r--r--src/core/hle/service/pm_app.cpp2
-rw-r--r--src/core/hle/service/ptm_play.cpp28
-rw-r--r--src/core/hle/service/ptm_play.h23
-rw-r--r--src/core/hle/service/ptm_sysm.cpp56
-rw-r--r--src/core/hle/service/ptm_sysm.h23
-rw-r--r--src/core/hle/service/ptm_u.cpp2
-rw-r--r--src/core/hle/service/service.cpp132
-rw-r--r--src/core/hle/service/service.h73
-rw-r--r--src/core/hle/service/soc_u.cpp15
-rw-r--r--src/core/hle/service/srv.cpp16
-rw-r--r--src/core/hle/service/ssl_c.cpp2
-rw-r--r--src/core/hle/service/y2r_u.cpp2
68 files changed, 1724 insertions, 586 deletions
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 20a3fa2e..53d920de 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -53,7 +53,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/act_u.cpp b/src/core/hle/service/act_u.cpp
index 10870f14..4ea7a9fb 100644
--- a/src/core/hle/service/act_u.cpp
+++ b/src/core/hle/service/act_u.cpp
@@ -18,7 +18,7 @@ namespace ACT_U {
// Interface class
Interface::Interface() {
- //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ //Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/am_app.cpp b/src/core/hle/service/am_app.cpp
index 0b396b6d..df10db87 100644
--- a/src/core/hle/service/am_app.cpp
+++ b/src/core/hle/service/am_app.cpp
@@ -18,7 +18,7 @@ namespace AM_APP {
// Interface class
Interface::Interface() {
- //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ //Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp
index 112844e5..c74012d9 100644
--- a/src/core/hle/service/am_net.cpp
+++ b/src/core/hle/service/am_net.cpp
@@ -38,7 +38,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/am_sys.cpp b/src/core/hle/service/am_sys.cpp
new file mode 100644
index 00000000..c5df8abd
--- /dev/null
+++ b/src/core/hle/service/am_sys.cpp
@@ -0,0 +1,24 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/am_sys.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace AM_SYS
+
+namespace AM_SYS {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/am_sys.h b/src/core/hle/service/am_sys.h
new file mode 100644
index 00000000..bb6178a4
--- /dev/null
+++ b/src/core/hle/service/am_sys.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace AM_SYS
+
+namespace AM_SYS {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "am:sys";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/apt_a.cpp b/src/core/hle/service/apt_a.cpp
index 37be4b02..e1dd2a5f 100644
--- a/src/core/hle/service/apt_a.cpp
+++ b/src/core/hle/service/apt_a.cpp
@@ -11,6 +11,7 @@ namespace APT_U {
extern void GetLockHandle(Service::Interface* self);
extern void ReceiveParameter(Service::Interface* self);
extern void GlanceParameter(Service::Interface* self);
+ extern void GetSharedFont(Service::Interface* self);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -29,6 +30,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x000E0080, APT_U::GlanceParameter, "GlanceParameter?"},
{0x003B0040, nullptr, "CancelLibraryApplet?"},
{0x00430040, nullptr, "NotifyToWait?"},
+ {0x00440000, APT_U::GetSharedFont, "GetSharedFont?"},
{0x004B00C2, nullptr, "AppletUtility?"},
{0x00550040, nullptr, "WriteInputToNsState?"},
};
@@ -37,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/apt_s.cpp b/src/core/hle/service/apt_s.cpp
new file mode 100644
index 00000000..68633542
--- /dev/null
+++ b/src/core/hle/service/apt_s.cpp
@@ -0,0 +1,123 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+
+#include "common/common.h"
+#include "common/file_util.h"
+
+#include "core/hle/hle.h"
+#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/mutex.h"
+#include "core/hle/kernel/shared_memory.h"
+#include "core/hle/kernel/thread.h"
+#include "core/hle/service/apt_s.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace APT_S
+
+namespace APT_U {
+ extern void GetLockHandle(Service::Interface* self);
+ extern void Initialize(Service::Interface* self);
+ extern void Enable(Service::Interface* self);
+ extern void InquireNotification(Service::Interface* self);
+ extern void NotifyToWait(Service::Interface* self);
+ extern void GetSharedFont(Service::Interface* self);
+ extern void AppletUtility(Service::Interface* self);
+ extern void GlanceParameter(Service::Interface* self);
+ extern void ReceiveParameter(Service::Interface* self);
+}
+
+namespace APT_S {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010040, APT_U::GetLockHandle, "GetLockHandle"},
+ {0x00020080, APT_U::Initialize, "Initialize"},
+ {0x00030040, APT_U::Enable, "Enable"},
+ {0x00040040, nullptr, "Finalize"},
+ {0x00050040, nullptr, "GetAppletManInfo"},
+ {0x00060040, nullptr, "GetAppletInfo"},
+ {0x00070000, nullptr, "GetLastSignaledAppletId"},
+ {0x00080000, nullptr, "CountRegisteredApplet"},
+ {0x00090040, nullptr, "IsRegistered"},
+ {0x000A0040, nullptr, "GetAttribute"},
+ {0x000B0040, APT_U::InquireNotification, "InquireNotification"},
+ {0x000C0104, nullptr, "SendParameter"},
+ {0x000D0080, APT_U::ReceiveParameter, "ReceiveParameter"},
+ {0x000E0080, APT_U::GlanceParameter, "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, APT_U::NotifyToWait, "NotifyToWait"},
+ {0x00440000, APT_U::GetSharedFont, "GetSharedFont"},
+ {0x00450040, nullptr, "GetWirelessRebootInfo"},
+ {0x00460104, nullptr, "Wrap"},
+ {0x00470104, nullptr, "Unwrap"},
+ {0x00480100, nullptr, "GetProgramInfo"},
+ {0x00490180, nullptr, "Reboot"},
+ {0x004A0040, nullptr, "GetCaptureInfo"},
+ {0x004B00C2, APT_U::AppletUtility, "AppletUtility"},
+ {0x004C0000, nullptr, "SetFatalErrDispMode"},
+ {0x004D0080, nullptr, "GetAppletProgramInfo"},
+ {0x004E0000, nullptr, "HardwareResetAsync"},
+ {0x004F0080, nullptr, "SetApplicationCpuTimeLimit"},
+ {0x00500040, nullptr, "GetApplicationCpuTimeLimit"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/apt_s.h b/src/core/hle/service/apt_s.h
new file mode 100644
index 00000000..f097c974
--- /dev/null
+++ b/src/core/hle/service/apt_s.h
@@ -0,0 +1,30 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace APT_S
+
+namespace APT_S {
+
+// Application and title launching service. These services handle signaling for home/power button as
+// well. Only one session for either APT service can be open at a time, normally processes close the
+// service handle immediately once finished using the service. The commands for APT:U and APT:S are
+// exactly the same, however certain commands are only accessible with APT:S(NS module will call
+// svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services.
+
+/// Interface to "APT:S" service
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "APT:S";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index d0ff4e58..ccfd0459 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -10,7 +10,8 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/shared_memory.h"
-#include "apt_u.h"
+#include "core/hle/kernel/thread.h"
+#include "core/hle/service/apt_u.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace APT_U
@@ -25,10 +26,12 @@ namespace APT_U {
// correctly mapping it in Citra, however we still do not understand how the mapping is determined.
static const VAddr SHARED_FONT_VADDR = 0x18000000;
-// Handle to shared memory region designated to for shared system font
-static Handle shared_font_mem = 0;
+/// Handle to shared memory region designated to for shared system font
+static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem;
-static Handle lock_handle = 0;
+static Kernel::SharedPtr<Kernel::Mutex> lock;
+static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event
+static Kernel::SharedPtr<Kernel::Event> pause_event = 0; ///< APT pause event
static std::vector<u8> shared_font;
/// Signals used by APT functions
@@ -39,31 +42,71 @@ enum class SignalType : u32 {
ExitingApp = 0xC,
};
+/// App Id's used by APT functions
+enum class AppID : u32 {
+ HomeMenu = 0x101,
+ AlternateMenu = 0x103,
+ Camera = 0x110,
+ FriendsList = 0x112,
+ GameNotes = 0x113,
+ InternetBrowser = 0x114,
+ InstructionManual = 0x115,
+ Notifications = 0x116,
+ Miiverse = 0x117,
+ SoftwareKeyboard1 = 0x201,
+ Ed = 0x202,
+ PnoteApp = 0x204,
+ SnoteApp = 0x205,
+ Error = 0x206,
+ Mint = 0x207,
+ Extrapad = 0x208,
+ Memolib = 0x209,
+ Application = 0x300,
+ SoftwareKeyboard2 = 0x401,
+};
+
void Initialize(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- 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
+ // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
+ notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification");
+ pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause");
+
+ cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
+ cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom();
- Kernel::SetEventLocked(cmd_buff[3], true);
- Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event
+ // TODO(bunnei): Check if these events are cleared/signaled every time Initialize is called.
+ notification_event->Clear();
+ pause_event->Signal(); // Fire start event
- _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock");
- Kernel::ReleaseMutex(lock_handle);
+ _assert_msg_(KERNEL, (nullptr != lock), "Cannot initialize without lock");
+ lock->Release();
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+}
+
+/**
+ * APT_U::NotifyToWait service function
+ * Inputs:
+ * 1 : AppID
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void NotifyToWait(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 app_id = cmd_buff[1];
+ // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further.
+ pause_event->Signal();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id);
}
void GetLockHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
- if (0 == lock_handle) {
- // TODO(bunnei): Verify if this is created here or at application boot?
- lock_handle = Kernel::CreateMutex(false, "APT_U:Lock");
- Kernel::ReleaseMutex(lock_handle);
- }
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
// Not sure what these parameters are used for, but retail apps check that they are 0 after
// GetLockHandle has been called.
@@ -71,26 +114,102 @@ void GetLockHandle(Service::Interface* self) {
cmd_buff[3] = 0;
cmd_buff[4] = 0;
- cmd_buff[5] = lock_handle;
+ cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom();
LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]);
}
void Enable(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for?
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
}
+/**
+ * APT_U::GetAppletManInfo service function.
+ * Inputs:
+ * 1 : Unknown
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Unknown u32 value
+ * 3 : Unknown u8 value
+ * 4 : Home Menu AppId
+ * 5 : AppID of currently active app
+ */
+void GetAppletManInfo(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 unk = cmd_buff[1];
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = 0;
+ cmd_buff[3] = 0;
+ cmd_buff[4] = static_cast<u32>(AppID::HomeMenu); // Home menu AppID
+ cmd_buff[5] = static_cast<u32>(AppID::Application); // TODO(purpasmart96): Do this correctly
+
+ LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
+}
+
+/**
+ * APT_U::IsRegistered service function. This returns whether the specified AppID is registered with NS yet.
+ * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu uses this
+ * command to determine when the launched process is running and to determine when to stop using GSP etc,
+ * while displaying the "Nintendo 3DS" loading screen.
+ * Inputs:
+ * 1 : AppID
+ * Outputs:
+ * 0 : Return header
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Output, 0 = not registered, 1 = registered.
+ */
+void IsRegistered(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 app_id = cmd_buff[1];
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = 1; // Set to registered
+ LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
+}
+
void InquireNotification(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 app_id = cmd_buff[2];
- cmd_buff[1] = 0; // No error
+ u32 app_id = cmd_buff[1];
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
}
/**
+ * APT_U::SendParameter service function. This sets the parameter data state.
+ * Inputs:
+ * 1 : Source AppID
+ * 2 : Destination AppID
+ * 3 : Signal type
+ * 4 : Parameter buffer size, max size is 0x1000 (this can be zero)
+ * 5 : Value
+ * 6 : Handle to the destination process, likely used for shared memory (this can be zero)
+ * 7 : (Size<<14) | 2
+ * 8 : Input parameter buffer ptr
+ * Outputs:
+ * 0 : Return Header
+ * 1 : Result of function, 0 on success, otherwise error code
+*/
+void SendParameter(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 src_app_id = cmd_buff[1];
+ u32 dst_app_id = cmd_buff[2];
+ u32 signal_type = cmd_buff[3];
+ u32 buffer_size = cmd_buff[4];
+ u32 value = cmd_buff[5];
+ u32 handle = cmd_buff[6];
+ u32 size = cmd_buff[7];
+ u32 in_param_buffer_ptr = cmd_buff[8];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+ LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X,"
+ "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X",
+ src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, in_param_buffer_ptr);
+}
+
+/**
* APT_U::ReceiveParameter service function. This returns the current parameter data from NS state,
* from the source process which set the parameters. Once finished, NS will clear a flag in the NS
* state so that this command will return an error if this command is used again if parameters were
@@ -101,8 +220,8 @@ void InquireNotification(Service::Interface* self) {
* 2 : Parameter buffer size, max size is 0x1000
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
- * 2 : Unknown, for now assume AppID of the process which sent these parameters
- * 3 : Unknown, for now assume Signal type
+ * 2 : AppID of the process which sent these parameters
+ * 3 : Signal type
* 4 : Actual parameter buffer size, this is <= to the the input size
* 5 : Value
* 6 : Handle from the source process which set the parameters, likely used for shared memory
@@ -113,7 +232,7 @@ void ReceiveParameter(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
u32 buffer_size = cmd_buff[2];
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 0;
cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type
cmd_buff[4] = 0x10; // Parameter buffer size (16)
@@ -145,7 +264,7 @@ void GlanceParameter(Service::Interface* self) {
u32 app_id = cmd_buff[1];
u32 buffer_size = cmd_buff[2];
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 0;
cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type
cmd_buff[4] = 0x10; // Parameter buffer size (16)
@@ -157,6 +276,36 @@ void GlanceParameter(Service::Interface* self) {
}
/**
+ * APT_U::CancelParameter service function. When the parameter data is available, and when the above
+ * specified fields match the ones in NS state(for the ones where the checks are enabled), this
+ * clears the flag which indicates that parameter data is available
+ * (same flag cleared by APT:ReceiveParameter).
+ * Inputs:
+ * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS state.
+ * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter.
+ * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS state.
+ * 4 : AppID
+ * Outputs:
+ * 0 : Return header
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Status flag, 0 = failure due to no parameter data being available, or the above enabled
+ * fields don't match the fields in NS state. 1 = success.
+ */
+void CancelParameter(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 flag1 = cmd_buff[1];
+ u32 unk = cmd_buff[2];
+ u32 flag2 = cmd_buff[3];
+ u32 app_id = cmd_buff[4];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = 1; // Set to Success
+
+ LOG_WARNING(Service_APT, "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X",
+ flag1, unk, flag2, app_id);
+}
+
+/**
* APT_U::AppletUtility service function
* Inputs:
* 1 : Unknown, but clearly used for something
@@ -177,7 +326,7 @@ void AppletUtility(Service::Interface* self) {
u32 buffer1_addr = cmd_buff[5];
u32 buffer2_addr = cmd_buff[65];
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08x, buffer2_size=0x%08x, "
"buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size,
@@ -201,96 +350,144 @@ void GetSharedFont(Service::Interface* self) {
memcpy(Memory::GetPointer(SHARED_FONT_VADDR), shared_font.data(), shared_font.size());
cmd_buff[0] = 0x00440082;
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = SHARED_FONT_VADDR;
- cmd_buff[4] = shared_font_mem;
+ cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom();
} else {
cmd_buff[1] = -1; // Generic error (not really possible to verify this on hardware)
LOG_ERROR(Kernel_SVC, "called, but %s has not been loaded!", SHARED_FONT);
}
}
+/**
+ * APT_U::SetAppCpuTimeLimit service function
+ * Inputs:
+ * 1 : Value, must be one
+ * 2 : Percentage of CPU time from 5 to 80
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void SetAppCpuTimeLimit(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 value = cmd_buff[1];
+ u32 percent = cmd_buff[2];
+
+ if (value != 1) {
+ LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value);
+ }
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+ LOG_WARNING(Service_APT, "(STUBBED) called percent=0x%08X, value=0x%08x", percent, value);
+}
+
+/**
+ * APT_U::GetAppCpuTimeLimit service function
+ * Inputs:
+ * 1 : Value, must be one
+ * Outputs:
+ * 0 : Return header
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : System core CPU time percentage
+ */
+void GetAppCpuTimeLimit(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 value = cmd_buff[1];
+
+ if (value != 1) {
+ LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value);
+ }
+
+ // TODO(purpasmart96): This is incorrect, I'm pretty sure the percentage should
+ // be set by the application.
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = 0x80; // Set to 80%
+
+ LOG_WARNING(Service_APT, "(STUBBED) called value=0x%08x", value);
+}
+
const Interface::FunctionInfo FunctionTable[] = {
- {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, ReceiveParameter, "ReceiveParameter"},
- {0x000E0080, GlanceParameter, "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, GetSharedFont, "GetSharedFont"},
- {0x00450040, nullptr, "GetWirelessRebootInfo"},
- {0x00460104, nullptr, "Wrap"},
- {0x00470104, nullptr, "Unwrap"},
- {0x00480100, nullptr, "GetProgramInfo"},
- {0x00490180, nullptr, "Reboot"},
- {0x004A0040, nullptr, "GetCaptureInfo"},
- {0x004B00C2, AppletUtility, "AppletUtility"},
- {0x004C0000, nullptr, "SetFatalErrDispMode"},
- {0x004D0080, nullptr, "GetAppletProgramInfo"},
- {0x004E0000, nullptr, "HardwareResetAsync"},
- {0x004F0080, nullptr, "SetApplicationCpuTimeLimit"},
- {0x00500040, nullptr, "GetApplicationCpuTimeLimit"},
+ {0x00010040, GetLockHandle, "GetLockHandle"},
+ {0x00020080, Initialize, "Initialize"},
+ {0x00030040, Enable, "Enable"},
+ {0x00040040, nullptr, "Finalize"},
+ {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
+ {0x00060040, nullptr, "GetAppletInfo"},
+ {0x00070000, nullptr, "GetLastSignaledAppletId"},
+ {0x00080000, nullptr, "CountRegisteredApplet"},
+ {0x00090040, IsRegistered, "IsRegistered"},
+ {0x000A0040, nullptr, "GetAttribute"},
+ {0x000B0040, InquireNotification, "InquireNotification"},
+ {0x000C0104, SendParameter, "SendParameter"},
+ {0x000D0080, ReceiveParameter, "ReceiveParameter"},
+ {0x000E0080, GlanceParameter, "GlanceParameter"},
+ {0x000F0100, CancelParameter, "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, NotifyToWait, "NotifyToWait"},
+ {0x00440000, GetSharedFont, "GetSharedFont"},
+ {0x00450040, nullptr, "GetWirelessRebootInfo"},
+ {0x00460104, nullptr, "Wrap"},
+ {0x00470104, nullptr, "Unwrap"},
+ {0x00480100, nullptr, "GetProgramInfo"},
+ {0x00490180, nullptr, "Reboot"},
+ {0x004A0040, nullptr, "GetCaptureInfo"},
+ {0x004B00C2, AppletUtility, "AppletUtility"},
+ {0x004C0000, nullptr, "SetFatalErrDispMode"},
+ {0x004D0080, nullptr, "GetAppletProgramInfo"},
+ {0x004E0000, nullptr, "HardwareResetAsync"},
+ {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
+ {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -315,15 +512,15 @@ Interface::Interface() {
file.ReadBytes(shared_font.data(), (size_t)file.GetSize());
// Create shared font memory object
- shared_font_mem = Kernel::CreateSharedMemory("APT_U:shared_font_mem");
+ shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem");
} else {
LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str());
- shared_font_mem = 0;
+ shared_font_mem = nullptr;
}
- lock_handle = 0;
+ lock = Kernel::Mutex::Create(false, "APT_U:Lock");
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/boss_p.cpp b/src/core/hle/service/boss_p.cpp
new file mode 100644
index 00000000..b3aa6ace
--- /dev/null
+++ b/src/core/hle/service/boss_p.cpp
@@ -0,0 +1,24 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/boss_p.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace BOSS_P
+
+namespace BOSS_P {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+// const Interface::FunctionInfo FunctionTable[] = { };
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/boss_p.h b/src/core/hle/service/boss_p.h
new file mode 100644
index 00000000..71f1e746
--- /dev/null
+++ b/src/core/hle/service/boss_p.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace BOSS_P
+
+namespace BOSS_P {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "boss:P";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/boss_u.cpp b/src/core/hle/service/boss_u.cpp
index 1820ea7a..50bb5d42 100644
--- a/src/core/hle/service/boss_u.cpp
+++ b/src/core/hle/service/boss_u.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/cam_u.cpp b/src/core/hle/service/cam_u.cpp
new file mode 100644
index 00000000..cf3b2766
--- /dev/null
+++ b/src/core/hle/service/cam_u.cpp
@@ -0,0 +1,24 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/cam_u.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CAM_U
+
+namespace CAM_U {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/cam_u.h b/src/core/hle/service/cam_u.h
new file mode 100644
index 00000000..878c20a8
--- /dev/null
+++ b/src/core/hle/service/cam_u.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CAM_U
+
+namespace CAM_U {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "cam:u";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/cecd_s.cpp b/src/core/hle/service/cecd_s.cpp
new file mode 100644
index 00000000..2c707baf
--- /dev/null
+++ b/src/core/hle/service/cecd_s.cpp
@@ -0,0 +1,24 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/cecd_s.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CECD_S
+
+namespace CECD_S {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+//const Interface::FunctionInfo FunctionTable[] = { };
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/cecd_s.h b/src/core/hle/service/cecd_s.h
new file mode 100644
index 00000000..d880d039
--- /dev/null
+++ b/src/core/hle/service/cecd_s.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CECD_S
+
+namespace CECD_S {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "cecd:s";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/cecd_u.cpp b/src/core/hle/service/cecd_u.cpp
index b7655ef0..b7ea3a18 100644
--- a/src/core/hle/service/cecd_u.cpp
+++ b/src/core/hle/service/cecd_u.cpp
@@ -18,7 +18,7 @@ namespace CECD_U {
// Interface class
Interface::Interface() {
- //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ //Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
index c74527ca..e818d7bd 100644
--- a/src/core/hle/service/cfg/cfg.h
+++ b/src/core/hle/service/cfg/cfg.h
@@ -110,7 +110,7 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output);
* The config savegame file in the filesystem is not updated.
* @param block_id The id of the block we want to create
* @param size The size of the block we want to create
- * @param flag The flags of the new block
+ * @param flags The flags of the new block
* @param data A pointer containing the data we will write to the new block
* @returns ResultCode indicating the result of the operation, 0 on success
*/
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 7c1ee8ac..555b7884 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -104,7 +104,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp
new file mode 100644
index 00000000..2170894d
--- /dev/null
+++ b/src/core/hle/service/cfg/cfg_s.cpp
@@ -0,0 +1,98 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/cfg/cfg.h"
+#include "core/hle/service/cfg/cfg_s.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CFG_S
+
+namespace CFG_S {
+
+/**
+ * CFG_S::GetConfigInfoBlk2 service function
+ * Inputs:
+ * 0 : 0x00010082
+ * 1 : Size
+ * 2 : Block ID
+ * 3 : Descriptor for the output buffer
+ * 4 : Output buffer pointer
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void GetConfigInfoBlk2(Service::Interface* self) {
+ u32* cmd_buffer = Kernel::GetCommandBuffer();
+ u32 size = cmd_buffer[1];
+ u32 block_id = cmd_buffer[2];
+ u8* data_pointer = Memory::GetPointer(cmd_buffer[4]);
+
+ if (data_pointer == nullptr) {
+ cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
+ return;
+ }
+
+ cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw;
+}
+
+/**
+ * CFG_S::GetConfigInfoBlk8 service function
+ * Inputs:
+ * 0 : 0x04010082
+ * 1 : Size
+ * 2 : Block ID
+ * 3 : Descriptor for the output buffer
+ * 4 : Output buffer pointer
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void GetConfigInfoBlk8(Service::Interface* self) {
+ u32* cmd_buffer = Kernel::GetCommandBuffer();
+ u32 size = cmd_buffer[1];
+ u32 block_id = cmd_buffer[2];
+ u8* data_pointer = Memory::GetPointer(cmd_buffer[4]);
+
+ if (data_pointer == nullptr) {
+ cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
+ return;
+ }
+
+ cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw;
+}
+
+/**
+ * CFG_S::UpdateConfigNANDSavegame service function
+ * Inputs:
+ * 0 : 0x04030000
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void UpdateConfigNANDSavegame(Service::Interface* self) {
+ u32* cmd_buffer = Kernel::GetCommandBuffer();
+ cmd_buffer[1] = Service::CFG::UpdateConfigNANDSavegame().raw;
+}
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
+ {0x00020000, nullptr, "SecureInfoGetRegion"},
+ {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
+ {0x04020082, nullptr, "SetConfigInfoBlk4"},
+ {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
+ {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
+ {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
+ {0x04060000, nullptr, "SecureInfoGetRegion"},
+ {0x04070000, nullptr, "SecureInfoGetByte101"},
+ {0x04080042, nullptr, "SecureInfoGetSerialNo"},
+ {0x04090000, nullptr, "UpdateConfigBlk00040003"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/cfg/cfg_s.h b/src/core/hle/service/cfg/cfg_s.h
new file mode 100644
index 00000000..d8b67137
--- /dev/null
+++ b/src/core/hle/service/cfg/cfg_s.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace CFG_S
+
+namespace CFG_S {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "cfg:s";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 83562090..1da9f59f 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -186,7 +186,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 3a557efe..39b00982 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index d4affdfb..0f86894a 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -13,8 +13,8 @@
namespace DSP_DSP {
static u32 read_pipe_count = 0;
-static Handle semaphore_event = 0;
-static Handle interrupt_event = 0;
+static Kernel::SharedPtr<Kernel::Event> semaphore_event;
+static Kernel::SharedPtr<Kernel::Event> interrupt_event;
void SignalInterrupt() {
// TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated
@@ -23,11 +23,8 @@ void SignalInterrupt() {
// that check the DSP interrupt signal event to run. We should figure out the different types of
// DSP interrupts, and trigger them at the appropriate times.
- if (interrupt_event == 0) {
- LOG_WARNING(Service_DSP, "cannot signal interrupt until DSP event has been created!");
- return;
- }
- Kernel::SignalEvent(interrupt_event);
+ if (interrupt_event != 0)
+ interrupt_event->Signal();
}
/**
@@ -81,8 +78,8 @@ void LoadComponent(Service::Interface* self) {
void GetSemaphoreEventHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = 0; // No error
- cmd_buff[3] = semaphore_event; // Event handle
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle
LOG_WARNING(Service_DSP, "(STUBBED) called");
}
@@ -99,9 +96,16 @@ void GetSemaphoreEventHandle(Service::Interface* self) {
void RegisterInterruptEvents(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- interrupt_event = static_cast<Handle>(cmd_buff[4]);
+ auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
+ if (evt != nullptr) {
+ interrupt_event = evt;
+ cmd_buff[1] = 0; // No error
+ } else {
+ LOG_ERROR(Service_DSP, "called with invalid handle=%08X", cmd_buff[4]);
- cmd_buff[1] = 0; // No error
+ // TODO(yuriks): An error should be returned from SendSyncRequest, not in the cmdbuf
+ cmd_buff[1] = -1;
+ }
LOG_WARNING(Service_DSP, "(STUBBED) called");
}
@@ -197,11 +201,11 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- semaphore_event = Kernel::CreateEvent(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
- interrupt_event = 0;
+ semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
+ interrupt_event = nullptr;
read_pipe_count = 0;
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 8c900eab..962de217 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/frd_a.cpp b/src/core/hle/service/frd_a.cpp
new file mode 100644
index 00000000..79140a75
--- /dev/null
+++ b/src/core/hle/service/frd_a.cpp
@@ -0,0 +1,24 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/frd_a.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace FRD_A
+
+namespace FRD_A {
+
+// Empty arrays are illegal -- commented out until an entry is added.
+// const Interface::FunctionInfo FunctionTable[] = { };
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/frd_a.h b/src/core/hle/service/frd_a.h
new file mode 100644
index 00000000..f068c610
--- /dev/null
+++ b/src/core/hle/service/frd_a.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace FRD_A
+
+namespace FRD_A {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "frd:a";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd_u.cpp
index 021186e5..59faca77 100644
--- a/src/core/hle/service/frd_u.cpp
+++ b/src/core/hle/service/frd_u.cpp
@@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 958dd934..ccf132f3 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -43,6 +43,11 @@ const std::string SDCARD_ID = "00000000000000000000000000000000";
namespace Service {
namespace FS {
+// TODO: Verify code
+/// Returned when a function is passed an invalid handle.
+const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS,
+ ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
+
// Command to access archive file
enum class FileCommand : u32 {
Dummy1 = 0x000100C6,
@@ -84,7 +89,7 @@ public:
class File : public Kernel::Session {
public:
File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
- : path(path), backend(std::move(backend)), priority(0) {
+ : path(path), priority(0), backend(std::move(backend)) {
}
std::string GetName() const override { return "Path: " + path.DebugStr(); }
@@ -158,7 +163,7 @@ public:
case FileCommand::OpenLinkFile:
{
LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
- cmd_buff[3] = GetHandle();
+ cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE);
break;
}
@@ -280,7 +285,7 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
ResultCode CloseArchive(ArchiveHandle handle) {
if (handle_map.erase(handle) == 0)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
else
return RESULT_SUCCESS;
}
@@ -298,10 +303,11 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc
return RESULT_SUCCESS;
}
-ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle,
+ const FileSys::Path& path, const FileSys::Mode mode) {
Archive* archive = GetArchive(archive_handle);
if (archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode);
if (backend == nullptr) {
@@ -309,16 +315,14 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy
ErrorSummary::NotFound, ErrorLevel::Status);
}
- auto file = Common::make_unique<File>(std::move(backend), path);
- // TOOD(yuriks): Fix error reporting
- Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE);
- return MakeResult<Handle>(handle);
+ auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path));
+ return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(file));
}
ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
Archive* archive = GetArchive(archive_handle);
if (archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
if (archive->backend->DeleteFile(path))
return RESULT_SUCCESS;
@@ -331,7 +335,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil
Archive* src_archive = GetArchive(src_archive_handle);
Archive* dest_archive = GetArchive(dest_archive_handle);
if (src_archive == nullptr || dest_archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
if (src_archive == dest_archive) {
if (src_archive->backend->RenameFile(src_path, dest_path))
@@ -350,7 +354,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil
ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
Archive* archive = GetArchive(archive_handle);
if (archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
if (archive->backend->DeleteDirectory(path))
return RESULT_SUCCESS;
@@ -361,7 +365,7 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) {
Archive* archive = GetArchive(archive_handle);
if (archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
return archive->backend->CreateFile(path, file_size);
}
@@ -369,7 +373,7 @@ ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path
ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
Archive* archive = GetArchive(archive_handle);
if (archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
if (archive->backend->CreateDirectory(path))
return RESULT_SUCCESS;
@@ -382,7 +386,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
Archive* src_archive = GetArchive(src_archive_handle);
Archive* dest_archive = GetArchive(dest_archive_handle);
if (src_archive == nullptr || dest_archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
if (src_archive == dest_archive) {
if (src_archive->backend->RenameDirectory(src_path, dest_path))
@@ -398,16 +402,11 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
ErrorSummary::NothingHappened, ErrorLevel::Status);
}
-/**
- * Open a Directory from an Archive
- * @param archive_handle Handle to an open Archive object
- * @param path Path to the Directory inside of the Archive
- * @return Opened Directory object
- */
-ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
+ const FileSys::Path& path) {
Archive* archive = GetArchive(archive_handle);
if (archive == nullptr)
- return InvalidHandle(ErrorModule::FS);
+ return ERR_INVALID_HANDLE;
std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path);
if (backend == nullptr) {
@@ -415,10 +414,8 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F
ErrorSummary::NotFound, ErrorLevel::Permanent);
}
- auto directory = Common::make_unique<Directory>(std::move(backend), path);
- // TOOD(yuriks): Fix error reporting
- Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
- return MakeResult<Handle>(handle);
+ auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
+ return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(directory));
}
ResultCode FormatSaveData() {
@@ -432,6 +429,28 @@ ResultCode FormatSaveData() {
return archive_itr->second->backend->Format(FileSys::Path());
}
+ResultCode CreateExtSaveData(u32 high, u32 low) {
+ // Construct the binary path to the archive first
+ std::vector<u8> binary_path;
+ binary_path.reserve(12);
+ // The first word is all zero to specify a NAND archive
+ for (unsigned i = 0; i < 4; ++i)
+ binary_path.push_back(0);
+ // Next is the low word
+ for (unsigned i = 0; i < 4; ++i)
+ binary_path.push_back((low >> (8 * i)) & 0xFF);
+ // Next is the high word
+ for (unsigned i = 0; i < 4; ++i)
+ binary_path.push_back((high >> i) & 0xFF);
+ FileSys::Path path(binary_path);
+ std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
+ std::string base_path = FileSys::GetExtDataContainerPath(nand_directory, true);
+ std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
+ if (!FileUtil::CreateFullPath(extsavedata_path))
+ return ResultCode(-1); // TODO(Subv): Find the right error code
+ return RESULT_SUCCESS;
+}
+
/// Initialize archives
void ArchiveInit() {
next_handle = 1;
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index b3f2134f..ab5ea4da 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -15,6 +15,10 @@ extern const std::string SYSTEM_ID;
/// The scrambled SD card CID, also known as ID1
extern const std::string SDCARD_ID;
+namespace Kernel {
+ class Session;
+}
+
namespace Service {
namespace FS {
@@ -42,7 +46,7 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
/**
* Closes an archive
- * @param id_code IdCode of the archive to open
+ * @param handle Handle to the archive to close
*/
ResultCode CloseArchive(ArchiveHandle handle);
@@ -58,9 +62,10 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc
* @param archive_handle Handle to an open Archive object
* @param path Path to the File inside of the Archive
* @param mode Mode under which to open the File
- * @return Handle to the opened File object
+ * @return The opened File object as a Session
*/
-ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode);
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle,
+ const FileSys::Path& path, const FileSys::Mode mode);
/**
* Delete a File from an Archive
@@ -121,9 +126,10 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
* Open a Directory from an Archive
* @param archive_handle Handle to an open Archive object
* @param path Path to the Directory inside of the Archive
- * @return Handle to the opened File object
+ * @return The opened Directory object as a Session
*/
-ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
+ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
+ const FileSys::Path& path);
/**
* Creates a blank SaveData archive.
@@ -131,6 +137,14 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F
*/
ResultCode FormatSaveData();
+/**
+ * Creates a blank SharedExtSaveData archive for the specified extdata ID
+ * @param high The high word of the extdata id to create
+ * @param low The low word of the extdata id to create
+ * @return ResultCode 0 on success or the corresponding code on error
+ */
+ResultCode CreateExtSaveData(u32 high, u32 low);
+
/// Initialize archives
void ArchiveInit();
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 56f3117f..94a3a31c 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -14,6 +14,9 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace FS_User
+using Kernel::SharedPtr;
+using Kernel::Session;
+
namespace Service {
namespace FS {
@@ -58,10 +61,10 @@ static void OpenFile(Service::Interface* self) {
LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
- ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode);
- cmd_buff[1] = handle.Code().raw;
- if (handle.Succeeded()) {
- cmd_buff[3] = *handle;
+ ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
+ cmd_buff[1] = file_res.Code().raw;
+ if (file_res.Succeeded()) {
+ cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
} else {
cmd_buff[3] = 0;
LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -114,10 +117,10 @@ static void OpenFileDirectly(Service::Interface* self) {
}
SCOPE_EXIT({ CloseArchive(*archive_handle); });
- ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode);
- cmd_buff[1] = handle.Code().raw;
- if (handle.Succeeded()) {
- cmd_buff[3] = *handle;
+ ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode);
+ cmd_buff[1] = file_res.Code().raw;
+ if (file_res.Succeeded()) {
+ cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
} else {
cmd_buff[3] = 0;
LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -334,10 +337,10 @@ static void OpenDirectory(Service::Interface* self) {
LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
- ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path);
- cmd_buff[1] = handle.Code().raw;
- if (handle.Succeeded()) {
- cmd_buff[3] = *handle;
+ ResultVal<SharedPtr<Session>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
+ cmd_buff[1] = dir_res.Code().raw;
+ if (dir_res.Succeeded()) {
+ cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom();
} else {
LOG_ERROR(Service_FS, "failed to get a handle for directory");
}
@@ -484,6 +487,15 @@ static void FormatThisUserSaveData(Service::Interface* self) {
cmd_buff[1] = FormatSaveData().raw;
}
+static void CreateExtSaveData(Service::Interface* self) {
+ // TODO(Subv): Figure out the other parameters.
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 save_high = cmd_buff[1];
+ u32 save_low = cmd_buff[2];
+ // TODO(Subv): For now it is assumed that only SharedExtSaveData can be created like this
+ cmd_buff[1] = CreateExtSaveData(save_high, save_low).raw;
+}
+
const FSUserInterface::FunctionInfo FunctionTable[] = {
{0x000100C6, nullptr, "Dummy1"},
{0x040100C4, nullptr, "Control"},
@@ -567,6 +579,8 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {
{0x084E0342, nullptr, "UpdateSha256Context"},
{0x084F0102, nullptr, "ReadSpecialFile"},
{0x08500040, nullptr, "GetSpecialFileSize"},
+ {0x08510242, CreateExtSaveData, "CreateExtSaveData"},
+ {0x08520100, nullptr, "DeleteExtSaveData"},
{0x08580000, nullptr, "GetMovableSedHashedKeyYRandomData"},
{0x08610042, nullptr, "InitializeWithSdkVersion"},
{0x08620040, nullptr, "SetPriority"},
@@ -577,7 +591,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {
// Interface class
FSUserInterface::FSUserInterface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace FS
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 2b115240..495c117e 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -22,13 +22,16 @@ GraphicsDebugger g_debugger;
namespace GSP_GPU {
-Handle g_interrupt_event = 0; ///< Handle to event triggered when GSP interrupt has been signalled
-Handle g_shared_memory = 0; ///< Handle to GSP shared memorys
-u32 g_thread_id = 1; ///< Thread index into interrupt relay queue, 1 is arbitrary
+/// Event triggered when GSP interrupt has been signalled
+Kernel::SharedPtr<Kernel::Event> g_interrupt_event;
+/// GSP shared memoryings
+Kernel::SharedPtr<Kernel::SharedMemory> g_shared_memory;
+/// Thread index into interrupt relay queue, 1 is arbitrary
+u32 g_thread_id = 1;
/// Gets a pointer to a thread command buffer in GSP shared memory
static inline u8* GetCommandBuffer(u32 thread_id) {
- ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * sizeof(CommandBuffer)));
+ ResultVal<u8*> ptr = g_shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer)));
return ptr.ValueOr(nullptr);
}
@@ -37,13 +40,13 @@ static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_in
// For each thread there are two FrameBufferUpdate fields
u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate);
- ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, offset);
+ ResultVal<u8*> ptr = g_shared_memory->GetPointer(offset);
return reinterpret_cast<FrameBufferUpdate*>(ptr.ValueOr(nullptr));
}
/// Gets a pointer to the interrupt relay queue for a given thread index
static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
- ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, sizeof(InterruptRelayQueue) * thread_id);
+ ResultVal<u8*> ptr = g_shared_memory->GetPointer(sizeof(InterruptRelayQueue) * thread_id);
return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr));
}
@@ -181,16 +184,18 @@ static void FlushDataCache(Service::Interface* self) {
static void RegisterInterruptRelayQueue(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 flags = cmd_buff[1];
- g_interrupt_event = cmd_buff[3];
- g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem");
- _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!");
+ g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]);
+ _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!");
+ g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem");
+
+ Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
cmd_buff[1] = 0x2A07; // Value verified by 3dmoo team, purpose unknown, but needed for GSP init
cmd_buff[2] = g_thread_id++; // Thread ID
- cmd_buff[4] = g_shared_memory; // GSP shared memory
+ cmd_buff[4] = shmem_handle; // GSP shared memory
- Kernel::SignalEvent(g_interrupt_event); // TODO(bunnei): Is this correct?
+ g_interrupt_event->Signal(); // TODO(bunnei): Is this correct?
}
/**
@@ -204,22 +209,35 @@ void SignalInterrupt(InterruptId interrupt_id) {
LOG_WARNING(Service_GSP, "cannot synchronize until GSP event has been created!");
return;
}
- if (0 == g_shared_memory) {
+ if (nullptr == g_shared_memory) {
LOG_WARNING(Service_GSP, "cannot synchronize until GSP shared memory has been created!");
return;
}
for (int thread_id = 0; thread_id < 0x4; ++thread_id) {
InterruptRelayQueue* interrupt_relay_queue = GetInterruptRelayQueue(thread_id);
- interrupt_relay_queue->number_interrupts = interrupt_relay_queue->number_interrupts + 1;
-
u8 next = interrupt_relay_queue->index;
next += interrupt_relay_queue->number_interrupts;
next = next % 0x34; // 0x34 is the number of interrupt slots
+ interrupt_relay_queue->number_interrupts += 1;
+
interrupt_relay_queue->slot[next] = interrupt_id;
interrupt_relay_queue->error_code = 0x0; // No error
+
+ // Update framebuffer information if requested
+ // TODO(yuriks): Confirm where this code should be called. It is definitely updated without
+ // executing any GSP commands, only waiting on the event.
+ for (int screen_id = 0; screen_id < 2; ++screen_id) {
+ FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id);
+
+ if (info->is_dirty) {
+ SetBufferSwap(screen_id, info->framebuffer_info[info->index]);
+ }
+
+ info->is_dirty = false;
+ }
}
- Kernel::SignalEvent(g_interrupt_event);
+ g_interrupt_event->Signal();
}
/// Executes the next GSP command
@@ -269,8 +287,6 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), Memory::VirtualToPhysicalAddress(params.end2) >> 3);
WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2);
WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2);
-
- SignalInterrupt(InterruptId::PSC0);
break;
}
@@ -283,22 +299,6 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size);
WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags);
WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1);
-
- // TODO(bunnei): Determine if these interrupts should be signalled here.
- SignalInterrupt(InterruptId::PSC1);
- SignalInterrupt(InterruptId::PPF);
-
- // Update framebuffer information if requested
- for (int screen_id = 0; screen_id < 2; ++screen_id) {
- FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id);
-
- if (info->is_dirty) {
- SetBufferSwap(screen_id, info->framebuffer_info[info->index]);
- info->framebuffer_info->active_fb = info->framebuffer_info->active_fb ^ 1;
- }
-
- info->is_dirty = false;
- }
break;
}
@@ -389,7 +389,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
g_interrupt_event = 0;
g_shared_memory = 0;
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 932b6170..65abb194 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -45,21 +45,16 @@ enum class CommandId : u32 {
/// GSP thread interrupt relay queue
struct InterruptRelayQueue {
- union {
- u32 hex;
-
- // Index of last interrupt in the queue
- BitField<0,8,u32> index;
-
- // Number of interrupts remaining to be processed by the userland code
- BitField<8,8,u32> number_interrupts;
-
- // Error code - zero on success, otherwise an error has occurred
- BitField<16,8,u32> error_code;
- };
-
- u32 unk0;
- u32 unk1;
+ // Index of last interrupt in the queue
+ u8 index;
+ // Number of interrupts remaining to be processed by the userland code
+ u8 number_interrupts;
+ // Error code - zero on success, otherwise an error has occurred
+ u8 error_code;
+ u8 padding1;
+
+ u32 missed_PDC0;
+ u32 missed_PDC1;
InterruptId slot[0x34]; ///< Interrupt ID slots
};
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp
new file mode 100644
index 00000000..d63fa1ee
--- /dev/null
+++ b/src/core/hle/service/gsp_lcd.cpp
@@ -0,0 +1,26 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+
+#include "common/log.h"
+#include "common/bit_field.h"
+
+#include "core/hle/service/gsp_lcd.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace GSP_LCD
+
+namespace GSP_LCD {
+
+/*const Interface::FunctionInfo FunctionTable[] = {
+};*/
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ //Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/gsp_lcd.h b/src/core/hle/service/gsp_lcd.h
new file mode 100644
index 00000000..56b3cfe8
--- /dev/null
+++ b/src/core/hle/service/gsp_lcd.h
@@ -0,0 +1,24 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace GSP_LCD
+
+namespace GSP_LCD {
+
+/// Interface to "gsp::Lcd" service
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "gsp::Lcd";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
new file mode 100644
index 00000000..7cb01729
--- /dev/null
+++ b/src/core/hle/service/hid/hid.cpp
@@ -0,0 +1,142 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/hid/hid.h"
+
+#include "core/arm/arm_interface.h"
+#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/shared_memory.h"
+#include "core/hle/hle.h"
+
+namespace Service {
+namespace HID {
+
+Kernel::SharedPtr<Kernel::SharedMemory> g_shared_mem = nullptr;
+
+Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_1;
+Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_2;
+Kernel::SharedPtr<Kernel::Event> g_event_accelerometer;
+Kernel::SharedPtr<Kernel::Event> g_event_gyroscope;
+Kernel::SharedPtr<Kernel::Event> g_event_debug_pad;
+
+// Next Pad state update information
+static PadState next_state = {{0}};
+static u32 next_index = 0;
+static s16 next_circle_x = 0;
+static s16 next_circle_y = 0;
+
+/**
+ * Gets a pointer to the PadData structure inside HID shared memory
+ */
+static inline PadData* GetPadData() {
+ if (g_shared_mem == nullptr)
+ return nullptr;
+ return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr));
+}
+
+/**
+ * Circle Pad from keys.
+ *
+ * This is implemented as "pushed all the way to an edge (max) or centered (0)".
+ *
+ * Indicate the circle pad is pushed completely to the edge in 1 of 8 directions.
+ */
+static void UpdateNextCirclePadState() {
+ static const s16 max_value = 0x9C;
+ next_circle_x = next_state.circle_left ? -max_value : 0x0;
+ next_circle_x += next_state.circle_right ? max_value : 0x0;
+ next_circle_y = next_state.circle_down ? -max_value : 0x0;
+ next_circle_y += next_state.circle_up ? max_value : 0x0;
+}
+
+/**
+ * Sets a Pad state (button or button combo) as pressed
+ */
+void PadButtonPress(const PadState& pad_state) {
+ next_state.hex |= pad_state.hex;
+ UpdateNextCirclePadState();
+}
+
+/**
+ * Sets a Pad state (button or button combo) as released
+ */
+void PadButtonRelease(const PadState& pad_state) {
+ next_state.hex &= ~pad_state.hex;
+ UpdateNextCirclePadState();
+}
+
+/**
+ * Called after all Pad changes to be included in this update have been made,
+ * including both Pad key changes and analog circle Pad changes.
+ */
+void PadUpdateComplete() {
+ PadData* pad_data = GetPadData();
+
+ if (pad_data == nullptr) {
+ return;
+ }
+
+ // Update PadData struct
+ pad_data->current_state.hex = next_state.hex;
+ pad_data->index = next_index;
+ next_index = (next_index + 1) % pad_data->entries.size();
+
+ // Get the previous Pad state
+ u32 last_entry_index = (pad_data->index - 1) % pad_data->entries.size();
+ PadState old_state = pad_data->entries[last_entry_index].current_state;
+
+ // Compute bitmask with 1s for bits different from the old state
+ PadState changed;
+ changed.hex = (next_state.hex ^ old_state.hex);
+
+ // Compute what was added
+ PadState additions;
+ additions.hex = changed.hex & next_state.hex;
+
+ // Compute what was removed
+ PadState removals;
+ removals.hex = changed.hex & old_state.hex;
+
+ // Get the current Pad entry
+ PadDataEntry* current_pad_entry = &pad_data->entries[pad_data->index];
+
+ // Update entry properties
+ current_pad_entry->current_state.hex = next_state.hex;
+ current_pad_entry->delta_additions.hex = additions.hex;
+ current_pad_entry->delta_removals.hex = removals.hex;
+
+ // Set circle Pad
+ current_pad_entry->circle_pad_x = next_circle_x;
+ current_pad_entry->circle_pad_y = next_circle_y;
+
+ // If we just updated index 0, provide a new timestamp
+ if (pad_data->index == 0) {
+ pad_data->index_reset_ticks_previous = pad_data->index_reset_ticks;
+ pad_data->index_reset_ticks = (s64)Core::g_app_core->GetTicks();
+ }
+
+ // Signal both handles when there's an update to Pad or touch
+ g_event_pad_or_touch_1->Signal();
+ g_event_pad_or_touch_2->Signal();
+}
+
+void HIDInit() {
+ using namespace Kernel;
+
+ g_shared_mem = SharedMemory::Create("HID:SharedMem");
+
+ // Create event handles
+ g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1");
+ g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2");
+ g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer");
+ g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope");
+ g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad");
+}
+
+void HIDShutdown() {
+
+}
+
+}
+}
diff --git a/src/core/hle/service/hid_user.h b/src/core/hle/service/hid/hid.h
index 5b96dda6..2116d2ca 100644
--- a/src/core/hle/service/hid_user.h
+++ b/src/core/hle/service/hid/hid.h
@@ -1,19 +1,31 @@
-// Copyright 2014 Citra Emulator Project
+// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
-#include "core/hle/service/service.h"
+#include <array>
+
+#include "core/hle/kernel/kernel.h"
#include "common/bit_field.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace HID_User
+namespace Kernel {
+ class SharedMemory;
+ class Event;
+}
+
+namespace Service {
+namespace HID {
-// This service is used for interfacing to physical user controls.
-// Uses include game pad controls, touchscreen, accelerometers, gyroscopes, and debug pad.
+// Handle to shared memory region designated to HID_User service
+extern Kernel::SharedPtr<Kernel::SharedMemory> g_shared_mem;
-namespace HID_User {
+// Event handles
+extern Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_1;
+extern Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_2;
+extern Kernel::SharedPtr<Kernel::Event> g_event_accelerometer;
+extern Kernel::SharedPtr<Kernel::Event> g_event_gyroscope;
+extern Kernel::SharedPtr<Kernel::Event> g_event_debug_pad;
/**
* Structure of a Pad controller state.
@@ -97,16 +109,8 @@ void PadButtonPress(const PadState& pad_state);
void PadButtonRelease(const PadState& pad_state);
void PadUpdateComplete();
-/**
- * HID service interface.
- */
-class Interface : public Service::Interface {
-public:
- Interface();
-
- std::string GetPortName() const override {
- return "hid:USER";
- }
-};
+void HIDInit();
+void HIDShutdown();
-} // namespace
+}
+}
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
new file mode 100644
index 00000000..054aa8b5
--- /dev/null
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -0,0 +1,38 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/hid/hid_spvr.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace HID_SPVR
+
+namespace HID_User {
+ extern void GetIPCHandles(Service::Interface* self);
+}
+
+namespace HID_SPVR {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000A0000, HID_User::GetIPCHandles, "GetIPCHandles"},
+ {0x000B0000, nullptr, "StartAnalogStickCalibration"},
+ {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
+ {0x00110000, nullptr, "EnableAccelerometer"},
+ {0x00120000, nullptr, "DisableAccelerometer"},
+ {0x00130000, nullptr, "EnableGyroscopeLow"},
+ {0x00140000, nullptr, "DisableGyroscopeLow"},
+ {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"},
+ {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"},
+ {0x00170000, nullptr, "GetSoundVolume"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/hid/hid_spvr.h b/src/core/hle/service/hid/hid_spvr.h
new file mode 100644
index 00000000..53ddc856
--- /dev/null
+++ b/src/core/hle/service/hid/hid_spvr.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace HID_SPVR
+
+namespace HID_SPVR {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "hid:SPVR";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
new file mode 100644
index 00000000..68edafeb
--- /dev/null
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -0,0 +1,78 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+
+#include "core/hle/hle.h"
+#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/shared_memory.h"
+#include "core/hle/service/hid/hid.h"
+#include "hid_user.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace HID_User
+
+namespace HID_User {
+
+
+// TODO(peachum):
+// Add a method for setting analog input from joystick device for the circle Pad.
+//
+// This method should:
+// * Be called after both PadButton<Press, Release>().
+// * Be called before PadUpdateComplete()
+// * Set current PadEntry.circle_pad_<axis> using analog data
+// * Set PadData.raw_circle_pad_data
+// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_x >= 41
+// * Set PadData.current_state.circle_up = 1 if current PadEntry.circle_pad_y >= 41
+// * Set PadData.current_state.circle_left = 1 if current PadEntry.circle_pad_x <= -41
+// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41
+
+
+/**
+ * HID_User::GetIPCHandles service function
+ * Inputs:
+ * None
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Unused
+ * 3 : Handle to HID_User shared memory
+ * 4 : Event signaled by HID_User
+ * 5 : Event signaled by HID_User
+ * 6 : Event signaled by HID_User
+ * 7 : Gyroscope event
+ * 8 : Event signaled by HID_User
+ */
+void GetIPCHandles(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = 0; // No error
+ // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
+ cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::g_shared_mem).MoveFrom();
+ cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_1).MoveFrom();
+ cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_2).MoveFrom();
+ cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::g_event_accelerometer).MoveFrom();
+ cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::g_event_gyroscope).MoveFrom();
+ cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::g_event_debug_pad).MoveFrom();
+}
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000A0000, GetIPCHandles, "GetIPCHandles"},
+ {0x00110000, nullptr, "EnableAccelerometer"},
+ {0x00120000, nullptr, "DisableAccelerometer"},
+ {0x00130000, nullptr, "EnableGyroscopeLow"},
+ {0x00140000, nullptr, "DisableGyroscopeLow"},
+ {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"},
+ {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"},
+ {0x00170000, nullptr, "GetSoundVolume"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/hid/hid_user.h b/src/core/hle/service/hid/hid_user.h
new file mode 100644
index 00000000..1d9929e6
--- /dev/null
+++ b/src/core/hle/service/hid/hid_user.h
@@ -0,0 +1,29 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace HID_User
+
+// This service is used for interfacing to physical user controls.
+// Uses include game pad controls, touchscreen, accelerometers, gyroscopes, and debug pad.
+
+namespace HID_User {
+
+/**
+ * HID service interface.
+ */
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "hid:USER";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp
deleted file mode 100644
index 1403b1de..00000000
--- a/src/core/hle/service/hid_user.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "common/log.h"
-
-#include "core/arm/arm_interface.h"
-#include "core/hle/hle.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "hid_user.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Namespace HID_User
-
-namespace HID_User {
-
-// Handle to shared memory region designated to HID_User service
-static Handle shared_mem = 0;
-
-// Event handles
-static Handle event_pad_or_touch_1 = 0;
-static Handle event_pad_or_touch_2 = 0;
-static Handle event_accelerometer = 0;
-static Handle event_gyroscope = 0;
-static Handle event_debug_pad = 0;
-
-// Next Pad state update information
-static PadState next_state = {{0}};
-static u32 next_index = 0;
-static s16 next_circle_x = 0;
-static s16 next_circle_y = 0;
-
-/**
- * Gets a pointer to the PadData structure inside HID shared memory
- */
-static inline PadData* GetPadData() {
- return reinterpret_cast<PadData*>(Kernel::GetSharedMemoryPointer(shared_mem, 0).ValueOr(nullptr));
-}
-
-/**
- * Circle Pad from keys.
- *
- * This is implemented as "pushed all the way to an edge (max) or centered (0)".
- *
- * Indicate the circle pad is pushed completely to the edge in 1 of 8 directions.
- */
-static void UpdateNextCirclePadState() {
- static const s16 max_value = 0x9C;
- next_circle_x = next_state.circle_left ? -max_value : 0x0;
- next_circle_x += next_state.circle_right ? max_value : 0x0;
- next_circle_y = next_state.circle_down ? -max_value : 0x0;
- next_circle_y += next_state.circle_up ? max_value : 0x0;
-}
-
-/**
- * Sets a Pad state (button or button combo) as pressed
- */
-void PadButtonPress(const PadState& pad_state) {
- next_state.hex |= pad_state.hex;
- UpdateNextCirclePadState();
-}
-
-/**
- * Sets a Pad state (button or button combo) as released
- */
-void PadButtonRelease(const PadState& pad_state) {
- next_state.hex &= ~pad_state.hex;
- UpdateNextCirclePadState();
-}
-
-/**
- * Called after all Pad changes to be included in this update have been made,
- * including both Pad key changes and analog circle Pad changes.
- */
-void PadUpdateComplete() {
- PadData* pad_data = GetPadData();
-
- if (pad_data == nullptr) {
- return;
- }
-
- // Update PadData struct
- pad_data->current_state.hex = next_state.hex;
- pad_data->index = next_index;
- next_index = (next_index + 1) % pad_data->entries.size();
-
- // Get the previous Pad state
- u32 last_entry_index = (pad_data->index - 1) % pad_data->entries.size();
- PadState old_state = pad_data->entries[last_entry_index].current_state;
-
- // Compute bitmask with 1s for bits different from the old state
- PadState changed;
- changed.hex = (next_state.hex ^ old_state.hex);
-
- // Compute what was added
- PadState additions;
- additions.hex = changed.hex & next_state.hex;
-
- // Compute what was removed
- PadState removals;
- removals.hex = changed.hex & old_state.hex;
-
- // Get the current Pad entry
- PadDataEntry* current_pad_entry = &pad_data->entries[pad_data->index];
-
- // Update entry properties
- current_pad_entry->current_state.hex = next_state.hex;
- current_pad_entry->delta_additions.hex = additions.hex;
- current_pad_entry->delta_removals.hex = removals.hex;
-
- // Set circle Pad
- current_pad_entry->circle_pad_x = next_circle_x;
- current_pad_entry->circle_pad_y = next_circle_y;
-
- // If we just updated index 0, provide a new timestamp
- if (pad_data->index == 0) {
- pad_data->index_reset_ticks_previous = pad_data->index_reset_ticks;
- pad_data->index_reset_ticks = (s64)Core::g_app_core->GetTicks();
- }
-
- // Signal both handles when there's an update to Pad or touch
- Kernel::SignalEvent(event_pad_or_touch_1);
- Kernel::SignalEvent(event_pad_or_touch_2);
-}
-
-
-// TODO(peachum):
-// Add a method for setting analog input from joystick device for the circle Pad.
-//
-// This method should:
-// * Be called after both PadButton<Press, Release>().
-// * Be called before PadUpdateComplete()
-// * Set current PadEntry.circle_pad_<axis> using analog data
-// * Set PadData.raw_circle_pad_data
-// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_x >= 41
-// * Set PadData.current_state.circle_up = 1 if current PadEntry.circle_pad_y >= 41
-// * Set PadData.current_state.circle_left = 1 if current PadEntry.circle_pad_x <= -41
-// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41
-
-
-/**
- * HID_User::GetIPCHandles service function
- * Inputs:
- * None
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Unused
- * 3 : Handle to HID_User shared memory
- * 4 : Event signaled by HID_User
- * 5 : Event signaled by HID_User
- * 6 : Event signaled by HID_User
- * 7 : Gyroscope event
- * 8 : Event signaled by HID_User
- */
-static void GetIPCHandles(Service::Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
-
- cmd_buff[1] = 0; // No error
- cmd_buff[3] = shared_mem;
- cmd_buff[4] = event_pad_or_touch_1;
- cmd_buff[5] = event_pad_or_touch_2;
- cmd_buff[6] = event_accelerometer;
- cmd_buff[7] = event_gyroscope;
- cmd_buff[8] = event_debug_pad;
-}
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x000A0000, GetIPCHandles, "GetIPCHandles"},
- {0x000B0000, nullptr, "StartAnalogStickCalibration"},
- {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
- {0x00110000, nullptr, "EnableAccelerometer"},
- {0x00120000, nullptr, "DisableAccelerometer"},
- {0x00130000, nullptr, "EnableGyroscopeLow"},
- {0x00140000, nullptr, "DisableGyroscopeLow"},
- {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"},
- {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"},
- {0x00170000, nullptr, "GetSoundVolume"},
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interface class
-
-Interface::Interface() {
- shared_mem = Kernel::CreateSharedMemory("HID_User:SharedMem"); // Create shared memory object
-
- // Create event handles
- event_pad_or_touch_1 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID_User:EventPadOrTouch1");
- event_pad_or_touch_2 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID_User:EventPadOrTouch2");
- event_accelerometer = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID_User:EventAccelerometer");
- event_gyroscope = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID_User:EventGyroscope");
- event_debug_pad = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID_User:EventDebugPad");
-
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
-}
-
-} // namespace
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp
index d0bff552..6595ca57 100644
--- a/src/core/hle/service/http_c.cpp
+++ b/src/core/hle/service/http_c.cpp
@@ -58,7 +58,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/ir_rst.cpp b/src/core/hle/service/ir_rst.cpp
index d49bd533..31da8e16 100644
--- a/src/core/hle/service/ir_rst.cpp
+++ b/src/core/hle/service/ir_rst.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/ir_u.cpp b/src/core/hle/service/ir_u.cpp
index da6f38e4..7fa23304 100644
--- a/src/core/hle/service/ir_u.cpp
+++ b/src/core/hle/service/ir_u.cpp
@@ -36,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp
index 7d6e2e8e..459717ff 100644
--- a/src/core/hle/service/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 82bce918..af967b5b 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -34,7 +34,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm_u.cpp
index 0f03de6a..df3c9719 100644
--- a/src/core/hle/service/ndm_u.cpp
+++ b/src/core/hle/service/ndm_u.cpp
@@ -24,7 +24,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/news_s.cpp b/src/core/hle/service/news_s.cpp
new file mode 100644
index 00000000..d7537875
--- /dev/null
+++ b/src/core/hle/service/news_s.cpp
@@ -0,0 +1,25 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/news_s.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace NEWS_S
+
+namespace NEWS_S {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000100C6, nullptr, "AddNotification"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/news_s.h b/src/core/hle/service/news_s.h
new file mode 100644
index 00000000..f8b4636d
--- /dev/null
+++ b/src/core/hle/service/news_s.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace NEWS_S
+
+namespace NEWS_S {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "news:s";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/news_u.cpp b/src/core/hle/service/news_u.cpp
index b5adad4c..a9e161c2 100644
--- a/src/core/hle/service/news_u.cpp
+++ b/src/core/hle/service/news_u.cpp
@@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/nim_aoc.cpp b/src/core/hle/service/nim_aoc.cpp
index 17d1c4ff..ab2ef442 100644
--- a/src/core/hle/service/nim_aoc.cpp
+++ b/src/core/hle/service/nim_aoc.cpp
@@ -25,7 +25,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp
new file mode 100644
index 00000000..5cf3e203
--- /dev/null
+++ b/src/core/hle/service/ns_s.cpp
@@ -0,0 +1,27 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+
+#include "common/common.h"
+
+#include "core/hle/hle.h"
+#include "core/hle/service/ns_s.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace NS_S
+
+namespace NS_S {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x000200C0, nullptr, "LaunchTitle"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/ns_s.h b/src/core/hle/service/ns_s.h
new file mode 100644
index 00000000..8d8e849b
--- /dev/null
+++ b/src/core/hle/service/ns_s.h
@@ -0,0 +1,24 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace NS_S
+
+namespace NS_S {
+
+/// Interface to "NS:S" service
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "ns:s";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index ce456a96..61fcb54c 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
index 529dccaf..d61eaf80 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/ptm_play.cpp b/src/core/hle/service/ptm_play.cpp
new file mode 100644
index 00000000..b357057f
--- /dev/null
+++ b/src/core/hle/service/ptm_play.cpp
@@ -0,0 +1,28 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/ptm_play.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace PTM_PLAY
+
+namespace PTM_PLAY {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ { 0x08070082, nullptr, "GetPlayHistory" },
+ { 0x08080000, nullptr, "GetPlayHistoryStart" },
+ { 0x08090000, nullptr, "GetPlayHistoryLength" },
+ { 0x080B0080, nullptr, "CalcPlayHistoryStart" },
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/ptm_play.h b/src/core/hle/service/ptm_play.h
new file mode 100644
index 00000000..2f4f0d6f
--- /dev/null
+++ b/src/core/hle/service/ptm_play.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace PTM_PLAY
+
+namespace PTM_PLAY {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+std::string GetPortName() const override {
+ return "ptm:play";
+}
+};
+
+} // namespace
diff --git a/src/core/hle/service/ptm_sysm.cpp b/src/core/hle/service/ptm_sysm.cpp
new file mode 100644
index 00000000..b6f688de
--- /dev/null
+++ b/src/core/hle/service/ptm_sysm.cpp
@@ -0,0 +1,56 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/log.h"
+#include "common/make_unique.h"
+#include "core/file_sys/archive_extsavedata.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/ptm_sysm.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace PTM_SYSM
+
+namespace PTM_SYSM {
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x040100C0, nullptr, "SetRtcAlarmEx"},
+ {0x04020042, nullptr, "ReplySleepQuery"},
+ {0x04030042, nullptr, "NotifySleepPreparationComplete"},
+ {0x04040102, nullptr, "SetWakeupTrigger"},
+ {0x04050000, nullptr, "GetAwakeReason"},
+ {0x04060000, nullptr, "RequestSleep"},
+ {0x040700C0, nullptr, "ShutdownAsync"},
+ {0x04080000, nullptr, "Awake"},
+ {0x04090080, nullptr, "RebootAsync"},
+ {0x040A0000, nullptr, "CheckNew3DS"},
+ {0x08010640, nullptr, "SetInfoLEDPattern"},
+ {0x08020040, nullptr, "SetInfoLEDPatternHeader"},
+ {0x08030000, nullptr, "GetInfoLEDStatus"},
+ {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"},
+ {0x08050000, nullptr, "ClearStepHistory"},
+ {0x080600C2, nullptr, "SetStepHistory"},
+ {0x08070082, nullptr, "GetPlayHistory"},
+ {0x08080000, nullptr, "GetPlayHistoryStart"},
+ {0x08090000, nullptr, "GetPlayHistoryLength"},
+ {0x080A0000, nullptr, "ClearPlayHistory"},
+ {0x080B0080, nullptr, "CalcPlayHistoryStart"},
+ {0x080C0080, nullptr, "SetUserTime"},
+ {0x080D0000, nullptr, "InvalidateSystemTime"},
+ {0x080E0140, nullptr, "NotifyPlayEvent"},
+ {0x080F0000, nullptr, "IsLegacyPowerOff"},
+ {0x08100000, nullptr, "ClearLegacyPowerOff"},
+ {0x08110000, nullptr, "GetShellStatus"},
+ {0x08120000, nullptr, "IsShutdownByBatteryEmpty"},
+ {0x08130000, nullptr, "FormatSavedata"},
+ {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/ptm_sysm.h b/src/core/hle/service/ptm_sysm.h
new file mode 100644
index 00000000..0f267b21
--- /dev/null
+++ b/src/core/hle/service/ptm_sysm.h
@@ -0,0 +1,23 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace PTM_SYSM
+
+namespace PTM_SYSM {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "ptm:sysm";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
index 753180ad..7b465a34 100644
--- a/src/core/hle/service/ptm_u.cpp
+++ b/src/core/hle/service/ptm_u.cpp
@@ -137,7 +137,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
// Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file
// TODO(Subv): In the future we should use the FS service to query this archive
std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 33c29a4a..e0979ea5 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -10,30 +10,43 @@
#include "core/hle/service/act_u.h"
#include "core/hle/service/am_app.h"
#include "core/hle/service/am_net.h"
+#include "core/hle/service/am_sys.h"
#include "core/hle/service/apt_a.h"
+#include "core/hle/service/apt_s.h"
#include "core/hle/service/apt_u.h"
+#include "core/hle/service/boss_p.h"
#include "core/hle/service/boss_u.h"
+#include "core/hle/service/cam_u.h"
#include "core/hle/service/cecd_u.h"
+#include "core/hle/service/cecd_s.h"
#include "core/hle/service/cfg/cfg_i.h"
+#include "core/hle/service/cfg/cfg_s.h"
#include "core/hle/service/cfg/cfg_u.h"
#include "core/hle/service/csnd_snd.h"
#include "core/hle/service/dsp_dsp.h"
#include "core/hle/service/err_f.h"
#include "core/hle/service/fs/fs_user.h"
+#include "core/hle/service/frd_a.h"
#include "core/hle/service/frd_u.h"
#include "core/hle/service/gsp_gpu.h"
-#include "core/hle/service/hid_user.h"
+#include "core/hle/service/hid/hid_spvr.h"
+#include "core/hle/service/hid/hid_user.h"
+#include "core/hle/service/gsp_lcd.h"
#include "core/hle/service/http_c.h"
#include "core/hle/service/ir_rst.h"
#include "core/hle/service/ir_u.h"
#include "core/hle/service/ldr_ro.h"
#include "core/hle/service/mic_u.h"
#include "core/hle/service/ndm_u.h"
+#include "core/hle/service/news_s.h"
#include "core/hle/service/news_u.h"
#include "core/hle/service/nim_aoc.h"
+#include "core/hle/service/ns_s.h"
#include "core/hle/service/nwm_uds.h"
#include "core/hle/service/pm_app.h"
+#include "core/hle/service/ptm_play.h"
#include "core/hle/service/ptm_u.h"
+#include "core/hle/service/ptm_sysm.h"
#include "core/hle/service/soc_u.h"
#include "core/hle/service/srv.h"
#include "core/hle/service/ssl_c.h"
@@ -41,83 +54,76 @@
namespace Service {
-Manager* g_manager = nullptr; ///< Service manager
+std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
+std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
////////////////////////////////////////////////////////////////////////////////////////////////////
-// Service Manager class
-
-void Manager::AddService(Interface* service) {
- // TOOD(yuriks): Fix error reporting
- m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE);
- m_services.push_back(service);
-}
-
-void Manager::DeleteService(const std::string& port_name) {
- 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);
-}
+// Module interface
-Interface* Manager::FetchFromHandle(Handle handle) {
- // TODO(yuriks): This function is very suspicious and should probably be exterminated.
- return Kernel::g_handle_table.Get<Interface>(handle).get();
+static void AddNamedPort(Interface* interface) {
+ g_kernel_named_ports.emplace(interface->GetPortName(), interface);
}
-Interface* Manager::FetchFromPortName(const std::string& port_name) {
- auto itr = m_port_map.find(port_name);
- if (itr == m_port_map.end()) {
- return nullptr;
- }
- return FetchFromHandle(itr->second);
+static void AddService(Interface* interface) {
+ g_srv_services.emplace(interface->GetPortName(), interface);
}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Module interface
-
/// Initialize ServiceManager
void Init() {
- g_manager = new Manager;
-
- g_manager->AddService(new SRV::Interface);
- g_manager->AddService(new AC_U::Interface);
- g_manager->AddService(new ACT_U::Interface);
- g_manager->AddService(new AM_APP::Interface);
- g_manager->AddService(new AM_NET::Interface);
- g_manager->AddService(new APT_A::Interface);
- g_manager->AddService(new APT_U::Interface);
- g_manager->AddService(new BOSS_U::Interface);
- g_manager->AddService(new CECD_U::Interface);
- g_manager->AddService(new CFG_I::Interface);
- g_manager->AddService(new CFG_U::Interface);
- g_manager->AddService(new CSND_SND::Interface);
- g_manager->AddService(new DSP_DSP::Interface);
- g_manager->AddService(new ERR_F::Interface);
- g_manager->AddService(new FRD_U::Interface);
- g_manager->AddService(new FS::FSUserInterface);
- g_manager->AddService(new GSP_GPU::Interface);
- g_manager->AddService(new HID_User::Interface);
- g_manager->AddService(new HTTP_C::Interface);
- g_manager->AddService(new IR_RST::Interface);
- g_manager->AddService(new IR_U::Interface);
- g_manager->AddService(new LDR_RO::Interface);
- g_manager->AddService(new MIC_U::Interface);
- g_manager->AddService(new NDM_U::Interface);
- g_manager->AddService(new NEWS_U::Interface);
- g_manager->AddService(new NIM_AOC::Interface);
- g_manager->AddService(new NWM_UDS::Interface);
- g_manager->AddService(new PM_APP::Interface);
- g_manager->AddService(new PTM_U::Interface);
- g_manager->AddService(new SOC_U::Interface);
- g_manager->AddService(new SSL_C::Interface);
- g_manager->AddService(new Y2R_U::Interface);
+ AddNamedPort(new SRV::Interface);
+
+ AddService(new AC_U::Interface);
+ AddService(new ACT_U::Interface);
+ AddService(new AM_APP::Interface);
+ AddService(new AM_NET::Interface);
+ AddService(new AM_SYS::Interface);
+ AddService(new APT_A::Interface);
+ AddService(new APT_S::Interface);
+ AddService(new APT_U::Interface);
+ AddService(new BOSS_P::Interface);
+ AddService(new BOSS_U::Interface);
+ AddService(new CAM_U::Interface);
+ AddService(new CECD_S::Interface);
+ AddService(new CECD_U::Interface);
+ AddService(new CFG_I::Interface);
+ AddService(new CFG_S::Interface);
+ AddService(new CFG_U::Interface);
+ AddService(new CSND_SND::Interface);
+ AddService(new DSP_DSP::Interface);
+ AddService(new ERR_F::Interface);
+ AddService(new FRD_A::Interface);
+ AddService(new FRD_U::Interface);
+ AddService(new FS::FSUserInterface);
+ AddService(new GSP_GPU::Interface);
+ AddService(new GSP_LCD::Interface);
+ AddService(new HID_User::Interface);
+ AddService(new HID_SPVR::Interface);
+ AddService(new HTTP_C::Interface);
+ AddService(new IR_RST::Interface);
+ AddService(new IR_U::Interface);
+ AddService(new LDR_RO::Interface);
+ AddService(new MIC_U::Interface);
+ AddService(new NDM_U::Interface);
+ AddService(new NEWS_S::Interface);
+ AddService(new NEWS_U::Interface);
+ AddService(new NIM_AOC::Interface);
+ AddService(new NS_S::Interface);
+ AddService(new NWM_UDS::Interface);
+ AddService(new PM_APP::Interface);
+ AddService(new PTM_PLAY::Interface);
+ AddService(new PTM_U::Interface);
+ AddService(new PTM_SYSM::Interface);
+ AddService(new SOC_U::Interface);
+ AddService(new SSL_C::Interface);
+ AddService(new Y2R_U::Interface);
LOG_DEBUG(Service, "initialized OK");
}
/// Shutdown ServiceManager
void Shutdown() {
- delete g_manager;
+ g_srv_services.clear();
+ g_kernel_named_ports.clear();
LOG_DEBUG(Service, "shutdown OK");
}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index e75d5008..3370f9f9 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -5,9 +5,11 @@
#pragma once
#include <algorithm>
-#include <vector>
-#include <map>
#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <boost/container/flat_map.hpp>
#include "common/common.h"
#include "common/string_util.h"
@@ -27,7 +29,7 @@ static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 character
class Manager;
/// Interface to a CTROS service
-class Interface : public Kernel::Session {
+class Interface : public Kernel::Session {
// TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
// just something that encapsulates a session and acts as a helper to implement service
// processes.
@@ -38,11 +40,11 @@ class Interface : public Kernel::Session {
* Creates a function string for logging, complete with the name (or header code, depending
* on what's passed in) the port name, and all the cmd_buff arguments.
*/
- std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) {
+ std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) {
// Number of params == bits 0-5 + bits 6-11
int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
- std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str());
+ std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name);
for (int i = 1; i <= num_params; ++i) {
function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
}
@@ -57,7 +59,7 @@ public:
struct FunctionInfo {
u32 id;
Function func;
- std::string name;
+ const char* name;
};
/**
@@ -68,34 +70,19 @@ public:
return "[UNKNOWN SERVICE PORT]";
}
- /// Allocates a new handle for the service
- Handle CreateHandle(Kernel::Object *obj) {
- // TODO(yuriks): Fix error reporting
- Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE);
- m_handles.push_back(handle);
- return handle;
- }
-
- /// Frees a handle from the service
- template <class T>
- void DeleteHandle(const Handle handle) {
- Kernel::g_handle_table.Close(handle);
- m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
- }
-
ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Kernel::GetCommandBuffer();
auto itr = m_functions.find(cmd_buff[0]);
if (itr == m_functions.end() || itr->second.func == nullptr) {
std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
- LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str());
+ LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
// TODO(bunnei): Hack - ignore error
cmd_buff[1] = 0;
return MakeResult<bool>(false);
} else {
- LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str());
+ LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
}
itr->second.func(this);
@@ -108,37 +95,18 @@ protected:
/**
* Registers the functions in the service
*/
- void Register(const FunctionInfo* functions, int len) {
- for (int i = 0; i < len; i++) {
- m_functions[functions[i].id] = functions[i];
+ template <size_t N>
+ void Register(const FunctionInfo (&functions)[N]) {
+ m_functions.reserve(N);
+ for (auto& fn : functions) {
+ // Usually this array is sorted by id already, so hint to instead at the end
+ m_functions.emplace_hint(m_functions.cend(), fn.id, fn);
}
}
private:
+ boost::container::flat_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
-class Manager {
-public:
- /// Add a service to the manager
- void AddService(Interface* service);
-
- /// Removes a service from the manager
- void DeleteService(const std::string& port_name);
-
- /// Get a Service Interface from its Handle
- Interface* FetchFromHandle(Handle handle);
-
- /// Get a Service Interface from its port
- Interface* FetchFromPortName(const std::string& port_name);
-
-private:
- std::vector<Interface*> m_services;
- std::map<std::string, u32> m_port_map;
};
/// Initialize ServiceManager
@@ -147,8 +115,9 @@ void Init();
/// Shutdown ServiceManager
void Shutdown();
-
-extern Manager* g_manager; ///< Service manager
-
+/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
+extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
+/// Map of services registered with the "srv:" service, retrieved using GetServiceHandle.
+extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
} // namespace
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index f502c6af..414c53c5 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -7,6 +7,19 @@
#if EMU_PLATFORM == PLATFORM_WINDOWS
#include <winsock2.h>
#include <ws2tcpip.h>
+
+// MinGW does not define several errno constants
+#ifndef _MSC_VER
+#define EBADMSG 104
+#define ENODATA 120
+#define ENOMSG 122
+#define ENOSR 124
+#define ENOSTR 125
+#define ETIME 137
+#define EIDRM 2001
+#define ENOLINK 2002
+#endif // _MSC_VER
+
#else
#include <sys/socket.h>
#include <netinet/in.h>
@@ -721,7 +734,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
Interface::~Interface() {
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index ac5f30a2..cc59a03c 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -11,7 +11,7 @@
namespace SRV {
-static Handle g_event_handle = 0;
+static Kernel::SharedPtr<Kernel::Event> event_handle;
static void Initialize(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -23,11 +23,11 @@ static void GetProcSemaphore(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
// TODO(bunnei): Change to a semaphore once these have been implemented
- g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event");
- Kernel::SetEventLocked(g_event_handle, false);
+ event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event");
+ event_handle->Clear();
cmd_buff[1] = 0; // No error
- cmd_buff[3] = g_event_handle;
+ cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom();
}
static void GetServiceHandle(Service::Interface* self) {
@@ -35,10 +35,10 @@ static void GetServiceHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
- Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
+ auto it = Service::g_srv_services.find(port_name);
- if (nullptr != service) {
- cmd_buff[3] = service->GetHandle();
+ if (it != Service::g_srv_services.end()) {
+ cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom();
LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]);
} else {
LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str());
@@ -63,7 +63,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index 360516cd..3f49c1c9 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index b3d873ef..fc76d272 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -54,7 +54,7 @@ const Interface::FunctionInfo FunctionTable[] = {
// Interface class
Interface::Interface() {
- Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+ Register(FunctionTable);
}
} // namespace