From 98fbadc77872cfdd13731870b6628d94c8266e5d Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 1 Aug 2019 12:24:22 -0400 Subject: [PATCH] Added appletUpdateLastForegroundCaptureImage, appletUpdateCallerAppletCaptureImage, appletGetLastForegroundCaptureImageEx, appletGetLastApplicationCaptureImageEx, appletGetCallerAppletCaptureImageEx, appletTakeScreenShotOfOwnLayer, appletCopyBetweenCaptureBuffers, appletClearCaptureBuffer, appletClearAppletTransitionBuffer, appletAcquireLastApplicationCaptureSharedBuffer, appletReleaseLastApplicationCaptureSharedBuffer, appletAcquireLastForegroundCaptureSharedBuffer, appletReleaseLastForegroundCaptureSharedBuffer, appletAcquireCallerAppletCaptureSharedBuffer, appletReleaseCallerAppletCaptureSharedBuffer, and appletTakeScreenShotOfOwnLayerEx. --- nx/include/switch/services/applet.h | 126 ++++++++++++ nx/source/services/applet.c | 305 ++++++++++++++++++++++++++++ 2 files changed, 431 insertions(+) diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h index c1dc9d6b..18fc4328 100644 --- a/nx/include/switch/services/applet.h +++ b/nx/include/switch/services/applet.h @@ -166,6 +166,13 @@ typedef enum { AppletWirelessPriorityMode_Unknown2 = 2, ///< Unknown. } AppletWirelessPriorityMode; +/// CaptureSharedBuffer for the IDisplayController commands. +typedef enum { + AppletCaptureSharedBuffer_LastApplication = 0, ///< LastApplication + AppletCaptureSharedBuffer_LastForeground = 1, ///< LastForeground + AppletCaptureSharedBuffer_CallerApplet = 2, ///< CallerApplet +} AppletCaptureSharedBuffer; + /// applet hook function. typedef void (*AppletHookFn)(AppletHookType hook, void* param); @@ -649,6 +656,125 @@ Result appletChangeMainAppletMasterVolume(float volume, u64 unk); */ Result appletSetTransparentVolumeRate(float val); +// IDisplayController + +/** + * @brief Update the LastForeground CaptureImage. + */ +Result appletUpdateLastForegroundCaptureImage(void); + +/** + * @brief Update the CallerApplet CaptureImage. + */ +Result appletUpdateCallerAppletCaptureImage(void); + +/** + * @brief Gets the LastForeground CaptureImage. + * @param[out] buffer Output buffer containing the 1280x720 RGBA8 image. + * @param[out] size Buffer size, must match 0x384000. + * @param[out] flag Output flag. + */ +Result appletGetLastForegroundCaptureImageEx(void* buffer, size_t size, bool *flag); + +/** + * @brief Gets the LastApplication CaptureImage. + * @param[out] buffer Output buffer containing the 1280x720 RGBA8 image. + * @param[out] size Buffer size, must match 0x384000. + * @param[out] flag Output flag. + */ +Result appletGetLastApplicationCaptureImageEx(void* buffer, size_t size, bool *flag); + +/** + * @brief Gets the CallerApplet CaptureImage. + * @param[out] buffer Output buffer containing the 1280x720 RGBA8 image. + * @param[out] size Buffer size, must match 0x384000. + * @param[out] flag Output flag. + */ +Result appletGetCallerAppletCaptureImageEx(void* buffer, size_t size, bool *flag); + +/** + * @brief Takes a screenshot of the current applet Layer into the specified CaptureSharedBuffer. + * @note Only available with [2.0.0+]. + * @param[in] flag Flag. + * @param[in] captureBuf \ref AppletCaptureSharedBuffer + */ +Result appletTakeScreenShotOfOwnLayer(bool flag, AppletCaptureSharedBuffer captureBuf); + +/** + * @brief Copies image data from a CaptureSharedBuffer to another CaptureSharedBuffer. + * @note Only available with [5.0.0+]. + * @param[in] dstCaptureBuf Destination \ref AppletCaptureSharedBuffer. + * @param[in] srcCaptureBuf Source \ref AppletCaptureSharedBuffer. + */ +Result appletCopyBetweenCaptureBuffers(AppletCaptureSharedBuffer dstCaptureBuf, AppletCaptureSharedBuffer srcCaptureBuf); + +/** + * @brief Clear the input CaptureSharedBuffer with the specified color. + * @note Only available with [3.0.0+]. + * @param[in] flag Flag. + * @param[in] captureBuf \ref AppletCaptureSharedBuffer + * @param[in] color RGBA8 color. + */ +Result appletClearCaptureBuffer(bool flag, AppletCaptureSharedBuffer captureBuf, u32 color); + +/** + * @brief Clear the AppletTransitionBuffer with the specified color. + * @note Only available with [3.0.0+]. + * @param[in] color RGBA8 color. + */ +Result appletClearAppletTransitionBuffer(u32 color); + +/** + * @brief Acquire the LastApplication CaptureSharedBuffer. + * @note Only available with [4.0.0+]. + * @param[out] flag Output flag. + * @param[out] id Output ID. + */ +Result appletAcquireLastApplicationCaptureSharedBuffer(bool *flag, s32 *id); + +/** + * @brief Release the LastApplication CaptureSharedBuffer. + * @note Only available with [4.0.0+]. + */ +Result appletReleaseLastApplicationCaptureSharedBuffer(void); + +/** + * @brief Acquire the LastForeground CaptureSharedBuffer. + * @note Only available with [4.0.0+]. + * @param[out] flag Output flag. + * @param[out] id Output ID. + */ +Result appletAcquireLastForegroundCaptureSharedBuffer(bool *flag, s32 *id); + +/** + * @brief Release the LastForeground CaptureSharedBuffer. + * @note Only available with [4.0.0+]. + */ +Result appletReleaseLastForegroundCaptureSharedBuffer(void); + +/** + * @brief Acquire the CallerApplet CaptureSharedBuffer. + * @note Only available with [4.0.0+]. + * @param[out] flag Output flag. + * @param[out] id Output ID. + */ +Result appletAcquireCallerAppletCaptureSharedBuffer(bool *flag, s32 *id); + +/** + * @brief Release the CallerApplet CaptureSharedBuffer. + * @note Only available with [4.0.0+]. + */ +Result appletReleaseCallerAppletCaptureSharedBuffer(void); + +/** + * @brief Takes a screenshot of the current applet Layer into the specified CaptureSharedBuffer. Same as \ref appletTakeScreenShotOfOwnLayer except for the additional immediately param. + * @note Only available with [6.0.0+]. + * @param[in] flag0 Flag0. + * @param[in] immediately Whether the screenshot should be taken immediately. + * @param[in] captureBuf \ref AppletCaptureSharedBuffer + */ +Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCaptureSharedBuffer captureBuf); + // ILibraryAppletCreator /** diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index f9e25809..a22f8f6b 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -2082,6 +2082,311 @@ Result appletSetTransparentVolumeRate(float val) { return rc; } +// IDisplayController + +Result appletUpdateLastForegroundCaptureImage(void) { + return _appletCmdNoIO(&g_appletIDisplayController, 1); +} + +Result appletUpdateCallerAppletCaptureImage(void) { + return _appletCmdNoIO(&g_appletIDisplayController, 4); +} + +static Result _appletGetCaptureImageEx(void* buffer, size_t size, bool *flag, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + ipcAddRecvBuffer(&c, buffer, size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + + Result rc = serviceIpcDispatch(&g_appletIDisplayController); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u8 flag; + } *resp; + + serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && flag) *flag = resp->flag!=0; + } + + return rc; +} + +Result appletGetLastForegroundCaptureImageEx(void* buffer, size_t size, bool *flag) { + return _appletGetCaptureImageEx(buffer, size, flag, 5); +} + +Result appletGetLastApplicationCaptureImageEx(void* buffer, size_t size, bool *flag) { + return _appletGetCaptureImageEx(buffer, size, flag, 6); +} + +Result appletGetCallerAppletCaptureImageEx(void* buffer, size_t size, bool *flag) { + return _appletGetCaptureImageEx(buffer, size, flag, 7); +} + +Result appletTakeScreenShotOfOwnLayer(bool flag, AppletCaptureSharedBuffer captureBuf) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 flag; + s32 captureBuf; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 8; + raw->flag = flag!=0; + raw->captureBuf = captureBuf; + + Result rc = serviceIpcDispatch(&g_appletIDisplayController); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result appletCopyBetweenCaptureBuffers(AppletCaptureSharedBuffer dstCaptureBuf, AppletCaptureSharedBuffer srcCaptureBuf) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + s32 dstCaptureBuf; + s32 srcCaptureBuf; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 9; + raw->dstCaptureBuf = dstCaptureBuf; + raw->srcCaptureBuf = srcCaptureBuf; + + Result rc = serviceIpcDispatch(&g_appletIDisplayController); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result appletClearCaptureBuffer(bool flag, AppletCaptureSharedBuffer captureBuf, u32 color) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 flag; + s32 captureBuf; + u32 color; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 20; + raw->flag = flag!=0; + raw->captureBuf = captureBuf; + raw->color = color; + + Result rc = serviceIpcDispatch(&g_appletIDisplayController); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result appletClearAppletTransitionBuffer(u32 color) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletCmdInU32(&g_appletIDisplayController, color, 21); +} + +static Result _appletAcquireCaptureSharedBuffer(bool *flag, s32 *id, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + + Result rc = serviceIpcDispatch(&g_appletIDisplayController); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u8 flag; + s32 id; + } *resp; + + serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && flag) *flag = resp->flag!=0; + if (R_SUCCEEDED(rc) && id) *id = resp->id; + } + + return rc; +} + +Result appletAcquireLastApplicationCaptureSharedBuffer(bool *flag, s32 *id) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletAcquireCaptureSharedBuffer(flag, id, 22); +} + +Result appletReleaseLastApplicationCaptureSharedBuffer(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletCmdNoIO(&g_appletIDisplayController, 23); +} + +Result appletAcquireLastForegroundCaptureSharedBuffer(bool *flag, s32 *id) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletAcquireCaptureSharedBuffer(flag, id, 24); +} + +Result appletReleaseLastForegroundCaptureSharedBuffer(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletCmdNoIO(&g_appletIDisplayController, 25); +} + +Result appletAcquireCallerAppletCaptureSharedBuffer(bool *flag, s32 *id) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletAcquireCaptureSharedBuffer(flag, id, 26); +} + +Result appletReleaseCallerAppletCaptureSharedBuffer(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _appletCmdNoIO(&g_appletIDisplayController, 27); +} + +Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCaptureSharedBuffer captureBuf) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 flag0; + u8 immediately; + s32 captureBuf; + } *raw; + + raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 28; + raw->flag0 = flag0!=0; + raw->immediately = immediately!=0; + raw->captureBuf = captureBuf; + + Result rc = serviceIpcDispatch(&g_appletIDisplayController); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + // ILibraryAppletCreator static Result _appletCreateLibraryApplet(Service* srv_out, AppletId id, LibAppletMode mode) {