service: mii: Move ver3 operations
This commit is contained in:
		| @@ -394,173 +394,9 @@ CharInfo MiiManager::BuildDefault(std::size_t index) { | |||||||
| } | } | ||||||
|  |  | ||||||
| CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const { | CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const { | ||||||
|     Service::Mii::MiiManager manager; |     CharInfo char_info{}; | ||||||
|     auto mii = manager.BuildBase(Mii::Gender::Male); |     mii_v3.BuildToStoreData(char_info); | ||||||
|  |     return char_info; | ||||||
|     if (!ValidateV3Info(mii_v3)) { |  | ||||||
|         return mii; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // TODO: We are ignoring a bunch of data from the mii_v3 |  | ||||||
|  |  | ||||||
|     mii.gender = static_cast<u8>(mii_v3.mii_information.gender); |  | ||||||
|     mii.favorite_color = static_cast<u8>(mii_v3.mii_information.favorite_color); |  | ||||||
|     mii.height = mii_v3.height; |  | ||||||
|     mii.build = mii_v3.build; |  | ||||||
|  |  | ||||||
|     // Copy name until string terminator |  | ||||||
|     mii.name = {}; |  | ||||||
|     for (std::size_t index = 0; index < mii.name.size() - 1; index++) { |  | ||||||
|         mii.name[index] = mii_v3.mii_name[index]; |  | ||||||
|         if (mii.name[index] == 0) { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     mii.font_region = mii_v3.region_information.character_set; |  | ||||||
|  |  | ||||||
|     mii.faceline_type = mii_v3.appearance_bits1.face_shape; |  | ||||||
|     mii.faceline_color = mii_v3.appearance_bits1.skin_color; |  | ||||||
|     mii.faceline_wrinkle = mii_v3.appearance_bits2.wrinkles; |  | ||||||
|     mii.faceline_make = mii_v3.appearance_bits2.makeup; |  | ||||||
|  |  | ||||||
|     mii.hair_type = mii_v3.hair_style; |  | ||||||
|     mii.hair_color = mii_v3.appearance_bits3.hair_color; |  | ||||||
|     mii.hair_flip = mii_v3.appearance_bits3.flip_hair; |  | ||||||
|  |  | ||||||
|     mii.eye_type = static_cast<u8>(mii_v3.appearance_bits4.eye_type); |  | ||||||
|     mii.eye_color = static_cast<u8>(mii_v3.appearance_bits4.eye_color); |  | ||||||
|     mii.eye_scale = static_cast<u8>(mii_v3.appearance_bits4.eye_scale); |  | ||||||
|     mii.eye_aspect = static_cast<u8>(mii_v3.appearance_bits4.eye_vertical_stretch); |  | ||||||
|     mii.eye_rotate = static_cast<u8>(mii_v3.appearance_bits4.eye_rotation); |  | ||||||
|     mii.eye_x = static_cast<u8>(mii_v3.appearance_bits4.eye_spacing); |  | ||||||
|     mii.eye_y = static_cast<u8>(mii_v3.appearance_bits4.eye_y_position); |  | ||||||
|  |  | ||||||
|     mii.eyebrow_type = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_style); |  | ||||||
|     mii.eyebrow_color = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_color); |  | ||||||
|     mii.eyebrow_scale = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_scale); |  | ||||||
|     mii.eyebrow_aspect = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_yscale); |  | ||||||
|     mii.eyebrow_rotate = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_rotation); |  | ||||||
|     mii.eyebrow_x = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_spacing); |  | ||||||
|     mii.eyebrow_y = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_y_position); |  | ||||||
|  |  | ||||||
|     mii.nose_type = static_cast<u8>(mii_v3.appearance_bits6.nose_type); |  | ||||||
|     mii.nose_scale = static_cast<u8>(mii_v3.appearance_bits6.nose_scale); |  | ||||||
|     mii.nose_y = static_cast<u8>(mii_v3.appearance_bits6.nose_y_position); |  | ||||||
|  |  | ||||||
|     mii.mouth_type = static_cast<u8>(mii_v3.appearance_bits7.mouth_type); |  | ||||||
|     mii.mouth_color = static_cast<u8>(mii_v3.appearance_bits7.mouth_color); |  | ||||||
|     mii.mouth_scale = static_cast<u8>(mii_v3.appearance_bits7.mouth_scale); |  | ||||||
|     mii.mouth_aspect = static_cast<u8>(mii_v3.appearance_bits7.mouth_horizontal_stretch); |  | ||||||
|     mii.mouth_y = static_cast<u8>(mii_v3.appearance_bits8.mouth_y_position); |  | ||||||
|  |  | ||||||
|     mii.mustache_type = static_cast<u8>(mii_v3.appearance_bits8.mustache_type); |  | ||||||
|     mii.mustache_scale = static_cast<u8>(mii_v3.appearance_bits9.mustache_scale); |  | ||||||
|     mii.mustache_y = static_cast<u8>(mii_v3.appearance_bits9.mustache_y_position); |  | ||||||
|  |  | ||||||
|     mii.beard_type = static_cast<u8>(mii_v3.appearance_bits9.bear_type); |  | ||||||
|     mii.beard_color = static_cast<u8>(mii_v3.appearance_bits9.facial_hair_color); |  | ||||||
|  |  | ||||||
|     mii.glasses_type = static_cast<u8>(mii_v3.appearance_bits10.glasses_type); |  | ||||||
|     mii.glasses_color = static_cast<u8>(mii_v3.appearance_bits10.glasses_color); |  | ||||||
|     mii.glasses_scale = static_cast<u8>(mii_v3.appearance_bits10.glasses_scale); |  | ||||||
|     mii.glasses_y = static_cast<u8>(mii_v3.appearance_bits10.glasses_y_position); |  | ||||||
|  |  | ||||||
|     mii.mole_type = static_cast<u8>(mii_v3.appearance_bits11.mole_enabled); |  | ||||||
|     mii.mole_scale = static_cast<u8>(mii_v3.appearance_bits11.mole_scale); |  | ||||||
|     mii.mole_x = static_cast<u8>(mii_v3.appearance_bits11.mole_x_position); |  | ||||||
|     mii.mole_y = static_cast<u8>(mii_v3.appearance_bits11.mole_y_position); |  | ||||||
|  |  | ||||||
|     // TODO: Validate mii data |  | ||||||
|  |  | ||||||
|     return mii; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const { |  | ||||||
|     Service::Mii::MiiManager manager; |  | ||||||
|     Ver3StoreData mii_v3{}; |  | ||||||
|  |  | ||||||
|     // TODO: We are ignoring a bunch of data from the mii_v3 |  | ||||||
|  |  | ||||||
|     mii_v3.version = 1; |  | ||||||
|     mii_v3.mii_information.gender.Assign(mii.gender); |  | ||||||
|     mii_v3.mii_information.favorite_color.Assign(mii.favorite_color); |  | ||||||
|     mii_v3.height = mii.height; |  | ||||||
|     mii_v3.build = mii.build; |  | ||||||
|  |  | ||||||
|     // Copy name until string terminator |  | ||||||
|     mii_v3.mii_name = {}; |  | ||||||
|     for (std::size_t index = 0; index < mii.name.size() - 1; index++) { |  | ||||||
|         mii_v3.mii_name[index] = mii.name[index]; |  | ||||||
|         if (mii_v3.mii_name[index] == 0) { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     mii_v3.region_information.character_set.Assign(mii.font_region); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type); |  | ||||||
|     mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle); |  | ||||||
|     mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make); |  | ||||||
|  |  | ||||||
|     mii_v3.hair_style = mii.hair_type; |  | ||||||
|     mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type); |  | ||||||
|     mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale); |  | ||||||
|     mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect); |  | ||||||
|     mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate); |  | ||||||
|     mii_v3.appearance_bits4.eye_spacing.Assign(mii.eye_x); |  | ||||||
|     mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type); |  | ||||||
|     mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale); |  | ||||||
|     mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect); |  | ||||||
|     mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate); |  | ||||||
|     mii_v3.appearance_bits5.eyebrow_spacing.Assign(mii.eyebrow_x); |  | ||||||
|     mii_v3.appearance_bits5.eyebrow_y_position.Assign(mii.eyebrow_y); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits6.nose_type.Assign(mii.nose_type); |  | ||||||
|     mii_v3.appearance_bits6.nose_scale.Assign(mii.nose_scale); |  | ||||||
|     mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type); |  | ||||||
|     mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale); |  | ||||||
|     mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect); |  | ||||||
|     mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits8.mustache_type.Assign(mii.mustache_type); |  | ||||||
|     mii_v3.appearance_bits9.mustache_scale.Assign(mii.mustache_scale); |  | ||||||
|     mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale); |  | ||||||
|     mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y); |  | ||||||
|  |  | ||||||
|     mii_v3.appearance_bits11.mole_enabled.Assign(mii.mole_type); |  | ||||||
|     mii_v3.appearance_bits11.mole_scale.Assign(mii.mole_scale); |  | ||||||
|     mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x); |  | ||||||
|     mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y); |  | ||||||
|  |  | ||||||
|     // These types are converted to V3 from a table |  | ||||||
|     mii_v3.appearance_bits1.skin_color.Assign( |  | ||||||
|         RawData::FromVer3GetFacelineColor(mii.faceline_color)); |  | ||||||
|     mii_v3.appearance_bits3.hair_color.Assign(RawData::FromVer3GetHairColor(mii.hair_color)); |  | ||||||
|     mii_v3.appearance_bits4.eye_color.Assign(RawData::FromVer3GetEyeColor(mii.eye_color)); |  | ||||||
|     mii_v3.appearance_bits5.eyebrow_color.Assign(RawData::FromVer3GetHairColor(mii.eyebrow_color)); |  | ||||||
|     mii_v3.appearance_bits7.mouth_color.Assign(RawData::FromVer3GetMouthlineColor(mii.mouth_color)); |  | ||||||
|     mii_v3.appearance_bits9.facial_hair_color.Assign( |  | ||||||
|         RawData::FromVer3GetHairColor(mii.beard_color)); |  | ||||||
|     mii_v3.appearance_bits10.glasses_color.Assign( |  | ||||||
|         RawData::FromVer3GetGlassColor(mii.glasses_color)); |  | ||||||
|     mii_v3.appearance_bits10.glasses_type.Assign(RawData::FromVer3GetGlassType(mii.glasses_type)); |  | ||||||
|  |  | ||||||
|     mii_v3.crc = MiiUtil::CalculateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16)); |  | ||||||
|  |  | ||||||
|     // TODO: Validate mii_v3 data |  | ||||||
|  |  | ||||||
|     return mii_v3; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const { | NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const { | ||||||
| @@ -576,71 +412,6 @@ NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { |  | ||||||
|     bool is_valid = mii_v3.version == 0 || mii_v3.version == 3; |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.mii_name[0] != 0); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.mii_information.birth_month < 13); |  | ||||||
|     is_valid = is_valid && (mii_v3.mii_information.birth_day < 32); |  | ||||||
|     is_valid = is_valid && (mii_v3.mii_information.favorite_color < 12); |  | ||||||
|     is_valid = is_valid && (mii_v3.height < 128); |  | ||||||
|     is_valid = is_valid && (mii_v3.build < 128); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits1.face_shape < 12); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits1.skin_color < 7); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits2.wrinkles < 12); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits2.makeup < 12); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.hair_style < 132); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits3.hair_color < 8); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits4.eye_type < 60); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits4.eye_color < 6); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits4.eye_scale < 8); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits4.eye_vertical_stretch < 7); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits4.eye_rotation < 8); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits4.eye_spacing < 13); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits4.eye_y_position < 19); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_style < 25); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_color < 8); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_scale < 9); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_yscale < 7); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_rotation < 12); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_spacing < 12); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_y_position < 19); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits6.nose_type < 18); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits6.nose_scale < 9); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits6.nose_y_position < 19); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits7.mouth_type < 36); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits7.mouth_color < 5); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits7.mouth_scale < 9); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits7.mouth_horizontal_stretch < 7); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits8.mouth_y_position < 19); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits8.mustache_type < 6); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits9.mustache_scale < 7); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits9.mustache_y_position < 17); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits9.bear_type < 6); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits9.facial_hair_color < 8); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits10.glasses_type < 9); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits10.glasses_color < 6); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits10.glasses_scale < 8); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits10.glasses_y_position < 21); |  | ||||||
|  |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits11.mole_enabled < 2); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits11.mole_scale < 9); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits11.mole_x_position < 17); |  | ||||||
|     is_valid = is_valid && (mii_v3.appearance_bits11.mole_y_position < 31); |  | ||||||
|  |  | ||||||
|     return is_valid; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| std::vector<CharInfoElement> MiiManager::GetDefault(SourceFlag source_flag) { | std::vector<CharInfoElement> MiiManager::GetDefault(SourceFlag source_flag) { | ||||||
|     std::vector<CharInfoElement> result; |     std::vector<CharInfoElement> result; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,13 +27,9 @@ public: | |||||||
|     CharInfo BuildBase(Gender gender); |     CharInfo BuildBase(Gender gender); | ||||||
|     CharInfo BuildDefault(std::size_t index); |     CharInfo BuildDefault(std::size_t index); | ||||||
|     CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; |     CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; | ||||||
|     bool ValidateV3Info(const Ver3StoreData& mii_v3) const; |  | ||||||
|     std::vector<CharInfoElement> GetDefault(SourceFlag source_flag); |     std::vector<CharInfoElement> GetDefault(SourceFlag source_flag); | ||||||
|     Result GetIndex(const CharInfo& info, u32& index); |     Result GetIndex(const CharInfo& info, u32& index); | ||||||
|  |  | ||||||
|     // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData |  | ||||||
|     Ver3StoreData BuildFromStoreData(const CharInfo& mii) const; |  | ||||||
|  |  | ||||||
|     // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData |     // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData | ||||||
|     NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const; |     NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,7 +8,8 @@ | |||||||
| namespace Service::Mii { | namespace Service::Mii { | ||||||
|  |  | ||||||
| // This is nn::mii::detail::CharInfoRaw | // This is nn::mii::detail::CharInfoRaw | ||||||
| struct CharInfo { | class CharInfo { | ||||||
|  | public: | ||||||
|     Common::UUID create_id; |     Common::UUID create_id; | ||||||
|     Nickname name; |     Nickname name; | ||||||
|     u16 null_terminator; |     u16 null_terminator; | ||||||
|   | |||||||
| @@ -1,6 +1,228 @@ | |||||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||||
| // SPDX-License-Identifier: GPL-2.0-or-later | // 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" | #include "core/hle/service/mii/types/ver3_store_data.h" | ||||||
|  |  | ||||||
| namespace Service::Mii {} // namespace Service::Mii | namespace Service::Mii { | ||||||
|  |  | ||||||
|  | void Ver3StoreData::BuildToStoreData(CharInfo& out_char_info) const { | ||||||
|  |     if (!IsValid()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // TODO: We are ignoring a bunch of data from the mii_v3 | ||||||
|  |  | ||||||
|  |     out_char_info.gender = static_cast<u8>(mii_information.gender); | ||||||
|  |     out_char_info.favorite_color = static_cast<u8>(mii_information.favorite_color); | ||||||
|  |     out_char_info.height = height; | ||||||
|  |     out_char_info.build = 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) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     out_char_info.font_region = region_information.character_set; | ||||||
|  |  | ||||||
|  |     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_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_char_info.eye_type = static_cast<u8>(appearance_bits4.eye_type); | ||||||
|  |     out_char_info.eye_color = static_cast<u8>(appearance_bits4.eye_color); | ||||||
|  |     out_char_info.eye_scale = static_cast<u8>(appearance_bits4.eye_scale); | ||||||
|  |     out_char_info.eye_aspect = static_cast<u8>(appearance_bits4.eye_vertical_stretch); | ||||||
|  |     out_char_info.eye_rotate = static_cast<u8>(appearance_bits4.eye_rotation); | ||||||
|  |     out_char_info.eye_x = static_cast<u8>(appearance_bits4.eye_spacing); | ||||||
|  |     out_char_info.eye_y = static_cast<u8>(appearance_bits4.eye_y_position); | ||||||
|  |  | ||||||
|  |     out_char_info.eyebrow_type = static_cast<u8>(appearance_bits5.eyebrow_style); | ||||||
|  |     out_char_info.eyebrow_color = static_cast<u8>(appearance_bits5.eyebrow_color); | ||||||
|  |     out_char_info.eyebrow_scale = static_cast<u8>(appearance_bits5.eyebrow_scale); | ||||||
|  |     out_char_info.eyebrow_aspect = static_cast<u8>(appearance_bits5.eyebrow_yscale); | ||||||
|  |     out_char_info.eyebrow_rotate = static_cast<u8>(appearance_bits5.eyebrow_rotation); | ||||||
|  |     out_char_info.eyebrow_x = static_cast<u8>(appearance_bits5.eyebrow_spacing); | ||||||
|  |     out_char_info.eyebrow_y = static_cast<u8>(appearance_bits5.eyebrow_y_position); | ||||||
|  |  | ||||||
|  |     out_char_info.nose_type = static_cast<u8>(appearance_bits6.nose_type); | ||||||
|  |     out_char_info.nose_scale = static_cast<u8>(appearance_bits6.nose_scale); | ||||||
|  |     out_char_info.nose_y = static_cast<u8>(appearance_bits6.nose_y_position); | ||||||
|  |  | ||||||
|  |     out_char_info.mouth_type = static_cast<u8>(appearance_bits7.mouth_type); | ||||||
|  |     out_char_info.mouth_color = static_cast<u8>(appearance_bits7.mouth_color); | ||||||
|  |     out_char_info.mouth_scale = static_cast<u8>(appearance_bits7.mouth_scale); | ||||||
|  |     out_char_info.mouth_aspect = static_cast<u8>(appearance_bits7.mouth_horizontal_stretch); | ||||||
|  |     out_char_info.mouth_y = static_cast<u8>(appearance_bits8.mouth_y_position); | ||||||
|  |  | ||||||
|  |     out_char_info.mustache_type = static_cast<u8>(appearance_bits8.mustache_type); | ||||||
|  |     out_char_info.mustache_scale = static_cast<u8>(appearance_bits9.mustache_scale); | ||||||
|  |     out_char_info.mustache_y = static_cast<u8>(appearance_bits9.mustache_y_position); | ||||||
|  |  | ||||||
|  |     out_char_info.beard_type = static_cast<u8>(appearance_bits9.bear_type); | ||||||
|  |     out_char_info.beard_color = static_cast<u8>(appearance_bits9.facial_hair_color); | ||||||
|  |  | ||||||
|  |     out_char_info.glasses_type = static_cast<u8>(appearance_bits10.glasses_type); | ||||||
|  |     out_char_info.glasses_color = static_cast<u8>(appearance_bits10.glasses_color); | ||||||
|  |     out_char_info.glasses_scale = static_cast<u8>(appearance_bits10.glasses_scale); | ||||||
|  |     out_char_info.glasses_y = static_cast<u8>(appearance_bits10.glasses_y_position); | ||||||
|  |  | ||||||
|  |     out_char_info.mole_type = static_cast<u8>(appearance_bits11.mole_enabled); | ||||||
|  |     out_char_info.mole_scale = static_cast<u8>(appearance_bits11.mole_scale); | ||||||
|  |     out_char_info.mole_x = static_cast<u8>(appearance_bits11.mole_x_position); | ||||||
|  |     out_char_info.mole_y = static_cast<u8>(appearance_bits11.mole_y_position); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Ver3StoreData::BuildFromStoreData(const CharInfo& char_info) { | ||||||
|  |     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; | ||||||
|  |  | ||||||
|  |     // 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]; | ||||||
|  |         if (mii_name[index] == 0) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     region_information.character_set.Assign(char_info.font_region); | ||||||
|  |  | ||||||
|  |     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); | ||||||
|  |  | ||||||
|  |     hair_style = char_info.hair_type; | ||||||
|  |     appearance_bits3.flip_hair.Assign(char_info.hair_flip); | ||||||
|  |  | ||||||
|  |     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_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_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_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_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_bits9.bear_type.Assign(char_info.beard_type); | ||||||
|  |  | ||||||
|  |     appearance_bits10.glasses_scale.Assign(char_info.glasses_scale); | ||||||
|  |     appearance_bits10.glasses_y_position.Assign(char_info.glasses_y); | ||||||
|  |  | ||||||
|  |     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); | ||||||
|  |  | ||||||
|  |     // 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)); | ||||||
|  |  | ||||||
|  |     crc = MiiUtil::CalculateCrc16(&version, sizeof(Ver3StoreData) - sizeof(u16)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | u32 Ver3StoreData::IsValid() const { | ||||||
|  |     bool is_valid = version == 0 || version == 3; | ||||||
|  |  | ||||||
|  |     is_valid = is_valid && (mii_name[0] != 0); | ||||||
|  |  | ||||||
|  |     is_valid = is_valid && (mii_information.birth_month < 13); | ||||||
|  |     is_valid = is_valid && (mii_information.birth_day < 32); | ||||||
|  |     is_valid = is_valid && (mii_information.favorite_color < 12); | ||||||
|  |     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 && (hair_style < 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_bits5.eyebrow_style < 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_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_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_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.bear_type < 6); | ||||||
|  |     is_valid = is_valid && (appearance_bits9.facial_hair_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_bits11.mole_enabled < 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); | ||||||
|  |  | ||||||
|  |     return is_valid; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace Service::Mii | ||||||
|   | |||||||
| @@ -4,10 +4,9 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "core/hle/service/mii/mii_types.h" | #include "core/hle/service/mii/mii_types.h" | ||||||
| #include "core/hle/service/mii/types/core_data.h" |  | ||||||
| #include "core/hle/service/mii/types/store_data.h" |  | ||||||
|  |  | ||||||
| namespace Service::Mii { | namespace Service::Mii { | ||||||
|  | class CharInfo; | ||||||
|  |  | ||||||
| // This is nn::mii::Ver3StoreData | // This is nn::mii::Ver3StoreData | ||||||
| // Based on citra HLE::Applets::MiiData and PretendoNetwork. | // Based on citra HLE::Applets::MiiData and PretendoNetwork. | ||||||
| @@ -15,7 +14,15 @@ namespace Service::Mii { | |||||||
| // https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299 | // https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299 | ||||||
|  |  | ||||||
| #pragma pack(push, 4) | #pragma pack(push, 4) | ||||||
| struct Ver3StoreData { | 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); | ||||||
|  |  | ||||||
|  |     u32 IsValid() const; | ||||||
|  |  | ||||||
|     u8 version; |     u8 version; | ||||||
|     union { |     union { | ||||||
|         u8 raw; |         u8 raw; | ||||||
|   | |||||||
| @@ -834,7 +834,7 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     SetAmiiboName(settings, register_info.amiibo_name); |     SetAmiiboName(settings, register_info.amiibo_name); | ||||||
|     tag_data.owner_mii = manager.BuildFromStoreData(mii); |     tag_data.owner_mii.BuildFromStoreData(mii); | ||||||
|     tag_data.mii_extension = manager.SetFromStoreData(mii); |     tag_data.mii_extension = manager.SetFromStoreData(mii); | ||||||
|     tag_data.unknown = 0; |     tag_data.unknown = 0; | ||||||
|     tag_data.unknown2 = {}; |     tag_data.unknown2 = {}; | ||||||
| @@ -1466,7 +1466,7 @@ void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, | |||||||
|     SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'}); |     SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'}); | ||||||
|     settings.settings.font_region.Assign(0); |     settings.settings.font_region.Assign(0); | ||||||
|     settings.init_date = GetAmiiboDate(GetCurrentPosixTime()); |     settings.init_date = GetAmiiboDate(GetCurrentPosixTime()); | ||||||
|     stubbed_tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildBase(Mii::Gender::Male)); |     stubbed_tag_data.owner_mii.BuildFromStoreData(manager.BuildBase(Mii::Gender::Male)); | ||||||
|  |  | ||||||
|     // Admin info |     // Admin info | ||||||
|     settings.settings.amiibo_initialized.Assign(1); |     settings.settings.amiibo_initialized.Assign(1); | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
|  |  | ||||||
| #include "common/swap.h" | #include "common/swap.h" | ||||||
| #include "core/hle/service/mii/types/char_info.h" | #include "core/hle/service/mii/types/char_info.h" | ||||||
|  | #include "core/hle/service/mii/types/store_data.h" | ||||||
| #include "core/hle/service/mii/types/ver3_store_data.h" | #include "core/hle/service/mii/types/ver3_store_data.h" | ||||||
| #include "core/hle/service/nfc/nfc_types.h" | #include "core/hle/service/nfc/nfc_types.h" | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user