diff --git a/nx/include/switch/services/caps.h b/nx/include/switch/services/caps.h index be34e8c3..fcfebf9c 100644 --- a/nx/include/switch/services/caps.h +++ b/nx/include/switch/services/caps.h @@ -23,9 +23,9 @@ typedef enum { } AlbumReportOption; typedef enum { - AlbumObjectLocation_BuiltInUser = 0, ///< BuiltInUser - AlbumObjectLocation_SdCard = 1, ///< SdCard -} AlbumObjectLocation; + CapsAlbumStorage_Nand = 0, ///< BuiltInUser + CapsAlbumStorage_Sd = 1, ///< SdCard +} CapsAlbumStorage; /// ContentType typedef enum { @@ -81,17 +81,18 @@ typedef struct { /// AlbumEntryId typedef struct { - u64 program_id; ///< ProgramId. + u64 application_id; ///< ApplicationId CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime - u8 location; ///< AlbumLocation - u8 unk_x11; ///< Unknown. - u8 pad[6]; ///< Padding? -} CapsAlbumEntryId; + u8 storage; ///< AlbumStorage + u8 contentsType; ///< FileContentsType + u32 pad_x12; ///< Set to 0 by official software + u16 pad_x16; ///< Set to 0 by official software +} CapsAlbumFileId; /// AlbumEntry typedef struct { u8 unk_x0[0x8]; ///< Unknown. - CapsAlbumEntryId id; ///< \ref CapsAlbumEntryId + CapsAlbumFileId file_id; ///< \ref CapsAlbumFileId } CapsAlbumEntry; /// ApplicationAlbumEntry @@ -105,7 +106,7 @@ typedef struct { struct { u64 size; ///< size of the entry - u64 program_id; ///< ProgramId + u64 application_id; ///< ApplicationId CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime u8 unk_x18[0x8]; ///< Unknown. } v1; ///< [7.0.0+] @@ -125,6 +126,37 @@ typedef struct { u32 size; ///< UserData size. } CapsApplicationData; +typedef enum { + CapsAlbumFileContents_ScreenShot = 0, + CapsAlbumFileContents_Movie = 1, + CapsAlbumFileContents_ExtraScreenShot = 2, + CapsAlbumFileContents_ExtraMovie = 3, +} CapsAlbumFileContents; + +typedef enum { + CapsAlbumContentsUsageFlag_HasGreaterUsage = BIT(0), ///< Indicates that there are additional files not captured by the count/size fields of CapsAlbumContentsUsage + CapsAlbumContentsUsageFlag_IsUnknownContents = BIT(1), ///< Indicates that the file is not a known content type +} CapsAlbumContentsUsageFlag; + +typedef struct { + s64 count; + s64 size; + u32 flags; + u8 file_contents; +} CapsAlbumContentsUsage; + +typedef struct { + CapsAlbumContentsUsage usages[2]; +} CapsAlbumUsage2; + +typedef struct { + CapsAlbumContentsUsage usages[3]; +} CapsAlbumUsage3; + +typedef struct { + CapsAlbumContentsUsage usages[16]; +} CapsAlbumUsage16; + /// UserIdList typedef struct { AccountUid uids[ACC_USER_LIST_SIZE]; ///< \ref AccountUid diff --git a/nx/include/switch/services/capsa.h b/nx/include/switch/services/capsa.h index 990cda7a..1e782d31 100644 --- a/nx/include/switch/services/capsa.h +++ b/nx/include/switch/services/capsa.h @@ -17,13 +17,28 @@ void capsaExit(void); /// Gets the Service for caps:a. Service* capsaGetServiceSession(void); +// 0-8 +Result capsaGetAlbumFileCount(CapsAlbumStorage storage, u64* count); +Result capsaGetAlbumFileList(CapsAlbumStorage storage, u64* count, CapsApplicationAlbumEntry* buffer, u64 size); +Result capsaLoadAlbumFile(CapsAlbumFileId file_id, u64 *out_size, void* jpeg_buffer, u64 jpeg_buffer_size); +Result capsaDeleteAlbumFile(CapsAlbumFileId file_id); +Result capsaStorageCopyAlbumFile(CapsAlbumFileId file_id, CapsAlbumStorage dst_storage); +Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool* is_mounted); +Result capsaGetAlbumUsage(CapsAlbumStorage storage, CapsAlbumUsage2 *out); +Result capsaGetAlbumFileSize(CapsAlbumFileId file_id, u64* size); +Result capsaLoadAlbumFileThumbnail(CapsAlbumFileId file_id, u64 *out_size, void* jpeg_buffer, u64 jpeg_buffer_size); +// 15-18 +Result capsaGetAlbumUsage3(CapsAlbumStorage storage, CapsAlbumUsage3 *out); +Result capsaGetAlbumMountResult(CapsAlbumStorage storage); +Result capsaGetAlbumUsage16(CapsAlbumStorage storage, CapsAlbumUsage16 *out); -Result capsaGetAlbumFileCount(AlbumObjectLocation location, u64* count); -Result capsaGetAlbumFileList(AlbumObjectLocation location, u64* count, CapsApplicationAlbumEntry* buffer, u64 size); -Result capsaLoadAlbumFile(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size); -Result capsaDeleteAlbumFile(CapsAlbumEntryId entry_id); -Result capsaStorageCopyAlbumFile(u8 unk[0x20]); -Result capsaIsAlbumMounted(AlbumObjectLocation location, bool* is_mounted); -Result capsaGetAlbumUsage(AlbumObjectLocation location, u8 unk_out[0x30]); -Result capsaGetAlbumFileSize(CapsAlbumEntryId entry_id, u64* size); -Result capsaLoadAlbumFileThumbnail(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size); +Result capsaGetAutoSavingStorage(CapsAlbumStorage* storage); +Result capsaGetRequiredStorageSpaceSizeToCopyAll(CapsAlbumStorage dst_storage, CapsAlbumStorage src_storage, u64* out); + +Result capsaLoadAlbumScreenShotThumbnailImage(u64* width, u64* height, CapsAlbumFileId file_id, void* jpeg_buffer, u64 jpeg_buffer_size, void* buffer, u64 buffer_size); +Result capsaLoadAlbumScreenShotThumbnailImageEx(u64* width, u64* height, CapsAlbumFileId file_id, void* jpeg_buffer, u64 jpeg_buffer_size, void* buffer, u64 buffer_size); +Result capsaLoadAlbumScreenShotThumbnailImageEx1(CapsAlbumFileId file_id, void* jpeg_buffer, u64 jpeg_buffer_size, void* buffer, u64 buffer_size, void* out, u64 out_size); + +Result capsaForceAlbumUnmounted(CapsAlbumStorage storage); +Result capsaResetAlbumMountStatus(CapsAlbumStorage storage); +Result capsaRefreshAlbumCache(CapsAlbumStorage storage); diff --git a/nx/include/switch/services/grc.h b/nx/include/switch/services/grc.h index 40fe6acb..58aa9f02 100644 --- a/nx/include/switch/services/grc.h +++ b/nx/include/switch/services/grc.h @@ -40,7 +40,7 @@ typedef struct { /// GameMovieId typedef struct { - CapsAlbumEntryId album_id; ///< \ref CapsAlbumEntryId + CapsAlbumFileId file_id; ///< \ref CapsAlbumFileId u8 reserved[0x28]; ///< Unused, always zero. } GrcGameMovieId; diff --git a/nx/source/services/capsa.c b/nx/source/services/capsa.c index a83d042b..f6ff2e6c 100644 --- a/nx/source/services/capsa.c +++ b/nx/source/services/capsa.c @@ -22,47 +22,139 @@ Service* capsaGetServiceSession(void) { return &g_capsaSrv; } -Result capsaGetAlbumFileCount(AlbumObjectLocation location, u64* count) { - return serviceDispatchInOut(&g_capsaSrv, 0, location, *count); +Result capsaGetAlbumFileCount(CapsAlbumStorage storage, u64* count) { + return serviceDispatchInOut(&g_capsaSrv, 0, storage, *count); } -Result capsaGetAlbumFileList(AlbumObjectLocation location, u64* count, CapsApplicationAlbumEntry* buffer, u64 buffer_size) { - return serviceDispatchInOut(&g_capsaSrv, 1, location, *count, +Result capsaGetAlbumFileList(CapsAlbumStorage storage, u64* count, CapsApplicationAlbumEntry* buffer, u64 buffer_size) { + return serviceDispatchInOut(&g_capsaSrv, 1, storage, *count, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { buffer, buffer_size } }, ); } -Result capsaLoadAlbumFile(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size) { - return serviceDispatchInOut(&g_capsaSrv, 2, entry_id, *unk, +Result capsaLoadAlbumFile(CapsAlbumFileId file_id, u64 *out_size, void* jpeg_buffer, u64 jpeg_buffer_size) { + return serviceDispatchInOut(&g_capsaSrv, 2, file_id, *out_size, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { jpeg_buffer, jpeg_buffer_size } }, ); } -Result capsaDeleteAlbumFile(CapsAlbumEntryId entry_id) { - return serviceDispatchIn(&g_capsaSrv, 3, entry_id); +Result capsaDeleteAlbumFile(CapsAlbumFileId file_id) { + return serviceDispatchIn(&g_capsaSrv, 3, file_id); } -Result capsaStorageCopyAlbumFile(u8 unk[0x20]) { - return serviceDispatchIn(&g_capsaSrv, 4, *unk); +Result capsaStorageCopyAlbumFile(CapsAlbumFileId file_id, CapsAlbumStorage dst_storage) { + return serviceDispatchIn(&g_capsaSrv, 4, dst_storage); } -Result capsaIsAlbumMounted(AlbumObjectLocation location, bool* is_mounted) { - return serviceDispatchInOut(&g_capsaSrv, 5, location, *is_mounted); +Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool* is_mounted) { + return serviceDispatchInOut(&g_capsaSrv, 5, storage, *is_mounted); } -Result capsaGetAlbumUsage(AlbumObjectLocation location, u8 unk_out[0x30]) { - return serviceDispatchInOut(&g_capsaSrv, 6, location, *unk_out); +Result capsaGetAlbumUsage(CapsAlbumStorage storage, CapsAlbumUsage2 *out) { + return serviceDispatchInOut(&g_capsaSrv, 6, storage, *out); } -Result capsaGetAlbumFileSize(CapsAlbumEntryId entry_id, u64* size) { - return serviceDispatchInOut(&g_capsaSrv, 7, entry_id, *size); +Result capsaGetAlbumFileSize(CapsAlbumFileId file_id, u64* size) { + return serviceDispatchInOut(&g_capsaSrv, 7, file_id, *size); } -Result capsaLoadAlbumFileThumbnail(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size) { - return serviceDispatchInOut(&g_capsaSrv, 8, entry_id, *unk, +Result capsaLoadAlbumFileThumbnail(CapsAlbumFileId file_id, u64 *out_size, void* jpeg_buffer, u64 jpeg_buffer_size) { + return serviceDispatchInOut(&g_capsaSrv, 8, file_id, *out_size, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { jpeg_buffer, jpeg_buffer_size } }, ); } + +Result capsaGetAlbumUsage3(CapsAlbumStorage storage, CapsAlbumUsage3 *out) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return serviceDispatchInOut(&g_capsaSrv, 15, storage, *out); +} + +Result capsaGetAlbumMountResult(CapsAlbumStorage storage) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return serviceDispatchIn(&g_capsaSrv, 17, storage); +} + +Result capsaGetAlbumUsage16(CapsAlbumStorage storage, CapsAlbumUsage16 *out) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return serviceDispatchInOut(&g_capsaSrv, 17, storage, *out); +} + + +Result capsaGetAutoSavingStorage(CapsAlbumStorage* storage) { + return serviceDispatchOut(&g_capsaSrv, 401, *storage); +} + +Result capsaGetRequiredStorageSpaceSizeToCopyAll(CapsAlbumStorage dst_storage, CapsAlbumStorage src_storage, u64* out) { + struct { + CapsAlbumStorage dest; + CapsAlbumStorage src; + } in = { dst_storage, src_storage }; + return serviceDispatchInOut(&g_capsaSrv, 501, in, *out); +} + +Result capsaLoadAlbumScreenShotThumbnailImage(u64* width, u64* height, CapsAlbumFileId file_id, void* jpeg_buffer, u64 jpeg_buffer_size, void* buffer, u64 buffer_size) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + struct { + u64 width; + u64 height; + } out; + Result rc = serviceDispatchInOut(&g_capsaSrv, 10, file_id, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, buffer_size }, { jpeg_buffer, jpeg_buffer_size } }, + ); + *width = out.width; + *height = out.height; + return rc; +} + +Result capsaLoadAlbumScreenShotThumbnailImageEx(u64* width, u64* height, CapsAlbumFileId file_id, void* jpeg_buffer, u64 jpeg_buffer_size, void* buffer, u64 buffer_size) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + struct { + CapsAlbumFileId file_id; + CapsScreenShotDecodeOption opts; + } in = { file_id, {{0}} }; + struct { + u64 width; + u64 height; + } out; + Result rc = serviceDispatchInOut(&g_capsaSrv, 13, in, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, buffer_size }, { jpeg_buffer, jpeg_buffer_size } }, + ); + *width = out.width; + *height = out.height; + return rc; +} + +Result capsaLoadAlbumScreenShotThumbnailImageEx1(CapsAlbumFileId file_id, void* jpeg_buffer, u64 jpeg_buffer_size, void* buffer, u64 buffer_size, void* out, u64 out_size) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + struct { + CapsAlbumFileId file_id; + CapsScreenShotDecodeOption opts; + } in = { file_id, {{0}} }; + return serviceDispatchIn(&g_capsaSrv, 1003, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_FixedSize, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out, out_size }, { buffer, buffer_size }, { jpeg_buffer, jpeg_buffer_size } }, + ); +} + +Result capsaForceAlbumUnmounted(CapsAlbumStorage storage) { + return serviceDispatchIn(&g_capsaSrv, 8001, storage); +} + +Result capsaResetAlbumMountStatus(CapsAlbumStorage storage) { + return serviceDispatchIn(&g_capsaSrv, 8002, storage); +} + +Result capsaRefreshAlbumCache(CapsAlbumStorage storage) { + return serviceDispatchIn(&g_capsaSrv, 8011, storage); +}