Added appletPushContext/appletPopContext. Added appletHolderJump. Added appletGetAppletInfo. Added libappletSetJumpFlag. Added structs AppletProcessLaunchReason and AppletInfo.

This commit is contained in:
yellows8 2019-08-15 21:34:42 -04:00
parent 8db92d48a5
commit eeaa63aa28
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
4 changed files with 229 additions and 6 deletions

View File

@ -82,7 +82,13 @@ Result libappletPushInData(AppletHolder *h, const void* buffer, size_t size);
Result libappletPopOutData(AppletHolder *h, void* buffer, size_t size, size_t *transfer_size);
/**
* @brief Starts the applet and waits for it to finish, then checks the \ref LibAppletExitReason.
* @brief Sets whether \ref libappletStart uses \ref appletHolderJump.
* @param flag Flag. Value true should not be used unless running as AppletType_LibraryApplet.
*/
void libappletSetJumpFlag(bool flag);
/**
* @brief If the flag from \ref libappletSetJumpFlag is set, this just uses \ref appletHolderJump. Otherwise, starts the applet and waits for it to finish, then checks the \ref LibAppletExitReason.
* @note Uses \ref appletHolderStart and \ref appletHolderJoin.
* @param h AppletHolder object.
*/

View File

@ -223,6 +223,19 @@ typedef struct {
LibAppletMode mode; ///< \ref LibAppletMode
} LibAppletInfo;
/// AppletProcessLaunchReason, from GetLaunchReason.
typedef struct {
u8 flag; ///< When non-zero, indicates that OpenCallingLibraryApplet should be used.
u8 unk_x1[3]; ///< Always zero.
} AppletProcessLaunchReason;
/// Cached info for the current LibraryApplet, from \ref appletGetAppletInfo.
typedef struct {
LibAppletInfo info; ///< Output from \ref appletGetLibraryAppletInfo.
bool caller_flag; ///< Loaded from AppletProcessLaunchReason::flag, indicates that the below AppletHolder is initialized.
AppletHolder caller; ///< \ref AppletHolder for the CallingLibraryApplet, automatically closed by \ref appletExit when needed.
} AppletInfo;
/// IdentityInfo
typedef struct {
AppletId appletId; ///< \ref AppletId
@ -823,6 +836,23 @@ Result appletReleaseCallerAppletCaptureSharedBuffer(void);
*/
Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCaptureSharedBuffer captureBuf);
// IProcessWindingController
/**
* @brief Pushes a storage to the ContextStack. Normally this should only be used when AppletInfo::caller_flag is true.
* @note Only available with AppletType_LibraryApplet.
* @note This uses \ref appletStorageClose automatically.
* @param[in] s Storage object.
*/
Result appletPushContext(AppletStorage *s);
/**
* @brief Pops a storage from the ContextStack. Normally this should only be used when AppletInfo::caller_flag is true.
* @note Only available with AppletType_LibraryApplet.
* @param[out] s Storage object.
*/
Result appletPopContext(AppletStorage *s);
// LockAccessor
/**
@ -890,6 +920,13 @@ Result appletHolderGetIndirectLayerConsumerHandle(AppletHolder *h, u64 *out);
*/
Result appletHolderStart(AppletHolder *h);
/**
* @brief Jumps to the LibraryApplet, with the current-LibraryApplet being terminated. This will enter an infinite-sleep-loop on success.
* @note Only available with AppletType_LibraryApplet.
* @param h AppletHolder object.
*/
Result appletHolderJump(AppletHolder *h);
/**
* @brief Requests the LibraryApplet to exit. The command is only used if \ref appletHolderCheckFinished returns false.
* @param h AppletHolder object.
@ -1652,6 +1689,12 @@ Result appletGetHomeButtonDoubleClickEnabled(bool *out);
// State / other
/**
* @brief Gets the cached \ref AppletInfo loaded during \ref appletInitialize. This will return NULL when the info is not initialized, due to not running as AppletType_LibraryApplet, or when any of the used cmds fail.
* @note Only available with AppletType_LibraryApplet.
*/
AppletInfo *appletGetAppletInfo(void);
/**
* @brief Gets a notification message.
*/

