diff --git a/nx/include/switch.h b/nx/include/switch.h index 81f14dcf..b6123a46 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -93,6 +93,7 @@ extern "C" { #include "switch/services/psc.h" #include "switch/services/caps.h" #include "switch/services/capsa.h" +#include "switch/services/capsdc.h" #include "switch/services/capsu.h" #include "switch/services/capssc.h" #include "switch/services/capssu.h" diff --git a/nx/include/switch/services/caps.h b/nx/include/switch/services/caps.h index 0aa966f1..d10e55c7 100644 --- a/nx/include/switch/services/caps.h +++ b/nx/include/switch/services/caps.h @@ -65,7 +65,10 @@ typedef struct { /// ScreenShotDecodeOption typedef struct { - u8 unk_x0[0x20]; ///< Unknown. Set to all-zero by official sw. + u8 fancy_upsampling; ///< See libjpeg-turbo do_fancy_upsampling. + u8 block_smoothing; ///< See libjpeg-turbo do_block_smoothing. + u8 pad_x2[0x6]; ///< Padding. + u64 unk_x8[0x3]; ///< Unknown. Ignored by official sw. } CapsScreenShotDecodeOption; /// AlbumFileDateTime. This corresponds to each field in the Album entry filename, prior to the "-": "YYYYMMDDHHMMSSII". diff --git a/nx/include/switch/services/capsdc.h b/nx/include/switch/services/capsdc.h new file mode 100644 index 00000000..3498e9cb --- /dev/null +++ b/nx/include/switch/services/capsdc.h @@ -0,0 +1,32 @@ +/** + * @file capsdc.h + * @brief Jpeg Decoder (caps:dc) service IPC wrapper. Only available on [4.0.0+]. + * @note Only holds one session that is occupied by capsrv. + * @author Behemoth + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../sf/service.h" +#include "../services/caps.h" + +/// Initialize caps:dc +Result capsdcInitialize(void); + +/// Exit caps:dc. +void capsdcExit(void); + +/// Gets the Service for caps:dc. +Service* capsdcGetServiceSession(void); + +/** + * @brief Decodes a jpeg buffer into RGBX. + * @param[in] width Image width. + * @param[in] height Image height. + * @param[in] opts \ref CapsScreenShotDecodeOption. + * @param[in] jpeg Jpeg image input buffer. + * @param[in] jpeg_size Input image buffer size. + * @param[out] out_image RGBA8 image output buffer. + * @param[in] out_image_size Output image buffer size, should be at least large enough for RGBA8 width x height. + */ +Result capsdcDecodeJpeg(u32 width, u32 height, const CapsScreenShotDecodeOption *opts, const void* jpeg, size_t jpeg_size, void* out_image, size_t out_image_size); diff --git a/nx/source/services/capsdc.c b/nx/source/services/capsdc.c new file mode 100644 index 00000000..7297e58a --- /dev/null +++ b/nx/source/services/capsdc.c @@ -0,0 +1,41 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" +#include "runtime/hosversion.h" +#include "services/capsdc.h" + +static Service g_capsdcSrv; + +NX_GENERATE_SERVICE_GUARD(capsdc); + +Result _capsdcInitialize(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return smGetService(&g_capsdcSrv, "caps:dc"); +} + +void _capsdcCleanup(void) { + serviceClose(&g_capsdcSrv); +} + +Service* capsdcGetServiceSession(void) { + return &g_capsdcSrv; +} + +Result capsdcDecodeJpeg(u32 width, u32 height, const CapsScreenShotDecodeOption *opts, const void* jpeg, size_t jpeg_size, void* out_image, size_t out_image_size) { + const struct { + u32 width; + u32 height; + CapsScreenShotDecodeOption opts; + } in = { width, height, *opts }; + return serviceDispatchIn(&g_capsdcSrv, 3001, in, + .buffer_attrs = { + SfBufferAttr_In | SfBufferAttr_HipcMapAlias, + SfBufferAttr_Out | SfBufferAttr_HipcMapAlias | SfBufferAttr_HipcMapTransferAllowsNonSecure, + }, + .buffers = { + { jpeg, jpeg_size }, + { out_image, out_image_size }, + } + ); +}