mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Added appletPushContext/appletPopContext. Added appletHolderJump. Added appletGetAppletInfo. Added libappletSetJumpFlag. Added structs AppletProcessLaunchReason and AppletInfo.
This commit is contained in:
parent
8db92d48a5
commit
eeaa63aa28
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user