View File

@ -5,6 +5,8 @@
#include "services/applet.h"
#include "applets/libapplet.h"
static bool g_libappletJumpFlag;
void libappletArgsCreate(LibAppletArgs* a, u32 version) {
memset(a, 0, sizeof(LibAppletArgs));
@ -117,9 +119,16 @@ Result libappletPopOutData(AppletHolder *h, void* buffer, size_t size, size_t *t
return rc;
}
void libappletSetJumpFlag(bool flag) {
g_libappletJumpFlag = flag;
}
Result libappletStart(AppletHolder *h) {
Result rc=0;
if (g_libappletJumpFlag)
return appletHolderJump(h);
rc = appletHolderStart(h);
if (R_SUCCEEDED(rc)) {

View File

@ -80,6 +80,9 @@ static AppletThemeColorType g_appletThemeColorType = AppletThemeColorType_Defaul
static ApmCpuBoostMode g_appletCpuBoostMode = ApmCpuBoostMode_Disabled;
static AppletInfo g_appletInfo;
static bool g_appletInfoInitialized;
static Result _appletGetHandle(Service* srv, Handle* handle_out, u64 cmd_id);
static Result _appletGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool autoclear);
static Result _appletGetSession(Service* srv, Service* srv_out, u64 cmd_id);
@ -107,6 +110,11 @@ static Result _appletExitProcessAndReturn(void);
static Result _appletGetAccumulatedSuspendedTickValue(u64 *tick);
static Result _appletGetAccumulatedSuspendedTickChangedEvent(Event *out_event);
static Result _appletGetLaunchReason(AppletProcessLaunchReason *reason);
static Result _appletOpenCallingLibraryApplet(AppletHolder *h);
static Result _appletHolderCreateState(AppletHolder *h, LibAppletMode mode, bool creating_self);
Result appletInitialize(void)
{
AppletAttribute *attr = NULL;
@ -129,6 +137,9 @@ Result appletInitialize(void)
g_appletExitProcessFlag = 0;
g_appletRecordingInitialized = 0;
g_appletInfoInitialized = 0;
memset(&g_appletInfo, 0, sizeof(g_appletInfo));
switch (__nx_applet_type) {
case AppletType_Default:
__nx_applet_type = AppletType_Application;
@ -310,6 +321,21 @@ Result appletInitialize(void)
}
}
if (R_SUCCEEDED(rc) && __nx_applet_type == AppletType_LibraryApplet) {
AppletProcessLaunchReason launchreason={0};
Result rc2 = appletGetLibraryAppletInfo(&g_appletInfo.info);
if (R_SUCCEEDED(rc2)) rc2 = _appletGetLaunchReason(&launchreason);
if (R_SUCCEEDED(rc2)) {
g_appletInfo.caller_flag = launchreason.flag!=0;
if (g_appletInfo.caller_flag) rc2 = _appletOpenCallingLibraryApplet(&g_appletInfo.caller);
}
if (R_SUCCEEDED(rc2)) g_appletInfoInitialized = true;
}
if (R_FAILED(rc))
appletExit();
@ -365,6 +391,12 @@ void appletExit(void)
}
}
if (g_appletInfoInitialized) {
if (g_appletInfo.caller_flag) appletHolderClose(&g_appletInfo.caller);
g_appletInfoInitialized = 0;
memset(&g_appletInfo, 0, sizeof(g_appletInfo));
}
eventClose(&g_appletLibraryAppletLaunchableEvent);
eventClose(&g_appletMessageEvent);
@ -2512,6 +2544,103 @@ Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCapt
return rc;
}
// IProcessWindingController
static Result _appletGetLaunchReason(AppletProcessLaunchReason *reason) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_appletIProcessWindingController, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
Result rc = serviceIpcDispatch(&g_appletIProcessWindingController);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
AppletProcessLaunchReason reason;
} *resp;
serviceIpcParse(&g_appletIProcessWindingController, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && reason) *reason = resp->reason;
}
return rc;
}
static Result _appletOpenCallingLibraryApplet(AppletHolder *h) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
Result rc=0;
LibAppletInfo info={0};
memset(h, 0, sizeof(AppletHolder));
rc = _appletGetSession(&g_appletIProcessWindingController, &h->s, 11);
if (R_SUCCEEDED(rc)) rc = appletHolderGetLibraryAppletInfo(h, &info);
if (R_SUCCEEDED(rc)) rc = _appletHolderCreateState(h, info.mode, false);
if (R_FAILED(rc)) appletHolderClose(h);
return rc;
}
Result appletPushContext(AppletStorage *s) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletCmdInStorage(&g_appletIProcessWindingController, s, 21);
}
Result appletPopContext(AppletStorage *s) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletCmdNoInOutStorage(&g_appletIProcessWindingController, s, 22);
}
static Result _appletWindAndDoReserved(void) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletCmdNoIO(&g_appletIProcessWindingController, 30);
}
static Result _appletReserveToStartAndWaitAndUnwindThis(AppletHolder *h) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _appletCmdInSession(&g_appletIProcessWindingController, &h->s, 40);
}
static Result _appletReserveToStartAndWait(AppletHolder *h) {
if (__nx_applet_type != AppletType_LibraryApplet)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _appletCmdInSession(&g_appletIProcessWindingController, &h->s, 41);
}
// LockAccessor
void appletLockAccessorClose(AppletLockAccessor *a) {
eventClose(&a->event);
@ -2679,20 +2808,29 @@ static Result _appletGetIndirectLayerConsumerHandle(Service* srv, u64 *out) {
return rc;
}
static Result _appletHolderCreateState(AppletHolder *h, LibAppletMode mode, bool creating_self) {
Result rc=0;
h->mode = mode;
h->creating_self = creating_self;
if (R_SUCCEEDED(rc)) rc = _appletGetEvent(&h->s, &h->StateChangedEvent, 0, false);//GetAppletStateChangedEvent
if (R_SUCCEEDED(rc) && hosversionAtLeast(2,0,0) && h->mode == LibAppletMode_BackgroundIndirect) rc = _appletGetIndirectLayerConsumerHandle(&h->s, &h->layer_handle);
return rc;
}
static Result _appletHolderCreate(AppletHolder *h, AppletId id, LibAppletMode mode, bool creating_self) {
Result rc=0;
memset(h, 0, sizeof(AppletHolder));
h->mode = mode;
h->creating_self = creating_self;
if (!h->creating_self) rc = _appletWaitLibraryAppletLaunchableEvent();
if (R_SUCCEEDED(rc)) rc = _appletCreateLibraryApplet(&h->s, id, mode);
if (R_SUCCEEDED(rc)) rc = _appletGetEvent(&h->s, &h->StateChangedEvent, 0, false);//GetAppletStateChangedEvent
if (R_SUCCEEDED(rc) && hosversionAtLeast(2,0,0) && h->mode == LibAppletMode_BackgroundIndirect) rc = _appletGetIndirectLayerConsumerHandle(&h->s, &h->layer_handle);
if (R_SUCCEEDED(rc)) rc = _appletHolderCreateState(h, mode, creating_self);
return rc;
}
@ -2743,6 +2881,28 @@ Result appletHolderStart(AppletHolder *h) {
return rc;
}
Result appletHolderJump(AppletHolder *h) {
Result rc=0;
if (!serviceIsActive(&h->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (!h->creating_self) rc = _appletWaitLibraryAppletLaunchableEvent();
if (hosversionBefore(4,0,0))
rc = _appletReserveToStartAndWaitAndUnwindThis(h);
else
rc = _appletReserveToStartAndWait(h);
if (R_SUCCEEDED(rc)) rc = _appletWindAndDoReserved();
if (R_FAILED(rc)) return rc;
while(1)svcSleepThread(86400000000000ULL);
return rc;
}
Result appletHolderRequestExit(AppletHolder *h) {
Result rc=0;
@ -4619,6 +4779,11 @@ AppletFocusState appletGetFocusState(void) {
return (AppletFocusState)g_appletFocusState;
}
AppletInfo *appletGetAppletInfo(void) {
if (!g_appletInfoInitialized) return NULL;
return &g_appletInfo;
}
Result appletGetMessage(u32 *msg) {
Result rc=0;
if (msg==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput);