diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index 5691d81..2b4f0e5 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -54,7 +54,8 @@ extern "C" { #include <3ds/services/nwmext.h> #include <3ds/services/ir.h> #include <3ds/services/ns.h> -#include <3ds/services/pm.h> +#include <3ds/services/pmapp.h> +#include <3ds/services/pmdbg.h> #include <3ds/services/ps.h> #include <3ds/services/ptmu.h> #include <3ds/services/ptmsysm.h> diff --git a/libctru/include/3ds/services/pm.h b/libctru/include/3ds/services/pm.h deleted file mode 100644 index 2d5c169..0000000 --- a/libctru/include/3ds/services/pm.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file pm.h - * @brief PM (Process Manager) service. - */ -#pragma once - -/// Launch flags for PM launch commands. -enum { - PMLAUNCHFLAG_NORMAL_APPLICATION = BIT(0), - PMLAUNCHFLAG_LOAD_DEPENDENCIES = BIT(1), - PMLAUNCHFLAG_NOTIFY_TERMINATION = BIT(2), - PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION = BIT(3), - PMLAUNCHFLAG_TERMINATION_NOTIFICATION_MASK = 0xF0, - PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM = BIT(8), ///< Forces the usage of the O3DS system mode app memory setting even if N3DS system mode is not "Legacy". Dev4 and Dev5 not supported. N3DS only. - PMLAUNCHFLAG_FORCE_USE_O3DS_MAX_APP_MEM = BIT(9), ///< In conjunction with the above, forces the 96MB app memory setting. N3DS only. - PMLAUNCHFLAG_USE_UPDATE_TITLE = BIT(16), -}; - -/// Initializes PM. -Result pmInit(void); - -/// Exits PM. -void pmExit(void); - -/** - * @brief Launches a title. - * @param mediatype Mediatype of the title. - * @param titleid ID of the title. - * @param launch_flags Flags to launch the title with. - */ -Result PM_LaunchTitle(u8 mediatype, u64 titleid, u32 launch_flags); - -/** - * @brief Gets launch flags from a title's exheader. - * @param mediatype Mediatype of the title. - * @param titleid ID of the title. - * @param out Pointer to write the launch flags to. - */ -Result PM_GetTitleExheaderFlags(u8 mediatype, u64 titleid, u8* out); - -/** - * @brief Sets the current FIRM launch parameters. - * @param size Size of the FIRM launch parameter buffer. - * @param in Buffer to retrieve the launch parameters from. - */ -Result PM_SetFIRMLaunchParams(u32 size, u8* in); - -/** - * @brief Gets the current FIRM launch parameters. - * @param size Size of the FIRM launch parameter buffer. - * @param out Buffer to write the launch parameters to. - */ -Result PM_GetFIRMLaunchParams(u32 size, u8* out); - -/** - * @brief Sets the current FIRM launch parameters. - * @param firm_titleid_low Low Title ID of the FIRM title to launch. - * @param size Size of the FIRM launch parameter buffer. - * @param in Buffer to retrieve the launch parameters from. - */ -Result PM_LaunchFIRMSetParams(u32 firm_titleid_low, u32 size, u8* in); - -/** - * @brief Terminates the current Application - * @param timeout Timeout in nanoseconds - */ -Result PM_TerminateCurrentApplication(u64 timeout); - -/** - * @brief Terminates the specified Process - * @param pid Process-ID of the process to terminate - * @param timeout Timeout on nanoseconds - */ -Result PM_TerminateProcess(u8 pid, u64 timeout); - -/** - * @brief Unregisters a process - * @param tid TitleID of the process to unregister - */ - Result PM_UnregisterProcess(u64 tid); diff --git a/libctru/include/3ds/services/pmapp.h b/libctru/include/3ds/services/pmapp.h new file mode 100644 index 0000000..12ae8bf --- /dev/null +++ b/libctru/include/3ds/services/pmapp.h @@ -0,0 +1,123 @@ +/** + * @file pmapp.h + * @brief PM (Process Manager) application service. + */ +#pragma once + +#include <3ds/services/fs.h> +#include <3ds/exheader.h> + +/// Launch flags for PM launch commands. +enum { + PMLAUNCHFLAG_NORMAL_APPLICATION = BIT(0), + PMLAUNCHFLAG_LOAD_DEPENDENCIES = BIT(1), + PMLAUNCHFLAG_NOTIFY_TERMINATION = BIT(2), + PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION = BIT(3), + PMLAUNCHFLAG_TERMINATION_NOTIFICATION_MASK = 0xF0, + PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM = BIT(8), ///< Forces the usage of the O3DS system mode app memory setting even if N3DS system mode is not "Legacy". Dev4 and Dev5 not supported. N3DS only. + PMLAUNCHFLAG_FORCE_USE_O3DS_MAX_APP_MEM = BIT(9), ///< In conjunction with the above, forces the 96MB app memory setting. N3DS only. + PMLAUNCHFLAG_USE_UPDATE_TITLE = BIT(16), +}; + +/// Initializes pm:app. +Result pmAppInit(void); + +/// Exits pm:app. +void pmAppExit(void); + +/** + * @brief Gets the current pm:app session handle. + * @return The current pm:app session handle. + */ +Handle *pmAppGetSessionHandle(void); + +/** + * @brief Launches a title. + * @param programInfo Program information of the title. + * @param launchFlags Flags to launch the title with. + */ +Result PMAPP_LaunchTitle(const FS_ProgramInfo *programInfo, u32 launchFlags); + +/** + * @brief Launches a title, applying patches. + * @param programInfo Program information of the title. + * @param programInfoUpdate Program information of the update title. + * @param launchFlags Flags to launch the title with. + */ +Result PMAPP_LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags); + +/** + * @brief Gets a title's ExHeader Arm11CoreInfo and SystemInfo flags. + * @param[out] outCoreInfo Pointer to write the ExHeader Arm11CoreInfo to. + * @param[out] outSiFlags Pointer to write the ExHeader SystemInfo flags to. + * @param programInfo Program information of the title. + */ +Result PMAPP_GetTitleExheaderFlags(ExHeader_Arm11CoreInfo* outCoreInfo, ExHeader_SystemInfoFlags* outSiFlags, const FS_ProgramInfo *programInfo); + +/** + * @brief Sets the current FIRM launch parameters. + * @param size Size of the FIRM launch parameter buffer. + * @param in Buffer to retrieve the launch parameters from. + */ +Result PMAPP_SetFIRMLaunchParams(u32 size, const void* in); + +/** + * @brief Gets the current FIRM launch parameters. + * @param size Size of the FIRM launch parameter buffer. + * @param[out] out Buffer to write the launch parameters to. + */ +Result PMAPP_GetFIRMLaunchParams(void *out, u32 size); + +/** + * @brief Sets the current FIRM launch parameters. + * @param firmTidLow Low Title ID of the FIRM title to launch. + * @param size Size of the FIRM launch parameter buffer. + * @param in Buffer to retrieve the launch parameters from. + */ +Result PMAPP_LaunchFIRMSetParams(u32 firmTidLow, u32 size, const void* in); + +/** + * @brief Terminate most processes, to prepare for a reboot or a shutdown. + * @param timeout Time limit in ns for process termination, after which the remaining processes are killed. + */ +Result PMAPP_PrepareForReboot(s64 timeout); + +/** + * @brief Terminates the current Application + * @param timeout Timeout in nanoseconds + */ +Result PMAPP_TerminateCurrentApplication(s64 timeout); + +/** + * @brief Terminates the processes having the specified titleId. + * @param titleId Title ID of the processes to terminate + * @param timeout Timeout in nanoseconds + */ +Result PMAPP_TerminateTitle(u64 titleId, s64 timeout); + +/** + * @brief Terminates the specified process + * @param pid Process-ID of the process to terminate + * @param timeout Timeout in nanoseconds + */ +Result PMAPP_TerminateProcess(u32 pid, s64 timeout); + +/** + * @brief Unregisters a process + * @param tid TitleID of the process to unregister + */ +Result PMAPP_UnregisterProcess(u64 tid); + +/** + * @brief Sets the APPLICATION cputime reslimit. + * @param cpuTime Reslimit value. + * @note cpuTime can be no higher than reslimitdesc[0] & 0x7F in exheader (or 80 if the latter is 0). + */ +Result PMAPP_SetAppResourceLimit(s64 cpuTime); + +/** + * @brief Gets the APPLICATION cputime reslimit. + * @param[out] cpuTime Pointer to write the reslimit value to. + */ +Result PMAPP_GetAppResourceLimit(s64 *outCpuTime); + diff --git a/libctru/include/3ds/services/pmdbg.h b/libctru/include/3ds/services/pmdbg.h new file mode 100644 index 0000000..18a5962 --- /dev/null +++ b/libctru/include/3ds/services/pmdbg.h @@ -0,0 +1,41 @@ +/** + * @file pmdbg.h + * @brief PM (Process Manager) debug service. + */ +#pragma once + +#include <3ds/services/pmapp.h> + +/// Initializes pm:dbg. +Result pmDbgInit(void); + +/// Exits pm:dbg. +void pmDbgExit(void); + +/** + * @brief Gets the current pm:dbg session handle. + * @return The current pm:dbg session handle. + */ +Handle *pmDbgGetSessionHandle(void); + +/** + * @brief Enqueues an application for debug after setting cpuTime to 0, and returns a debug handle to it. + * If another process was enqueued, this just calls @ref RunQueuedProcess instead. + * @param[out] Pointer to output the debug handle to. + * @param programInfo Program information of the title. + * @param launchFlags Flags to launch the title with. + */ +Result PMDBG_LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags); + +/** + * @brief Launches an application for debug after setting cpuTime to 0. + * @param programInfo Program information of the title. + * @param launchFlags Flags to launch the title with. + */ +Result PMDBG_LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags); + +/** + * @brief Runs the queued process and returns a debug handle to it. + * @param[out] Pointer to output the debug handle to. + */ +Result PMDBG_RunQueuedProcess(Handle *outDebug); diff --git a/libctru/source/services/pm.c b/libctru/source/services/pm.c deleted file mode 100644 index 0498342..0000000 --- a/libctru/source/services/pm.c +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include -#include <3ds/types.h> -#include <3ds/result.h> -#include <3ds/svc.h> -#include <3ds/srv.h> -#include <3ds/synchronization.h> -#include <3ds/services/pm.h> -#include <3ds/ipc.h> - -static Handle pmHandle; -static int pmRefCount; - -Result pmInit(void) -{ - Result res; - if (AtomicPostIncrement(&pmRefCount)) return 0; - res = srvGetServiceHandle(&pmHandle, "pm:app"); - if (R_FAILED(res)) AtomicDecrement(&pmRefCount); - return res; -} - -void pmExit(void) -{ - if (AtomicDecrement(&pmRefCount)) return; - svcCloseHandle(pmHandle); -} - -Result PM_LaunchTitle(u8 mediatype, u64 titleid, u32 launch_flags) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x1,5,0); // 0x10140 - cmdbuf[1] = titleid & 0xffffffff; - cmdbuf[2] = (titleid >> 32) & 0xffffffff; - cmdbuf[3] = mediatype; - cmdbuf[4] = 0x0; - cmdbuf[5] = launch_flags; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - return (Result)cmdbuf[1]; -} - -Result PM_LaunchFIRMSetParams(u32 firm_titleid_low, u32 size, u8* in) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x2,2,2); // 0x20082 - cmdbuf[1] = firm_titleid_low; - cmdbuf[2] = size; - cmdbuf[3] = IPC_Desc_Buffer(size,IPC_BUFFER_R); - cmdbuf[4] = (u32)in; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - return (Result)cmdbuf[1]; -} - -Result PM_TerminateCurrentApplication(u64 timeout) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x3,2,0); // 0x30080 - cmdbuf[1] = timeout & 0xffffffff; - cmdbuf[2] = (timeout >> 32) & 0xffffffff; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - return (Result)cmdbuf[1]; -} - -Result PM_TerminateProcess(u8 pid, u64 timeout) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x5,3,0); // 0x500C0 - cmdbuf[1] = pid; - cmdbuf[2] = timeout & 0xffffffff; - cmdbuf[3] = (timeout >> 32) & 0xffffffff; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - return (Result)cmdbuf[1]; -} - -Result PM_GetFIRMLaunchParams(u32 size, u8* out) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x7,1,2); // 0x70042 - cmdbuf[1] = size; - cmdbuf[2] = IPC_Desc_Buffer(size,IPC_BUFFER_W); - cmdbuf[3] = (u32)out; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - return (Result)cmdbuf[1]; -} - -Result PM_GetTitleExheaderFlags(u8 mediatype, u64 titleid, u8* out) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x8,4,0); // 0x80100 - cmdbuf[1] = titleid & 0xffffffff; - cmdbuf[2] = (titleid >> 32) & 0xffffffff; - cmdbuf[3] = mediatype; - cmdbuf[4] = 0x0; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - memcpy(out, (u8*)(&cmdbuf[2]), 8); - - return (Result)cmdbuf[1]; -} - -Result PM_SetFIRMLaunchParams(u32 size, u8* in) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x9,1,2); // 0x90042 - cmdbuf[1] = size; - cmdbuf[2] = IPC_Desc_Buffer(size,IPC_BUFFER_R); - cmdbuf[3] = (u32)in; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - return (Result)cmdbuf[1]; -} - -Result PM_UnregisterProcess(u64 tid) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0xC,0,0); // 0xC0000 - cmdbuf[1] = tid & 0xffffffff; - cmdbuf[2] = (tid >> 32) & 0xffffffff; - - if(R_FAILED(ret = svcSendSyncRequest(pmHandle)))return ret; - - return (Result)cmdbuf[1]; -} \ No newline at end of file diff --git a/libctru/source/services/pmapp.c b/libctru/source/services/pmapp.c new file mode 100644 index 0000000..2e3bca2 --- /dev/null +++ b/libctru/source/services/pmapp.c @@ -0,0 +1,232 @@ +#include +#include <3ds/types.h> +#include <3ds/result.h> +#include <3ds/svc.h> +#include <3ds/srv.h> +#include <3ds/synchronization.h> +#include <3ds/services/pmapp.h> +#include <3ds/ipc.h> + +static Handle pmAppHandle; +static int pmAppRefcount; + +Result pmAppInit(void) +{ + Result res; + if (AtomicPostIncrement(&pmAppRefcount)) return 0; + res = srvGetServiceHandle(&pmAppHandle, "pm:app"); + if (R_FAILED(res)) AtomicDecrement(&pmAppRefcount); + return res; +} + +void pmAppExit(void) +{ + if (AtomicDecrement(&pmAppRefcount)) return; + svcCloseHandle(pmAppHandle); +} + +Handle *pmAppGetSessionHandle(void) +{ + return &pmAppHandle; +} + +Result PMAPP_LaunchTitle(const FS_ProgramInfo *programInfo, u32 launchFlags) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1, 5, 0); // 0x10140 + memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo)); + cmdbuf[5] = launchFlags; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_LaunchFIRMSetParams(u32 firmTidLow, u32 size, const void* in) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x2, 2, 2); // 0x20082 + cmdbuf[1] = firmTidLow; + cmdbuf[2] = size; + cmdbuf[3] = IPC_Desc_Buffer(size, IPC_BUFFER_R); + cmdbuf[4] = (u32)in; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_TerminateCurrentApplication(s64 timeout) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x3, 2, 0); // 0x30080 + cmdbuf[1] = (u32)timeout; + cmdbuf[2] = (u32)(timeout >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_TerminateTitle(u64 titleId, s64 timeout) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x3, 4, 0); // 0x40100 + cmdbuf[1] = (u32)titleId; + cmdbuf[2] = (u32)(titleId >> 32); + cmdbuf[3] = (u32)timeout; + cmdbuf[4] = (u32)(timeout >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_TerminateProcess(u32 pid, s64 timeout) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x5, 3, 0); // 0x500C0 + cmdbuf[1] = pid; + cmdbuf[2] = (u32)timeout; + cmdbuf[3] = (u32)(timeout >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_PrepareForReboot(s64 timeout) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x6, 2, 2); // 0x60082 + cmdbuf[1] = (u32)timeout; + cmdbuf[2] = (u32)(timeout >> 32); + cmdbuf[3] = IPC_Desc_CurProcessId(); + cmdbuf[4] = 0; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_GetFIRMLaunchParams(void *out, u32 size) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x7, 1, 2); // 0x70042 + cmdbuf[1] = size; + cmdbuf[2] = IPC_Desc_Buffer(size, IPC_BUFFER_W); + cmdbuf[3] = (u32)out; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_GetTitleExheaderFlags(ExHeader_Arm11CoreInfo* outCoreInfo, ExHeader_SystemInfoFlags* outSiFlags, const FS_ProgramInfo *programInfo) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x8, 4, 0); // 0x80100 + memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo)); + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + memcpy(outCoreInfo, &cmdbuf[2], sizeof(ExHeader_Arm11CoreInfo)); + memcpy(outSiFlags, &cmdbuf[4], sizeof(ExHeader_SystemInfoFlags)); + + return (Result)cmdbuf[1]; +} + +Result PMAPP_SetFIRMLaunchParams(u32 size, const void* in) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x9, 1, 2); // 0x90042 + cmdbuf[1] = size; + cmdbuf[2] = IPC_Desc_Buffer(size, IPC_BUFFER_R); + cmdbuf[3] = (u32)in; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_SetAppResourceLimit(s64 cpuTime) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xA, 5, 0); // 0xA0140 + cmdbuf[1] = 0; + cmdbuf[2] = RESLIMIT_CPUTIME; + cmdbuf[3] = (u32)cpuTime; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_GetAppResourceLimit(s64 *outCpuTime) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xB, 5, 0); // 0xB0140 + cmdbuf[1] = 0; + cmdbuf[2] = RESLIMIT_CPUTIME; + cmdbuf[3] = 0; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + *outCpuTime = cmdbuf[2] | ((s64)cmdbuf[3] << 32); + + return (Result)cmdbuf[1]; +} + +Result PMAPP_UnregisterProcess(u64 tid) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xC, 0, 0); // 0xC0000 + cmdbuf[1] = (u32)tid; + cmdbuf[2] = (u32)(tid >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMAPP_LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xD, 9, 0); // 0xD0240 + memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo)); + memcpy(&cmdbuf[5], programInfoUpdate, sizeof(FS_ProgramInfo)); + cmdbuf[9] = launchFlags; + + if(R_FAILED(ret = svcSendSyncRequest(pmAppHandle)))return ret; + + return (Result)cmdbuf[1]; +} diff --git a/libctru/source/services/pmdbg.c b/libctru/source/services/pmdbg.c new file mode 100644 index 0000000..6e3f2ba --- /dev/null +++ b/libctru/source/services/pmdbg.c @@ -0,0 +1,74 @@ +#include +#include <3ds/types.h> +#include <3ds/result.h> +#include <3ds/svc.h> +#include <3ds/srv.h> +#include <3ds/synchronization.h> +#include <3ds/services/pmdbg.h> +#include <3ds/ipc.h> + +static Handle pmDbgHandle; +static int pmDbgRefcount; + +Result pmDbgInit(void) +{ + Result res; + if (AtomicPostIncrement(&pmDbgRefcount)) return 0; + res = srvGetServiceHandle(&pmDbgHandle, "pm:dbg"); + if (R_FAILED(res)) AtomicDecrement(&pmDbgRefcount); + return res; +} + +void pmDbgExit(void) +{ + if (AtomicDecrement(&pmDbgRefcount)) return; + svcCloseHandle(pmDbgHandle); +} + +Handle *pmDbgGetSessionHandle(void) +{ + return &pmDbgHandle; +} + +Result PMDBG_LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1, 5, 0); // 0x10140 + memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo)); + cmdbuf[5] = launchFlags; + + if(R_FAILED(ret = svcSendSyncRequest(pmDbgHandle)))return ret; + + *outDebug = cmdbuf[3]; + return (Result)cmdbuf[1]; +} + +Result PMDBG_LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x2, 5, 0); // 0x20140 + memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo)); + cmdbuf[5] = launchFlags; + + if(R_FAILED(ret = svcSendSyncRequest(pmDbgHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result PMDBG_RunQueuedProcess(Handle *outDebug) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x3, 0, 0); // 0x30000 + + if(R_FAILED(ret = svcSendSyncRequest(pmDbgHandle)))return ret; + + *outDebug = cmdbuf[3]; + + return (Result)cmdbuf[1]; +}