From 9d9e72b3acf67d3caab60242398f43c730d86e06 Mon Sep 17 00:00:00 2001 From: XorTroll Date: Thu, 16 Apr 2020 14:49:03 +0200 Subject: [PATCH] Add mii and miiimg services --- nx/include/switch.h | 2 + nx/include/switch/services/mii.h | 126 ++++++++++++++++++++++++++++ nx/include/switch/services/miiimg.h | 35 ++++++++ nx/include/switch/services/nfc.h | 59 +------------ nx/source/services/mii.c | 74 ++++++++++++++++ nx/source/services/miiimg.c | 58 +++++++++++++ 6 files changed, 297 insertions(+), 57 deletions(-) create mode 100644 nx/include/switch/services/mii.h create mode 100644 nx/include/switch/services/miiimg.h create mode 100644 nx/source/services/mii.c create mode 100644 nx/source/services/miiimg.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 755a0430..8be1a533 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -109,6 +109,8 @@ extern "C" { #include "switch/services/grc.h" #include "switch/services/friends.h" #include "switch/services/notif.h" +#include "switch/services/mii.h" +#include "switch/services/miiimg.h" #include "switch/display/binder.h" #include "switch/display/parcel.h" diff --git a/nx/include/switch/services/mii.h b/nx/include/switch/services/mii.h new file mode 100644 index 00000000..f9ddaaa8 --- /dev/null +++ b/nx/include/switch/services/mii.h @@ -0,0 +1,126 @@ +/** + * @file mii.h + * @brief Mii services IPC wrapper. + * @author XorTroll + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../sf/service.h" + +typedef enum { + MiiServiceType_System, + MiiServiceType_User +} MiiServiceType; + +typedef enum { + MiiAge_Young, + MiiAge_Normal, + MiiAge_Old, + MiiAge_All +} MiiAge; + +typedef enum { + MiiGender_Male, + MiiGender_Female, + MiiGender_All +} MiiGender; + +typedef enum { + MiiRace_Black, + MiiRace_White, + MiiRace_Asian, + MiiRace_All +} MiiRace; + +typedef enum { + MiiSourceFlag_Database = BIT(0), + MiiSourceFlag_Default = BIT(1), + MiiSourceFlag_All = MiiSourceFlag_Database | MiiSourceFlag_Default +} MiiSourceFlag; + +typedef enum { + MiiSpecialKeyCode_Normal, + MiiSpecialKeyCode_Special = 0xA523B78F +} MiiSpecialKeyCode; + +typedef struct { + Service s; +} MiiDatabase; + +typedef struct { + Uuid uuid; +} MiiCreateId; + +typedef struct { + MiiCreateId create_id; + u16 mii_name[10+1]; ///< utf-16be, null-terminated + u8 unk_x26; + u8 mii_color; + u8 mii_sex; + u8 mii_height; + u8 mii_width; + u8 unk_x2b[2]; + u8 mii_face_shape; + u8 mii_face_color; + u8 mii_wrinkles_style; + u8 mii_makeup_style; + u8 mii_hair_style; + u8 mii_hair_color; + u8 mii_has_hair_flipped; + u8 mii_eye_style; + u8 mii_eye_color; + u8 mii_eye_size; + u8 mii_eye_thickness; + u8 mii_eye_angle; + u8 mii_eye_pos_x; + u8 mii_eye_pos_y; + u8 mii_eyebrow_style; + u8 mii_eyebrow_color; + u8 mii_eyebrow_size; + u8 mii_eyebrow_thickness; + u8 mii_eyebrow_angle; + u8 mii_eyebrow_pos_x; + u8 mii_eyebrow_pos_y; + u8 mii_nose_style; + u8 mii_nose_size; + u8 mii_nose_pos; + u8 mii_mouth_style; + u8 mii_mouth_color; + u8 mii_mouth_size; + u8 mii_mouth_thickness; + u8 mii_mouth_pos; + u8 mii_facial_hair_color; + u8 mii_beard_style; + u8 mii_mustache_style; + u8 mii_mustache_size; + u8 mii_mustache_pos; + u8 mii_glasses_style; + u8 mii_glasses_color; + u8 mii_glasses_size; + u8 mii_glasses_pos; + u8 mii_has_mole; + u8 mii_mole_size; + u8 mii_mole_pos_x; + u8 mii_mole_pos_y; + u8 unk_x57; +} MiiCharInfo; + +/// Initialize mii (mii:e). +Result miiInitialize(MiiServiceType service_type); + +/// Exit mii. +void miiExit(void); + +/// Gets the Service object for the actual mii service session. +Service* miiGetServiceSession(void); + +Result miiOpenDatabase(MiiDatabase *out, MiiSpecialKeyCode key_code); + +Result miiDatabaseIsUpdated(MiiDatabase *db, u8 *out, MiiSourceFlag flag); +Result miiDatabaseIsFull(MiiDatabase *db, u8 *out); +Result miiDatabaseGetCount(MiiDatabase *db, u32 *out, MiiSourceFlag flag); +Result miiDatabaseGetCharInfo(MiiDatabase *db, MiiSourceFlag flag, MiiCharInfo *out_infos, size_t out_infos_count, u32 *out_count); +Result miiDatabaseBuildRandom(MiiDatabase *db, MiiAge age, MiiGender gender, MiiRace race, MiiCharInfo *out_info); + +void miiDatabaseClose(MiiDatabase *db); diff --git a/nx/include/switch/services/miiimg.h b/nx/include/switch/services/miiimg.h new file mode 100644 index 00000000..7a086c16 --- /dev/null +++ b/nx/include/switch/services/miiimg.h @@ -0,0 +1,35 @@ +/** + * @file miiimg.h + * @brief Mii image (miiimg) service IPC wrapper. + * @author XorTroll + * @copyright libnx Authors + */ +#pragma once +#include "mii.h" + +typedef struct { + Uuid uuid; +} MiiimgImageId; + +typedef struct { + MiiimgImageId image_id; + MiiCreateId create_id; + u32 unk; + u16 mii_name[10+1]; +} PACKED MiiimgImageAttribute; + +/// Initialize miiimg. +Result miiimgInitialize(void); + +/// Exit miiimg. +void miiimgExit(void); + +/// Gets the Service object for the actual miiimg service session. +Service* miiimgGetServiceSession(void); + +Result miiimgReload(); +Result miiimgGetCount(u32 *out_count); +Result miiimgIsEmpty(u8 *out_empty); +Result miiimgIsFull(u8 *out_full); +Result miiimgGetAttribute(u32 index, MiiimgImageAttribute *out_attr); +Result miiimgLoadImage(MiiimgImageId id, void *out_image, size_t out_image_size); diff --git a/nx/include/switch/services/nfc.h b/nx/include/switch/services/nfc.h index 89f3612a..58519fb0 100644 --- a/nx/include/switch/services/nfc.h +++ b/nx/include/switch/services/nfc.h @@ -6,8 +6,7 @@ */ #pragma once -#include "../types.h" -#include "../sf/service.h" +#include "mii.h" /// NfpServiceType typedef enum { @@ -72,61 +71,7 @@ typedef struct { } PACKED NfpModelInfo; typedef struct { - u8 unk_x0[0x10]; // Hash? - u16 mii_name[10+1]; ///< utf-16be, null-terminated - u8 unk_x26; - u8 mii_color; - u8 mii_sex; - u8 mii_height; - u8 mii_width; - u8 unk_x2b[2]; - u8 mii_face_shape; - u8 mii_face_color; - u8 mii_wrinkles_style; - u8 mii_makeup_style; - u8 mii_hair_style; - u8 mii_hair_color; - u8 mii_has_hair_flipped; - u8 mii_eye_style; - u8 mii_eye_color; - u8 mii_eye_size; - u8 mii_eye_thickness; - u8 mii_eye_angle; - u8 mii_eye_pos_x; - u8 mii_eye_pos_y; - u8 mii_eyebrow_style; - u8 mii_eyebrow_color; - u8 mii_eyebrow_size; - u8 mii_eyebrow_thickness; - u8 mii_eyebrow_angle; - u8 mii_eyebrow_pos_x; - u8 mii_eyebrow_pos_y; - u8 mii_nose_style; - u8 mii_nose_size; - u8 mii_nose_pos; - u8 mii_mouth_style; - u8 mii_mouth_color; - u8 mii_mouth_size; - u8 mii_mouth_thickness; - u8 mii_mouth_pos; - u8 mii_facial_hair_color; - u8 mii_beard_style; - u8 mii_mustache_style; - u8 mii_mustache_size; - u8 mii_mustache_pos; - u8 mii_glasses_style; - u8 mii_glasses_color; - u8 mii_glasses_size; - u8 mii_glasses_pos; - u8 mii_has_mole; - u8 mii_mole_size; - u8 mii_mole_pos_x; - u8 mii_mole_pos_y; - u8 unk_x57; -} PACKED NfpMiiCharInfo; - -typedef struct { - NfpMiiCharInfo mii; + MiiCharInfo mii; u16 first_write_year; u8 first_write_month; u8 first_write_day; diff --git a/nx/source/services/mii.c b/nx/source/services/mii.c new file mode 100644 index 00000000..fe2ff89d --- /dev/null +++ b/nx/source/services/mii.c @@ -0,0 +1,74 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" +#include "services/mii.h" + +static MiiServiceType g_miiServiceType; +static Service g_miiSrv; + +NX_GENERATE_SERVICE_GUARD_PARAMS(mii, (MiiServiceType service_type), (service_type)); + +Result _miiInitialize(MiiServiceType service_type) { + Result rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); + + g_miiServiceType = service_type; + switch (g_miiServiceType) { + case MiiServiceType_System: + rc = smGetService(&g_miiSrv, "mii:e"); + break; + case MiiServiceType_User: + rc = smGetService(&g_miiSrv, "mii:u"); + break; + } + + return rc; +} + +void _miiCleanup(void) { + serviceClose(&g_miiSrv); +} + +Service* miiGetServiceSession(void) { + return &g_miiSrv; +} + +Result miiOpenDatabase(MiiDatabase *out, MiiSpecialKeyCode key_code) { + u32 in = (u32)key_code; + return serviceDispatchIn(&g_miiSrv, 0, in, + .out_num_objects = 1, + .out_objects = &out->s, + ); +} + +Result miiDatabaseIsUpdated(MiiDatabase *db, u8 *out, MiiSourceFlag flag) { + u32 in = (u32)flag; + return serviceDispatchInOut(&db->s, 0, in, *out); +} + +Result miiDatabaseIsFull(MiiDatabase *db, u8 *out) { + return serviceDispatchOut(&db->s, 1, *out); +} +Result miiDatabaseGetCount(MiiDatabase *db, u32 *out, MiiSourceFlag flag) { + u32 in = (u32)flag; + return serviceDispatchInOut(&db->s, 2, in, *out); +} + +Result miiDatabaseGetCharInfo(MiiDatabase *db, MiiSourceFlag flag, MiiCharInfo *out_infos, size_t out_infos_count, u32 *out_count) { + u32 in = (u32)flag; + return serviceDispatchInOut(&db->s, 4, in, *out_count, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_infos, out_infos_count * sizeof(MiiCharInfo) } }, + ); +} + +Result miiDatabaseBuildRandom(MiiDatabase *db, MiiAge age, MiiGender gender, MiiRace race, MiiCharInfo *out_info) { + const struct { + u32 age; + u32 gender; + u32 race; + } in = { age, gender, race }; + return serviceDispatchInOut(&db->s, 6, in, *out_info); +} + +void miiDatabaseClose(MiiDatabase *db) { + serviceClose(&db->s); +} diff --git a/nx/source/services/miiimg.c b/nx/source/services/miiimg.c new file mode 100644 index 00000000..07fb3466 --- /dev/null +++ b/nx/source/services/miiimg.c @@ -0,0 +1,58 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" +#include "services/miiimg.h" +#include "runtime/hosversion.h" + +static Service g_miiimgSrv; + +NX_GENERATE_SERVICE_GUARD(miiimg); + +static Result _miiimgInitializeCmd(u8 in, u8 *out) { + return serviceDispatchInOut(&g_miiimgSrv, 0, in, *out); +} + +Result _miiimgInitialize(void) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + Result rc = smGetService(&g_miiimgSrv, "miiimg"); + if (R_SUCCEEDED(rc)) { + u8 tmp; + rc = _miiimgInitializeCmd(1, &tmp); + } + return rc; +} + +void _miiimgCleanup(void) { + serviceClose(&g_miiimgSrv); +} + +Service* miiimgGetServiceSession(void) { + return &g_miiimgSrv; +} + +Result miiimgReload() { + return serviceDispatch(&g_miiimgSrv, 10); +} + +Result miiimgGetCount(u32 *out_count) { + return serviceDispatchOut(&g_miiimgSrv, 11, *out_count); +} + +Result miiimgIsEmpty(u8 *out_empty) { + return serviceDispatchOut(&g_miiimgSrv, 12, *out_empty); +} + +Result miiimgIsFull(u8 *out_full) { + return serviceDispatchOut(&g_miiimgSrv, 13, *out_full); +} + +Result miiimgGetAttribute(u32 index, MiiimgImageAttribute *out_attr) { + return serviceDispatchInOut(&g_miiimgSrv, 14, index, *out_attr); +} + +Result miiimgLoadImage(MiiimgImageId id, void *out_image, size_t out_image_size) { + return serviceDispatchIn(&g_miiimgSrv, 15, id, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_image, out_image_size } }, + ); +}