From 446aaf2a55ddaded55d7c29c8e5f0b9623881b47 Mon Sep 17 00:00:00 2001 From: HookedBehemoth Date: Fri, 17 Jan 2020 01:29:28 +0100 Subject: [PATCH] add capsa IAlbumAccessorSession and more capsa calls (#363) * add capsa IAlbumAccessorSession * add documentation for capsa and change parameter order and names for image loading * add CapsLoadAlbumScreenShotImageOutput for caps:a * add remaining LoadAlbumScreenShot- calls * add more calls, add structs and add doc * fix query and use count instead of size for listing --- nx/include/switch/services/caps.h | 94 ++++--- nx/include/switch/services/capsa.h | 380 +++++++++++++++++++++++++++-- nx/include/switch/services/capsu.h | 8 +- nx/source/services/capsa.c | 329 ++++++++++++++++++++++--- nx/source/services/capsu.c | 2 +- 5 files changed, 718 insertions(+), 95 deletions(-) diff --git a/nx/include/switch/services/caps.h b/nx/include/switch/services/caps.h index 1fa9f5a6..0aa966f1 100644 --- a/nx/include/switch/services/caps.h +++ b/nx/include/switch/services/caps.h @@ -18,13 +18,13 @@ typedef enum { /// AlbumReportOption typedef enum { - AlbumReportOption_Disable = 0, ///< Don't display the screenshot-taken Overlay-applet notification. - AlbumReportOption_Enable = 1, ///< Display the screenshot-taken Overlay notification. + AlbumReportOption_Disable = 0, ///< Don't display the screenshot-taken Overlay-applet notification. + AlbumReportOption_Enable = 1, ///< Display the screenshot-taken Overlay notification. } AlbumReportOption; typedef enum { - CapsAlbumStorage_Nand = 0, ///< Nand - CapsAlbumStorage_Sd = 1, ///< Sd + CapsAlbumStorage_Nand = 0, ///< Nand + CapsAlbumStorage_Sd = 1, ///< Sd } CapsAlbumStorage; /// ContentType @@ -70,38 +70,38 @@ typedef struct { /// AlbumFileDateTime. This corresponds to each field in the Album entry filename, prior to the "-": "YYYYMMDDHHMMSSII". typedef struct { - u16 year; ///< Year. - u8 month; ///< Month. - u8 day; ///< Day of the month. - u8 hour; ///< Hour. - u8 minute; ///< Minute. - u8 second; ///< Second. - u8 id; ///< Unique ID for when there's multiple Album files with the same timestamp. + u16 year; ///< Year. + u8 month; ///< Month. + u8 day; ///< Day of the month. + u8 hour; ///< Hour. + u8 minute; ///< Minute. + u8 second; ///< Second. + u8 id; ///< Unique ID for when there's multiple Album files with the same timestamp. } CapsAlbumFileDateTime; /// AlbumEntryId typedef struct { - u64 application_id; ///< ApplicationId - CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime - u8 storage; ///< \ref CapsAlbumStorage - u8 content; ///< \ref CapsAlbumFileContents - u32 pad_x12; ///< Set to 0 by official software - u16 pad_x16; ///< Set to 0 by official software + u64 application_id; ///< ApplicationId + CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime + u8 storage; ///< \ref CapsAlbumStorage + u8 content; ///< \ref CapsAlbumFileContents + u32 pad_x12; ///< Set to 0 by official software + u16 pad_x16; ///< Set to 0 by official software } PACKED CapsAlbumFileId; /// AlbumEntry typedef struct { - u64 size; ///< Size. - CapsAlbumFileId file_id; ///< \ref CapsAlbumFileId + u64 size; ///< Size. + CapsAlbumFileId file_id; ///< \ref CapsAlbumFileId } CapsAlbumEntry; /// ApplicationAlbumEntry typedef struct { union { - u8 data[0x20]; ///< Data. + u8 data[0x20]; ///< Data. struct { - u8 unk_x0[0x20]; ///< Unknown. + u8 unk_x0[0x20]; ///< Unknown. } v0; ///< Pre-7.0.0 struct { @@ -115,15 +115,15 @@ typedef struct { /// ApplicationAlbumFileEntry typedef struct { - CapsApplicationAlbumEntry entry; ///< \ref CapsApplicationAlbumEntry - CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime - u64 unk_x28; ///< Unknown. + CapsApplicationAlbumEntry entry; ///< \ref CapsApplicationAlbumEntry + CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime + u64 unk_x28; ///< Unknown. } CapsApplicationAlbumFileEntry; /// ApplicationData typedef struct { - u8 userdata[0x400]; ///< UserData. - u32 size; ///< UserData size. + u8 userdata[0x400]; ///< UserData. + u32 size; ///< UserData size. } CapsApplicationData; /// AlbumFileContents @@ -140,25 +140,31 @@ typedef enum { } CapsAlbumContentsUsageFlag; typedef struct { - s64 count; - s64 size; - u32 flags; - u8 file_contents; - u8 pad_x15[0x3]; + s64 count; ///< Count. + s64 size; ///< Size. Used storage space. + u32 flags; ///< \ref CapsAlbumContentsUsageFlag + u8 file_contents; ///< \ref CapsAlbumFileContents + u8 pad_x15[0x3]; ///< Unused } CapsAlbumContentsUsage; typedef struct { - CapsAlbumContentsUsage usages[2]; + CapsAlbumContentsUsage usages[2]; ///< \ref CapsAlbumContentsUsage } CapsAlbumUsage2; typedef struct { - CapsAlbumContentsUsage usages[3]; + CapsAlbumContentsUsage usages[3]; ///< \ref CapsAlbumContentsUsage } CapsAlbumUsage3; typedef struct { - CapsAlbumContentsUsage usages[16]; + CapsAlbumContentsUsage usages[16]; ///< \ref CapsAlbumContentsUsage } CapsAlbumUsage16; +/// OverlayThumbnailData +typedef struct { + CapsAlbumFileId file_id; ///< \ref CapsAlbumFileId + u64 size; ///< Size. +} CapsOverlayThumbnailData; + /// UserIdList typedef struct { AccountUid uids[ACC_USER_LIST_SIZE]; ///< \ref AccountUid @@ -175,6 +181,26 @@ typedef struct { u8 reserved[0xac]; ///< Unused. } CapsLoadAlbumScreenShotImageOutputForApplication; +/// LoadAlbumScreenShotImageOutput +typedef struct { + s64 width; ///< Width. Official sw copies this to a s32 output field. + s64 height; ///< Height. Official sw copies this to a s32 output field. + CapsScreenShotAttribute attr; ///< \ref CapsScreenShotAttribute + u8 unk_x50[0x400]; ///< Unused. +} CapsLoadAlbumScreenShotImageOutput; + +/// AlbumFileContentsFlag +typedef enum { + CapsAlbumFileContentsFlag_ScreenShot = BIT(0), ///< Query for ScreenShot files. + CapsAlbumFileContentsFlag_Movie = BIT(1), ///< Query for Movie files. +} CapsAlbumFileContentsFlag; + +/// AlbumCache +typedef struct { + u64 count; ///< Count + u8 unk_x8[8]; ///< Unknown +} CapsAlbumCache; + /// Gets the ShimLibraryVersion. u64 capsGetShimLibraryVersion(void); diff --git a/nx/include/switch/services/capsa.h b/nx/include/switch/services/capsa.h index 2f5d458a..7dce12b8 100644 --- a/nx/include/switch/services/capsa.h +++ b/nx/include/switch/services/capsa.h @@ -18,31 +18,377 @@ void capsaExit(void); /// Gets the Service for caps:a. Service* capsaGetServiceSession(void); -Result capsaGetAlbumFileCount(CapsAlbumStorage storage, u64* count); -Result capsaGetAlbumFileList(CapsAlbumStorage storage, u64* count, CapsAlbumEntry* buffer, u64 size); -Result capsaLoadAlbumFile(const CapsAlbumFileId *file_id, u64 *out_size, void* workbuf, u64 workbuf_size); +/// Gets the Service for IAlbumAccessorSession, only initialized after \ref capsaOpenAlbumMovieStream was used (unaffected by using \ref capsaCloseAlbumMovieStream). +Service* capsaGetServiceSession_Accessor(void); + +/** + * @brief Gets the amount of files at a AlbumStorage. + * @param[in] storage \ref CapsAlbumStorage + * @param[out] count Amount of files. + */ +Result capsaGetAlbumFileCount(CapsAlbumStorage storage, u64 *count); + +/** + * @brief Gets a listing of \ref CapsAlbumEntry, where the AlbumFile's storage matches the input one. + * @param[in] storage \ref CapsAlbumStorage + * @param[out] out Total output entries. + * @param[out] entries Output array of \ref CapsAlbumEntry. + * @param[in] count Reserved entry count. + */ +Result capsaGetAlbumFileList(CapsAlbumStorage storage, u64 *out, CapsAlbumEntry *entries, u64 count); + +/** + * @brief Loads a file into the specified buffer. + * @param[in] file_id \ref CapsAlbumFileId + * @param[out] out_size Size of the AlbumFile. + * @param[out] filebuf File output buffer. + * @param[in] filebuf_size Size of the filebuf. + */ +Result capsaLoadAlbumFile(const CapsAlbumFileId *file_id, u64 *out_size, void* filebuf, u64 filebuf_size); + +/** + * @brief Deletes an AlbumFile corresponding to the specified \ref CapsAlbumFileId. + * @param[in] file_id \ref CapsAlbumFileId + */ Result capsaDeleteAlbumFile(const CapsAlbumFileId *file_id); + +/** + * @brief Copies an AlbumFile to the specified \ref CapsAlbumStorage. + * @param[in] file_id \ref CapsAlbumFileId + * @param[in] dst_storage \ref CapsAlbumStorage + */ Result capsaStorageCopyAlbumFile(const CapsAlbumFileId *file_id, CapsAlbumStorage dst_storage); -Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool* is_mounted); + +/** + * @brief Gets the mount status of the specified \ref CapsAlbumStorage. + * @param[in] storage \ref CapsAlbumStorage + * @param[out] is_mounted Boolean over whether the storage is mounted or not. + */ +Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool *is_mounted); + +/** + * @brief Returns the AlbumUsage for a specified \ref CapsAlbumStorage. + * @param[in] storage \ref CapsAlbumStorage + * @param[out] out \ref CapsAlbumUsage2 + */ Result capsaGetAlbumUsage(CapsAlbumStorage storage, CapsAlbumUsage2 *out); -Result capsaGetAlbumFileSize(const CapsAlbumFileId *file_id, u64* size); -Result capsaLoadAlbumFileThumbnail(const CapsAlbumFileId *file_id, u64 *out_size, void* workbuf, u64 workbuf_size); -/// Only available on [2.0.0+]. -Result capsaLoadAlbumScreenShotImage(u64* width, u64* height, const CapsAlbumFileId *file_id, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size); -Result capsaLoadAlbumScreenShotThumbnailImage(u64* width, u64* height, const CapsAlbumFileId *file_id, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size); -/// Only available on [3.0.0+]. -Result capsaLoadAlbumScreenShotImageEx(u64* width, u64* height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size); -Result capsaLoadAlbumScreenShotThumbnailImageEx(u64* width, u64* height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size); -/// Only available on [4.0.0+]. + +/** + * @brief Gets the size for the specified AlbumFile. + * @param[in] file_id \ref CapsAlbumFileId + * @param[out] size Size of the file. + */ +Result capsaGetAlbumFileSize(const CapsAlbumFileId *file_id, u64 *size); + +/** + * @brief Load the Thumbnail for the specified AlbumFile. + * @note Will always be 320x180. + * @param[in] file_id \ref CapsAlbumFileId + * @param[out] out_size Size of the Thumbnail. + * @param[out] image JPEG image output buffer. + * @param[in] image_size Image buffer size. + */ +Result capsaLoadAlbumFileThumbnail(const CapsAlbumFileId *file_id, u64 *out_size, void* image, u64 image_size); + +/** + * @brief Load the ScreenShotImage for the specified AlbumFile. + * @note Only available on [2.0.0+]. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[in] file_id \ref CapsAlbumFileId + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 1280x720. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsaLoadAlbumScreenShotImage(u64 *width, u64 *height, const CapsAlbumFileId *file_id, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Load the ScreenShotThumbnailImage for the specified AlbumFile. + * @note Only available on [2.0.0+]. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[in] file_id \ref CapsAlbumFileId + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 320x180. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsaLoadAlbumScreenShotThumbnailImage(u64 *width, u64 *height, const CapsAlbumFileId *file_id, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Load the ScreenShotImage for the specified AlbumFile. + * @note Only available on [3.0.0+]. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[in] file_id \ref CapsAlbumFileId + * @param[in] opts \ref CapsScreenShotDecodeOption + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 1280x720. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsaLoadAlbumScreenShotImageEx(u64 *width, u64 *height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Load the ScreenShotThumbnailImage for the specified AlbumFile. + * @note Only available on [3.0.0+]. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[in] file_id \ref CapsAlbumFileId + * @param[in] opts \ref CapsScreenShotDecodeOption + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 320x180. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsaLoadAlbumScreenShotThumbnailImageEx(u64 *width, u64 *height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Load the ScreenShotImage for the specified AlbumFile. + * @note Only available on [3.0.0+]. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[out] attr \ref CapsScreenShotAttribute + * @param[in] file_id \ref CapsAlbumFileId + * @param[in] opts \ref CapsScreenShotDecodeOption + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 1280x720. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsaLoadAlbumScreenShotImageEx0(u64 *width, u64 *height, CapsScreenShotAttribute *attr, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Returns the AlbumUsage for a specified \ref CapsAlbumStorage. + * @note Only available on [4.0.0+]. + * @param[in] storage \ref CapsAlbumStorage + * @param[out] out \ref CapsAlbumUsage3 + */ Result capsaGetAlbumUsage3(CapsAlbumStorage storage, CapsAlbumUsage3 *out); + +/** + * @brief Returns the result for a AlbumStorage mount. + * @note Only available on [4.0.0+]. + * @param[in] storage \ref CapsAlbumStorage + */ Result capsaGetAlbumMountResult(CapsAlbumStorage storage); + +/** + * @brief Returns the AlbumUsage for a specified \ref CapsAlbumStorage. + * @note Only available on [4.0.0+]. + * @param[in] storage \ref CapsAlbumStorage + * @param[out] out \ref CapsAlbumUsage16 + */ Result capsaGetAlbumUsage16(CapsAlbumStorage storage, CapsAlbumUsage16 *out); -Result capsaGetAutoSavingStorage(CapsAlbumStorage* storage); -Result capsaGetRequiredStorageSpaceSizeToCopyAll(CapsAlbumStorage dst_storage, CapsAlbumStorage src_storage, u64* out); -/// Only available on [4.0.0+]. -Result capsaLoadAlbumScreenShotThumbnailImageEx1(const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size, void* out, u64 out_size); +/** + * @brief Returns the start and end of the Applet Id range. + * @note Only available on [6.0.0+]. + * @param[out] success Returns bool over whether the call was handled or not. + * @param[out] min Mimimum applet id. Always 0x0100000000001000 + * @param[out] max Maximum applet id. Always 0x0100000000001FFF + */ +Result capsaGetMinMaxAppletId(bool* success, u64* min, u64* max); +/** + * @brief Gets the amount of files of the specified type at a AlbumStorage. + * @note Only available on [5.0.0+]. + * @param[in] storage \ref CapsAlbumStorage + * @param[in] flags \ref CapsAlbumFileContentsFlag + * @param[out] count Amount of files. + */ +Result capsaGetAlbumFileCountEx0(CapsAlbumStorage storage, u8 flags, u64 *count); + +/** + * @brief Gets a listing of \ref CapsAlbumEntry, where the AlbumFile's storage and type matches the input one. + * @note Only available on [5.0.0+]. + * @param[in] storage \ref CapsAlbumStorage + * @param[in] flags \ref CapsAlbumFileContentsFlag + * @param[out] out Total output entries. + * @param[out] entries Output array of \ref CapsAlbumEntry. + * @param[in] count Reserved entry count. + */ +Result capsaGetAlbumFileListEx0(CapsAlbumStorage storage, u8 flags, u64 *out, CapsAlbumEntry *entries, u64 count); + +/** + * @brief Returns the image from the last shown ScreenShot Overlay. + * @param[out] data \ref CapsOverlayThumbnailData + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 96×54. + */ +Result capsaGetLastOverlayScreenShotThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size); + +/** + * @brief Returns the image from the last shown Movie Overlay. + * @note Only available on [4.0.0+]. + * @param[out] data \ref CapsOverlayThumbnailData + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 96×54. + */ +Result capsaGetLastOverlayMovieThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size); + +/** + * @brief Gets the currently set autosaving storage. + * @note Wrapper around setsysGetPrimaryAlbumStorage but defaults to NAND if SD isn't available. + * @param[out] storage \ref CapsAlbumStorage + */ +Result capsaGetAutoSavingStorage(CapsAlbumStorage *storage); + +/** + * @brief Gets required size to copy all files from one Storage to another. + * @param[in] dst_storage \ref CapsAlbumStorage + * @param[in] src_storage \ref CapsAlbumStorage + * @param[out] out Required storage space size. + */ +Result capsaGetRequiredStorageSpaceSizeToCopyAll(CapsAlbumStorage dst_storage, CapsAlbumStorage src_storage, u64 *out); + +/** + * @brief Load the ScreenShotThumbnailImage for the specified AlbumFile. + * @note Only available on [3.0.0+]. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[out] attr \ref CapsScreenShotAttribute + * @param[in] file_id \ref CapsAlbumFileId + * @param[in] opts \ref CapsScreenShotDecodeOption + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 320x180. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsLoadAlbumScreenShotThumbnailImageEx0(u64 *width, u64 *height, CapsScreenShotAttribute *attr, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Load the ScreenShotImage for the specified AlbumFile. + * @note Only available on [4.0.0+]. + * @param[in] file_id \ref CapsAlbumFileId + * @param[in] opts \ref CapsScreenShotDecodeOption + * @param[out] out \ref CapsLoadAlbumScreenShotImageOutput + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 1280x720. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsaLoadAlbumScreenShotImageEx1(const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, CapsLoadAlbumScreenShotImageOutput *out, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Load the ScreenShotThumbnailImage for the specified AlbumFile. + * @note Only available on [4.0.0+]. + * @param[in] file_id \ref CapsAlbumFileId + * @param[in] opts \ref CapsScreenShotDecodeOption + * @param[out] out \ref CapsLoadAlbumScreenShotImageOutput + * @param[out] image RGBA8 image output buffer. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 320x180. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + */ +Result capsaLoadAlbumScreenShotThumbnailImageEx1(const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, CapsLoadAlbumScreenShotImageOutput *out, void* image, u64 image_size, void* workbuf, u64 workbuf_size); + +/** + * @brief Unmounts the specified AlbumStorage. + * @param[in] storage \ref CapsAlbumStorage + */ Result capsaForceAlbumUnmounted(CapsAlbumStorage storage); + +/** + * @brief Resets mount status for the specified AlbumStorage. + * @note Mounts the Storage if available. + * @param[in] storage \ref CapsAlbumStorage + */ Result capsaResetAlbumMountStatus(CapsAlbumStorage storage); + +/** + * @brief Refreshs Album Cache for the specified AlbumStorage. + * @param[in] storage \ref CapsAlbumStorage + */ Result capsaRefreshAlbumCache(CapsAlbumStorage storage); + +/** + * @brief Gets the AlbumCache of the specified AlbumStorage. + * @note use \ref capsaGetAlbumCacheEx instead. + * @param[in] storage \ref CapsAlbumStorage + * @param[out] cache \ref CapsAlbumCache + */ +Result capsaGetAlbumCache(CapsAlbumStorage storage, CapsAlbumCache *cache); + +/** + * @brief Gets the AlbumCache for the specified type of the specified AlbumStorage. + * @note Stubbed on [4.0.0+]. + * @param[in] storage \ref CapsAlbumStorage + * @param[in] contents \ref CapsAlbumFileContents + * @param[out] cache \ref CapsAlbumCache + */ +Result capsaGetAlbumCacheEx(CapsAlbumStorage storage, CapsAlbumFileContents contents, CapsAlbumCache *cache); + +/** + * @brief Opens an AlbumMovieStream. + * @note This opens IAlbumAccessorSession if not previously opened, it's closed during \ref capsaExit. + * @note Up to 4 streams can be open at the same time. Multiple streams can be open at the same time for the same \ref CapsAlbumFileId. + * @note Only available on [4.0.0+]. + * @param[out] stream Stream handle. + * @param[in] entry \ref CapsAlbumFileId + */ +Result capsaOpenAlbumMovieStream(u64 *stream, const CapsAlbumFileId *file_id); + +/** + * @brief Closes an AlbumMovieStream. + * @note Only available on [4.0.0+]. + * @param[in] stream Stream handle. + */ +Result capsaCloseAlbumMovieStream(u64 stream); + +/** + * @brief Gets the data size of an AlbumMovieStream. + * @note Only available on [4.0.0+]. + * @param[in] stream Stream handle. + * @param[out] size Size of the actual MP4, without the JPEG at the end. + */ +Result capsaGetAlbumMovieStreamSize(u64 stream, u64 *size); + +/** + * @brief Reads data from an AlbumMovieStream. + * @note offset(+size) must not be negative. offset and size must be aligned to 0x40000-bytes. + * @note When offset(+size) goes beyond the size from \ref capsaGetAlbumMovieStreamSize, the regions of the buffer which goes beyond that are cleared to 0, and actual_size is still set to the input size. + * @note Only available on [4.0.0+]. + * @param[in] stream Stream handle. + * @param[in] offset Offset. + * @param[out] Output data buffer. + * @param[in] size Data buffer size. + * @param[out] actual_size Actual read size. + */ +Result capsaReadMovieDataFromAlbumMovieReadStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size); + +/** + * @brief Gets the BrokenReason for an AlbumMovieStream. + * @note Official sw doesn't use this. + * @note Only available on [4.0.0+]. + * @param[in] stream Stream handle. + */ +Result capsaGetAlbumMovieReadStreamBrokenReason(u64 stream); + +/** + * @brief Gets the data size of an Image taken from an AlbumMovieStream. + * @note Only available on [4.0.0+]. + * @param[in] stream Stream handle. + * @param[out] size Expected size of an Image. + */ +Result capsaGetAlbumMovieReadStreamImageDataSize(u64 stream, u64 *size); + +/** + * @brief Reads data of an Image taken from an AlbumMovieStream. + * @note Only available on [4.0.0+]. + * @param[in] stream Stream handle. + * @param[in] offset Offset. + * @param[out] Output data buffer. + * @param[in] size Data buffer size. + * @param[out] actual_size Actual read size. + */ +Result capsaReadImageDataFromAlbumMovieReadStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size); + +/** + * @brief Gets the file attribute of an AlbumMovieStream. + * @note Only available on [4.0.0+]. + * @param[in] stream Stream handle. + * @param[out] attr \ref CapsScreenShotAttribute + */ +Result capsaReadFileAttributeFromAlbumMovieReadStream(u64 stream, CapsScreenShotAttribute *attr); diff --git a/nx/include/switch/services/capsu.h b/nx/include/switch/services/capsu.h index 7e4a11b8..06dfd090 100644 --- a/nx/include/switch/services/capsu.h +++ b/nx/include/switch/services/capsu.h @@ -98,9 +98,9 @@ Result capsuGetAlbumFileSize(const CapsApplicationAlbumFileEntry *entry, u64 *si * @param[in] userdata_maxsize Max size of the userdata buffer. Optional, can be 0. * @param[out] userdata_size Userdata size field, clamped to max size sizeof(CapsApplicationData::userdata) when needed. * @param[out] image RGBA8 image output buffer. - * @param[out] image_size Image buffer size, should be at least large enough for RGBA8 1280x720. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 1280x720. * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. - * @param[out] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. * @param[in] entry \ref CapsApplicationAlbumFileEntry * @param[in] option \ref CapsScreenShotDecodeOption */ @@ -115,9 +115,9 @@ Result capsuLoadAlbumScreenShotImage(s32 *width, s32 *height, CapsScreenShotAttr * @param[in] userdata_maxsize Max size of the userdata buffer. Optional, can be 0. * @param[out] userdata_size Userdata size field, clamped to max size sizeof(CapsApplicationData::userdata) when needed. * @param[out] image RGBA8 image output buffer. - * @param[out] image_size Image buffer size, should be at least large enough for RGBA8 320x180. + * @param[in] image_size Image buffer size, should be at least large enough for RGBA8 320x180. * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. - * @param[out] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + * @param[in] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. * @param[in] entry \ref CapsApplicationAlbumFileEntry * @param[in] option \ref CapsScreenShotDecodeOption */ diff --git a/nx/source/services/capsa.c b/nx/source/services/capsa.c index 2d004a33..bf571a1c 100644 --- a/nx/source/services/capsa.c +++ b/nx/source/services/capsa.c @@ -7,6 +7,7 @@ #include "services/capsa.h" static Service g_capsaSrv; +static Service g_capsaAccessor; NX_GENERATE_SERVICE_GUARD(capsa); @@ -15,6 +16,7 @@ Result _capsaInitialize(void) { } void _capsaCleanup(void) { + serviceClose(&g_capsaAccessor); serviceClose(&g_capsaSrv); } @@ -22,27 +24,31 @@ Service* capsaGetServiceSession(void) { return &g_capsaSrv; } -static Result _capsaCmdInU8NoOut(Service* srv, u8 inval, u32 cmd_id) { +Service* capsaGetServiceSession_Accessor(void) { + return &g_capsaAccessor; +} + +static Result _capsaCmdInU8NoOut(Service *srv, u8 inval, u32 cmd_id) { return serviceDispatchIn(srv, cmd_id, inval); } -Result capsaGetAlbumFileCount(CapsAlbumStorage storage, u64* count) { +Result capsaGetAlbumFileCount(CapsAlbumStorage storage, u64 *count) { u8 inval = storage; return serviceDispatchInOut(&g_capsaSrv, 0, inval, *count); } -Result capsaGetAlbumFileList(CapsAlbumStorage storage, u64* count, CapsAlbumEntry* buffer, u64 buffer_size) { +Result capsaGetAlbumFileList(CapsAlbumStorage storage, u64 *out, CapsAlbumEntry *entries, u64 count) { u8 inval = storage; - return serviceDispatchInOut(&g_capsaSrv, 1, inval, *count, + return serviceDispatchInOut(&g_capsaSrv, 1, inval, *out, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { buffer, buffer_size } }, + .buffers = { { entries, count * sizeof(CapsAlbumEntry) } }, ); } -Result capsaLoadAlbumFile(const CapsAlbumFileId *file_id, u64 *out_size, void* workbuf, u64 workbuf_size) { +Result capsaLoadAlbumFile(const CapsAlbumFileId *file_id, u64 *out_size, void* filebuf, u64 filebuf_size) { return serviceDispatchInOut(&g_capsaSrv, 2, *file_id, *out_size, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { workbuf, workbuf_size } }, + .buffers = { { filebuf, filebuf_size } }, ); } @@ -50,8 +56,8 @@ Result capsaDeleteAlbumFile(const CapsAlbumFileId *file_id) { return serviceDispatchIn(&g_capsaSrv, 3, *file_id); } -Result capsaStorageCopyAlbumFile(const CapsAlbumFileId* file_id, CapsAlbumStorage dst_storage) { - struct { +Result capsaStorageCopyAlbumFile(const CapsAlbumFileId *file_id, CapsAlbumStorage dst_storage) { + const struct { u8 storage; u8 pad_x1[0x7]; CapsAlbumFileId file_id; @@ -59,7 +65,7 @@ Result capsaStorageCopyAlbumFile(const CapsAlbumFileId* file_id, CapsAlbumStorag return serviceDispatchIn(&g_capsaSrv, 4, in); } -Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool* is_mounted) { +Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool *is_mounted) { u8 inval = storage; return serviceDispatchInOut(&g_capsaSrv, 5, inval, *is_mounted); } @@ -69,18 +75,18 @@ Result capsaGetAlbumUsage(CapsAlbumStorage storage, CapsAlbumUsage2 *out) { return serviceDispatchInOut(&g_capsaSrv, 6, inval, *out); } -Result capsaGetAlbumFileSize(const CapsAlbumFileId *file_id, u64* size) { +Result capsaGetAlbumFileSize(const CapsAlbumFileId *file_id, u64 *size) { return serviceDispatchInOut(&g_capsaSrv, 7, *file_id, *size); } -Result capsaLoadAlbumFileThumbnail(const CapsAlbumFileId *file_id, u64 *out_size, void* workbuf, u64 workbuf_size) { +Result capsaLoadAlbumFileThumbnail(const CapsAlbumFileId *file_id, u64 *out_size, void* image, u64 image_size) { return serviceDispatchInOut(&g_capsaSrv, 8, *file_id, *out_size, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { workbuf, workbuf_size } }, + .buffers = { { image, image_size } }, ); } -static Result _capsaLoadAlbumScreenshot(u64* width, u64* height, const CapsAlbumFileId *file_id, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size, u32 cmd_id) { +static Result _capsaLoadAlbumScreenshot(u64 *width, u64 *height, const CapsAlbumFileId *file_id, void* image, u64 image_size, void* workbuf, u64 workbuf_size, u32 cmd_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); struct { @@ -89,25 +95,27 @@ static Result _capsaLoadAlbumScreenshot(u64* width, u64* height, const CapsAlbum } out; Result rc = serviceDispatchInOut(&g_capsaSrv, cmd_id, *file_id, out, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { rawbuf, rawbuf_size }, { workbuf, workbuf_size } }, + .buffers = { { image, image_size }, { workbuf, workbuf_size } }, ); - *width = out.width; - *height = out.height; + if (R_SUCCEEDED(rc)) { + if (width) *width = out.width; + if (height) *height = out.height; + } return rc; } -Result capsaLoadAlbumScreenShotImage(u64* width, u64* height, const CapsAlbumFileId *file_id, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size) { - return _capsaLoadAlbumScreenshot(width, height, file_id, workbuf, workbuf_size, rawbuf, rawbuf_size, 9); +Result capsaLoadAlbumScreenShotImage(u64 *width, u64 *height, const CapsAlbumFileId *file_id, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenshot(width, height, file_id, image, image_size, workbuf, workbuf_size, 9); } -Result capsaLoadAlbumScreenShotThumbnailImage(u64* width, u64* height, const CapsAlbumFileId *file_id, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size) { - return _capsaLoadAlbumScreenshot(width, height, file_id, workbuf, workbuf_size, rawbuf, rawbuf_size, 10); +Result capsaLoadAlbumScreenShotThumbnailImage(u64 *width, u64 *height, const CapsAlbumFileId *file_id, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenshot(width, height, file_id, image, image_size, workbuf, workbuf_size, 10); } -static Result _capsaLoadAlbumScreenshotEx(u64* width, u64* height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size, u32 cmd_id) { +static Result _capsaLoadAlbumScreenshotEx(u64 *width, u64 *height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size, u32 cmd_id) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - struct { + const struct { CapsAlbumFileId file_id; CapsScreenShotDecodeOption opts; } in = { *file_id, *opts }; @@ -117,19 +125,49 @@ static Result _capsaLoadAlbumScreenshotEx(u64* width, u64* height, const CapsAlb } out; Result rc = serviceDispatchInOut(&g_capsaSrv, cmd_id, in, out, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { rawbuf, rawbuf_size }, { workbuf, workbuf_size } }, + .buffers = { { image, image_size }, { workbuf, workbuf_size } }, ); - *width = out.width; - *height = out.height; + if (R_SUCCEEDED(rc)) { + if (width) *width = out.width; + if (height) *height = out.height; + } return rc; } -Result capsaLoadAlbumScreenShotImageEx(u64* width, u64* height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size) { - return _capsaLoadAlbumScreenshotEx(width, height, file_id, opts, workbuf, workbuf_size, rawbuf, rawbuf_size, 12); +Result capsaLoadAlbumScreenShotImageEx(u64 *width, u64 *height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenshotEx(width, height, file_id, opts, image, image_size, workbuf, workbuf_size, 12); } -Result capsaLoadAlbumScreenShotThumbnailImageEx(u64* width, u64* height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* workbuf, u64 workbuf_size, void* rawbuf, u64 rawbuf_size) { - return _capsaLoadAlbumScreenshotEx(width, height, file_id, opts, workbuf, workbuf_size, rawbuf, rawbuf_size, 13); +Result capsaLoadAlbumScreenShotThumbnailImageEx(u64 *width, u64 *height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenshotEx(width, height, file_id, opts, image, image_size, workbuf, workbuf_size, 13); +} + +Result _capsaLoadAlbumScreenShotEx0(u64 *width, u64 *height, CapsScreenShotAttribute *attr, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size, u32 cmd_id) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { + CapsAlbumFileId file_id; + CapsScreenShotDecodeOption opts; + } in = { *file_id, *opts }; + struct { + CapsScreenShotAttribute attr; + s64 width; + s64 height; + } out = {0}; + Result rc = serviceDispatchInOut(&g_capsaSrv, cmd_id, in, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { image, image_size }, { workbuf, workbuf_size } }, + ); + if (R_SUCCEEDED(rc)) { + if (attr) *attr = out.attr; + if (width) *width = out.width; + if (height) *height = out.height; + } + return rc; +} + +Result capsaLoadAlbumScreenShotImageEx0(u64 *width, u64 *height, CapsScreenShotAttribute *attr, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenShotEx0(width, height, attr, file_id, opts, image, image_size, workbuf, workbuf_size, 14); } Result capsaGetAlbumUsage3(CapsAlbumStorage storage, CapsAlbumUsage3 *out) { @@ -152,34 +190,112 @@ Result capsaGetAlbumUsage16(CapsAlbumStorage storage, CapsAlbumUsage16 *out) { return serviceDispatchInOut(&g_capsaSrv, 17, inval, *out); } -Result capsaGetAutoSavingStorage(CapsAlbumStorage* storage) { - u8 tmpval = 0; - Result rc = serviceDispatchOut(&g_capsaSrv, 401, tmpval); - *storage = tmpval; +Result capsaGetMinMaxAppletId(bool *success, u64* min, u64* max) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u64 app_ids[2]; + struct { + bool success; + u8 pad[0x3]; + } out; + Result rc = serviceDispatchOut(&g_capsaSrv, 18, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, }, + .buffers = { { app_ids, sizeof(app_ids) }, }, + ); + if (R_SUCCEEDED(rc)) { + if (min) *min = app_ids[0]; + if (max) *max = app_ids[1]; + if (success) *success = out.success; + } return rc; } -Result capsaGetRequiredStorageSpaceSizeToCopyAll(CapsAlbumStorage dst_storage, CapsAlbumStorage src_storage, u64* out) { +Result capsaGetAlbumFileCountEx0(CapsAlbumStorage storage, u8 flags, u64 *count) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); struct { + u8 storage; + u8 pad_x1[7]; + u8 flags; + u8 pad_x9[7]; + } in = { storage, {0}, flags, {0} }; + return serviceDispatchInOut(&g_capsaSrv, 100, in, *count); +} + +Result capsaGetAlbumFileListEx0(CapsAlbumStorage storage, u8 flags, u64 *out, CapsAlbumEntry *entries, u64 count) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + struct { + u8 storage; + u8 pad_x1[7]; + u8 contents; + u8 pad_x9[7]; + } in = { storage, {0}, flags, {0} }; + return serviceDispatchInOut(&g_capsaSrv, 101, in, *out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { entries, count * sizeof(CapsAlbumEntry) } }, + ); +} + +Result _capsaGetLastOverlayThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size, u32 cmd_id) { + return serviceDispatchOut(&g_capsaSrv, cmd_id, *data, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, }, + .buffers = { { image, image_size }, }, + ); +} + +Result capsaGetLastOverlayScreenShotThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size) { + return _capsaGetLastOverlayThumbnail(data, image, image_size, 301); +} + +Result capsaGetLastOverlayMovieThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _capsaGetLastOverlayThumbnail(data, image, image_size, 302); +} + +Result capsaGetAutoSavingStorage(CapsAlbumStorage *storage) { + u8 tmpval = 0; + Result rc = serviceDispatchOut(&g_capsaSrv, 401, tmpval); + if (R_SUCCEEDED(rc)) { + if (storage) *storage = tmpval; + } + return rc; +} + +Result capsaGetRequiredStorageSpaceSizeToCopyAll(CapsAlbumStorage dst_storage, CapsAlbumStorage src_storage, u64 *out) { + const struct { u8 dest; u8 src; } in = { dst_storage, src_storage }; return serviceDispatchInOut(&g_capsaSrv, 501, in, *out); } -Result capsaLoadAlbumScreenShotThumbnailImageEx1(const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* work_buffer, u64 work_buffer_size, void* raw_buffer, u64 raw_buffer_size, void* out, u64 out_size) { +Result capsLoadAlbumScreenShotThumbnailImageEx0(u64 *width, u64 *height, CapsScreenShotAttribute *attr, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenShotEx0(width, height, attr, file_id, opts, image, image_size, workbuf, workbuf_size, 1001); +} + +Result _capsaLoadAlbumScreenShotEx1(const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, CapsLoadAlbumScreenShotImageOutput *out, void* image, u64 image_size, void* workbuf, u64 workbuf_size, u32 cmd_id) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - struct { + const struct { CapsAlbumFileId file_id; CapsScreenShotDecodeOption opts; } in = { *file_id, *opts }; - return serviceDispatchIn(&g_capsaSrv, 1003, in, + return serviceDispatchIn(&g_capsaSrv, cmd_id, in, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_FixedSize, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { out, out_size }, { raw_buffer, raw_buffer_size }, { work_buffer, work_buffer_size } }, + .buffers = { { out, sizeof(CapsLoadAlbumScreenShotImageOutput) }, { image, image_size }, { workbuf, workbuf_size } }, ); } +Result capsaLoadAlbumScreenShotImageEx1(const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, CapsLoadAlbumScreenShotImageOutput *out, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenShotEx1(file_id, opts, out, image, image_size, workbuf, workbuf_size, 1002); +} + +Result capsaLoadAlbumScreenShotThumbnailImageEx1(const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, CapsLoadAlbumScreenShotImageOutput *out, void* image, u64 image_size, void* workbuf, u64 workbuf_size) { + return _capsaLoadAlbumScreenShotEx1(file_id, opts, out, image, image_size, workbuf, workbuf_size, 1003); +} + Result capsaForceAlbumUnmounted(CapsAlbumStorage storage) { return _capsaCmdInU8NoOut(&g_capsaSrv, storage, 8001); } @@ -191,3 +307,138 @@ Result capsaResetAlbumMountStatus(CapsAlbumStorage storage) { Result capsaRefreshAlbumCache(CapsAlbumStorage storage) { return _capsaCmdInU8NoOut(&g_capsaSrv, storage, 8011); } + +Result capsaGetAlbumCache(CapsAlbumStorage storage, CapsAlbumCache *cache) { + return serviceDispatchInOut(&g_capsaSrv, 8012, storage, *cache); +} + +Result capsaGetAlbumCacheEx(CapsAlbumStorage storage, CapsAlbumFileContents contents, CapsAlbumCache *cache) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + struct { + u8 storage; + u8 contents; + } in = { storage, contents }; + return serviceDispatchInOut(&g_capsaSrv, 8013, in, *cache); +} + +static Result _capsaOpenAccessorSession(Service *srv_out) { + u64 AppletResourceUserId = appletGetAppletResourceUserId(); + + return serviceDispatchIn(&g_capsaSrv, 60002, AppletResourceUserId, + .in_send_pid = true, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} + +static Result _capsaOpenAlbumMovieReadStream(u64 *stream, const CapsAlbumFileId *file_id) { + return serviceDispatchInOut(&g_capsaAccessor, 2001, *file_id, *stream); +} + +static Result _capsaReadMovieDataFromAlbumMovieReadStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size) { + const struct { + u64 stream; + s64 offset; + } in = { stream, offset }; + + return serviceDispatchInOut(&g_capsaAccessor, 2004, in, *actual_size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); +} + +static Result _capsaReadImageDataFromAlbumMovieReadStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size) { + const struct { + u64 stream; + s64 offset; + } in = { stream, offset }; + + return serviceDispatchInOut(&g_capsaAccessor, 2007, in, *actual_size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); +} + +Result capsaOpenAlbumMovieStream(u64 *stream, const CapsAlbumFileId *file_id) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc=0; + + if (!serviceIsActive(&g_capsaAccessor)) rc = _capsaOpenAccessorSession(&g_capsaAccessor); + + if (R_SUCCEEDED(rc)) rc = _capsaOpenAlbumMovieReadStream(stream, file_id); + + return rc; +} + +Result capsaCloseAlbumMovieStream(u64 stream) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (!serviceIsActive(&g_capsaAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchIn(&g_capsaAccessor, 2002, stream); +} + +Result capsaGetAlbumMovieStreamSize(u64 stream, u64 *size) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (!serviceIsActive(&g_capsaAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchInOut(&g_capsaAccessor, 2003, stream, *size); +} + +Result capsaReadMovieDataFromAlbumMovieReadStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (!serviceIsActive(&g_capsaAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _capsaReadMovieDataFromAlbumMovieReadStream(stream, offset, buffer, size, actual_size); +} + +Result capsaGetAlbumMovieReadStreamBrokenReason(u64 stream) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (!serviceIsActive(&g_capsaAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchIn(&g_capsaAccessor, 2005, stream); +} + +Result capsaGetAlbumMovieReadStreamImageDataSize(u64 stream, u64 *size) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (!serviceIsActive(&g_capsaAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchInOut(&g_capsaAccessor, 2006, stream, *size); +} + +Result capsaReadImageDataFromAlbumMovieReadStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (!serviceIsActive(&g_capsaAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _capsaReadImageDataFromAlbumMovieReadStream(stream, offset, buffer, size, actual_size); +} + +Result capsaReadFileAttributeFromAlbumMovieReadStream(u64 stream, CapsScreenShotAttribute *attribute) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (!serviceIsActive(&g_capsaAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchInOut(&g_capsaAccessor, 2008, stream, *attribute); +} diff --git a/nx/source/services/capsu.c b/nx/source/services/capsu.c index 9fdeff33..f9bd8919 100644 --- a/nx/source/services/capsu.c +++ b/nx/source/services/capsu.c @@ -318,7 +318,7 @@ Result capsuPrecheckToCreateContents(CapsContentType type, u64 unk) { Result capsuOpenAlbumMovieStream(u64 *stream, const CapsApplicationAlbumFileEntry *entry) { Result rc=0; - if (!serviceIsActive(&g_capsuAccessor)) rc =_capsuOpenAccessorSessionForApplication(&g_capsuAccessor, entry); + if (!serviceIsActive(&g_capsuAccessor)) rc = _capsuOpenAccessorSessionForApplication(&g_capsuAccessor, entry); if (R_SUCCEEDED(rc)) rc = _capsuOpenAlbumMovieReadStream(stream, entry);