From eeabd3bed010e49ce545a8c38311978e60ce1508 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Fri, 30 Aug 2019 23:14:31 -0400 Subject: [PATCH] Added capssuSaveScreenShotWithUserData, capssuSaveScreenShotWithUserIds, capssuSaveScreenShotEx1, and capssuSaveScreenShotEx2. Updated params for capssuSaveScreenShot and capssuSaveScreenShotEx0. Added enum AlbumReportOption, and structs CapsApplicationData/CapsUserIdList. Updated CapsScreenShotAttribute. Updated docs. --- nx/include/switch/services/caps.h | 43 ++++++++--- nx/include/switch/services/capssu.h | 79 ++++++++++++++++++- nx/source/services/capssu.c | 116 ++++++++++++++++++++++++++-- 3 files changed, 217 insertions(+), 21 deletions(-) diff --git a/nx/include/switch/services/caps.h b/nx/include/switch/services/caps.h index 6ddd65bf..97365793 100644 --- a/nx/include/switch/services/caps.h +++ b/nx/include/switch/services/caps.h @@ -7,10 +7,30 @@ #pragma once #include "../types.h" #include "../services/sm.h" +#include "../services/acc.h" + +/// ImageOrientation +typedef enum { + AlbumImageOrientation_Unknown0 = 0, ///< Unknown. Default. + AlbumImageOrientation_Unknown1 = 1, ///< Unknown. + AlbumImageOrientation_Unknown2 = 2, ///< Unknown. + AlbumImageOrientation_Unknown3 = 3, ///< Unknown. +} AlbumImageOrientation; + +/// AlbumReportOption +typedef enum { + AlbumReportOption_Unknown0 = 0, ///< Unknown. + AlbumReportOption_Unknown1 = 1, ///< Unknown. + AlbumReportOption_Unknown2 = 2, ///< Unknown. + AlbumReportOption_Unknown3 = 3, ///< Unknown. +} AlbumReportOption; typedef struct { - u32 unk_x0; - u8 unk_x4[0x3c]; + u32 unk_x0; ///< Always set to 0 by official sw. + u32 orientation; ///< \ref AlbumImageOrientation + u32 unk_x8; ///< Always set to 0 by official sw. + u32 unk_xc; ///< Always set to 1 by official sw. + u8 unk_x10[0x30]; ///< Always set to 0 by official sw. } CapsScreenShotAttribute; /// AlbumFileDateTime. This corresponds to each field in the Album entry filename, prior to the "-". @@ -44,13 +64,18 @@ typedef struct { u8 data[0x20]; } CapsApplicationAlbumEntry; -/// ImageOrientation -typedef enum { - AlbumImageOrientation_Unknown0 = 0, ///< Unknown. - AlbumImageOrientation_Unknown1 = 1, ///< Unknown. - AlbumImageOrientation_Unknown2 = 2, ///< Unknown. - AlbumImageOrientation_Unknown3 = 3, ///< Unknown. -} AlbumImageOrientation; +/// ApplicationData +typedef struct { + u8 userdata[0x400]; ///< UserData. + u32 size; ///< UserData size. +} CapsApplicationData; + +/// UserIdList +typedef struct { + union { u128 userIDs[ACC_USER_LIST_SIZE]; } PACKED; ///< userIDs. + u8 count; ///< Total userIDs. + u8 pad[7]; ///< Padding. +} CapsUserIdList; // Get the ShimLibraryVersion. u64 capsGetShimLibraryVersion(void); diff --git a/nx/include/switch/services/capssu.h b/nx/include/switch/services/capssu.h index b4e910c8..adfb0fab 100644 --- a/nx/include/switch/services/capssu.h +++ b/nx/include/switch/services/capssu.h @@ -11,12 +11,83 @@ /// Initialize caps:su. Only available on [4.0.0+]. Result capssuInitialize(void); + +/// Exit caps:su. void capssuExit(void); + +/// Gets the Service for caps:su. Service* capssuGetServiceSession(void); -/// Same as \ref capssuSaveScreenShotEx0, except this uses an all-zero CapsScreenShotAttribute where the first u32 is set to attr_val. attr_val can be zero. -Result capssuSaveScreenShot(const void* buffer, size_t size, u32 unk, u32 attr_val, CapsApplicationAlbumEntry *out); +/** + * @brief This is a wrapper for \ref capssuSaveScreenShotEx0. + * @note This uses an all-zero \ref CapsScreenShotAttribute with orientation = input orientation, and unk_xc = 1. + * @param[in] buffer RGBA8 1280x720 image buffer. + * @param[in] size Size of the buffer. + * @param[in] reportoption \ref AlbumReportOption + * @param[in] orientation \ref AlbumImageOrientation + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShot(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, CapsApplicationAlbumEntry *out); -/// Saves an Album screenshot using the specified gfx data in buffer (1280x720 RGBA8), size must be at least 0x384000. unk can be zero. -Result capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScreenShotAttribute *attr, u32 unk, CapsApplicationAlbumEntry *out); +/** + * @brief Similar to \ref capssuSaveScreenShot, except this is a wrapper for \ref capssuSaveScreenShotEx1. + * @note This uses an all-zero \ref CapsScreenShotAttribute with orientation = input orientation, and unk_xc = 1. + * @note Only available on [8.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer. + * @param[in] reportoption \ref AlbumReportOption + * @param[in] orientation \ref AlbumImageOrientation + * @param[in] userdata Input UserData buffer. If NULL, the \ref CapsApplicationData will be empty. + * @param[in] userdata_size Input UserData size, must be within bounds for CapsApplicationData::userdata. If 0, the \ref CapsApplicationData will be empty. + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotWithUserData(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const void* userdata, size_t userdata_size, CapsApplicationAlbumEntry *out); + +/** + * @brief Similar to \ref capssuSaveScreenShot, except this is a wrapper for \ref capssuSaveScreenShotEx2. + * @note This uses an all-zero \ref CapsScreenShotAttribute with orientation = input orientation, and unk_xc = 1. + * @note Only available on [6.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer. + * @param[in] reportoption \ref AlbumReportOption + * @param[in] orientation \ref AlbumImageOrientation + * @param[in] userIDs Input array of account userIDs. If NULL, the \ref CapsUserIdList will be empty. + * @param[in] userID_count Size of the userID array in entries, must be within bounds for CapsUserIdList::userIDs. If 0, the \ref CapsUserIdList will be empty. + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotWithUserIds(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const u128* userIDs, size_t userID_count, CapsApplicationAlbumEntry *out); + +/** + * @brief Saves an Album screenshot using the specified gfx data in the buffer, with the specified \ref CapsScreenShotAttribute. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer, must be at least 0x384000. + * @param[in] attr \ref CapsScreenShotAttribute + * @param[in] reportoption \ref AlbumReportOption + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotEx0(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out); + +/** + * @brief Same as \ref capssuSaveScreenShotEx0, except this allows specifying the \ref CapsApplicationData. + * @note Only available on [8.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer, must be at least 0x384000. + * @param[in] attr \ref CapsScreenShotAttribute + * @param[in] reportoption \ref AlbumReportOption + * @parma[in] appdata \ref CapsApplicationData + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotEx1(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationData *appdata, CapsApplicationAlbumEntry *out); + +/** + * @brief Same as \ref capssuSaveScreenShotEx0, except this allows specifying the \ref CapsUserIdList. + * @note Only available on [6.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer, must be at least 0x384000. + * @param[in] attr \ref CapsScreenShotAttribute + * @param[in] reportoption \ref AlbumReportOption + * @parma[in] list \ref CapsUserIdList + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotEx2(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsUserIdList *list, CapsApplicationAlbumEntry *out); diff --git a/nx/source/services/capssu.c b/nx/source/services/capssu.c index d9e6c957..2bc11744 100644 --- a/nx/source/services/capssu.c +++ b/nx/source/services/capssu.c @@ -7,6 +7,7 @@ #include "services/applet.h" #include "services/caps.h" #include "services/capssu.h" +#include "services/acc.h" #include "services/sm.h" static Service g_capssuSrv; @@ -87,7 +88,7 @@ static Result _capssuSetShimLibraryVersion(u64 version) { return rc; } -static Result _capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScreenShotAttribute *attr, u32 unk, CapsApplicationAlbumEntry *out) { +static Result _capssuSaveScreenShotEx0(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out) { u64 AppletResourceUserId = 0; appletGetAppletResourceUserId(&AppletResourceUserId); @@ -98,7 +99,7 @@ static Result _capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScre u64 magic; u64 cmd_id; CapsScreenShotAttribute attr; - u32 unk; + u32 reportoption; u64 AppletResourceUserId; } *raw; @@ -110,7 +111,7 @@ static Result _capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScre raw->magic = SFCI_MAGIC; raw->cmd_id = 203; raw->attr = *attr; - raw->unk = unk; + raw->reportoption = reportoption; raw->AppletResourceUserId = AppletResourceUserId; Result rc = serviceIpcDispatch(&g_capssuSrv); @@ -134,16 +135,115 @@ static Result _capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScre return rc; } -Result capssuSaveScreenShot(const void* buffer, size_t size, u32 unk, u32 attr_val, CapsApplicationAlbumEntry *out) { +static Result _capssuSaveScreenShotEx(u64 cmd_id, bool pid, const void* argbuf, size_t argbuf_size, const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + CapsScreenShotAttribute attr; + u32 reportoption; + u64 AppletResourceUserId; + } *raw; + + if (pid) ipcSendPid(&c); + ipcAddSendBuffer(&c, argbuf, argbuf_size, BufferType_Normal); + ipcAddSendBuffer(&c, buffer, size, BufferType_Type1); + + raw = serviceIpcPrepareHeader(&g_capssuSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->attr = *attr; + raw->reportoption = reportoption; + raw->AppletResourceUserId = AppletResourceUserId; + + Result rc = serviceIpcDispatch(&g_capssuSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + CapsApplicationAlbumEntry out; + } *resp; + + serviceIpcParse(&g_capssuSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out) *out = resp->out; + } + + return rc; +} + +Result capssuSaveScreenShot(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, CapsApplicationAlbumEntry *out) { CapsScreenShotAttribute attr; memset(&attr, 0, sizeof(attr)); - attr.unk_x0 = attr_val; + attr.orientation = orientation; + attr.unk_xc = 1; - return _capssuSaveScreenShotEx0(buffer, size, &attr, unk, out); + return _capssuSaveScreenShotEx0(buffer, size, &attr, reportoption, out); } -Result capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScreenShotAttribute *attr, u32 unk, CapsApplicationAlbumEntry *out) { - return _capssuSaveScreenShotEx0(buffer, size, attr, unk, out); +Result capssuSaveScreenShotWithUserData(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const void* userdata, size_t userdata_size, CapsApplicationAlbumEntry *out) { + CapsScreenShotAttribute attr; + CapsApplicationData appdata; + + if (userdata_size > sizeof(appdata).userdata) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + memset(&attr, 0, sizeof(attr)); + attr.orientation = orientation; + attr.unk_xc = 1; + + memset(&appdata, 0, sizeof(appdata)); + if (userdata && userdata_size) memcpy(appdata.userdata, userdata, userdata_size); + appdata.size = userdata_size; + + return capssuSaveScreenShotEx1(buffer, size, &attr, reportoption, &appdata, out); +} + +Result capssuSaveScreenShotWithUserIds(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const u128* userIDs, size_t userID_count, CapsApplicationAlbumEntry *out) { + CapsScreenShotAttribute attr; + CapsUserIdList list; + + if (userID_count > ACC_USER_LIST_SIZE) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + memset(&attr, 0, sizeof(attr)); + attr.orientation = orientation; + attr.unk_xc = 1; + + memset(&list, 0, sizeof(list)); + if (userIDs && userID_count) memcpy(list.userIDs, userIDs, userID_count*sizeof(u128)); + list.count = userID_count; + + return capssuSaveScreenShotEx2(buffer, size, &attr, reportoption, &list, out); +} + +Result capssuSaveScreenShotEx0(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out) { + return _capssuSaveScreenShotEx0(buffer, size, attr, reportoption, out); +} + +Result capssuSaveScreenShotEx1(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationData *appdata, CapsApplicationAlbumEntry *out) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _capssuSaveScreenShotEx(205, true, appdata, sizeof(*appdata), buffer, size, attr, reportoption, out); +} + +Result capssuSaveScreenShotEx2(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsUserIdList *list, CapsApplicationAlbumEntry *out) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _capssuSaveScreenShotEx(210, false, list, sizeof(*list), buffer, size, attr, reportoption, out); }