diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h index e5a6fa05..fe27f1bb 100644 --- a/nx/include/switch/services/applet.h +++ b/nx/include/switch/services/applet.h @@ -112,6 +112,7 @@ typedef struct { Event StateChangedEvent; ///< Output from GetAppletStateChangedEvent, autoclear=false. LibAppletMode mode; ///< See ref \ref LibAppletMode. u64 layer_handle; ///< Output from GetIndirectLayerConsumerHandle on 2.0.0+. + bool creating_self; ///< When set, indicates that the LibraryApplet title is creating itself. } AppletHolder; Result appletInitialize(void); @@ -189,6 +190,15 @@ Result appletPushToGeneralChannel(AppletStorage *s); */ Result appletCreateLibraryApplet(AppletHolder *h, AppletId id, LibAppletMode mode); +/** + * @brief Creates a LibraryApplet. This is for when a LibraryApplet title creates itself. + * @note Identical to \ref appletCreateLibraryApplet except this sets the creating_self flag to true. + * @param h AppletHolder object. + * @param id See \ref AppletId. + * @param mode See \ref LibAppletMode. + */ +Result appletCreateLibraryAppletSelf(AppletHolder *h, AppletId id, LibAppletMode mode); + /// Closes an AppletHolder object. void appletHolderClose(AppletHolder *h); @@ -200,6 +210,12 @@ void appletHolderClose(AppletHolder *h); */ Result appletHolderGetIndirectLayerConsumerHandle(AppletHolder *h, u64 *out); +/** + * @brief Starts the LibraryApplet. + * @param h AppletHolder object. + */ +Result appletHolderStart(AppletHolder *h); + /** * @brief Creates a storage. * @param s Storage object. diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index 4b23d500..1c621b9d 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -55,6 +55,9 @@ static AppletHookCookie g_appletFirstHook; static TransferMemory g_appletRecordingTmem; static u32 g_appletRecordingInitialized; +static Event g_appletLibraryAppletLaunchableEvent; +static bool g_appletLibraryAppletLaunchableEventInitialized; + static Result _appletGetHandle(Service* srv, Handle* handle_out, u64 cmd_id); static Result _appletGetEvent(Service* srv, Event* event_out, u64 cmd_id, bool autoclear); static Result _appletGetSession(Service* srv, Service* srv_out, u64 cmd_id); @@ -99,6 +102,7 @@ Result appletInitialize(void) g_appletNotifiedRunning = 0; g_appletExitProcessFlag = 0; g_appletRecordingInitialized = 0; + g_appletLibraryAppletLaunchableEventInitialized = false; switch (__nx_applet_type) { case AppletType_Default: @@ -312,6 +316,11 @@ void appletExit(void) } } + if (g_appletLibraryAppletLaunchableEventInitialized) { + g_appletLibraryAppletLaunchableEventInitialized = false; + eventClose(&g_appletLibraryAppletLaunchableEvent); + } + eventClose(&g_appletMessageEvent); serviceClose(&g_appletIDebugFunctions); @@ -1180,6 +1189,19 @@ Result appletUnlockExit(void) { return _appletCmdNoIO(&g_appletISelfController, 2); } +static Result _appletWaitLibraryAppletLaunchableEvent(void) { + Result rc=0; + + if (!g_appletLibraryAppletLaunchableEventInitialized) { + rc = _appletGetEvent(&g_appletICommonStateGetter, &g_appletLibraryAppletLaunchableEvent, 9, false); + if (R_SUCCEEDED(rc)) g_appletLibraryAppletLaunchableEventInitialized = true; + } + + if (R_SUCCEEDED(rc)) eventWait(&g_appletLibraryAppletLaunchableEvent, U64_MAX); + + return rc; +} + Result appletSetScreenShotPermission(s32 val) { IpcCommand c; ipcInitialize(&c); @@ -1522,13 +1544,16 @@ static Result _appletGetIndirectLayerConsumerHandle(Service* srv, u64 *out) { return rc; } -Result appletCreateLibraryApplet(AppletHolder *h, AppletId id, LibAppletMode mode) { +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; - rc = _appletCreateLibraryApplet(&h->s, id, mode); + 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 @@ -1537,6 +1562,14 @@ Result appletCreateLibraryApplet(AppletHolder *h, AppletId id, LibAppletMode mod return rc; } +Result appletCreateLibraryApplet(AppletHolder *h, AppletId id, LibAppletMode mode) { + return _appletHolderCreate(h, id, mode, false); +} + +Result appletCreateLibraryAppletSelf(AppletHolder *h, AppletId id, LibAppletMode mode) { + return _appletHolderCreate(h, id, mode, true); +} + void appletHolderClose(AppletHolder *h) { eventClose(&h->StateChangedEvent); serviceClose(&h->s); @@ -1556,6 +1589,19 @@ Result appletHolderGetIndirectLayerConsumerHandle(AppletHolder *h, u64 *out) { return 0; } +Result appletHolderStart(AppletHolder *h) { + Result rc=0; + + if (!serviceIsActive(&h->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + if (!h->creating_self) rc = _appletWaitLibraryAppletLaunchableEvent(); + + if (R_SUCCEEDED(rc)) rc = _appletCmdNoIO(&h->s, 10);//Start + + return rc; +} + Result appletCreateStorage(AppletStorage *s, s64 size) { memset(s, 0, sizeof(AppletStorage));