Added appletExecuteProgram, appletJumpToSubApplicationProgramForDevelopment, appletRestartProgram, and appletGetPreviousProgramIndex. Added AppletProgramSpecifyKind.

This commit is contained in:
yellows8 2019-08-21 17:38:35 -04:00
parent 79e6db16be
commit c7cab0351c
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 149 additions and 0 deletions

View File

@ -189,6 +189,13 @@ typedef enum {
AppletCaptureSharedBuffer_CallerApplet = 2, ///< CallerApplet AppletCaptureSharedBuffer_CallerApplet = 2, ///< CallerApplet
} AppletCaptureSharedBuffer; } AppletCaptureSharedBuffer;
/// ProgramSpecifyKind for the ExecuteProgram cmd. Controls the type of the u64 passed to the ExecuteProgram cmd.
typedef enum {
AppletProgramSpecifyKind_ExecuteProgram = 0, ///< u8 ProgramIndex.
AppletProgramSpecifyKind_JumpToSubApplicationProgramForDevelopment = 1, ///< u64 titleID. Only available when DebugMode is enabled.
AppletProgramSpecifyKind_RestartProgram = 2, ///< u64 = value 0.
} AppletProgramSpecifyKind;
/// applet hook function. /// applet hook function.
typedef void (*AppletHookFn)(AppletHookType hook, void* param); typedef void (*AppletHookFn)(AppletHookType hook, void* param);
@ -1345,6 +1352,42 @@ Result appletQueryApplicationPlayStatistics(PdmApplicationPlayStatistics *stats,
*/ */
Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out); Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out);
/**
* @brief Launches Application title {current_titleID}+programIndex. This will enter an infinite-sleep-loop on success.
* @note Only available with AppletType_*Application on [5.0.0+].
* @note Creates the storage if needed. Uses cmd ClearUserChannel. Uses cmd UnpopToUserChannel when the storage was created. Lastly cmd ExecuteProgramCmd is used.
* @param[in] programIndex ProgramIndex, must be 0x0-0xFF. 0 is the same as the current titleID. ProgramIndex values where the title is not installed should not be used.
* @param[in] buffer Optional buffer containing the storage data which will be used for ::AppletLaunchParameterKind_UserChannel with the launched Application, can be NULL.
* @param[in] size Size of the above buffer, 0 to not use the storage. Must be <=0x1000.
*/
Result appletExecuteProgram(s32 programIndex, const void* buffer, size_t size);
/**
* @brief Launches the specified Application titleID.
* @note Only available with AppletType_*Application on [5.0.0+], with DebugMode enabled.
* @note Creates the storage if needed. Uses cmd ClearUserChannel. Uses cmd UnpopToUserChannel when the storage was created. Lastly cmd ExecuteProgramCmd is used.
* @param[in] titleID Application titleID.
* @param[in] buffer Optional buffer containing the storage data which will be used for ::AppletLaunchParameterKind_UserChannel with the launched Application, can be NULL.
* @param[in] size Size of the above buffer, 0 to not use the storage. Must be <=0x1000.
*/
Result appletJumpToSubApplicationProgramForDevelopment(u64 titleID, const void* buffer, size_t size);
/**
* @brief Relaunches the current Application.
* @note Only available with AppletType_*Application on [5.0.0+].
* @note Creates the storage if needed. Uses cmd ClearUserChannel. Uses cmd UnpopToUserChannel when the storage was created. Lastly cmd ExecuteProgramCmd is used.
* @param[in] buffer Optional buffer containing the storage data which will be used for ::AppletLaunchParameterKind_UserChannel with the launched Application, can be NULL.
* @param[in] size Size of the above buffer, 0 to not use the storage. Must be <=0x1000.
*/
Result appletRestartProgram(const void* buffer, size_t size);
/**
* @brief Gets the ProgramIndex of the Application which launched this title.
* @note Only available with AppletType_*Application on [5.0.0+].
* @param[out] programIndex ProgramIndex, -1 when there was no previous title.
*/
Result appletGetPreviousProgramIndex(s32 *programIndex);
/** /**
* @brief Gets an Event which is signaled for GpuErrorDetected. * @brief Gets an Event which is signaled for GpuErrorDetected.
* @note Only available with AppletType_*Application on [8.0.0+]. * @note Only available with AppletType_*Application on [8.0.0+].

View File

@ -4277,6 +4277,112 @@ Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlay
return rc; return rc;
} }
static Result _appletExecuteProgramCmd(AppletProgramSpecifyKind kind, u64 inval) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 kind;
u64 inval;
} *raw;
raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 120;
raw->kind = kind;
raw->inval = inval;
Result rc = serviceIpcDispatch(&g_appletIFunctions);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _appletClearUserChannel(void) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdNoIO(&g_appletIFunctions, 121);
}
static Result _appletUnpopToUserChannel(AppletStorage *s) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdInStorage(&g_appletIFunctions, s, 122);
}
static Result _appletExecuteProgram(AppletProgramSpecifyKind kind, u64 inval, const void* buffer, size_t size) {
Result rc=0;
AppletStorage storage={0};
if (size > 0x1000)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (buffer!=NULL && size!=0) {
rc = appletCreateStorage(&storage, size);
if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&storage, 0, buffer, size);
}
if (R_SUCCEEDED(rc)) rc = _appletClearUserChannel();
if (R_SUCCEEDED(rc) && buffer!=0 && size!=0) rc = _appletUnpopToUserChannel(&storage);
if (R_SUCCEEDED(rc)) rc = _appletExecuteProgramCmd(kind, inval);
appletStorageClose(&storage);
return rc;
}
Result appletExecuteProgram(s32 programIndex, const void* buffer, size_t size) {
Result rc=0;
if (programIndex<0 || programIndex>0xff) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (R_SUCCEEDED(rc)) rc = _appletExecuteProgram(AppletProgramSpecifyKind_ExecuteProgram, (u64)programIndex, buffer, size);
if (R_SUCCEEDED(rc)) _appletInfiniteSleepLoop();
return rc;
}
Result appletJumpToSubApplicationProgramForDevelopment(u64 titleID, const void* buffer, size_t size) {
return _appletExecuteProgram(AppletProgramSpecifyKind_JumpToSubApplicationProgramForDevelopment, titleID, buffer, size);
}
Result appletRestartProgram(const void* buffer, size_t size) {
return _appletExecuteProgram(AppletProgramSpecifyKind_RestartProgram, 0, buffer, size);
}
Result appletGetPreviousProgramIndex(s32 *programIndex) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdNoInOut32(&g_appletIFunctions, (u32*)programIndex, 123);
}
Result appletGetGpuErrorDetectedSystemEvent(Event *out_event) { Result appletGetGpuErrorDetectedSystemEvent(Event *out_event) {
if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication())
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);