From 933cfb543dd7189c760af27301142c63ce8f2afd Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 14 Jul 2019 17:42:46 -0400 Subject: [PATCH] Added support for applet ApplicationCopyright. Fixed a comment. --- nx/include/switch/services/applet.h | 30 ++++++- nx/source/services/applet.c | 133 ++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h index 8defa352..d5b8fd64 100644 --- a/nx/include/switch/services/applet.h +++ b/nx/include/switch/services/applet.h @@ -161,7 +161,7 @@ typedef struct { /// Initialize applet, called automatically during app startup. Result appletInitialize(void); -/// Exit applet, called automatically during app startup. +/// Exit applet, called automatically during app exit. void appletExit(void); Result appletGetAppletResourceUserId(u64 *out); @@ -271,6 +271,34 @@ Result appletRequestToShutdown(void); */ Result appletRequestToReboot(void); +/** + * @brief Initializes the ApplicationCopyrightFrameBuffer, with dimensions 1280x720 + the tmem for it. This is used as an overlay for screenshots. + * @note Only available with AppletType_*Application on 5.0.0+. + * @note Cleanup for this is handled automatically during app exit in \ref appletExit. + */ +Result appletInitializeApplicationCopyrightFrameBuffer(void); + +/** + * @brief Sets the RGBA8 image for use with \ref appletInitializeApplicationCopyrightFrameBuffer. Overrides the current image, if this was already used previously. + * @note Only available with AppletType_*Application on 5.0.0+. + * @note The specified coordinates and width/height must be within the bounds of the framebuffer setup by \ref appletInitializeApplicationCopyrightFrameBuffer. + * @param[in] buffer Input image buffer. + * @param[in] size Input image buffer size. + * @param[in] x X coordinate. Must not be negative. + * @param[in] y Y coordinate. Must not be negative. + * @param[in] width Image width. Must be >=1. + * @param[in] height Image height. Must be >=1. + * @param[in] mode WindowOriginMode. Should be at least 1. + */ +Result appletSetApplicationCopyrightImage(const void* buffer, size_t size, s32 x, s32 y, s32 width, s32 height, s32 mode); + +/** + * @brief Sets the visibility for the image set by \ref appletSetApplicationCopyrightImage, in screenshots. + * @note Only available with AppletType_*Application on 5.0.0+. + * @param[in] visible Whether the image is visible. The default is true. + */ +Result appletSetApplicationCopyrightVisibility(bool visible); + /** * @brief Gets ApplicationPlayStatistics. * @note Only available with AppletType_*Application on 5.0.0+. diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index ce0694a4..9926acaa 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -56,6 +56,9 @@ static AppletHookCookie g_appletFirstHook; static TransferMemory g_appletRecordingTmem; static u32 g_appletRecordingInitialized; +static TransferMemory g_appletCopyrightTmem; +static bool g_appletCopyrightInitialized; + static Event g_appletLibraryAppletLaunchableEvent; static AppletThemeColorType g_appletThemeColorType = AppletThemeColorType_Default; @@ -354,6 +357,11 @@ void appletExit(void) tmemClose(&g_appletRecordingTmem); g_appletRecordingInitialized = 0; } + + if (g_appletCopyrightInitialized) { + tmemClose(&g_appletCopyrightTmem); + g_appletCopyrightInitialized = 0; + } } } @@ -1579,6 +1587,131 @@ Result appletRequestToReboot(void) { return _appletCmdNoIO(&g_appletIFunctions, 71); } +static Result _appletInitializeApplicationCopyrightFrameBuffer(TransferMemory *tmem, s32 width, s32 height) { + IpcCommand c; + ipcInitialize(&c); + + ipcSendHandleCopy(&c, tmem->handle); + + struct { + u64 magic; + u64 cmd_id; + s32 width; + s32 height; + u64 size; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 100; + raw->width = width; + raw->height = height; + raw->size = tmem->size; + + 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; +} + +Result appletInitializeApplicationCopyrightFrameBuffer(void) { + Result rc=0; + s32 width = 1280; + s32 height = 720; + size_t size = 0x3C0000; + + if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + if (g_appletCopyrightInitialized) + return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + + rc = tmemCreate(&g_appletCopyrightTmem, size, Perm_None); + if (R_FAILED(rc)) return rc; + + rc = _appletInitializeApplicationCopyrightFrameBuffer(&g_appletCopyrightTmem, width, height); + if (R_FAILED(rc)) { + tmemClose(&g_appletCopyrightTmem); + return rc; + } + + g_appletCopyrightInitialized = 1; + + return rc; +} + +Result appletSetApplicationCopyrightImage(const void* buffer, size_t size, s32 x, s32 y, s32 width, s32 height, s32 mode) { + 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); + + ipcAddSendBuffer(&c, buffer, size, BufferType_Type1); + + struct { + u64 magic; + u64 cmd_id; + s32 x; + s32 y; + s32 width; + s32 height; + s32 mode; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 101; + raw->x = x; + raw->y = y; + raw->width = width; + raw->height = height; + raw->mode = mode; + + 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; +} + +Result appletSetApplicationCopyrightVisibility(bool visible) { + if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletCmdInBool(&g_appletIFunctions, visible, 102); +} + //Official sw has these under 'pdm'. Result appletQueryApplicationPlayStatistics(PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out) { IpcCommand c;