PM services overhaul

This commit is contained in:
TuxSH 2019-03-27 23:57:08 +01:00 committed by fincs
parent 8ffc9461ea
commit 09688ea6fc
7 changed files with 472 additions and 232 deletions

View File

@ -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>

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -1,151 +0,0 @@
#include <stdlib.h>
#include <string.h>
#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];
}

View File

@ -0,0 +1,232 @@
#include <string.h>
#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];
}

View File

@ -0,0 +1,74 @@
#include <string.h>
#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];
}