rosalina: implement dirty hb chainload
This commit is contained in:
@@ -129,16 +129,21 @@ Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_Syste
|
||||
return res;
|
||||
}
|
||||
|
||||
Result GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid)
|
||||
Result GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags)
|
||||
{
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
Result res;
|
||||
|
||||
memset(outProgramInfo, 0, sizeof(FS_ProgramInfo));
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
*outTitleId = g_manager.runningApplicationData->titleId;
|
||||
*outPid = g_manager.runningApplicationData->pid;
|
||||
ProcessData *app = g_manager.runningApplicationData;
|
||||
outProgramInfo->programId = app->titleId;
|
||||
outProgramInfo->mediaType = app->mediaType;
|
||||
*outPid = app->pid;
|
||||
*outLaunchFlags = app->launchFlags;
|
||||
res = 0;
|
||||
} else {
|
||||
*outTitleId = 0;
|
||||
*outPid = 0;
|
||||
res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
|
||||
}
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
@@ -12,4 +12,4 @@ Result listMergeUniqueDependencies(ProcessData **procs, u64 *dependencies, u32 *
|
||||
Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_SystemInfoFlags *outSiFlags, const FS_ProgramInfo *programInfo);
|
||||
|
||||
// Custom
|
||||
Result GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid);
|
||||
Result GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags);
|
||||
|
||||
@@ -56,10 +56,12 @@ static Result loadWithoutDependencies(Handle *outDebug, ProcessData **outProcess
|
||||
process->pid = pid;
|
||||
process->titleId = exheaderInfo->aci.local_caps.title_id;;
|
||||
process->programHandle = programHandle;
|
||||
process->launchFlags = launchFlags; // not in official PM
|
||||
process->flags = 0; // will be filled later
|
||||
process->terminatedNotificationVariation = (launchFlags & 0xF0) >> 4;
|
||||
process->terminationStatus = TERMSTATUS_RUNNING;
|
||||
process->refcount = 1;
|
||||
process->mediaType = programInfo->mediaType; // not in official PM
|
||||
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
svcSignalEvent(g_manager.newProcessEvent);
|
||||
@@ -135,6 +137,11 @@ static Result loadWithDependencies(Handle *outDebug, ProcessData **outProcessDat
|
||||
process->flags |= PROCESSFLAG_DEPENDENCIES_LOADED;
|
||||
}
|
||||
|
||||
if (launchFlags & PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING) {
|
||||
// See no evil
|
||||
numUnique = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Official pm does this:
|
||||
for each dependency:
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
#include <3ds/services/fs.h>
|
||||
#include "process_data.h"
|
||||
|
||||
/// Custom launch flags for PM launch commands.
|
||||
enum {
|
||||
PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING = BIT(24),
|
||||
};
|
||||
|
||||
Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFlags);
|
||||
Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags);
|
||||
Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags);
|
||||
|
||||
@@ -52,7 +52,7 @@ void initSystem()
|
||||
}
|
||||
|
||||
static const ServiceManagerServiceEntry services[] = {
|
||||
{ "pm:app", 3, pmAppHandleCommands, false },
|
||||
{ "pm:app", 4, pmAppHandleCommands, false },
|
||||
{ "pm:dbg", 2, pmDbgHandleCommands, false },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
@@ -69,3 +69,27 @@ Result UnregisterProcess(u64 titleId)
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result PrepareToChainloadHomebrew(u64 titleId)
|
||||
{
|
||||
// Note: I'm allowing this command to be called for non-applications, maybe that'll be useful
|
||||
// in the future...
|
||||
|
||||
ProcessData *foundProcess = NULL;
|
||||
Result res;
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
foundProcess = ProcessList_FindProcessByTitleId(&g_manager.processList, titleId & ~N3DS_TID_MASK);
|
||||
if (foundProcess != NULL) {
|
||||
// Clear the "notify on termination, don't cleanup" flag, so that for ex. APT isn't notified & no need for UnregisterProcess,
|
||||
// and the "dependencies loaded" flag, so that the dependencies aren't killed (for ex. when
|
||||
// booting hbmenu instead of Home Menu, in which case the same title is going to be launched...)
|
||||
|
||||
foundProcess->flags &= ~(PROCESSFLAG_DEPENDENCIES_LOADED | PROCESSFLAG_NOTIFY_TERMINATION);
|
||||
res = 0;
|
||||
} else {
|
||||
res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
|
||||
}
|
||||
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -21,3 +21,4 @@ extern Manager g_manager;
|
||||
void Manager_Init(void *procBuf, size_t numProc);
|
||||
void Manager_RegisterKips(void);
|
||||
Result UnregisterProcess(u64 titleId);
|
||||
Result PrepareToChainloadHomebrew(u64 titleId);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "launch.h"
|
||||
#include "info.h"
|
||||
#include "util.h"
|
||||
#include "manager.h"
|
||||
|
||||
void pmDbgHandleCommands(void *ctx)
|
||||
{
|
||||
@@ -11,10 +12,10 @@ void pmDbgHandleCommands(void *ctx)
|
||||
u32 cmdhdr = cmdbuf[0];
|
||||
|
||||
FS_ProgramInfo programInfo;
|
||||
Handle debug;
|
||||
|
||||
u64 titleId;
|
||||
Handle debug;
|
||||
u32 pid;
|
||||
u32 launchFlags;
|
||||
|
||||
switch (cmdhdr >> 16) {
|
||||
case 1:
|
||||
@@ -40,12 +41,11 @@ void pmDbgHandleCommands(void *ctx)
|
||||
|
||||
// Custom
|
||||
case 0x100:
|
||||
titleId = 0;
|
||||
pid = 0xFFFFFFFF;
|
||||
cmdbuf[1] = GetCurrentAppTitleIdAndPid(&titleId, &pid);
|
||||
cmdbuf[0] = IPC_MakeHeader(0x100, 4, 0);
|
||||
memcpy(cmdbuf + 2, &titleId, 8);
|
||||
cmdbuf[4] = pid;
|
||||
cmdbuf[1] = GetCurrentAppInfo(&programInfo, &pid, &launchFlags);
|
||||
cmdbuf[0] = IPC_MakeHeader(0x100, 7, 0);
|
||||
memcpy(cmdbuf + 2, &programInfo, sizeof(FS_ProgramInfo));
|
||||
cmdbuf[6] = pid;
|
||||
cmdbuf[7] = launchFlags;
|
||||
break;
|
||||
case 0x101:
|
||||
cmdbuf[1] = DebugNextApplicationByForce(cmdbuf[1] != 0);
|
||||
@@ -59,7 +59,11 @@ void pmDbgHandleCommands(void *ctx)
|
||||
cmdbuf[2] = IPC_Desc_MoveHandles(1);
|
||||
cmdbuf[3] = debug;
|
||||
break;
|
||||
|
||||
case 0x103:
|
||||
memcpy(&titleId, cmdbuf + 1, 8);
|
||||
cmdbuf[1] = PrepareToChainloadHomebrew(titleId);
|
||||
cmdbuf[0] = IPC_MakeHeader(0x103, 1, 0);
|
||||
break;
|
||||
default:
|
||||
cmdbuf[0] = IPC_MakeHeader(0, 1, 0);
|
||||
cmdbuf[1] = 0xD900182F;
|
||||
|
||||
@@ -29,10 +29,12 @@ typedef struct ProcessData {
|
||||
u32 pid;
|
||||
u64 titleId;
|
||||
u64 programHandle;
|
||||
u32 launchFlags;
|
||||
u8 flags;
|
||||
u8 terminatedNotificationVariation;
|
||||
TerminationStatus terminationStatus;
|
||||
u8 refcount;
|
||||
FS_MediaType mediaType;
|
||||
} ProcessData;
|
||||
|
||||
typedef struct ProcessList {
|
||||
|
||||
Reference in New Issue
Block a user