From 571399930cc3578acff064a7087fe85e7b2dd9b7 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 11 Sep 2023 00:23:46 -0600 Subject: [PATCH] service: mii: Fix ver3 inconsistencies --- src/core/hle/service/mii/mii_manager.cpp | 17 +- src/core/hle/service/mii/mii_manager.h | 3 - src/core/hle/service/mii/mii_types.h | 16 - src/core/hle/service/mii/types/char_info.cpp | 2 +- src/core/hle/service/mii/types/store_data.cpp | 202 ++++++++++++- src/core/hle/service/mii/types/store_data.h | 54 +++- .../hle/service/mii/types/ver3_store_data.cpp | 280 ++++++++++-------- .../hle/service/mii/types/ver3_store_data.h | 80 ++--- src/core/hle/service/nfc/common/device.cpp | 16 +- 9 files changed, 463 insertions(+), 207 deletions(-) diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index 2137a9af1..3951e0b9c 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -98,23 +98,12 @@ CharInfo MiiManager::BuildDefault(std::size_t index) { CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const { CharInfo char_info{}; - mii_v3.BuildToStoreData(char_info); + StoreData store_data{}; + mii_v3.BuildToStoreData(store_data); + char_info.SetFromStoreData(store_data); return char_info; } -NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const { - return { - .faceline_color = static_cast(mii.GetFacelineColor() & 0xf), - .hair_color = static_cast(mii.GetHairColor() & 0x7f), - .eye_color = static_cast(mii.GetEyeColor() & 0x7f), - .eyebrow_color = static_cast(mii.GetEyebrowColor() & 0x7f), - .mouth_color = static_cast(mii.GetMouthColor() & 0x7f), - .beard_color = static_cast(mii.GetBeardColor() & 0x7f), - .glass_color = static_cast(mii.GetGlassColor() & 0x7f), - .glass_type = static_cast(mii.GetGlassType() & 0x1f), - }; -} - std::vector MiiManager::GetDefault(SourceFlag source_flag) { std::vector result; diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index 0a47e613f..6098474e9 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h @@ -30,9 +30,6 @@ public: std::vector GetDefault(SourceFlag source_flag); Result GetIndex(const CharInfo& info, u32& index); - // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData - NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const; - struct MiiDatabase { u32 magic{}; // 'NFDB' std::array miis{}; diff --git a/src/core/hle/service/mii/mii_types.h b/src/core/hle/service/mii/mii_types.h index 20d4e40ab..d62005f61 100644 --- a/src/core/hle/service/mii/mii_types.h +++ b/src/core/hle/service/mii/mii_types.h @@ -108,25 +108,9 @@ struct Nickname { } return index == MaxNameSize; } - - bool operator==(const Nickname& name) { - return data == name.data; - }; }; static_assert(sizeof(Nickname) == 0x14, "Nickname is an invalid size"); -struct NfpStoreDataExtension { - u8 faceline_color; - u8 hair_color; - u8 eye_color; - u8 eyebrow_color; - u8 mouth_color; - u8 beard_color; - u8 glass_color; - u8 glass_type; -}; -static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size"); - struct DefaultMii { u32 face_type{}; u32 face_color{}; diff --git a/src/core/hle/service/mii/types/char_info.cpp b/src/core/hle/service/mii/types/char_info.cpp index e1d874860..0f9c37b84 100644 --- a/src/core/hle/service/mii/types/char_info.cpp +++ b/src/core/hle/service/mii/types/char_info.cpp @@ -425,7 +425,7 @@ u8 CharInfo::GetMoleY() const { bool CharInfo::operator==(const CharInfo& info) { bool is_identical = info.Verify() == 0; - is_identical &= name == info.GetNickname(); + is_identical &= name.data == info.GetNickname().data; is_identical &= create_id == info.GetCreateId(); is_identical &= font_region == info.GetFontRegion(); is_identical &= favorite_color == info.GetFavoriteColor(); diff --git a/src/core/hle/service/mii/types/store_data.cpp b/src/core/hle/service/mii/types/store_data.cpp index 72c8fa2e9..91dfd3271 100644 --- a/src/core/hle/service/mii/types/store_data.cpp +++ b/src/core/hle/service/mii/types/store_data.cpp @@ -180,6 +180,206 @@ u32 StoreData::IsValid() const { return 0; } +void StoreData::SetFontRegion(FontRegion value) { + core_data.SetFontRegion(value); +} + +void StoreData::SetFavoriteColor(u8 value) { + core_data.SetFavoriteColor(value); +} + +void StoreData::SetGender(Gender value) { + core_data.SetGender(value); +} + +void StoreData::SetHeight(u8 value) { + core_data.SetHeight(value); +} + +void StoreData::SetBuild(u8 value) { + core_data.SetBuild(value); +} + +void StoreData::SetType(u8 value) { + core_data.SetType(value); +} + +void StoreData::SetRegionMove(u8 value) { + core_data.SetRegionMove(value); +} + +void StoreData::SetFacelineType(u8 value) { + core_data.SetFacelineType(value); +} + +void StoreData::SetFacelineColor(u8 value) { + core_data.SetFacelineColor(value); +} + +void StoreData::SetFacelineWrinkle(u8 value) { + core_data.SetFacelineWrinkle(value); +} + +void StoreData::SetFacelineMake(u8 value) { + core_data.SetFacelineMake(value); +} + +void StoreData::SetHairType(u8 value) { + core_data.SetHairType(value); +} + +void StoreData::SetHairColor(u8 value) { + core_data.SetHairColor(value); +} + +void StoreData::SetHairFlip(HairFlip value) { + core_data.SetHairFlip(value); +} + +void StoreData::SetEyeType(u8 value) { + core_data.SetEyeType(value); +} + +void StoreData::SetEyeColor(u8 value) { + core_data.SetEyeColor(value); +} + +void StoreData::SetEyeScale(u8 value) { + core_data.SetEyeScale(value); +} + +void StoreData::SetEyeAspect(u8 value) { + core_data.SetEyeAspect(value); +} + +void StoreData::SetEyeRotate(u8 value) { + core_data.SetEyeRotate(value); +} + +void StoreData::SetEyeX(u8 value) { + core_data.SetEyeX(value); +} + +void StoreData::SetEyeY(u8 value) { + core_data.SetEyeY(value); +} + +void StoreData::SetEyebrowType(u8 value) { + core_data.SetEyebrowType(value); +} + +void StoreData::SetEyebrowColor(u8 value) { + core_data.SetEyebrowColor(value); +} + +void StoreData::SetEyebrowScale(u8 value) { + core_data.SetEyebrowScale(value); +} + +void StoreData::SetEyebrowAspect(u8 value) { + core_data.SetEyebrowAspect(value); +} + +void StoreData::SetEyebrowRotate(u8 value) { + core_data.SetEyebrowRotate(value); +} + +void StoreData::SetEyebrowX(u8 value) { + core_data.SetEyebrowX(value); +} + +void StoreData::SetEyebrowY(u8 value) { + core_data.SetEyebrowY(value); +} + +void StoreData::SetNoseType(u8 value) { + core_data.SetNoseType(value); +} + +void StoreData::SetNoseScale(u8 value) { + core_data.SetNoseScale(value); +} + +void StoreData::SetNoseY(u8 value) { + core_data.SetNoseY(value); +} + +void StoreData::SetMouthType(u8 value) { + core_data.SetMouthType(value); +} + +void StoreData::SetMouthColor(u8 value) { + core_data.SetMouthColor(value); +} + +void StoreData::SetMouthScale(u8 value) { + core_data.SetMouthScale(value); +} + +void StoreData::SetMouthAspect(u8 value) { + core_data.SetMouthAspect(value); +} + +void StoreData::SetMouthY(u8 value) { + core_data.SetMouthY(value); +} + +void StoreData::SetBeardColor(u8 value) { + core_data.SetBeardColor(value); +} + +void StoreData::SetBeardType(BeardType value) { + core_data.SetBeardType(value); +} + +void StoreData::SetMustacheType(MustacheType value) { + core_data.SetMustacheType(value); +} + +void StoreData::SetMustacheScale(u8 value) { + core_data.SetMustacheScale(value); +} + +void StoreData::SetMustacheY(u8 value) { + core_data.SetMustacheY(value); +} + +void StoreData::SetGlassType(u8 value) { + core_data.SetGlassType(value); +} + +void StoreData::SetGlassColor(u8 value) { + core_data.SetGlassColor(value); +} + +void StoreData::SetGlassScale(u8 value) { + core_data.SetGlassScale(value); +} + +void StoreData::SetGlassY(u8 value) { + core_data.SetGlassY(value); +} + +void StoreData::SetMoleType(u8 value) { + core_data.SetMoleType(value); +} + +void StoreData::SetMoleScale(u8 value) { + core_data.SetMoleScale(value); +} + +void StoreData::SetMoleX(u8 value) { + core_data.SetMoleX(value); +} + +void StoreData::SetMoleY(u8 value) { + core_data.SetMoleY(value); +} + +void StoreData::SetNickname(Nickname value) { + core_data.SetNickname(value); +} + Common::UUID StoreData::GetCreateId() const { return create_id; } @@ -386,7 +586,7 @@ Nickname StoreData::GetNickname() const { bool StoreData::operator==(const StoreData& data) { bool is_identical = data.core_data.IsValid() == 0; - is_identical &= core_data.GetNickname() == data.core_data.GetNickname(); + is_identical &= core_data.GetNickname().data == data.core_data.GetNickname().data; is_identical &= GetCreateId() == data.GetCreateId(); is_identical &= GetFontRegion() == data.GetFontRegion(); is_identical &= GetFavoriteColor() == data.GetFavoriteColor(); diff --git a/src/core/hle/service/mii/types/store_data.h b/src/core/hle/service/mii/types/store_data.h index cc8551a66..1e010000b 100644 --- a/src/core/hle/service/mii/types/store_data.h +++ b/src/core/hle/service/mii/types/store_data.h @@ -18,12 +18,62 @@ public: // nn::mii::detail::StoreDataRaw::BuildRandom void BuildRandom(Age age, Gender gender, Race race); - void SetInvalidName(); - bool IsSpecial() const; u32 IsValid() const; + void SetFontRegion(FontRegion value); + void SetFavoriteColor(u8 value); + void SetGender(Gender value); + void SetHeight(u8 value); + void SetBuild(u8 value); + void SetType(u8 value); + void SetRegionMove(u8 value); + void SetFacelineType(u8 value); + void SetFacelineColor(u8 value); + void SetFacelineWrinkle(u8 value); + void SetFacelineMake(u8 value); + void SetHairType(u8 value); + void SetHairColor(u8 value); + void SetHairFlip(HairFlip value); + void SetEyeType(u8 value); + void SetEyeColor(u8 value); + void SetEyeScale(u8 value); + void SetEyeAspect(u8 value); + void SetEyeRotate(u8 value); + void SetEyeX(u8 value); + void SetEyeY(u8 value); + void SetEyebrowType(u8 value); + void SetEyebrowColor(u8 value); + void SetEyebrowScale(u8 value); + void SetEyebrowAspect(u8 value); + void SetEyebrowRotate(u8 value); + void SetEyebrowX(u8 value); + void SetEyebrowY(u8 value); + void SetNoseType(u8 value); + void SetNoseScale(u8 value); + void SetNoseY(u8 value); + void SetMouthType(u8 value); + void SetMouthColor(u8 value); + void SetMouthScale(u8 value); + void SetMouthAspect(u8 value); + void SetMouthY(u8 value); + void SetBeardColor(u8 value); + void SetBeardType(BeardType value); + void SetMustacheType(MustacheType value); + void SetMustacheScale(u8 value); + void SetMustacheY(u8 value); + void SetGlassType(u8 value); + void SetGlassColor(u8 value); + void SetGlassScale(u8 value); + void SetGlassY(u8 value); + void SetMoleType(u8 value); + void SetMoleScale(u8 value); + void SetMoleX(u8 value); + void SetMoleY(u8 value); + void SetNickname(Nickname nickname); + void SetInvalidName(); + Common::UUID GetCreateId() const; FontRegion GetFontRegion() const; u8 GetFavoriteColor() const; diff --git a/src/core/hle/service/mii/types/ver3_store_data.cpp b/src/core/hle/service/mii/types/ver3_store_data.cpp index c774f4b47..53a3fe44b 100644 --- a/src/core/hle/service/mii/types/ver3_store_data.cpp +++ b/src/core/hle/service/mii/types/ver3_store_data.cpp @@ -2,160 +2,180 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/mii/mii_util.h" -#include "core/hle/service/mii/types/char_info.h" #include "core/hle/service/mii/types/raw_data.h" #include "core/hle/service/mii/types/store_data.h" #include "core/hle/service/mii/types/ver3_store_data.h" namespace Service::Mii { -void Ver3StoreData::BuildToStoreData(CharInfo& out_char_info) const { +void NfpStoreDataExtension::SetFromStoreData(const StoreData& store_data) { + faceline_color = static_cast(store_data.GetFacelineColor() & 0xf); + hair_color = static_cast(store_data.GetHairColor() & 0x7f); + eye_color = static_cast(store_data.GetEyeColor() & 0x7f); + eyebrow_color = static_cast(store_data.GetEyebrowColor() & 0x7f); + mouth_color = static_cast(store_data.GetMouthColor() & 0x7f); + beard_color = static_cast(store_data.GetBeardColor() & 0x7f); + glass_color = static_cast(store_data.GetGlassColor() & 0x7f); + glass_type = static_cast(store_data.GetGlassType() & 0x1f); +} + +void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const { + out_store_data.BuildBase(Gender::Male); + if (!IsValid()) { return; } // TODO: We are ignoring a bunch of data from the mii_v3 - out_char_info.gender = static_cast(mii_information.gender); - out_char_info.favorite_color = static_cast(mii_information.favorite_color); - out_char_info.height = height; - out_char_info.build = build; + out_store_data.SetGender(static_cast(static_cast(mii_information.gender))); + out_store_data.SetFavoriteColor(static_cast(mii_information.favorite_color)); + out_store_data.SetHeight(height); + out_store_data.SetBuild(build); // Copy name until string terminator - out_char_info.name = {}; - for (std::size_t index = 0; index < out_char_info.name.size() - 1; index++) { - out_char_info.name[index] = mii_name[index]; - if (out_char_info.name[index] == 0) { + Nickname name = {}; + for (std::size_t index = 0; index < name.data.size() - 1; index++) { + name.data[index] = mii_name[index]; + if (name.data[index] == 0) { break; } } - out_char_info.font_region = region_information.character_set; + out_store_data.SetNickname(name); + out_store_data.SetFontRegion( + static_cast(static_cast(region_information.font_region))); - out_char_info.faceline_type = appearance_bits1.face_shape; - out_char_info.faceline_color = appearance_bits1.skin_color; - out_char_info.faceline_wrinkle = appearance_bits2.wrinkles; - out_char_info.faceline_make = appearance_bits2.makeup; + out_store_data.SetFacelineType(appearance_bits1.faceline_type); + out_store_data.SetFacelineColor(appearance_bits1.faceline_color); + out_store_data.SetFacelineWrinkle(appearance_bits2.faceline_wrinkle); + out_store_data.SetFacelineMake(appearance_bits2.faceline_make); - out_char_info.hair_type = hair_style; - out_char_info.hair_color = appearance_bits3.hair_color; - out_char_info.hair_flip = appearance_bits3.flip_hair; + out_store_data.SetHairType(hair_type); + out_store_data.SetHairColor(appearance_bits3.hair_color); + out_store_data.SetHairFlip(static_cast(static_cast(appearance_bits3.hair_flip))); - out_char_info.eye_type = static_cast(appearance_bits4.eye_type); - out_char_info.eye_color = static_cast(appearance_bits4.eye_color); - out_char_info.eye_scale = static_cast(appearance_bits4.eye_scale); - out_char_info.eye_aspect = static_cast(appearance_bits4.eye_vertical_stretch); - out_char_info.eye_rotate = static_cast(appearance_bits4.eye_rotation); - out_char_info.eye_x = static_cast(appearance_bits4.eye_spacing); - out_char_info.eye_y = static_cast(appearance_bits4.eye_y_position); + out_store_data.SetEyeType(static_cast(appearance_bits4.eye_type)); + out_store_data.SetEyeColor(static_cast(appearance_bits4.eye_color)); + out_store_data.SetEyeScale(static_cast(appearance_bits4.eye_scale)); + out_store_data.SetEyeAspect(static_cast(appearance_bits4.eye_aspect)); + out_store_data.SetEyeRotate(static_cast(appearance_bits4.eye_rotate)); + out_store_data.SetEyeX(static_cast(appearance_bits4.eye_x)); + out_store_data.SetEyeY(static_cast(appearance_bits4.eye_y)); - out_char_info.eyebrow_type = static_cast(appearance_bits5.eyebrow_style); - out_char_info.eyebrow_color = static_cast(appearance_bits5.eyebrow_color); - out_char_info.eyebrow_scale = static_cast(appearance_bits5.eyebrow_scale); - out_char_info.eyebrow_aspect = static_cast(appearance_bits5.eyebrow_yscale); - out_char_info.eyebrow_rotate = static_cast(appearance_bits5.eyebrow_rotation); - out_char_info.eyebrow_x = static_cast(appearance_bits5.eyebrow_spacing); - out_char_info.eyebrow_y = static_cast(appearance_bits5.eyebrow_y_position); + out_store_data.SetEyebrowType(static_cast(appearance_bits5.eyebrow_type)); + out_store_data.SetEyebrowColor(static_cast(appearance_bits5.eyebrow_color)); + out_store_data.SetEyebrowScale(static_cast(appearance_bits5.eyebrow_scale)); + out_store_data.SetEyebrowAspect(static_cast(appearance_bits5.eyebrow_aspect)); + out_store_data.SetEyebrowRotate(static_cast(appearance_bits5.eyebrow_rotate)); + out_store_data.SetEyebrowX(static_cast(appearance_bits5.eyebrow_x)); + out_store_data.SetEyebrowY(static_cast(appearance_bits5.eyebrow_y)); - out_char_info.nose_type = static_cast(appearance_bits6.nose_type); - out_char_info.nose_scale = static_cast(appearance_bits6.nose_scale); - out_char_info.nose_y = static_cast(appearance_bits6.nose_y_position); + out_store_data.SetNoseType(static_cast(appearance_bits6.nose_type)); + out_store_data.SetNoseScale(static_cast(appearance_bits6.nose_scale)); + out_store_data.SetNoseY(static_cast(appearance_bits6.nose_y)); - out_char_info.mouth_type = static_cast(appearance_bits7.mouth_type); - out_char_info.mouth_color = static_cast(appearance_bits7.mouth_color); - out_char_info.mouth_scale = static_cast(appearance_bits7.mouth_scale); - out_char_info.mouth_aspect = static_cast(appearance_bits7.mouth_horizontal_stretch); - out_char_info.mouth_y = static_cast(appearance_bits8.mouth_y_position); + out_store_data.SetMouthType(static_cast(appearance_bits7.mouth_type)); + out_store_data.SetMouthColor(static_cast(appearance_bits7.mouth_color)); + out_store_data.SetMouthScale(static_cast(appearance_bits7.mouth_scale)); + out_store_data.SetMouthAspect(static_cast(appearance_bits7.mouth_aspect)); + out_store_data.SetMouthY(static_cast(appearance_bits8.mouth_y)); - out_char_info.mustache_type = static_cast(appearance_bits8.mustache_type); - out_char_info.mustache_scale = static_cast(appearance_bits9.mustache_scale); - out_char_info.mustache_y = static_cast(appearance_bits9.mustache_y_position); + out_store_data.SetMustacheType( + static_cast(static_cast(appearance_bits8.mustache_type))); + out_store_data.SetMustacheScale(static_cast(appearance_bits9.mustache_scale)); + out_store_data.SetMustacheY(static_cast(appearance_bits9.mustache_y)); - out_char_info.beard_type = static_cast(appearance_bits9.bear_type); - out_char_info.beard_color = static_cast(appearance_bits9.facial_hair_color); + out_store_data.SetBeardType( + static_cast(static_cast(appearance_bits9.beard_type))); + out_store_data.SetBeardColor(static_cast(appearance_bits9.beard_color)); - out_char_info.glasses_type = static_cast(appearance_bits10.glasses_type); - out_char_info.glasses_color = static_cast(appearance_bits10.glasses_color); - out_char_info.glasses_scale = static_cast(appearance_bits10.glasses_scale); - out_char_info.glasses_y = static_cast(appearance_bits10.glasses_y_position); + out_store_data.SetGlassType(static_cast(appearance_bits10.glass_type)); + out_store_data.SetGlassColor(static_cast(appearance_bits10.glass_color)); + out_store_data.SetGlassScale(static_cast(appearance_bits10.glass_scale)); + out_store_data.SetGlassY(static_cast(appearance_bits10.glass_y)); - out_char_info.mole_type = static_cast(appearance_bits11.mole_enabled); - out_char_info.mole_scale = static_cast(appearance_bits11.mole_scale); - out_char_info.mole_x = static_cast(appearance_bits11.mole_x_position); - out_char_info.mole_y = static_cast(appearance_bits11.mole_y_position); + out_store_data.SetMoleType(static_cast(appearance_bits11.mole_type)); + out_store_data.SetMoleScale(static_cast(appearance_bits11.mole_scale)); + out_store_data.SetMoleX(static_cast(appearance_bits11.mole_x)); + out_store_data.SetMoleY(static_cast(appearance_bits11.mole_y)); } -void Ver3StoreData::BuildFromStoreData(const CharInfo& char_info) { +void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { version = 1; - mii_information.gender.Assign(char_info.gender); - mii_information.favorite_color.Assign(char_info.favorite_color); - height = char_info.height; - build = char_info.build; + mii_information.gender.Assign(store_data.GetGender()); + mii_information.favorite_color.Assign(store_data.GetFavoriteColor()); + height = store_data.GetHeight(); + build = store_data.GetBuild(); // Copy name until string terminator mii_name = {}; - for (std::size_t index = 0; index < char_info.name.size() - 1; index++) { - mii_name[index] = char_info.name[index]; + for (std::size_t index = 0; index < store_data.GetNickname().data.size() - 1; index++) { + mii_name[index] = store_data.GetNickname().data[index]; if (mii_name[index] == 0) { break; } } - region_information.character_set.Assign(char_info.font_region); + region_information.font_region.Assign(static_cast(store_data.GetFontRegion())); - appearance_bits1.face_shape.Assign(char_info.faceline_type); - appearance_bits2.wrinkles.Assign(char_info.faceline_wrinkle); - appearance_bits2.makeup.Assign(char_info.faceline_make); + appearance_bits1.faceline_type.Assign(store_data.GetFacelineType()); + appearance_bits2.faceline_wrinkle.Assign(store_data.GetFacelineWrinkle()); + appearance_bits2.faceline_make.Assign(store_data.GetFacelineMake()); - hair_style = char_info.hair_type; - appearance_bits3.flip_hair.Assign(char_info.hair_flip); + hair_type = store_data.GetHairType(); + appearance_bits3.hair_flip.Assign(store_data.GetHairFlip()); - appearance_bits4.eye_type.Assign(char_info.eye_type); - appearance_bits4.eye_scale.Assign(char_info.eye_scale); - appearance_bits4.eye_vertical_stretch.Assign(char_info.eye_aspect); - appearance_bits4.eye_rotation.Assign(char_info.eye_rotate); - appearance_bits4.eye_spacing.Assign(char_info.eye_x); - appearance_bits4.eye_y_position.Assign(char_info.eye_y); + appearance_bits4.eye_type.Assign(store_data.GetEyeType()); + appearance_bits4.eye_scale.Assign(store_data.GetEyeScale()); + appearance_bits4.eye_aspect.Assign(store_data.GetEyebrowAspect()); + appearance_bits4.eye_rotate.Assign(store_data.GetEyeRotate()); + appearance_bits4.eye_x.Assign(store_data.GetEyeX()); + appearance_bits4.eye_y.Assign(store_data.GetEyeY()); - appearance_bits5.eyebrow_style.Assign(char_info.eyebrow_type); - appearance_bits5.eyebrow_scale.Assign(char_info.eyebrow_scale); - appearance_bits5.eyebrow_yscale.Assign(char_info.eyebrow_aspect); - appearance_bits5.eyebrow_rotation.Assign(char_info.eyebrow_rotate); - appearance_bits5.eyebrow_spacing.Assign(char_info.eyebrow_x); - appearance_bits5.eyebrow_y_position.Assign(char_info.eyebrow_y); + appearance_bits5.eyebrow_type.Assign(store_data.GetEyebrowType()); + appearance_bits5.eyebrow_scale.Assign(store_data.GetEyebrowScale()); + appearance_bits5.eyebrow_aspect.Assign(store_data.GetEyebrowAspect()); + appearance_bits5.eyebrow_rotate.Assign(store_data.GetEyebrowRotate()); + appearance_bits5.eyebrow_x.Assign(store_data.GetEyebrowX()); + appearance_bits5.eyebrow_y.Assign(store_data.GetEyebrowY()); - appearance_bits6.nose_type.Assign(char_info.nose_type); - appearance_bits6.nose_scale.Assign(char_info.nose_scale); - appearance_bits6.nose_y_position.Assign(char_info.nose_y); + appearance_bits6.nose_type.Assign(store_data.GetNoseType()); + appearance_bits6.nose_scale.Assign(store_data.GetNoseScale()); + appearance_bits6.nose_y.Assign(store_data.GetNoseY()); - appearance_bits7.mouth_type.Assign(char_info.mouth_type); - appearance_bits7.mouth_scale.Assign(char_info.mouth_scale); - appearance_bits7.mouth_horizontal_stretch.Assign(char_info.mouth_aspect); - appearance_bits8.mouth_y_position.Assign(char_info.mouth_y); + appearance_bits7.mouth_type.Assign(store_data.GetMouthType()); + appearance_bits7.mouth_scale.Assign(store_data.GetMouthScale()); + appearance_bits7.mouth_aspect.Assign(store_data.GetMouthAspect()); + appearance_bits8.mouth_y.Assign(store_data.GetMouthY()); - appearance_bits8.mustache_type.Assign(char_info.mustache_type); - appearance_bits9.mustache_scale.Assign(char_info.mustache_scale); - appearance_bits9.mustache_y_position.Assign(char_info.mustache_y); + appearance_bits8.mustache_type.Assign(store_data.GetMustacheType()); + appearance_bits9.mustache_scale.Assign(store_data.GetMustacheScale()); + appearance_bits9.mustache_y.Assign(store_data.GetMustacheY()); - appearance_bits9.bear_type.Assign(char_info.beard_type); + appearance_bits9.beard_type.Assign(store_data.GetBeardType()); - appearance_bits10.glasses_scale.Assign(char_info.glasses_scale); - appearance_bits10.glasses_y_position.Assign(char_info.glasses_y); + appearance_bits10.glass_scale.Assign(store_data.GetGlassScale()); + appearance_bits10.glass_y.Assign(store_data.GetGlassY()); - appearance_bits11.mole_enabled.Assign(char_info.mole_type); - appearance_bits11.mole_scale.Assign(char_info.mole_scale); - appearance_bits11.mole_x_position.Assign(char_info.mole_x); - appearance_bits11.mole_y_position.Assign(char_info.mole_y); + appearance_bits11.mole_type.Assign(store_data.GetMoleType()); + appearance_bits11.mole_scale.Assign(store_data.GetMoleScale()); + appearance_bits11.mole_x.Assign(store_data.GetMoleX()); + appearance_bits11.mole_y.Assign(store_data.GetMoleY()); // These types are converted to V3 from a table - appearance_bits1.skin_color.Assign(RawData::FromVer3GetFacelineColor(char_info.faceline_color)); - appearance_bits3.hair_color.Assign(RawData::FromVer3GetHairColor(char_info.hair_color)); - appearance_bits4.eye_color.Assign(RawData::FromVer3GetEyeColor(char_info.eye_color)); - appearance_bits5.eyebrow_color.Assign(RawData::FromVer3GetHairColor(char_info.eyebrow_color)); - appearance_bits7.mouth_color.Assign(RawData::FromVer3GetMouthlineColor(char_info.mouth_color)); - appearance_bits9.facial_hair_color.Assign(RawData::FromVer3GetHairColor(char_info.beard_color)); - appearance_bits10.glasses_color.Assign(RawData::FromVer3GetGlassColor(char_info.glasses_color)); - appearance_bits10.glasses_type.Assign(RawData::FromVer3GetGlassType(char_info.glasses_type)); + appearance_bits1.faceline_color.Assign( + RawData::FromVer3GetFacelineColor(store_data.GetFacelineColor())); + appearance_bits3.hair_color.Assign(RawData::FromVer3GetHairColor(store_data.GetHairColor())); + appearance_bits4.eye_color.Assign(RawData::FromVer3GetEyeColor(store_data.GetEyeColor())); + appearance_bits5.eyebrow_color.Assign( + RawData::FromVer3GetHairColor(store_data.GetEyebrowColor())); + appearance_bits7.mouth_color.Assign( + RawData::FromVer3GetMouthlineColor(store_data.GetMouthColor())); + appearance_bits9.beard_color.Assign(RawData::FromVer3GetHairColor(store_data.GetBeardColor())); + appearance_bits10.glass_color.Assign( + RawData::FromVer3GetGlassColor(store_data.GetGlassColor())); + appearance_bits10.glass_type.Assign(RawData::FromVer3GetGlassType(store_data.GetGlassType())); crc = MiiUtil::CalculateCrc16(&version, sizeof(Ver3StoreData) - sizeof(u16)); } @@ -171,56 +191,56 @@ u32 Ver3StoreData::IsValid() const { is_valid = is_valid && (height < 128); is_valid = is_valid && (build < 128); - is_valid = is_valid && (appearance_bits1.face_shape < 12); - is_valid = is_valid && (appearance_bits1.skin_color < 7); - is_valid = is_valid && (appearance_bits2.wrinkles < 12); - is_valid = is_valid && (appearance_bits2.makeup < 12); + is_valid = is_valid && (appearance_bits1.faceline_type < 12); + is_valid = is_valid && (appearance_bits1.faceline_color < 7); + is_valid = is_valid && (appearance_bits2.faceline_wrinkle < 12); + is_valid = is_valid && (appearance_bits2.faceline_make < 12); - is_valid = is_valid && (hair_style < 132); + is_valid = is_valid && (hair_type < 132); is_valid = is_valid && (appearance_bits3.hair_color < 8); is_valid = is_valid && (appearance_bits4.eye_type < 60); is_valid = is_valid && (appearance_bits4.eye_color < 6); is_valid = is_valid && (appearance_bits4.eye_scale < 8); - is_valid = is_valid && (appearance_bits4.eye_vertical_stretch < 7); - is_valid = is_valid && (appearance_bits4.eye_rotation < 8); - is_valid = is_valid && (appearance_bits4.eye_spacing < 13); - is_valid = is_valid && (appearance_bits4.eye_y_position < 19); + is_valid = is_valid && (appearance_bits4.eye_aspect < 7); + is_valid = is_valid && (appearance_bits4.eye_rotate < 8); + is_valid = is_valid && (appearance_bits4.eye_x < 13); + is_valid = is_valid && (appearance_bits4.eye_y < 19); - is_valid = is_valid && (appearance_bits5.eyebrow_style < 25); + is_valid = is_valid && (appearance_bits5.eyebrow_type < 25); is_valid = is_valid && (appearance_bits5.eyebrow_color < 8); is_valid = is_valid && (appearance_bits5.eyebrow_scale < 9); - is_valid = is_valid && (appearance_bits5.eyebrow_yscale < 7); - is_valid = is_valid && (appearance_bits5.eyebrow_rotation < 12); - is_valid = is_valid && (appearance_bits5.eyebrow_spacing < 12); - is_valid = is_valid && (appearance_bits5.eyebrow_y_position < 19); + is_valid = is_valid && (appearance_bits5.eyebrow_aspect < 7); + is_valid = is_valid && (appearance_bits5.eyebrow_rotate < 12); + is_valid = is_valid && (appearance_bits5.eyebrow_x < 12); + is_valid = is_valid && (appearance_bits5.eyebrow_y < 19); is_valid = is_valid && (appearance_bits6.nose_type < 18); is_valid = is_valid && (appearance_bits6.nose_scale < 9); - is_valid = is_valid && (appearance_bits6.nose_y_position < 19); + is_valid = is_valid && (appearance_bits6.nose_y < 19); is_valid = is_valid && (appearance_bits7.mouth_type < 36); is_valid = is_valid && (appearance_bits7.mouth_color < 5); is_valid = is_valid && (appearance_bits7.mouth_scale < 9); - is_valid = is_valid && (appearance_bits7.mouth_horizontal_stretch < 7); - is_valid = is_valid && (appearance_bits8.mouth_y_position < 19); + is_valid = is_valid && (appearance_bits7.mouth_aspect < 7); + is_valid = is_valid && (appearance_bits8.mouth_y < 19); is_valid = is_valid && (appearance_bits8.mustache_type < 6); is_valid = is_valid && (appearance_bits9.mustache_scale < 7); - is_valid = is_valid && (appearance_bits9.mustache_y_position < 17); + is_valid = is_valid && (appearance_bits9.mustache_y < 17); - is_valid = is_valid && (appearance_bits9.bear_type < 6); - is_valid = is_valid && (appearance_bits9.facial_hair_color < 8); + is_valid = is_valid && (appearance_bits9.beard_type < 6); + is_valid = is_valid && (appearance_bits9.beard_color < 8); - is_valid = is_valid && (appearance_bits10.glasses_type < 9); - is_valid = is_valid && (appearance_bits10.glasses_color < 6); - is_valid = is_valid && (appearance_bits10.glasses_scale < 8); - is_valid = is_valid && (appearance_bits10.glasses_y_position < 21); + is_valid = is_valid && (appearance_bits10.glass_type < 9); + is_valid = is_valid && (appearance_bits10.glass_color < 6); + is_valid = is_valid && (appearance_bits10.glass_scale < 8); + is_valid = is_valid && (appearance_bits10.glass_y < 21); - is_valid = is_valid && (appearance_bits11.mole_enabled < 2); + is_valid = is_valid && (appearance_bits11.mole_type < 2); is_valid = is_valid && (appearance_bits11.mole_scale < 9); - is_valid = is_valid && (appearance_bits11.mole_x_position < 17); - is_valid = is_valid && (appearance_bits11.mole_y_position < 31); + is_valid = is_valid && (appearance_bits11.mole_x < 17); + is_valid = is_valid && (appearance_bits11.mole_y < 31); return is_valid; } diff --git a/src/core/hle/service/mii/types/ver3_store_data.h b/src/core/hle/service/mii/types/ver3_store_data.h index 6b4e1eb9c..11caeb5c3 100644 --- a/src/core/hle/service/mii/types/ver3_store_data.h +++ b/src/core/hle/service/mii/types/ver3_store_data.h @@ -6,20 +6,32 @@ #include "core/hle/service/mii/mii_types.h" namespace Service::Mii { -class CharInfo; +class StoreData; // This is nn::mii::Ver3StoreData // Based on citra HLE::Applets::MiiData and PretendoNetwork. // https://github.com/citra-emu/citra/blob/master/src/core/hle/applets/mii_selector.h#L48 // https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299 +struct NfpStoreDataExtension { + void SetFromStoreData(const StoreData& store_data); + + u8 faceline_color; + u8 hair_color; + u8 eye_color; + u8 eyebrow_color; + u8 mouth_color; + u8 beard_color; + u8 glass_color; + u8 glass_type; +}; +static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size"); + #pragma pack(push, 4) class Ver3StoreData { public: - // TODO: This function is wrong. It should use StoreData. - void BuildToStoreData(CharInfo& out_char_info) const; - // TODO: This function is wrong. It should use StoreData. - void BuildFromStoreData(const CharInfo& char_info); + void BuildToStoreData(StoreData& out_store_data) const; + void BuildFromStoreData(const StoreData& store_data); u32 IsValid() const; @@ -30,7 +42,7 @@ public: BitField<0, 1, u8> allow_copying; BitField<1, 1, u8> profanity_flag; BitField<2, 2, u8> region_lock; - BitField<4, 2, u8> character_set; + BitField<4, 2, u8> font_region; } region_information; u16_be mii_id; u64_be system_id; @@ -53,21 +65,21 @@ public: u8 raw; BitField<0, 1, u8> disable_sharing; - BitField<1, 4, u8> face_shape; - BitField<5, 3, u8> skin_color; + BitField<1, 4, u8> faceline_type; + BitField<5, 3, u8> faceline_color; } appearance_bits1; union { u8 raw; - BitField<0, 4, u8> wrinkles; - BitField<4, 4, u8> makeup; + BitField<0, 4, u8> faceline_wrinkle; + BitField<4, 4, u8> faceline_make; } appearance_bits2; - u8 hair_style; + u8 hair_type; union { u8 raw; BitField<0, 3, u8> hair_color; - BitField<3, 1, u8> flip_hair; + BitField<3, 1, u8> hair_flip; } appearance_bits3; union { u32 raw; @@ -75,28 +87,28 @@ public: BitField<0, 6, u32> eye_type; BitField<6, 3, u32> eye_color; BitField<9, 4, u32> eye_scale; - BitField<13, 3, u32> eye_vertical_stretch; - BitField<16, 5, u32> eye_rotation; - BitField<21, 4, u32> eye_spacing; - BitField<25, 5, u32> eye_y_position; + BitField<13, 3, u32> eye_aspect; + BitField<16, 5, u32> eye_rotate; + BitField<21, 4, u32> eye_x; + BitField<25, 5, u32> eye_y; } appearance_bits4; union { u32 raw; - BitField<0, 5, u32> eyebrow_style; + BitField<0, 5, u32> eyebrow_type; BitField<5, 3, u32> eyebrow_color; BitField<8, 4, u32> eyebrow_scale; - BitField<12, 3, u32> eyebrow_yscale; - BitField<16, 4, u32> eyebrow_rotation; - BitField<21, 4, u32> eyebrow_spacing; - BitField<25, 5, u32> eyebrow_y_position; + BitField<12, 3, u32> eyebrow_aspect; + BitField<16, 4, u32> eyebrow_rotate; + BitField<21, 4, u32> eyebrow_x; + BitField<25, 5, u32> eyebrow_y; } appearance_bits5; union { u16 raw; BitField<0, 5, u16> nose_type; BitField<5, 4, u16> nose_scale; - BitField<9, 5, u16> nose_y_position; + BitField<9, 5, u16> nose_y; } appearance_bits6; union { u16 raw; @@ -104,38 +116,38 @@ public: BitField<0, 6, u16> mouth_type; BitField<6, 3, u16> mouth_color; BitField<9, 4, u16> mouth_scale; - BitField<13, 3, u16> mouth_horizontal_stretch; + BitField<13, 3, u16> mouth_aspect; } appearance_bits7; union { u8 raw; - BitField<0, 5, u8> mouth_y_position; + BitField<0, 5, u8> mouth_y; BitField<5, 3, u8> mustache_type; } appearance_bits8; u8 allow_copying; union { u16 raw; - BitField<0, 3, u16> bear_type; - BitField<3, 3, u16> facial_hair_color; + BitField<0, 3, u16> beard_type; + BitField<3, 3, u16> beard_color; BitField<6, 4, u16> mustache_scale; - BitField<10, 5, u16> mustache_y_position; + BitField<10, 5, u16> mustache_y; } appearance_bits9; union { u16 raw; - BitField<0, 4, u16> glasses_type; - BitField<4, 3, u16> glasses_color; - BitField<7, 4, u16> glasses_scale; - BitField<11, 5, u16> glasses_y_position; + BitField<0, 4, u16> glass_type; + BitField<4, 3, u16> glass_color; + BitField<7, 4, u16> glass_scale; + BitField<11, 5, u16> glass_y; } appearance_bits10; union { u16 raw; - BitField<0, 1, u16> mole_enabled; + BitField<0, 1, u16> mole_type; BitField<1, 4, u16> mole_scale; - BitField<5, 5, u16> mole_x_position; - BitField<10, 5, u16> mole_y_position; + BitField<5, 5, u16> mole_x; + BitField<10, 5, u16> mole_y; } appearance_bits11; std::array author_name; diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 5e61d2595..eb7706015 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -824,8 +824,11 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe return ResultWrongDeviceState; } - Service::Mii::MiiManager manager; - const auto mii = manager.BuildBase(Mii::Gender::Male); + Service::Mii::StoreData store_data{}; + Service::Mii::NfpStoreDataExtension extension{}; + store_data.BuildBase(Mii::Gender::Male); + extension.SetFromStoreData(store_data); + auto& settings = tag_data.settings; if (tag_data.settings.settings.amiibo_initialized == 0) { @@ -834,8 +837,8 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe } SetAmiiboName(settings, register_info.amiibo_name); - tag_data.owner_mii.BuildFromStoreData(mii); - tag_data.mii_extension = manager.SetFromStoreData(mii); + tag_data.owner_mii.BuildFromStoreData(store_data); + tag_data.mii_extension = extension; tag_data.unknown = 0; tag_data.unknown2 = {}; settings.country_code_id = 0; @@ -1452,7 +1455,7 @@ void NfcDevice::UpdateRegisterInfoCrc() { void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, const NFP::EncryptedNTAG215File& encrypted_file) const { - Service::Mii::MiiManager manager; + Service::Mii::StoreData store_data{}; auto& settings = stubbed_tag_data.settings; stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file); @@ -1466,7 +1469,8 @@ void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'}); settings.settings.font_region.Assign(0); settings.init_date = GetAmiiboDate(GetCurrentPosixTime()); - stubbed_tag_data.owner_mii.BuildFromStoreData(manager.BuildBase(Mii::Gender::Male)); + store_data.BuildBase(Mii::Gender::Male); + stubbed_tag_data.owner_mii.BuildFromStoreData(store_data); // Admin info settings.settings.amiibo_initialized.Assign(1);