mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
parent
1719eda9fb
commit
f34de8fb54
@ -92,6 +92,7 @@ extern "C" {
|
||||
#include "switch/services/ncm.h"
|
||||
#include "switch/services/psc.h"
|
||||
#include "switch/services/caps.h"
|
||||
#include "switch/services/capsa.h"
|
||||
#include "switch/services/capsu.h"
|
||||
#include "switch/services/capssc.h"
|
||||
#include "switch/services/capssu.h"
|
||||
|
@ -22,6 +22,11 @@ typedef enum {
|
||||
AlbumReportOption_Enable = 1, ///< Display the screenshot-taken Overlay notification.
|
||||
} AlbumReportOption;
|
||||
|
||||
typedef enum {
|
||||
CapsAlbumStorage_Nand = 0, ///< Nand
|
||||
CapsAlbumStorage_Sd = 1, ///< Sd
|
||||
} CapsAlbumStorage;
|
||||
|
||||
/// ContentType
|
||||
typedef enum {
|
||||
CapsContentType_Screenshot = 0, ///< Album screenshots.
|
||||
@ -76,17 +81,18 @@ typedef struct {
|
||||
|
||||
/// AlbumEntryId
|
||||
typedef struct {
|
||||
u64 program_id; ///< ProgramId.
|
||||
u64 application_id; ///< ApplicationId
|
||||
CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime
|
||||
u8 unk_x10; ///< Unknown.
|
||||
u8 unk_x11; ///< Unknown.
|
||||
u8 pad[6]; ///< Padding?
|
||||
} CapsAlbumEntryId;
|
||||
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 {
|
||||
u8 unk_x0[0x8]; ///< Unknown.
|
||||
CapsAlbumEntryId id; ///< \ref CapsAlbumEntryId
|
||||
u64 size; ///< Size.
|
||||
CapsAlbumFileId file_id; ///< \ref CapsAlbumFileId
|
||||
} CapsAlbumEntry;
|
||||
|
||||
/// ApplicationAlbumEntry
|
||||
@ -99,8 +105,8 @@ typedef struct {
|
||||
} v0; ///< Pre-7.0.0
|
||||
|
||||
struct {
|
||||
u8 unk_x0[0x8]; ///< Unknown.
|
||||
u8 unk_x8[0x8]; ///< Unknown.
|
||||
u64 size; ///< size of the entry
|
||||
u64 application_id; ///< ApplicationId
|
||||
CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime
|
||||
u8 unk_x18[0x8]; ///< Unknown.
|
||||
} v1; ///< [7.0.0+]
|
||||
@ -120,6 +126,39 @@ typedef struct {
|
||||
u32 size; ///< UserData size.
|
||||
} CapsApplicationData;
|
||||
|
||||
/// AlbumFileContents
|
||||
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;
|
||||
u8 pad_x15[0x3];
|
||||
} 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
|
||||
|
48
nx/include/switch/services/capsa.h
Normal file
48
nx/include/switch/services/capsa.h
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file capsa.h
|
||||
* @brief Album Accessor (caps:a) service IPC wrapper.
|
||||
* @author Behemoth
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
#include "../sf/service.h"
|
||||
#include "../services/caps.h"
|
||||
|
||||
/// Initialize caps:a.
|
||||
Result capsaInitialize(void);
|
||||
|
||||
/// Exit caps:a.
|
||||
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);
|
||||
Result capsaDeleteAlbumFile(const CapsAlbumFileId *file_id);
|
||||
Result capsaStorageCopyAlbumFile(const CapsAlbumFileId *file_id, CapsAlbumStorage dst_storage);
|
||||
Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool* is_mounted);
|
||||
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+].
|
||||
Result capsaGetAlbumUsage3(CapsAlbumStorage storage, CapsAlbumUsage3 *out);
|
||||
Result capsaGetAlbumMountResult(CapsAlbumStorage storage);
|
||||
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);
|
||||
|
||||
Result capsaForceAlbumUnmounted(CapsAlbumStorage storage);
|
||||
Result capsaResetAlbumMountStatus(CapsAlbumStorage storage);
|
||||
Result capsaRefreshAlbumCache(CapsAlbumStorage storage);
|
@ -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;
|
||||
|
||||
|
193
nx/source/services/capsa.c
Normal file
193
nx/source/services/capsa.c
Normal file
@ -0,0 +1,193 @@
|
||||
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "service_guard.h"
|
||||
#include "runtime/hosversion.h"
|
||||
#include "services/applet.h"
|
||||
#include "services/capsa.h"
|
||||
|
||||
static Service g_capsaSrv;
|
||||
|
||||
NX_GENERATE_SERVICE_GUARD(capsa);
|
||||
|
||||
Result _capsaInitialize(void) {
|
||||
return smGetService(&g_capsaSrv, "caps:a");
|
||||
}
|
||||
|
||||
void _capsaCleanup(void) {
|
||||
serviceClose(&g_capsaSrv);
|
||||
}
|
||||
|
||||
Service* capsaGetServiceSession(void) {
|
||||
return &g_capsaSrv;
|
||||
}
|
||||
|
||||
static Result _capsaCmdInU8NoOut(Service* srv, u8 inval, u32 cmd_id) {
|
||||
return serviceDispatchIn(srv, cmd_id, inval);
|
||||
}
|
||||
|
||||
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) {
|
||||
u8 inval = storage;
|
||||
return serviceDispatchInOut(&g_capsaSrv, 1, inval, *count,
|
||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||
.buffers = { { buffer, buffer_size } },
|
||||
);
|
||||
}
|
||||
|
||||
Result capsaLoadAlbumFile(const CapsAlbumFileId *file_id, u64 *out_size, void* workbuf, u64 workbuf_size) {
|
||||
return serviceDispatchInOut(&g_capsaSrv, 2, *file_id, *out_size,
|
||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||
.buffers = { { workbuf, workbuf_size } },
|
||||
);
|
||||
}
|
||||
|
||||
Result capsaDeleteAlbumFile(const CapsAlbumFileId *file_id) {
|
||||
return serviceDispatchIn(&g_capsaSrv, 3, *file_id);
|
||||
}
|
||||
|
||||
Result capsaStorageCopyAlbumFile(const CapsAlbumFileId* file_id, CapsAlbumStorage dst_storage) {
|
||||
struct {
|
||||
u8 storage;
|
||||
u8 pad_x1[0x7];
|
||||
CapsAlbumFileId file_id;
|
||||
} in = { dst_storage, {0}, *file_id };
|
||||
return serviceDispatchIn(&g_capsaSrv, 4, in);
|
||||
}
|
||||
|
||||
Result capsaIsAlbumMounted(CapsAlbumStorage storage, bool* is_mounted) {
|
||||
u8 inval = storage;
|
||||
return serviceDispatchInOut(&g_capsaSrv, 5, inval, *is_mounted);
|
||||
}
|
||||
|
||||
Result capsaGetAlbumUsage(CapsAlbumStorage storage, CapsAlbumUsage2 *out) {
|
||||
u8 inval = storage;
|
||||
return serviceDispatchInOut(&g_capsaSrv, 6, inval, *out);
|
||||
}
|
||||
|
||||
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) {
|
||||
return serviceDispatchInOut(&g_capsaSrv, 8, *file_id, *out_size,
|
||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||
.buffers = { { workbuf, workbuf_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) {
|
||||
if (hosversionBefore(2,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
struct {
|
||||
u64 width;
|
||||
u64 height;
|
||||
} 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 } },
|
||||
);
|
||||
*width = out.width;
|
||||
*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 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (hosversionBefore(3,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
struct {
|
||||
CapsAlbumFileId file_id;
|
||||
CapsScreenShotDecodeOption opts;
|
||||
} in = { *file_id, *opts };
|
||||
struct {
|
||||
u64 width;
|
||||
u64 height;
|
||||
} 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 } },
|
||||
);
|
||||
*width = out.width;
|
||||
*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 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 capsaGetAlbumUsage3(CapsAlbumStorage storage, CapsAlbumUsage3 *out) {
|
||||
if (hosversionBefore(4,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
u8 inval = storage;
|
||||
return serviceDispatchInOut(&g_capsaSrv, 15, inval, *out);
|
||||
}
|
||||
|
||||
Result capsaGetAlbumMountResult(CapsAlbumStorage storage) {
|
||||
if (hosversionBefore(4,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
return _capsaCmdInU8NoOut(&g_capsaSrv, storage, 16);
|
||||
}
|
||||
|
||||
Result capsaGetAlbumUsage16(CapsAlbumStorage storage, CapsAlbumUsage16 *out) {
|
||||
if (hosversionBefore(4,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
u8 inval = storage;
|
||||
return serviceDispatchInOut(&g_capsaSrv, 17, inval, *out);
|
||||
}
|
||||
|
||||
Result capsaGetAutoSavingStorage(CapsAlbumStorage* storage) {
|
||||
u8 tmpval = 0;
|
||||
Result rc = serviceDispatchOut(&g_capsaSrv, 401, tmpval);
|
||||
*storage = tmpval;
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result capsaGetRequiredStorageSpaceSizeToCopyAll(CapsAlbumStorage dst_storage, CapsAlbumStorage src_storage, u64* out) {
|
||||
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) {
|
||||
if (hosversionBefore(4,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
struct {
|
||||
CapsAlbumFileId file_id;
|
||||
CapsScreenShotDecodeOption opts;
|
||||
} in = { *file_id, *opts };
|
||||
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 }, { raw_buffer, raw_buffer_size }, { work_buffer, work_buffer_size } },
|
||||
);
|
||||
}
|
||||
|
||||
Result capsaForceAlbumUnmounted(CapsAlbumStorage storage) {
|
||||
return _capsaCmdInU8NoOut(&g_capsaSrv, storage, 8001);
|
||||
}
|
||||
|
||||
Result capsaResetAlbumMountStatus(CapsAlbumStorage storage) {
|
||||
return _capsaCmdInU8NoOut(&g_capsaSrv, storage, 8002);
|
||||
}
|
||||
|
||||
Result capsaRefreshAlbumCache(CapsAlbumStorage storage) {
|
||||
return _capsaCmdInU8NoOut(&g_capsaSrv, storage, 8011);
|
||||
}
|
Loading…
Reference in New Issue
Block a user