diff options
Diffstat (limited to 'src/core/hle/service/mii/types')
-rw-r--r-- | src/core/hle/service/mii/types/char_info.cpp | 482 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/char_info.h | 137 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/core_data.cpp | 601 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/core_data.h | 216 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/raw_data.cpp | 1778 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/raw_data.h | 73 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/store_data.cpp | 643 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/store_data.h | 145 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/ver3_store_data.cpp | 241 | ||||
-rw-r--r-- | src/core/hle/service/mii/types/ver3_store_data.h | 160 |
10 files changed, 4476 insertions, 0 deletions
diff --git a/src/core/hle/service/mii/types/char_info.cpp b/src/core/hle/service/mii/types/char_info.cpp new file mode 100644 index 000000000..bb948c628 --- /dev/null +++ b/src/core/hle/service/mii/types/char_info.cpp @@ -0,0 +1,482 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/mii/types/char_info.h" +#include "core/hle/service/mii/types/store_data.h" + +namespace Service::Mii { + +void CharInfo::SetFromStoreData(const StoreData& store_data) { + name = store_data.GetNickname(); + null_terminator = '\0'; + create_id = store_data.GetCreateId(); + font_region = store_data.GetFontRegion(); + favorite_color = store_data.GetFavoriteColor(); + gender = store_data.GetGender(); + height = store_data.GetHeight(); + build = store_data.GetBuild(); + type = store_data.GetType(); + region_move = store_data.GetRegionMove(); + faceline_type = store_data.GetFacelineType(); + faceline_color = store_data.GetFacelineColor(); + faceline_wrinkle = store_data.GetFacelineWrinkle(); + faceline_make = store_data.GetFacelineMake(); + hair_type = store_data.GetHairType(); + hair_color = store_data.GetHairColor(); + hair_flip = store_data.GetHairFlip(); + eye_type = store_data.GetEyeType(); + eye_color = store_data.GetEyeColor(); + eye_scale = store_data.GetEyeScale(); + eye_aspect = store_data.GetEyeAspect(); + eye_rotate = store_data.GetEyeRotate(); + eye_x = store_data.GetEyeX(); + eye_y = store_data.GetEyeY(); + eyebrow_type = store_data.GetEyebrowType(); + eyebrow_color = store_data.GetEyebrowColor(); + eyebrow_scale = store_data.GetEyebrowScale(); + eyebrow_aspect = store_data.GetEyebrowAspect(); + eyebrow_rotate = store_data.GetEyebrowRotate(); + eyebrow_x = store_data.GetEyebrowX(); + eyebrow_y = store_data.GetEyebrowY(); + nose_type = store_data.GetNoseType(); + nose_scale = store_data.GetNoseScale(); + nose_y = store_data.GetNoseY(); + mouth_type = store_data.GetMouthType(); + mouth_color = store_data.GetMouthColor(); + mouth_scale = store_data.GetMouthScale(); + mouth_aspect = store_data.GetMouthAspect(); + mouth_y = store_data.GetMouthY(); + beard_color = store_data.GetBeardColor(); + beard_type = store_data.GetBeardType(); + mustache_type = store_data.GetMustacheType(); + mustache_scale = store_data.GetMustacheScale(); + mustache_y = store_data.GetMustacheY(); + glass_type = store_data.GetGlassType(); + glass_color = store_data.GetGlassColor(); + glass_scale = store_data.GetGlassScale(); + glass_y = store_data.GetGlassY(); + mole_type = store_data.GetMoleType(); + mole_scale = store_data.GetMoleScale(); + mole_x = store_data.GetMoleX(); + mole_y = store_data.GetMoleY(); + padding = '\0'; +} + +ValidationResult CharInfo::Verify() const { + if (!create_id.IsValid()) { + return ValidationResult::InvalidCreateId; + } + if (!name.IsValid()) { + return ValidationResult::InvalidName; + } + if (font_region > FontRegion::Max) { + return ValidationResult::InvalidFont; + } + if (favorite_color > FavoriteColor::Max) { + return ValidationResult::InvalidColor; + } + if (gender > Gender::Max) { + return ValidationResult::InvalidGender; + } + if (height > MaxHeight) { + return ValidationResult::InvalidHeight; + } + if (build > MaxBuild) { + return ValidationResult::InvalidBuild; + } + if (type > MaxType) { + return ValidationResult::InvalidType; + } + if (region_move > MaxRegionMove) { + return ValidationResult::InvalidRegionMove; + } + if (faceline_type > FacelineType::Max) { + return ValidationResult::InvalidFacelineType; + } + if (faceline_color > FacelineColor::Max) { + return ValidationResult::InvalidFacelineColor; + } + if (faceline_wrinkle > FacelineWrinkle::Max) { + return ValidationResult::InvalidFacelineWrinkle; + } + if (faceline_make > FacelineMake::Max) { + return ValidationResult::InvalidFacelineMake; + } + if (hair_type > HairType::Max) { + return ValidationResult::InvalidHairType; + } + if (hair_color > CommonColor::Max) { + return ValidationResult::InvalidHairColor; + } + if (hair_flip > HairFlip::Max) { + return ValidationResult::InvalidHairFlip; + } + if (eye_type > EyeType::Max) { + return ValidationResult::InvalidEyeType; + } + if (eye_color > CommonColor::Max) { + return ValidationResult::InvalidEyeColor; + } + if (eye_scale > MaxEyeScale) { + return ValidationResult::InvalidEyeScale; + } + if (eye_aspect > MaxEyeAspect) { + return ValidationResult::InvalidEyeAspect; + } + if (eye_rotate > MaxEyeX) { + return ValidationResult::InvalidEyeRotate; + } + if (eye_x > MaxEyeX) { + return ValidationResult::InvalidEyeX; + } + if (eye_y > MaxEyeY) { + return ValidationResult::InvalidEyeY; + } + if (eyebrow_type > EyebrowType::Max) { + return ValidationResult::InvalidEyebrowType; + } + if (eyebrow_color > CommonColor::Max) { + return ValidationResult::InvalidEyebrowColor; + } + if (eyebrow_scale > MaxEyebrowScale) { + return ValidationResult::InvalidEyebrowScale; + } + if (eyebrow_aspect > MaxEyebrowAspect) { + return ValidationResult::InvalidEyebrowAspect; + } + if (eyebrow_rotate > MaxEyebrowRotate) { + return ValidationResult::InvalidEyebrowRotate; + } + if (eyebrow_x > MaxEyebrowX) { + return ValidationResult::InvalidEyebrowX; + } + if (eyebrow_y > MaxEyebrowY) { + return ValidationResult::InvalidEyebrowY; + } + if (nose_type > NoseType::Max) { + return ValidationResult::InvalidNoseType; + } + if (nose_scale > MaxNoseScale) { + return ValidationResult::InvalidNoseScale; + } + if (nose_y > MaxNoseY) { + return ValidationResult::InvalidNoseY; + } + if (mouth_type > MouthType::Max) { + return ValidationResult::InvalidMouthType; + } + if (mouth_color > CommonColor::Max) { + return ValidationResult::InvalidMouthColor; + } + if (mouth_scale > MaxMouthScale) { + return ValidationResult::InvalidMouthScale; + } + if (mouth_aspect > MaxMoutAspect) { + return ValidationResult::InvalidMouthAspect; + } + if (mouth_y > MaxMouthY) { + return ValidationResult::InvalidMoleY; + } + if (beard_color > CommonColor::Max) { + return ValidationResult::InvalidBeardColor; + } + if (beard_type > BeardType::Max) { + return ValidationResult::InvalidBeardType; + } + if (mustache_type > MustacheType::Max) { + return ValidationResult::InvalidMustacheType; + } + if (mustache_scale > MaxMustacheScale) { + return ValidationResult::InvalidMustacheScale; + } + if (mustache_y > MasMustacheY) { + return ValidationResult::InvalidMustacheY; + } + if (glass_type > GlassType::Max) { + return ValidationResult::InvalidGlassType; + } + if (glass_color > CommonColor::Max) { + return ValidationResult::InvalidGlassColor; + } + if (glass_scale > MaxGlassScale) { + return ValidationResult::InvalidGlassScale; + } + if (glass_y > MaxGlassY) { + return ValidationResult::InvalidGlassY; + } + if (mole_type > MoleType::Max) { + return ValidationResult::InvalidMoleType; + } + if (mole_scale > MaxMoleScale) { + return ValidationResult::InvalidMoleScale; + } + if (mole_x > MaxMoleX) { + return ValidationResult::InvalidMoleX; + } + if (mole_y > MaxMoleY) { + return ValidationResult::InvalidMoleY; + } + return ValidationResult::NoErrors; +} + +Common::UUID CharInfo::GetCreateId() const { + return create_id; +} + +Nickname CharInfo::GetNickname() const { + return name; +} + +FontRegion CharInfo::GetFontRegion() const { + return font_region; +} + +FavoriteColor CharInfo::GetFavoriteColor() const { + return favorite_color; +} + +Gender CharInfo::GetGender() const { + return gender; +} + +u8 CharInfo::GetHeight() const { + return height; +} + +u8 CharInfo::GetBuild() const { + return build; +} + +u8 CharInfo::GetType() const { + return type; +} + +u8 CharInfo::GetRegionMove() const { + return region_move; +} + +FacelineType CharInfo::GetFacelineType() const { + return faceline_type; +} + +FacelineColor CharInfo::GetFacelineColor() const { + return faceline_color; +} + +FacelineWrinkle CharInfo::GetFacelineWrinkle() const { + return faceline_wrinkle; +} + +FacelineMake CharInfo::GetFacelineMake() const { + return faceline_make; +} + +HairType CharInfo::GetHairType() const { + return hair_type; +} + +CommonColor CharInfo::GetHairColor() const { + return hair_color; +} + +HairFlip CharInfo::GetHairFlip() const { + return hair_flip; +} + +EyeType CharInfo::GetEyeType() const { + return eye_type; +} + +CommonColor CharInfo::GetEyeColor() const { + return eye_color; +} + +u8 CharInfo::GetEyeScale() const { + return eye_scale; +} + +u8 CharInfo::GetEyeAspect() const { + return eye_aspect; +} + +u8 CharInfo::GetEyeRotate() const { + return eye_rotate; +} + +u8 CharInfo::GetEyeX() const { + return eye_x; +} + +u8 CharInfo::GetEyeY() const { + return eye_y; +} + +EyebrowType CharInfo::GetEyebrowType() const { + return eyebrow_type; +} + +CommonColor CharInfo::GetEyebrowColor() const { + return eyebrow_color; +} + +u8 CharInfo::GetEyebrowScale() const { + return eyebrow_scale; +} + +u8 CharInfo::GetEyebrowAspect() const { + return eyebrow_aspect; +} + +u8 CharInfo::GetEyebrowRotate() const { + return eyebrow_rotate; +} + +u8 CharInfo::GetEyebrowX() const { + return eyebrow_x; +} + +u8 CharInfo::GetEyebrowY() const { + return eyebrow_y; +} + +NoseType CharInfo::GetNoseType() const { + return nose_type; +} + +u8 CharInfo::GetNoseScale() const { + return nose_scale; +} + +u8 CharInfo::GetNoseY() const { + return nose_y; +} + +MouthType CharInfo::GetMouthType() const { + return mouth_type; +} + +CommonColor CharInfo::GetMouthColor() const { + return mouth_color; +} + +u8 CharInfo::GetMouthScale() const { + return mouth_scale; +} + +u8 CharInfo::GetMouthAspect() const { + return mouth_aspect; +} + +u8 CharInfo::GetMouthY() const { + return mouth_y; +} + +CommonColor CharInfo::GetBeardColor() const { + return beard_color; +} + +BeardType CharInfo::GetBeardType() const { + return beard_type; +} + +MustacheType CharInfo::GetMustacheType() const { + return mustache_type; +} + +u8 CharInfo::GetMustacheScale() const { + return mustache_scale; +} + +u8 CharInfo::GetMustacheY() const { + return mustache_y; +} + +GlassType CharInfo::GetGlassType() const { + return glass_type; +} + +CommonColor CharInfo::GetGlassColor() const { + return glass_color; +} + +u8 CharInfo::GetGlassScale() const { + return glass_scale; +} + +u8 CharInfo::GetGlassY() const { + return glass_y; +} + +MoleType CharInfo::GetMoleType() const { + return mole_type; +} + +u8 CharInfo::GetMoleScale() const { + return mole_scale; +} + +u8 CharInfo::GetMoleX() const { + return mole_x; +} + +u8 CharInfo::GetMoleY() const { + return mole_y; +} + +bool CharInfo::operator==(const CharInfo& info) { + bool is_identical = info.Verify() == ValidationResult::NoErrors; + 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(); + is_identical &= gender == info.GetGender(); + is_identical &= height == info.GetHeight(); + is_identical &= build == info.GetBuild(); + is_identical &= type == info.GetType(); + is_identical &= region_move == info.GetRegionMove(); + is_identical &= faceline_type == info.GetFacelineType(); + is_identical &= faceline_color == info.GetFacelineColor(); + is_identical &= faceline_wrinkle == info.GetFacelineWrinkle(); + is_identical &= faceline_make == info.GetFacelineMake(); + is_identical &= hair_type == info.GetHairType(); + is_identical &= hair_color == info.GetHairColor(); + is_identical &= hair_flip == info.GetHairFlip(); + is_identical &= eye_type == info.GetEyeType(); + is_identical &= eye_color == info.GetEyeColor(); + is_identical &= eye_scale == info.GetEyeScale(); + is_identical &= eye_aspect == info.GetEyeAspect(); + is_identical &= eye_rotate == info.GetEyeRotate(); + is_identical &= eye_x == info.GetEyeX(); + is_identical &= eye_y == info.GetEyeY(); + is_identical &= eyebrow_type == info.GetEyebrowType(); + is_identical &= eyebrow_color == info.GetEyebrowColor(); + is_identical &= eyebrow_scale == info.GetEyebrowScale(); + is_identical &= eyebrow_aspect == info.GetEyebrowAspect(); + is_identical &= eyebrow_rotate == info.GetEyebrowRotate(); + is_identical &= eyebrow_x == info.GetEyebrowX(); + is_identical &= eyebrow_y == info.GetEyebrowY(); + is_identical &= nose_type == info.GetNoseType(); + is_identical &= nose_scale == info.GetNoseScale(); + is_identical &= nose_y == info.GetNoseY(); + is_identical &= mouth_type == info.GetMouthType(); + is_identical &= mouth_color == info.GetMouthColor(); + is_identical &= mouth_scale == info.GetMouthScale(); + is_identical &= mouth_aspect == info.GetMouthAspect(); + is_identical &= mouth_y == info.GetMouthY(); + is_identical &= beard_color == info.GetBeardColor(); + is_identical &= beard_type == info.GetBeardType(); + is_identical &= mustache_type == info.GetMustacheType(); + is_identical &= mustache_scale == info.GetMustacheScale(); + is_identical &= mustache_y == info.GetMustacheY(); + is_identical &= glass_type == info.GetGlassType(); + is_identical &= glass_color == info.GetGlassColor(); + is_identical &= glass_scale == info.GetGlassScale(); + is_identical &= glass_y == info.GetGlassY(); + is_identical &= mole_type == info.GetMoleType(); + is_identical &= mole_scale == info.GetMoleScale(); + is_identical &= mole_x == info.GetMoleX(); + is_identical &= mole_y == info.GetMoleY(); + return is_identical; +} + +} // namespace Service::Mii diff --git a/src/core/hle/service/mii/types/char_info.h b/src/core/hle/service/mii/types/char_info.h new file mode 100644 index 000000000..d069b221f --- /dev/null +++ b/src/core/hle/service/mii/types/char_info.h @@ -0,0 +1,137 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/mii/mii_types.h" + +namespace Service::Mii { +class StoreData; + +// This is nn::mii::detail::CharInfoRaw +class CharInfo { +public: + void SetFromStoreData(const StoreData& store_data_raw); + + ValidationResult Verify() const; + + Common::UUID GetCreateId() const; + Nickname GetNickname() const; + FontRegion GetFontRegion() const; + FavoriteColor GetFavoriteColor() const; + Gender GetGender() const; + u8 GetHeight() const; + u8 GetBuild() const; + u8 GetType() const; + u8 GetRegionMove() const; + FacelineType GetFacelineType() const; + FacelineColor GetFacelineColor() const; + FacelineWrinkle GetFacelineWrinkle() const; + FacelineMake GetFacelineMake() const; + HairType GetHairType() const; + CommonColor GetHairColor() const; + HairFlip GetHairFlip() const; + EyeType GetEyeType() const; + CommonColor GetEyeColor() const; + u8 GetEyeScale() const; + u8 GetEyeAspect() const; + u8 GetEyeRotate() const; + u8 GetEyeX() const; + u8 GetEyeY() const; + EyebrowType GetEyebrowType() const; + CommonColor GetEyebrowColor() const; + u8 GetEyebrowScale() const; + u8 GetEyebrowAspect() const; + u8 GetEyebrowRotate() const; + u8 GetEyebrowX() const; + u8 GetEyebrowY() const; + NoseType GetNoseType() const; + u8 GetNoseScale() const; + u8 GetNoseY() const; + MouthType GetMouthType() const; + CommonColor GetMouthColor() const; + u8 GetMouthScale() const; + u8 GetMouthAspect() const; + u8 GetMouthY() const; + CommonColor GetBeardColor() const; + BeardType GetBeardType() const; + MustacheType GetMustacheType() const; + u8 GetMustacheScale() const; + u8 GetMustacheY() const; + GlassType GetGlassType() const; + CommonColor GetGlassColor() const; + u8 GetGlassScale() const; + u8 GetGlassY() const; + MoleType GetMoleType() const; + u8 GetMoleScale() const; + u8 GetMoleX() const; + u8 GetMoleY() const; + + bool operator==(const CharInfo& info); + +private: + Common::UUID create_id; + Nickname name; + u16 null_terminator; + FontRegion font_region; + FavoriteColor favorite_color; + Gender gender; + u8 height; + u8 build; + u8 type; + u8 region_move; + FacelineType faceline_type; + FacelineColor faceline_color; + FacelineWrinkle faceline_wrinkle; + FacelineMake faceline_make; + HairType hair_type; + CommonColor hair_color; + HairFlip hair_flip; + EyeType eye_type; + CommonColor eye_color; + u8 eye_scale; + u8 eye_aspect; + u8 eye_rotate; + u8 eye_x; + u8 eye_y; + EyebrowType eyebrow_type; + CommonColor eyebrow_color; + u8 eyebrow_scale; + u8 eyebrow_aspect; + u8 eyebrow_rotate; + u8 eyebrow_x; + u8 eyebrow_y; + NoseType nose_type; + u8 nose_scale; + u8 nose_y; + MouthType mouth_type; + CommonColor mouth_color; + u8 mouth_scale; + u8 mouth_aspect; + u8 mouth_y; + CommonColor beard_color; + BeardType beard_type; + MustacheType mustache_type; + u8 mustache_scale; + u8 mustache_y; + GlassType glass_type; + CommonColor glass_color; + u8 glass_scale; + u8 glass_y; + MoleType mole_type; + u8 mole_scale; + u8 mole_x; + u8 mole_y; + u8 padding; +}; +static_assert(sizeof(CharInfo) == 0x58, "CharInfo has incorrect size."); +static_assert(std::has_unique_object_representations_v<CharInfo>, + "All bits of CharInfo must contribute to its value."); + +struct CharInfoElement { + CharInfo char_info{}; + Source source{}; +}; +static_assert(sizeof(CharInfoElement) == 0x5c, "CharInfoElement has incorrect size."); + +}; // namespace Service::Mii diff --git a/src/core/hle/service/mii/types/core_data.cpp b/src/core/hle/service/mii/types/core_data.cpp new file mode 100644 index 000000000..659288b51 --- /dev/null +++ b/src/core/hle/service/mii/types/core_data.cpp @@ -0,0 +1,601 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "core/hle/service/mii/mii_util.h" +#include "core/hle/service/mii/types/core_data.h" +#include "core/hle/service/mii/types/raw_data.h" + +namespace Service::Mii { + +void CoreData::SetDefault() { + data = {}; + name = GetDefaultNickname(); +} + +void CoreData::BuildRandom(Age age, Gender gender, Race race) { + if (gender == Gender::All) { + gender = MiiUtil::GetRandomValue(Gender::Max); + } + + if (age == Age::All) { + const auto random{MiiUtil::GetRandomValue<int>(10)}; + if (random >= 8) { + age = Age::Old; + } else if (random >= 4) { + age = Age::Normal; + } else { + age = Age::Young; + } + } + + if (race == Race::All) { + const auto random{MiiUtil::GetRandomValue<int>(10)}; + if (random >= 8) { + race = Race::Black; + } else if (random >= 4) { + race = Race::White; + } else { + race = Race::Asian; + } + } + + SetGender(gender); + SetFavoriteColor(MiiUtil::GetRandomValue(FavoriteColor::Max)); + SetRegionMove(0); + SetFontRegion(FontRegion::Standard); + SetType(0); + SetHeight(64); + SetBuild(64); + + u32 axis_y{}; + if (gender == Gender::Female && age == Age::Young) { + axis_y = MiiUtil::GetRandomValue<u32>(3); + } + + const std::size_t index{3 * static_cast<std::size_t>(age) + + 9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)}; + + const auto& faceline_type_info{RawData::RandomMiiFaceline.at(index)}; + const auto& faceline_color_info{RawData::RandomMiiFacelineColor.at( + 3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))}; + const auto& faceline_wrinkle_info{RawData::RandomMiiFacelineWrinkle.at(index)}; + const auto& faceline_makeup_info{RawData::RandomMiiFacelineMakeup.at(index)}; + const auto& hair_type_info{RawData::RandomMiiHairType.at(index)}; + const auto& hair_color_info{RawData::RandomMiiHairColor.at(3 * static_cast<std::size_t>(race) + + static_cast<std::size_t>(age))}; + const auto& eye_type_info{RawData::RandomMiiEyeType.at(index)}; + const auto& eye_color_info{RawData::RandomMiiEyeColor.at(static_cast<std::size_t>(race))}; + const auto& eyebrow_type_info{RawData::RandomMiiEyebrowType.at(index)}; + const auto& nose_type_info{RawData::RandomMiiNoseType.at(index)}; + const auto& mouth_type_info{RawData::RandomMiiMouthType.at(index)}; + const auto& glasses_type_info{RawData::RandomMiiGlassType.at(static_cast<std::size_t>(age))}; + + data.faceline_type.Assign( + faceline_type_info + .values[MiiUtil::GetRandomValue<std::size_t>(faceline_type_info.values_count)]); + data.faceline_color.Assign( + faceline_color_info + .values[MiiUtil::GetRandomValue<std::size_t>(faceline_color_info.values_count)]); + data.faceline_wrinkle.Assign( + faceline_wrinkle_info + .values[MiiUtil::GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]); + data.faceline_makeup.Assign( + faceline_makeup_info + .values[MiiUtil::GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]); + + data.hair_type.Assign( + hair_type_info.values[MiiUtil::GetRandomValue<std::size_t>(hair_type_info.values_count)]); + SetHairColor(RawData::GetHairColorFromVer3( + hair_color_info + .values[MiiUtil::GetRandomValue<std::size_t>(hair_color_info.values_count)])); + SetHairFlip(MiiUtil::GetRandomValue(HairFlip::Max)); + + data.eye_type.Assign( + eye_type_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_type_info.values_count)]); + + const auto eye_rotate_1{gender != Gender::Male ? 4 : 2}; + const auto eye_rotate_2{gender != Gender::Male ? 3 : 4}; + const auto eye_rotate_offset{32 - RawData::EyeRotateLookup[eye_rotate_1] + eye_rotate_2}; + const auto eye_rotate{32 - RawData::EyeRotateLookup[data.eye_type]}; + + SetEyeColor(RawData::GetEyeColorFromVer3( + eye_color_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_color_info.values_count)])); + SetEyeScale(4); + SetEyeAspect(3); + SetEyeRotate(static_cast<u8>(eye_rotate_offset - eye_rotate)); + SetEyeX(2); + SetEyeY(static_cast<u8>(axis_y + 12)); + + data.eyebrow_type.Assign( + eyebrow_type_info + .values[MiiUtil::GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]); + + const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0}; + const auto eyebrow_y{race == Race::Asian ? 9 : 10}; + const auto eyebrow_rotate_offset{32 - RawData::EyebrowRotateLookup[eyebrow_rotate_1] + 6}; + const auto eyebrow_rotate{ + 32 - RawData::EyebrowRotateLookup[static_cast<std::size_t>(data.eyebrow_type.Value())]}; + + SetEyebrowColor(GetHairColor()); + SetEyebrowScale(4); + SetEyebrowAspect(3); + SetEyebrowRotate(static_cast<u8>(eyebrow_rotate_offset - eyebrow_rotate)); + SetEyebrowX(2); + SetEyebrowY(static_cast<u8>(axis_y + eyebrow_y)); + + data.nose_type.Assign( + nose_type_info.values[MiiUtil::GetRandomValue<std::size_t>(nose_type_info.values_count)]); + SetNoseScale(gender == Gender::Female ? 3 : 4); + SetNoseY(static_cast<u8>(axis_y + 9)); + + const auto mouth_color{gender == Gender::Female ? MiiUtil::GetRandomValue<int>(4) : 0}; + + data.mouth_type.Assign( + mouth_type_info.values[MiiUtil::GetRandomValue<std::size_t>(mouth_type_info.values_count)]); + SetMouthColor(RawData::GetMouthColorFromVer3(mouth_color)); + SetMouthScale(4); + SetMouthAspect(3); + SetMouthY(static_cast<u8>(axis_y + 13)); + + SetBeardColor(GetHairColor()); + SetMustacheScale(4); + + if (gender == Gender::Male && age != Age::Young && MiiUtil::GetRandomValue<int>(10) < 2) { + const auto mustache_and_beard_flag{MiiUtil::GetRandomValue(BeardAndMustacheFlag::All)}; + + auto beard_type{BeardType::None}; + auto mustache_type{MustacheType::None}; + + if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) == + BeardAndMustacheFlag::Beard) { + beard_type = MiiUtil::GetRandomValue(BeardType::Min, BeardType::Max); + } + + if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) == + BeardAndMustacheFlag::Mustache) { + mustache_type = MiiUtil::GetRandomValue(MustacheType::Min, MustacheType::Max); + } + + SetMustacheType(mustache_type); + SetBeardType(beard_type); + SetMustacheY(10); + } else { + SetMustacheType(MustacheType::None); + SetBeardType(BeardType::None); + SetMustacheY(static_cast<u8>(axis_y + 10)); + } + + const auto glasses_type_start{MiiUtil::GetRandomValue<std::size_t>(100)}; + u8 glasses_type{}; + while (glasses_type_start < glasses_type_info.values[glasses_type]) { + if (++glasses_type >= glasses_type_info.values_count) { + ASSERT(false); + break; + } + } + + SetGlassType(static_cast<GlassType>(glasses_type)); + SetGlassColor(RawData::GetGlassColorFromVer3(0)); + SetGlassScale(4); + + SetMoleType(MoleType::None); + SetMoleScale(4); + SetMoleX(2); + SetMoleY(20); +} + +u32 CoreData::IsValid() const { + // TODO: Complete this + return 0; +} + +void CoreData::SetFontRegion(FontRegion value) { + data.font_region.Assign(static_cast<u32>(value)); +} + +void CoreData::SetFavoriteColor(FavoriteColor value) { + data.favorite_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetGender(Gender value) { + data.gender.Assign(static_cast<u32>(value)); +} + +void CoreData::SetHeight(u8 value) { + data.height.Assign(value); +} + +void CoreData::SetBuild(u8 value) { + data.build.Assign(value); +} + +void CoreData::SetType(u8 value) { + data.type.Assign(value); +} + +void CoreData::SetRegionMove(u8 value) { + data.region_move.Assign(value); +} + +void CoreData::SetFacelineType(FacelineType value) { + data.faceline_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetFacelineColor(FacelineColor value) { + data.faceline_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetFacelineWrinkle(FacelineWrinkle value) { + data.faceline_wrinkle.Assign(static_cast<u32>(value)); +} + +void CoreData::SetFacelineMake(FacelineMake value) { + data.faceline_makeup.Assign(static_cast<u32>(value)); +} + +void CoreData::SetHairType(HairType value) { + data.hair_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetHairColor(CommonColor value) { + data.hair_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetHairFlip(HairFlip value) { + data.hair_flip.Assign(static_cast<u32>(value)); +} + +void CoreData::SetEyeType(EyeType value) { + data.eye_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetEyeColor(CommonColor value) { + data.eye_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetEyeScale(u8 value) { + data.eye_scale.Assign(value); +} + +void CoreData::SetEyeAspect(u8 value) { + data.eye_aspect.Assign(value); +} + +void CoreData::SetEyeRotate(u8 value) { + data.eye_rotate.Assign(value); +} + +void CoreData::SetEyeX(u8 value) { + data.eye_x.Assign(value); +} + +void CoreData::SetEyeY(u8 value) { + data.eye_y.Assign(value); +} + +void CoreData::SetEyebrowType(EyebrowType value) { + data.eyebrow_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetEyebrowColor(CommonColor value) { + data.eyebrow_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetEyebrowScale(u8 value) { + data.eyebrow_scale.Assign(value); +} + +void CoreData::SetEyebrowAspect(u8 value) { + data.eyebrow_aspect.Assign(value); +} + +void CoreData::SetEyebrowRotate(u8 value) { + data.eyebrow_rotate.Assign(value); +} + +void CoreData::SetEyebrowX(u8 value) { + data.eyebrow_x.Assign(value); +} + +void CoreData::SetEyebrowY(u8 value) { + data.eyebrow_y.Assign(value); +} + +void CoreData::SetNoseType(NoseType value) { + data.nose_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetNoseScale(u8 value) { + data.nose_scale.Assign(value); +} + +void CoreData::SetNoseY(u8 value) { + data.nose_y.Assign(value); +} + +void CoreData::SetMouthType(u8 value) { + data.mouth_type.Assign(value); +} + +void CoreData::SetMouthColor(CommonColor value) { + data.mouth_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetMouthScale(u8 value) { + data.mouth_scale.Assign(value); +} + +void CoreData::SetMouthAspect(u8 value) { + data.mouth_aspect.Assign(value); +} + +void CoreData::SetMouthY(u8 value) { + data.mouth_y.Assign(value); +} + +void CoreData::SetBeardColor(CommonColor value) { + data.beard_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetBeardType(BeardType value) { + data.beard_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetMustacheType(MustacheType value) { + data.mustache_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetMustacheScale(u8 value) { + data.mustache_scale.Assign(value); +} + +void CoreData::SetMustacheY(u8 value) { + data.mustache_y.Assign(value); +} + +void CoreData::SetGlassType(GlassType value) { + data.glasses_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetGlassColor(CommonColor value) { + data.glasses_color.Assign(static_cast<u32>(value)); +} + +void CoreData::SetGlassScale(u8 value) { + data.glasses_scale.Assign(value); +} + +void CoreData::SetGlassY(u8 value) { + data.glasses_y.Assign(value); +} + +void CoreData::SetMoleType(MoleType value) { + data.mole_type.Assign(static_cast<u32>(value)); +} + +void CoreData::SetMoleScale(u8 value) { + data.mole_scale.Assign(value); +} + +void CoreData::SetMoleX(u8 value) { + data.mole_x.Assign(value); +} + +void CoreData::SetMoleY(u8 value) { + data.mole_y.Assign(value); +} + +void CoreData::SetNickname(Nickname nickname) { + name = nickname; +} + +FontRegion CoreData::GetFontRegion() const { + return static_cast<FontRegion>(data.font_region.Value()); +} + +FavoriteColor CoreData::GetFavoriteColor() const { + return static_cast<FavoriteColor>(data.favorite_color.Value()); +} + +Gender CoreData::GetGender() const { + return static_cast<Gender>(data.gender.Value()); +} + +u8 CoreData::GetHeight() const { + return static_cast<u8>(data.height.Value()); +} + +u8 CoreData::GetBuild() const { + return static_cast<u8>(data.build.Value()); +} + +u8 CoreData::GetType() const { + return static_cast<u8>(data.type.Value()); +} + +u8 CoreData::GetRegionMove() const { + return static_cast<u8>(data.region_move.Value()); +} + +FacelineType CoreData::GetFacelineType() const { + return static_cast<FacelineType>(data.faceline_type.Value()); +} + +FacelineColor CoreData::GetFacelineColor() const { + return static_cast<FacelineColor>(data.faceline_color.Value()); +} + +FacelineWrinkle CoreData::GetFacelineWrinkle() const { + return static_cast<FacelineWrinkle>(data.faceline_wrinkle.Value()); +} + +FacelineMake CoreData::GetFacelineMake() const { + return static_cast<FacelineMake>(data.faceline_makeup.Value()); +} + +HairType CoreData::GetHairType() const { + return static_cast<HairType>(data.hair_type.Value()); +} + +CommonColor CoreData::GetHairColor() const { + return static_cast<CommonColor>(data.hair_color.Value()); +} + +HairFlip CoreData::GetHairFlip() const { + return static_cast<HairFlip>(data.hair_flip.Value()); +} + +EyeType CoreData::GetEyeType() const { + return static_cast<EyeType>(data.eye_type.Value()); +} + +CommonColor CoreData::GetEyeColor() const { + return static_cast<CommonColor>(data.eye_color.Value()); +} + +u8 CoreData::GetEyeScale() const { + return static_cast<u8>(data.eye_scale.Value()); +} + +u8 CoreData::GetEyeAspect() const { + return static_cast<u8>(data.eye_aspect.Value()); +} + +u8 CoreData::GetEyeRotate() const { + return static_cast<u8>(data.eye_rotate.Value()); +} + +u8 CoreData::GetEyeX() const { + return static_cast<u8>(data.eye_x.Value()); +} + +u8 CoreData::GetEyeY() const { + return static_cast<u8>(data.eye_y.Value()); +} + +EyebrowType CoreData::GetEyebrowType() const { + return static_cast<EyebrowType>(data.eyebrow_type.Value()); +} + +CommonColor CoreData::GetEyebrowColor() const { + return static_cast<CommonColor>(data.eyebrow_color.Value()); +} + +u8 CoreData::GetEyebrowScale() const { + return static_cast<u8>(data.eyebrow_scale.Value()); +} + +u8 CoreData::GetEyebrowAspect() const { + return static_cast<u8>(data.eyebrow_aspect.Value()); +} + +u8 CoreData::GetEyebrowRotate() const { + return static_cast<u8>(data.eyebrow_rotate.Value()); +} + +u8 CoreData::GetEyebrowX() const { + return static_cast<u8>(data.eyebrow_x.Value()); +} + +u8 CoreData::GetEyebrowY() const { + return static_cast<u8>(data.eyebrow_y.Value()); +} + +NoseType CoreData::GetNoseType() const { + return static_cast<NoseType>(data.nose_type.Value()); +} + +u8 CoreData::GetNoseScale() const { + return static_cast<u8>(data.nose_scale.Value()); +} + +u8 CoreData::GetNoseY() const { + return static_cast<u8>(data.nose_y.Value()); +} + +MouthType CoreData::GetMouthType() const { + return static_cast<MouthType>(data.mouth_type.Value()); +} + +CommonColor CoreData::GetMouthColor() const { + return static_cast<CommonColor>(data.mouth_color.Value()); +} + +u8 CoreData::GetMouthScale() const { + return static_cast<u8>(data.mouth_scale.Value()); +} + +u8 CoreData::GetMouthAspect() const { + return static_cast<u8>(data.mouth_aspect.Value()); +} + +u8 CoreData::GetMouthY() const { + return static_cast<u8>(data.mouth_y.Value()); +} + +CommonColor CoreData::GetBeardColor() const { + return static_cast<CommonColor>(data.beard_color.Value()); +} + +BeardType CoreData::GetBeardType() const { + return static_cast<BeardType>(data.beard_type.Value()); +} + +MustacheType CoreData::GetMustacheType() const { + return static_cast<MustacheType>(data.mustache_type.Value()); +} + +u8 CoreData::GetMustacheScale() const { + return static_cast<u8>(data.mustache_scale.Value()); +} + +u8 CoreData::GetMustacheY() const { + return static_cast<u8>(data.mustache_y.Value()); +} + +GlassType CoreData::GetGlassType() const { + return static_cast<GlassType>(data.glasses_type.Value()); +} + +CommonColor CoreData::GetGlassColor() const { + return static_cast<CommonColor>(data.glasses_color.Value()); +} + +u8 CoreData::GetGlassScale() const { + return static_cast<u8>(data.glasses_scale.Value()); +} + +u8 CoreData::GetGlassY() const { + return static_cast<u8>(data.glasses_y.Value()); +} + +MoleType CoreData::GetMoleType() const { + return static_cast<MoleType>(data.mole_type.Value()); +} + +u8 CoreData::GetMoleScale() const { + return static_cast<u8>(data.mole_scale.Value()); +} + +u8 CoreData::GetMoleX() const { + return static_cast<u8>(data.mole_x.Value()); +} + +u8 CoreData::GetMoleY() const { + return static_cast<u8>(data.mole_y.Value()); +} + +Nickname CoreData::GetNickname() const { + return name; +} + +Nickname CoreData::GetDefaultNickname() const { + return {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}; +} + +Nickname CoreData::GetInvalidNickname() const { + return {u'?', u'?', u'?'}; +} + +} // namespace Service::Mii diff --git a/src/core/hle/service/mii/types/core_data.h b/src/core/hle/service/mii/types/core_data.h new file mode 100644 index 000000000..cebcd2ee4 --- /dev/null +++ b/src/core/hle/service/mii/types/core_data.h @@ -0,0 +1,216 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/mii/mii_types.h" + +namespace Service::Mii { + +struct StoreDataBitFields { + union { + u32 word_0{}; + + BitField<0, 8, u32> hair_type; + BitField<8, 7, u32> height; + BitField<15, 1, u32> mole_type; + BitField<16, 7, u32> build; + BitField<23, 1, u32> hair_flip; + BitField<24, 7, u32> hair_color; + BitField<31, 1, u32> type; + }; + + union { + u32 word_1{}; + + BitField<0, 7, u32> eye_color; + BitField<7, 1, u32> gender; + BitField<8, 7, u32> eyebrow_color; + BitField<16, 7, u32> mouth_color; + BitField<24, 7, u32> beard_color; + }; + + union { + u32 word_2{}; + + BitField<0, 7, u32> glasses_color; + BitField<8, 6, u32> eye_type; + BitField<14, 2, u32> region_move; + BitField<16, 6, u32> mouth_type; + BitField<22, 2, u32> font_region; + BitField<24, 5, u32> eye_y; + BitField<29, 3, u32> glasses_scale; + }; + + union { + u32 word_3{}; + + BitField<0, 5, u32> eyebrow_type; + BitField<5, 3, u32> mustache_type; + BitField<8, 5, u32> nose_type; + BitField<13, 3, u32> beard_type; + BitField<16, 5, u32> nose_y; + BitField<21, 3, u32> mouth_aspect; + BitField<24, 5, u32> mouth_y; + BitField<29, 3, u32> eyebrow_aspect; + }; + + union { + u32 word_4{}; + + BitField<0, 5, u32> mustache_y; + BitField<5, 3, u32> eye_rotate; + BitField<8, 5, u32> glasses_y; + BitField<13, 3, u32> eye_aspect; + BitField<16, 5, u32> mole_x; + BitField<21, 3, u32> eye_scale; + BitField<24, 5, u32> mole_y; + }; + + union { + u32 word_5{}; + + BitField<0, 5, u32> glasses_type; + BitField<8, 4, u32> favorite_color; + BitField<12, 4, u32> faceline_type; + BitField<16, 4, u32> faceline_color; + BitField<20, 4, u32> faceline_wrinkle; + BitField<24, 4, u32> faceline_makeup; + BitField<28, 4, u32> eye_x; + }; + + union { + u32 word_6{}; + + BitField<0, 4, u32> eyebrow_scale; + BitField<4, 4, u32> eyebrow_rotate; + BitField<8, 4, u32> eyebrow_x; + BitField<12, 4, u32> eyebrow_y; + BitField<16, 4, u32> nose_scale; + BitField<20, 4, u32> mouth_scale; + BitField<24, 4, u32> mustache_scale; + BitField<28, 4, u32> mole_scale; + }; +}; +static_assert(sizeof(StoreDataBitFields) == 0x1c, "StoreDataBitFields has incorrect size."); +static_assert(std::is_trivially_copyable_v<StoreDataBitFields>, + "StoreDataBitFields is not trivially copyable."); + +class CoreData { +public: + void SetDefault(); + void BuildRandom(Age age, Gender gender, Race race); + + u32 IsValid() const; + + void SetFontRegion(FontRegion value); + void SetFavoriteColor(FavoriteColor value); + void SetGender(Gender value); + void SetHeight(u8 value); + void SetBuild(u8 value); + void SetType(u8 value); + void SetRegionMove(u8 value); + void SetFacelineType(FacelineType value); + void SetFacelineColor(FacelineColor value); + void SetFacelineWrinkle(FacelineWrinkle value); + void SetFacelineMake(FacelineMake value); + void SetHairType(HairType value); + void SetHairColor(CommonColor value); + void SetHairFlip(HairFlip value); + void SetEyeType(EyeType value); + void SetEyeColor(CommonColor value); + void SetEyeScale(u8 value); + void SetEyeAspect(u8 value); + void SetEyeRotate(u8 value); + void SetEyeX(u8 value); + void SetEyeY(u8 value); + void SetEyebrowType(EyebrowType value); + void SetEyebrowColor(CommonColor value); + void SetEyebrowScale(u8 value); + void SetEyebrowAspect(u8 value); + void SetEyebrowRotate(u8 value); + void SetEyebrowX(u8 value); + void SetEyebrowY(u8 value); + void SetNoseType(NoseType value); + void SetNoseScale(u8 value); + void SetNoseY(u8 value); + void SetMouthType(u8 value); + void SetMouthColor(CommonColor value); + void SetMouthScale(u8 value); + void SetMouthAspect(u8 value); + void SetMouthY(u8 value); + void SetBeardColor(CommonColor value); + void SetBeardType(BeardType value); + void SetMustacheType(MustacheType value); + void SetMustacheScale(u8 value); + void SetMustacheY(u8 value); + void SetGlassType(GlassType value); + void SetGlassColor(CommonColor value); + void SetGlassScale(u8 value); + void SetGlassY(u8 value); + void SetMoleType(MoleType value); + void SetMoleScale(u8 value); + void SetMoleX(u8 value); + void SetMoleY(u8 value); + void SetNickname(Nickname nickname); + + FontRegion GetFontRegion() const; + FavoriteColor GetFavoriteColor() const; + Gender GetGender() const; + u8 GetHeight() const; + u8 GetBuild() const; + u8 GetType() const; + u8 GetRegionMove() const; + FacelineType GetFacelineType() const; + FacelineColor GetFacelineColor() const; + FacelineWrinkle GetFacelineWrinkle() const; + FacelineMake GetFacelineMake() const; + HairType GetHairType() const; + CommonColor GetHairColor() const; + HairFlip GetHairFlip() const; + EyeType GetEyeType() const; + CommonColor GetEyeColor() const; + u8 GetEyeScale() const; + u8 GetEyeAspect() const; + u8 GetEyeRotate() const; + u8 GetEyeX() const; + u8 GetEyeY() const; + EyebrowType GetEyebrowType() const; + CommonColor GetEyebrowColor() const; + u8 GetEyebrowScale() const; + u8 GetEyebrowAspect() const; + u8 GetEyebrowRotate() const; + u8 GetEyebrowX() const; + u8 GetEyebrowY() const; + NoseType GetNoseType() const; + u8 GetNoseScale() const; + u8 GetNoseY() const; + MouthType GetMouthType() const; + CommonColor GetMouthColor() const; + u8 GetMouthScale() const; + u8 GetMouthAspect() const; + u8 GetMouthY() const; + CommonColor GetBeardColor() const; + BeardType GetBeardType() const; + MustacheType GetMustacheType() const; + u8 GetMustacheScale() const; + u8 GetMustacheY() const; + GlassType GetGlassType() const; + CommonColor GetGlassColor() const; + u8 GetGlassScale() const; + u8 GetGlassY() const; + MoleType GetMoleType() const; + u8 GetMoleScale() const; + u8 GetMoleX() const; + u8 GetMoleY() const; + Nickname GetNickname() const; + Nickname GetDefaultNickname() const; + Nickname GetInvalidNickname() const; + +private: + StoreDataBitFields data{}; + Nickname name{}; +}; +static_assert(sizeof(CoreData) == 0x30, "CoreData has incorrect size."); + +}; // namespace Service::Mii diff --git a/src/core/hle/service/mii/types/raw_data.cpp b/src/core/hle/service/mii/types/raw_data.cpp new file mode 100644 index 000000000..5143abcc8 --- /dev/null +++ b/src/core/hle/service/mii/types/raw_data.cpp @@ -0,0 +1,1778 @@ +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: MIT + +#include "core/hle/service/mii/types/raw_data.h" + +namespace Service::Mii::RawData { + +constexpr std::array<u8, static_cast<u8>(FacelineColor::Count)> FromVer3FacelineColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5, +}; + +constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3HairColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0, + 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4, +}; + +constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3EyeColorTable{ + 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4, + 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, + 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, +}; + +constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3MouthlineColorTable{ + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4, + 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4, + 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, + 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, + 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, + 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3, +}; + +constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3GlassColorTable{ + 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3, + 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4, + 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, +}; + +constexpr std::array<u8, static_cast<u8>(GlassType::Count)> FromVer3GlassTypeTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, + 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7, +}; + +constexpr std::array<u8, 8> Ver3FacelineColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, +}; + +constexpr std::array<u8, 8> Ver3HairColorTable{ + 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, +}; + +constexpr std::array<u8, 6> Ver3EyeColorTable{ + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, +}; + +constexpr std::array<u8, 5> Ver3MouthColorTable{ + 0x13, 0x14, 0x15, 0x16, 0x17, +}; + +constexpr std::array<u8, 7> Ver3GlassColorTable{ + 0x8, 0xe, 0xf, 0x10, 0x11, 0x12, 0x0, +}; + +const std::array<u8, 62> EyeRotateLookup{ + 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04, + 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04, +}; + +const std::array<u8, 24> EyebrowRotateLookup{ + 0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07, 0x04, 0x07, 0x06, 0x08, + 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05, +}; + +const std::array<Service::Mii::DefaultMii, 2> BaseMii{ + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 0, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 33, + .hair_color = 1, + .hair_flip = 0, + .eye_type = 2, + .eye_color = 0, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 4, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 6, + .eyebrow_color = 1, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 0, + .favorite_color = 0, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 0, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 12, + .hair_color = 1, + .hair_flip = 0, + .eye_type = 4, + .eye_color = 0, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 3, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 0, + .eyebrow_color = 1, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 1, + .favorite_color = 0, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, +}; + +const std::array<Service::Mii::DefaultMii, 6> DefaultMii{ + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 4, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 68, + .hair_color = 0, + .hair_flip = 0, + .eye_type = 2, + .eye_color = 0, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 4, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 6, + .eyebrow_color = 0, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 0, + .favorite_color = 4, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 0, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 55, + .hair_color = 6, + .hair_flip = 0, + .eye_type = 2, + .eye_color = 4, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 4, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 6, + .eyebrow_color = 6, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 0, + .favorite_color = 5, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 1, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 33, + .hair_color = 1, + .hair_flip = 0, + .eye_type = 2, + .eye_color = 0, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 4, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 6, + .eyebrow_color = 1, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 0, + .favorite_color = 0, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 2, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 24, + .hair_color = 0, + .hair_flip = 0, + .eye_type = 4, + .eye_color = 0, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 3, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 0, + .eyebrow_color = 0, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 1, + .favorite_color = 2, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 0, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 14, + .hair_color = 7, + .hair_flip = 0, + .eye_type = 4, + .eye_color = 5, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 3, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 0, + .eyebrow_color = 7, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 1, + .favorite_color = 6, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, + Service::Mii::DefaultMii{ + .face_type = 0, + .face_color = 0, + .face_wrinkle = 0, + .face_makeup = 0, + .hair_type = 12, + .hair_color = 1, + .hair_flip = 0, + .eye_type = 4, + .eye_color = 0, + .eye_scale = 4, + .eye_aspect = 3, + .eye_rotate = 3, + .eye_x = 2, + .eye_y = 12, + .eyebrow_type = 0, + .eyebrow_color = 1, + .eyebrow_scale = 4, + .eyebrow_aspect = 3, + .eyebrow_rotate = 6, + .eyebrow_x = 2, + .eyebrow_y = 10, + .nose_type = 1, + .nose_scale = 4, + .nose_y = 9, + .mouth_type = 23, + .mouth_color = 0, + .mouth_scale = 4, + .mouth_aspect = 3, + .mouth_y = 13, + .mustache_type = 0, + .beard_type = 0, + .beard_color = 0, + .mustache_scale = 4, + .mustache_y = 10, + .glasses_type = 0, + .glasses_color = 0, + .glasses_scale = 4, + .glasses_y = 10, + .mole_type = 0, + .mole_scale = 4, + .mole_x = 2, + .mole_y = 20, + .height = 64, + .weight = 64, + .gender = 1, + .favorite_color = 7, + .region_move = 0, + .font_region = 0, + .type = 0, + .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'}, + }, + +}; + +const std::array<RandomMiiData4, 18> RandomMiiFaceline{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 10, + .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 10, + .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 10, + .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 12, + .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 13, + .values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 12, + .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 12, + .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 13, + .values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 12, + .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 10, + .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 10, + .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 10, + .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 12, + .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 12, + .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 12, + .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 12, + .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 12, + .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 12, + .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, + }, +}; + +const std::array<RandomMiiData3, 6> RandomMiiFacelineColor{ + RandomMiiData3{ + .arg_1 = 0, + .arg_2 = 0, + .values_count = 10, + .values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5}, + }, + RandomMiiData3{ + .arg_1 = 0, + .arg_2 = 1, + .values_count = 10, + .values = {0, 0, 0, 0, 1, 1, 2, 3, 3, 3}, + }, + RandomMiiData3{ + .arg_1 = 0, + .arg_2 = 2, + .values_count = 10, + .values = {0, 0, 1, 1, 1, 1, 1, 1, 1, 2}, + }, + RandomMiiData3{ + .arg_1 = 1, + .arg_2 = 0, + .values_count = 10, + .values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5}, + }, + RandomMiiData3{ + .arg_1 = 1, + .arg_2 = 1, + .values_count = 10, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 3}, + }, + RandomMiiData3{ + .arg_1 = 1, + .arg_2 = 2, + .values_count = 10, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + }, +}; + +const std::array<RandomMiiData4, 18> RandomMiiFacelineWrinkle{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11}, + }, +}; + +const std::array<RandomMiiData4, 18> RandomMiiFacelineMakeup{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, +}; + +const std::array<RandomMiiData4, 18> RandomMiiHairType{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 30, + .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, + 47, 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 75, 76, 86, 89}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 31, + .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47, + 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 31, + .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47, + 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 38, + .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 40, 42, 43, 44, 45, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 75, 76, 86, 89}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 39, + .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 39, + .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 18, + .values = {13, 23, 30, 36, 37, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 19, + .values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 19, + .values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 39, + .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 24, 25, 26, 28, 46, 50, 61, 62, 63, 64, 69, 76, 77, 79, 80, 83, 85}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 42, + .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50, + 61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 42, + .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50, + 61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 44, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 42, 50, + 58, 60, 62, 63, 64, 69, 71, 76, 79, 80, 81, 82, 83, 86}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 44, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58, + 60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 44, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58, + 60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 24, + .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, + 16, 17, 18, 20, 21, 24, 25, 58, 62, 69, 76, 83}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 27, + .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17, + 18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 27, + .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17, + 18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85}, + }, +}; + +const std::array<RandomMiiData3, 9> RandomMiiHairColor{ + RandomMiiData3{ + .arg_1 = 0, + .arg_2 = 0, + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + RandomMiiData3{ + .arg_1 = 0, + .arg_2 = 1, + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + RandomMiiData3{ + .arg_1 = 0, + .arg_2 = 2, + .values_count = 20, + .values = {0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + }, + RandomMiiData3{ + .arg_1 = 1, + .arg_2 = 0, + .values_count = 20, + .values = {2, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7}, + }, + RandomMiiData3{ + .arg_1 = 1, + .arg_2 = 1, + .values_count = 20, + .values = {2, 3, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7}, + }, + RandomMiiData3{ + .arg_1 = 1, + .arg_2 = 2, + .values_count = 20, + .values = {2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7}, + }, + RandomMiiData3{ + .arg_1 = 2, + .arg_2 = 0, + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, + }, + RandomMiiData3{ + .arg_1 = 2, + .arg_2 = 1, + .values_count = 20, + .values = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3}, + }, + RandomMiiData3{ + .arg_1 = 2, + .arg_2 = 2, + .values_count = 20, + .values = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + }, +}; + +const std::array<RandomMiiData4, 18> RandomMiiEyeType{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 26, + .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27, + 29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 26, + .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27, + 29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 27, + .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 26, 27, + 29, 32, 34, 36, 38, 39, 41, 43, 47, 48, 49, 53, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 35, + .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29, + 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 35, + .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29, + 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 35, + .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 21, 22, 26, 27, 29, + 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 48, 49, 50, 53, 56, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 30, + .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21, + 22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 30, + .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21, + 22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 30, + .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 21, 22, + 26, 31, 32, 34, 36, 37, 39, 41, 44, 48, 49, 50, 51, 53, 57}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 39, + .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27, + 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 39, + .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27, + 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 40, + .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 26, + 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 46, + .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, + 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37, + 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 46, + .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, + 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37, + 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 46, + .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, + 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 37, + 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 34, + .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, + 24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 34, + .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, + 24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 35, + .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, + 25, 26, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47}, + }, +}; + +const std::array<RandomMiiData2, 3> RandomMiiEyeColor{ + RandomMiiData2{ + .arg_1 = 0, + .values_count = 10, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + }, + RandomMiiData2{ + .arg_1 = 1, + .values_count = 10, + .values = {0, 1, 1, 2, 3, 3, 4, 4, 4, 5}, + }, + RandomMiiData2{ + .arg_1 = 2, + .values_count = 10, + .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + }, +}; + +const std::array<RandomMiiData4, 18> RandomMiiEyebrowType{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 18, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 18, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 18, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 23, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 23, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 23, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 21, + .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 21, + .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 21, + .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 9, + .values = {0, 1, 3, 7, 8, 9, 10, 11, 13}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 9, + .values = {0, 1, 3, 7, 8, 9, 10, 11, 13}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 9, + .values = {0, 1, 3, 7, 8, 9, 10, 11, 13}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 11, + .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 11, + .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 11, + .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 9, + .values = {0, 3, 7, 8, 9, 10, 11, 13, 15}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 9, + .values = {0, 3, 7, 8, 9, 10, 11, 13, 15}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 9, + .values = {0, 3, 7, 8, 9, 10, 11, 13, 15}, + }, +}; + +const std::array<RandomMiiData4, 18> RandomMiiNoseType{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 11, + .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 11, + .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 11, + .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 18, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 18, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 15, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 18, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 18, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 15, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 8, + .values = {0, 1, 3, 4, 8, 10, 13, 14}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 8, + .values = {0, 1, 3, 4, 8, 10, 13, 14}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 8, + .values = {0, 1, 3, 4, 8, 10, 13, 14}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 12, + .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 11, + .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 10, + .values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 12, + .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 11, + .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 10, + .values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14}, + }, +}; + +const std::array<RandomMiiData4, 18> RandomMiiMouthType{ + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 25, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 17, 18, + 19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 27, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, + 18, 19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 28, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, + 18, 19, 21, 22, 23, 25, 26, 28, 30, 31, 32, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 24, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 26, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 26, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 24, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 26, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Male), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 26, + .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Black), + .values_count = 25, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15, + 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Black), + .values_count = 26, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, + 15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Black), + .values_count = 26, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, + 15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::White), + .values_count = 25, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15, + 17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::White), + .values_count = 26, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, + 15, 17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::White), + .values_count = 25, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, + 15, 17, 18, 19, 21, 22, 23, 24, 25, 29, 33, 35}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Young), + .race = static_cast<u32>(Race::Asian), + .values_count = 24, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, + 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Normal), + .race = static_cast<u32>(Race::Asian), + .values_count = 25, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, + 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33}, + }, + RandomMiiData4{ + .gender = static_cast<u32>(Gender::Female), + .age = static_cast<u32>(Age::Old), + .race = static_cast<u32>(Race::Asian), + .values_count = 25, + .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, + 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33}, + }, +}; + +const std::array<RandomMiiData2, 3> RandomMiiGlassType{ + RandomMiiData2{ + .arg_1 = 0, + .values_count = 9, + .values = {90, 94, 96, 100, 0, 0, 0, 0, 0}, + }, + RandomMiiData2{ + .arg_1 = 1, + .values_count = 9, + .values = {83, 86, 90, 93, 94, 96, 98, 100, 0}, + }, + RandomMiiData2{ + .arg_1 = 2, + .values_count = 9, + .values = {78, 83, 0, 93, 0, 0, 98, 100, 0}, + }, +}; + +u8 FromVer3GetFacelineColor(u8 color) { + return FromVer3FacelineColorTable[color]; +} + +u8 FromVer3GetHairColor(u8 color) { + return FromVer3HairColorTable[color]; +} + +u8 FromVer3GetEyeColor(u8 color) { + return FromVer3EyeColorTable[color]; +} + +u8 FromVer3GetMouthlineColor(u8 color) { + return FromVer3MouthlineColorTable[color]; +} + +u8 FromVer3GetGlassColor(u8 color) { + return FromVer3GlassColorTable[color]; +} + +u8 FromVer3GetGlassType(u8 type) { + return FromVer3GlassTypeTable[type]; +} + +FacelineColor GetFacelineColorFromVer3(u32 color) { + return static_cast<FacelineColor>(Ver3FacelineColorTable[color]); +} + +CommonColor GetHairColorFromVer3(u32 color) { + return static_cast<CommonColor>(Ver3HairColorTable[color]); +} + +CommonColor GetEyeColorFromVer3(u32 color) { + return static_cast<CommonColor>(Ver3EyeColorTable[color]); +} + +CommonColor GetMouthColorFromVer3(u32 color) { + return static_cast<CommonColor>(Ver3MouthColorTable[color]); +} + +CommonColor GetGlassColorFromVer3(u32 color) { + return static_cast<CommonColor>(Ver3GlassColorTable[color]); +} + +} // namespace Service::Mii::RawData diff --git a/src/core/hle/service/mii/types/raw_data.h b/src/core/hle/service/mii/types/raw_data.h new file mode 100644 index 000000000..9a4cfa738 --- /dev/null +++ b/src/core/hle/service/mii/types/raw_data.h @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <array> + +#include "core/hle/service/mii/mii_types.h" + +namespace Service::Mii::RawData { + +struct RandomMiiValues { + std::array<u8, 188> values{}; +}; +static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size."); + +struct RandomMiiData4 { + u32 gender{}; + u32 age{}; + u32 race{}; + u32 values_count{}; + std::array<u32, 47> values{}; +}; +static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size."); + +struct RandomMiiData3 { + u32 arg_1; + u32 arg_2; + u32 values_count; + std::array<u32, 47> values{}; +}; +static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size."); + +struct RandomMiiData2 { + u32 arg_1; + u32 values_count; + std::array<u32, 47> values{}; +}; +static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size."); + +extern const std::array<Service::Mii::DefaultMii, 2> BaseMii; +extern const std::array<Service::Mii::DefaultMii, 6> DefaultMii; + +extern const std::array<u8, 62> EyeRotateLookup; +extern const std::array<u8, 24> EyebrowRotateLookup; + +extern const std::array<RandomMiiData4, 18> RandomMiiFaceline; +extern const std::array<RandomMiiData3, 6> RandomMiiFacelineColor; +extern const std::array<RandomMiiData4, 18> RandomMiiFacelineWrinkle; +extern const std::array<RandomMiiData4, 18> RandomMiiFacelineMakeup; +extern const std::array<RandomMiiData4, 18> RandomMiiHairType; +extern const std::array<RandomMiiData3, 9> RandomMiiHairColor; +extern const std::array<RandomMiiData4, 18> RandomMiiEyeType; +extern const std::array<RandomMiiData2, 3> RandomMiiEyeColor; +extern const std::array<RandomMiiData4, 18> RandomMiiEyebrowType; +extern const std::array<RandomMiiData4, 18> RandomMiiNoseType; +extern const std::array<RandomMiiData4, 18> RandomMiiMouthType; +extern const std::array<RandomMiiData2, 3> RandomMiiGlassType; + +u8 FromVer3GetFacelineColor(u8 color); +u8 FromVer3GetHairColor(u8 color); +u8 FromVer3GetEyeColor(u8 color); +u8 FromVer3GetMouthlineColor(u8 color); +u8 FromVer3GetGlassColor(u8 color); +u8 FromVer3GetGlassType(u8 type); + +FacelineColor GetFacelineColorFromVer3(u32 color); +CommonColor GetHairColorFromVer3(u32 color); +CommonColor GetEyeColorFromVer3(u32 color); +CommonColor GetMouthColorFromVer3(u32 color); +CommonColor GetGlassColorFromVer3(u32 color); + +} // namespace Service::Mii::RawData diff --git a/src/core/hle/service/mii/types/store_data.cpp b/src/core/hle/service/mii/types/store_data.cpp new file mode 100644 index 000000000..8fce636c7 --- /dev/null +++ b/src/core/hle/service/mii/types/store_data.cpp @@ -0,0 +1,643 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/mii/mii_util.h" +#include "core/hle/service/mii/types/raw_data.h" +#include "core/hle/service/mii/types/store_data.h" + +namespace Service::Mii { + +void StoreData::BuildDefault(u32 mii_index) { + const auto& default_mii = RawData::DefaultMii[mii_index]; + core_data.SetDefault(); + + core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type)); + core_data.SetFacelineColor( + RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color))); + core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle)); + core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup)); + + core_data.SetHairType(static_cast<HairType>(default_mii.hair_type)); + core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color))); + core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip)); + core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type)); + core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color))); + core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale)); + core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect)); + core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate)); + core_data.SetEyeX(static_cast<u8>(default_mii.eye_x)); + core_data.SetEyeY(static_cast<u8>(default_mii.eye_y)); + + core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type)); + core_data.SetEyebrowColor( + RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color))); + core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale)); + core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect)); + core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate)); + core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x)); + core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y)); + + core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type)); + core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale)); + core_data.SetNoseY(static_cast<u8>(default_mii.nose_y)); + + core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type)); + core_data.SetMouthColor( + RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color))); + core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale)); + core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect)); + core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y)); + + core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type)); + core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type)); + core_data.SetBeardColor( + RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color))); + core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale)); + core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y)); + + core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type)); + core_data.SetGlassColor( + RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color))); + core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale)); + core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y)); + + core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type)); + core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale)); + core_data.SetMoleX(static_cast<u8>(default_mii.mole_x)); + core_data.SetMoleY(static_cast<u8>(default_mii.mole_y)); + + core_data.SetHeight(static_cast<u8>(default_mii.height)); + core_data.SetBuild(static_cast<u8>(default_mii.weight)); + core_data.SetGender(static_cast<Gender>(default_mii.gender)); + core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color)); + core_data.SetRegionMove(static_cast<u8>(default_mii.region_move)); + core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region)); + core_data.SetType(static_cast<u8>(default_mii.type)); + core_data.SetNickname(default_mii.nickname); + + const auto device_id = MiiUtil::GetDeviceId(); + create_id = MiiUtil::MakeCreateId(); + device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID)); + data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData)); +} + +void StoreData::BuildBase(Gender gender) { + const auto& default_mii = RawData::BaseMii[gender == Gender::Female ? 1 : 0]; + core_data.SetDefault(); + + core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type)); + core_data.SetFacelineColor( + RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color))); + core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle)); + core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup)); + + core_data.SetHairType(static_cast<HairType>(default_mii.hair_type)); + core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color))); + core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip)); + core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type)); + core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color))); + core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale)); + core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect)); + core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate)); + core_data.SetEyeX(static_cast<u8>(default_mii.eye_x)); + core_data.SetEyeY(static_cast<u8>(default_mii.eye_y)); + + core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type)); + core_data.SetEyebrowColor( + RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color))); + core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale)); + core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect)); + core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate)); + core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x)); + core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y)); + + core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type)); + core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale)); + core_data.SetNoseY(static_cast<u8>(default_mii.nose_y)); + + core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type)); + core_data.SetMouthColor( + RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color))); + core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale)); + core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect)); + core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y)); + + core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type)); + core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type)); + core_data.SetBeardColor( + RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color))); + core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale)); + core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y)); + + core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type)); + core_data.SetGlassColor( + RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color))); + core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale)); + core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y)); + + core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type)); + core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale)); + core_data.SetMoleX(static_cast<u8>(default_mii.mole_x)); + core_data.SetMoleY(static_cast<u8>(default_mii.mole_y)); + + core_data.SetHeight(static_cast<u8>(default_mii.height)); + core_data.SetBuild(static_cast<u8>(default_mii.weight)); + core_data.SetGender(static_cast<Gender>(default_mii.gender)); + core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color)); + core_data.SetRegionMove(static_cast<u8>(default_mii.region_move)); + core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region)); + core_data.SetType(static_cast<u8>(default_mii.type)); + core_data.SetNickname(default_mii.nickname); + + const auto device_id = MiiUtil::GetDeviceId(); + create_id = MiiUtil::MakeCreateId(); + device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID)); + data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData)); +} + +void StoreData::BuildRandom(Age age, Gender gender, Race race) { + core_data.BuildRandom(age, gender, race); + const auto device_id = MiiUtil::GetDeviceId(); + create_id = MiiUtil::MakeCreateId(); + device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID)); + data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData)); +} + +void StoreData::SetInvalidName() { + const auto& invalid_name = core_data.GetInvalidNickname(); + const auto device_id = MiiUtil::GetDeviceId(); + core_data.SetNickname(invalid_name); + device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID)); + data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData)); +} + +bool StoreData::IsSpecial() const { + return GetType() == 1; +} + +u32 StoreData::IsValid() const { + // TODO: complete this + return 0; +} + +void StoreData::SetFontRegion(FontRegion value) { + core_data.SetFontRegion(value); +} + +void StoreData::SetFavoriteColor(FavoriteColor 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(FacelineType value) { + core_data.SetFacelineType(value); +} + +void StoreData::SetFacelineColor(FacelineColor value) { + core_data.SetFacelineColor(value); +} + +void StoreData::SetFacelineWrinkle(FacelineWrinkle value) { + core_data.SetFacelineWrinkle(value); +} + +void StoreData::SetFacelineMake(FacelineMake value) { + core_data.SetFacelineMake(value); +} + +void StoreData::SetHairType(HairType value) { + core_data.SetHairType(value); +} + +void StoreData::SetHairColor(CommonColor value) { + core_data.SetHairColor(value); +} + +void StoreData::SetHairFlip(HairFlip value) { + core_data.SetHairFlip(value); +} + +void StoreData::SetEyeType(EyeType value) { + core_data.SetEyeType(value); +} + +void StoreData::SetEyeColor(CommonColor 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(EyebrowType value) { + core_data.SetEyebrowType(value); +} + +void StoreData::SetEyebrowColor(CommonColor 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(NoseType 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(CommonColor 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(CommonColor 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(GlassType value) { + core_data.SetGlassType(value); +} + +void StoreData::SetGlassColor(CommonColor 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(MoleType 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; +} + +FontRegion StoreData::GetFontRegion() const { + return static_cast<FontRegion>(core_data.GetFontRegion()); +} + +FavoriteColor StoreData::GetFavoriteColor() const { + return core_data.GetFavoriteColor(); +} + +Gender StoreData::GetGender() const { + return core_data.GetGender(); +} + +u8 StoreData::GetHeight() const { + return core_data.GetHeight(); +} + +u8 StoreData::GetBuild() const { + return core_data.GetBuild(); +} + +u8 StoreData::GetType() const { + return core_data.GetType(); +} + +u8 StoreData::GetRegionMove() const { + return core_data.GetRegionMove(); +} + +FacelineType StoreData::GetFacelineType() const { + return core_data.GetFacelineType(); +} + +FacelineColor StoreData::GetFacelineColor() const { + return core_data.GetFacelineColor(); +} + +FacelineWrinkle StoreData::GetFacelineWrinkle() const { + return core_data.GetFacelineWrinkle(); +} + +FacelineMake StoreData::GetFacelineMake() const { + return core_data.GetFacelineMake(); +} + +HairType StoreData::GetHairType() const { + return core_data.GetHairType(); +} + +CommonColor StoreData::GetHairColor() const { + return core_data.GetHairColor(); +} + +HairFlip StoreData::GetHairFlip() const { + return core_data.GetHairFlip(); +} + +EyeType StoreData::GetEyeType() const { + return core_data.GetEyeType(); +} + +CommonColor StoreData::GetEyeColor() const { + return core_data.GetEyeColor(); +} + +u8 StoreData::GetEyeScale() const { + return core_data.GetEyeScale(); +} + +u8 StoreData::GetEyeAspect() const { + return core_data.GetEyeAspect(); +} + +u8 StoreData::GetEyeRotate() const { + return core_data.GetEyeRotate(); +} + +u8 StoreData::GetEyeX() const { + return core_data.GetEyeX(); +} + +u8 StoreData::GetEyeY() const { + return core_data.GetEyeY(); +} + +EyebrowType StoreData::GetEyebrowType() const { + return core_data.GetEyebrowType(); +} + +CommonColor StoreData::GetEyebrowColor() const { + return core_data.GetEyebrowColor(); +} + +u8 StoreData::GetEyebrowScale() const { + return core_data.GetEyebrowScale(); +} + +u8 StoreData::GetEyebrowAspect() const { + return core_data.GetEyebrowAspect(); +} + +u8 StoreData::GetEyebrowRotate() const { + return core_data.GetEyebrowRotate(); +} + +u8 StoreData::GetEyebrowX() const { + return core_data.GetEyebrowX(); +} + +u8 StoreData::GetEyebrowY() const { + return core_data.GetEyebrowY(); +} + +NoseType StoreData::GetNoseType() const { + return core_data.GetNoseType(); +} + +u8 StoreData::GetNoseScale() const { + return core_data.GetNoseScale(); +} + +u8 StoreData::GetNoseY() const { + return core_data.GetNoseY(); +} + +MouthType StoreData::GetMouthType() const { + return core_data.GetMouthType(); +} + +CommonColor StoreData::GetMouthColor() const { + return core_data.GetMouthColor(); +} + +u8 StoreData::GetMouthScale() const { + return core_data.GetMouthScale(); +} + +u8 StoreData::GetMouthAspect() const { + return core_data.GetMouthAspect(); +} + +u8 StoreData::GetMouthY() const { + return core_data.GetMouthY(); +} + +CommonColor StoreData::GetBeardColor() const { + return core_data.GetBeardColor(); +} + +BeardType StoreData::GetBeardType() const { + return core_data.GetBeardType(); +} + +MustacheType StoreData::GetMustacheType() const { + return core_data.GetMustacheType(); +} + +u8 StoreData::GetMustacheScale() const { + return core_data.GetMustacheScale(); +} + +u8 StoreData::GetMustacheY() const { + return core_data.GetMustacheY(); +} + +GlassType StoreData::GetGlassType() const { + return core_data.GetGlassType(); +} + +CommonColor StoreData::GetGlassColor() const { + return core_data.GetGlassColor(); +} + +u8 StoreData::GetGlassScale() const { + return core_data.GetGlassScale(); +} + +u8 StoreData::GetGlassY() const { + return core_data.GetGlassY(); +} + +MoleType StoreData::GetMoleType() const { + return core_data.GetMoleType(); +} + +u8 StoreData::GetMoleScale() const { + return core_data.GetMoleScale(); +} + +u8 StoreData::GetMoleX() const { + return core_data.GetMoleX(); +} + +u8 StoreData::GetMoleY() const { + return core_data.GetMoleY(); +} + +Nickname StoreData::GetNickname() const { + return core_data.GetNickname(); +} + +bool StoreData::operator==(const StoreData& data) { + bool is_identical = data.core_data.IsValid() == 0; + 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(); + is_identical &= GetGender() == data.GetGender(); + is_identical &= GetHeight() == data.GetHeight(); + is_identical &= GetBuild() == data.GetBuild(); + is_identical &= GetType() == data.GetType(); + is_identical &= GetRegionMove() == data.GetRegionMove(); + is_identical &= GetFacelineType() == data.GetFacelineType(); + is_identical &= GetFacelineColor() == data.GetFacelineColor(); + is_identical &= GetFacelineWrinkle() == data.GetFacelineWrinkle(); + is_identical &= GetFacelineMake() == data.GetFacelineMake(); + is_identical &= GetHairType() == data.GetHairType(); + is_identical &= GetHairColor() == data.GetHairColor(); + is_identical &= GetHairFlip() == data.GetHairFlip(); + is_identical &= GetEyeType() == data.GetEyeType(); + is_identical &= GetEyeColor() == data.GetEyeColor(); + is_identical &= GetEyeScale() == data.GetEyeScale(); + is_identical &= GetEyeAspect() == data.GetEyeAspect(); + is_identical &= GetEyeRotate() == data.GetEyeRotate(); + is_identical &= GetEyeX() == data.GetEyeX(); + is_identical &= GetEyeY() == data.GetEyeY(); + is_identical &= GetEyebrowType() == data.GetEyebrowType(); + is_identical &= GetEyebrowColor() == data.GetEyebrowColor(); + is_identical &= GetEyebrowScale() == data.GetEyebrowScale(); + is_identical &= GetEyebrowAspect() == data.GetEyebrowAspect(); + is_identical &= GetEyebrowRotate() == data.GetEyebrowRotate(); + is_identical &= GetEyebrowX() == data.GetEyebrowX(); + is_identical &= GetEyebrowY() == data.GetEyebrowY(); + is_identical &= GetNoseType() == data.GetNoseType(); + is_identical &= GetNoseScale() == data.GetNoseScale(); + is_identical &= GetNoseY() == data.GetNoseY(); + is_identical &= GetMouthType() == data.GetMouthType(); + is_identical &= GetMouthColor() == data.GetMouthColor(); + is_identical &= GetMouthScale() == data.GetMouthScale(); + is_identical &= GetMouthAspect() == data.GetMouthAspect(); + is_identical &= GetMouthY() == data.GetMouthY(); + is_identical &= GetBeardColor() == data.GetBeardColor(); + is_identical &= GetBeardType() == data.GetBeardType(); + is_identical &= GetMustacheType() == data.GetMustacheType(); + is_identical &= GetMustacheScale() == data.GetMustacheScale(); + is_identical &= GetMustacheY() == data.GetMustacheY(); + is_identical &= GetGlassType() == data.GetGlassType(); + is_identical &= GetGlassColor() == data.GetGlassColor(); + is_identical &= GetGlassScale() == data.GetGlassScale(); + is_identical &= GetGlassY() == data.GetGlassY(); + is_identical &= GetMoleType() == data.GetMoleType(); + is_identical &= GetMoleScale() == data.GetMoleScale(); + is_identical &= GetMoleX() == data.GetMoleX(); + is_identical &= data.GetMoleY() == data.GetMoleY(); + return is_identical; +} + +} // namespace Service::Mii diff --git a/src/core/hle/service/mii/types/store_data.h b/src/core/hle/service/mii/types/store_data.h new file mode 100644 index 000000000..224c32cf8 --- /dev/null +++ b/src/core/hle/service/mii/types/store_data.h @@ -0,0 +1,145 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/mii/mii_types.h" +#include "core/hle/service/mii/types/core_data.h" + +namespace Service::Mii { + +class StoreData { +public: + // nn::mii::detail::StoreDataRaw::BuildDefault + void BuildDefault(u32 mii_index); + // nn::mii::detail::StoreDataRaw::BuildDefault + + void BuildBase(Gender gender); + // nn::mii::detail::StoreDataRaw::BuildRandom + void BuildRandom(Age age, Gender gender, Race race); + + bool IsSpecial() const; + + u32 IsValid() const; + + void SetFontRegion(FontRegion value); + void SetFavoriteColor(FavoriteColor value); + void SetGender(Gender value); + void SetHeight(u8 value); + void SetBuild(u8 value); + void SetType(u8 value); + void SetRegionMove(u8 value); + void SetFacelineType(FacelineType value); + void SetFacelineColor(FacelineColor value); + void SetFacelineWrinkle(FacelineWrinkle value); + void SetFacelineMake(FacelineMake value); + void SetHairType(HairType value); + void SetHairColor(CommonColor value); + void SetHairFlip(HairFlip value); + void SetEyeType(EyeType value); + void SetEyeColor(CommonColor value); + void SetEyeScale(u8 value); + void SetEyeAspect(u8 value); + void SetEyeRotate(u8 value); + void SetEyeX(u8 value); + void SetEyeY(u8 value); + void SetEyebrowType(EyebrowType value); + void SetEyebrowColor(CommonColor value); + void SetEyebrowScale(u8 value); + void SetEyebrowAspect(u8 value); + void SetEyebrowRotate(u8 value); + void SetEyebrowX(u8 value); + void SetEyebrowY(u8 value); + void SetNoseType(NoseType value); + void SetNoseScale(u8 value); + void SetNoseY(u8 value); + void SetMouthType(u8 value); + void SetMouthColor(CommonColor value); + void SetMouthScale(u8 value); + void SetMouthAspect(u8 value); + void SetMouthY(u8 value); + void SetBeardColor(CommonColor value); + void SetBeardType(BeardType value); + void SetMustacheType(MustacheType value); + void SetMustacheScale(u8 value); + void SetMustacheY(u8 value); + void SetGlassType(GlassType value); + void SetGlassColor(CommonColor value); + void SetGlassScale(u8 value); + void SetGlassY(u8 value); + void SetMoleType(MoleType 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; + FavoriteColor GetFavoriteColor() const; + Gender GetGender() const; + u8 GetHeight() const; + u8 GetBuild() const; + u8 GetType() const; + u8 GetRegionMove() const; + FacelineType GetFacelineType() const; + FacelineColor GetFacelineColor() const; + FacelineWrinkle GetFacelineWrinkle() const; + FacelineMake GetFacelineMake() const; + HairType GetHairType() const; + CommonColor GetHairColor() const; + HairFlip GetHairFlip() const; + EyeType GetEyeType() const; + CommonColor GetEyeColor() const; + u8 GetEyeScale() const; + u8 GetEyeAspect() const; + u8 GetEyeRotate() const; + u8 GetEyeX() const; + u8 GetEyeY() const; + EyebrowType GetEyebrowType() const; + CommonColor GetEyebrowColor() const; + u8 GetEyebrowScale() const; + u8 GetEyebrowAspect() const; + u8 GetEyebrowRotate() const; + u8 GetEyebrowX() const; + u8 GetEyebrowY() const; + NoseType GetNoseType() const; + u8 GetNoseScale() const; + u8 GetNoseY() const; + MouthType GetMouthType() const; + CommonColor GetMouthColor() const; + u8 GetMouthScale() const; + u8 GetMouthAspect() const; + u8 GetMouthY() const; + CommonColor GetBeardColor() const; + BeardType GetBeardType() const; + MustacheType GetMustacheType() const; + u8 GetMustacheScale() const; + u8 GetMustacheY() const; + GlassType GetGlassType() const; + CommonColor GetGlassColor() const; + u8 GetGlassScale() const; + u8 GetGlassY() const; + MoleType GetMoleType() const; + u8 GetMoleScale() const; + u8 GetMoleX() const; + u8 GetMoleY() const; + Nickname GetNickname() const; + + bool operator==(const StoreData& data); + +private: + CoreData core_data{}; + Common::UUID create_id{}; + u16 data_crc{}; + u16 device_crc{}; +}; +static_assert(sizeof(StoreData) == 0x44, "StoreData has incorrect size."); + +struct StoreDataElement { + StoreData store_data{}; + Source source{}; +}; +static_assert(sizeof(StoreDataElement) == 0x48, "StoreDataElement has incorrect size."); + +}; // namespace Service::Mii diff --git a/src/core/hle/service/mii/types/ver3_store_data.cpp b/src/core/hle/service/mii/types/ver3_store_data.cpp new file mode 100644 index 000000000..1c28e0b1b --- /dev/null +++ b/src/core/hle/service/mii/types/ver3_store_data.cpp @@ -0,0 +1,241 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/mii/mii_util.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 NfpStoreDataExtension::SetFromStoreData(const StoreData& store_data) { + faceline_color = static_cast<u8>(store_data.GetFacelineColor()) & 0xf; + hair_color = static_cast<u8>(store_data.GetHairColor()) & 0x7f; + eye_color = static_cast<u8>(store_data.GetEyeColor()) & 0x7f; + eyebrow_color = static_cast<u8>(store_data.GetEyebrowColor()) & 0x7f; + mouth_color = static_cast<u8>(store_data.GetMouthColor()) & 0x7f; + beard_color = static_cast<u8>(store_data.GetBeardColor()) & 0x7f; + glass_color = static_cast<u8>(store_data.GetGlassColor()) & 0x7f; + glass_type = static_cast<u8>(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_store_data.SetGender(static_cast<Gender>(mii_information.gender.Value())); + out_store_data.SetFavoriteColor( + static_cast<FavoriteColor>(mii_information.favorite_color.Value())); + out_store_data.SetHeight(height); + out_store_data.SetBuild(build); + + out_store_data.SetNickname(mii_name); + out_store_data.SetFontRegion( + static_cast<FontRegion>(static_cast<u8>(region_information.font_region))); + + out_store_data.SetFacelineType( + static_cast<FacelineType>(appearance_bits1.faceline_type.Value())); + out_store_data.SetFacelineColor( + static_cast<FacelineColor>(appearance_bits1.faceline_color.Value())); + out_store_data.SetFacelineWrinkle( + static_cast<FacelineWrinkle>(appearance_bits2.faceline_wrinkle.Value())); + out_store_data.SetFacelineMake( + static_cast<FacelineMake>(appearance_bits2.faceline_make.Value())); + + out_store_data.SetHairType(static_cast<HairType>(hair_type)); + out_store_data.SetHairColor(static_cast<CommonColor>(appearance_bits3.hair_color.Value())); + out_store_data.SetHairFlip(static_cast<HairFlip>(appearance_bits3.hair_flip.Value())); + + out_store_data.SetEyeType(static_cast<EyeType>(appearance_bits4.eye_type.Value())); + out_store_data.SetEyeColor(static_cast<CommonColor>(appearance_bits4.eye_color.Value())); + out_store_data.SetEyeScale(static_cast<u8>(appearance_bits4.eye_scale)); + out_store_data.SetEyeAspect(static_cast<u8>(appearance_bits4.eye_aspect)); + out_store_data.SetEyeRotate(static_cast<u8>(appearance_bits4.eye_rotate)); + out_store_data.SetEyeX(static_cast<u8>(appearance_bits4.eye_x)); + out_store_data.SetEyeY(static_cast<u8>(appearance_bits4.eye_y)); + + out_store_data.SetEyebrowType(static_cast<EyebrowType>(appearance_bits5.eyebrow_type.Value())); + out_store_data.SetEyebrowColor( + static_cast<CommonColor>(appearance_bits5.eyebrow_color.Value())); + out_store_data.SetEyebrowScale(static_cast<u8>(appearance_bits5.eyebrow_scale)); + out_store_data.SetEyebrowAspect(static_cast<u8>(appearance_bits5.eyebrow_aspect)); + out_store_data.SetEyebrowRotate(static_cast<u8>(appearance_bits5.eyebrow_rotate)); + out_store_data.SetEyebrowX(static_cast<u8>(appearance_bits5.eyebrow_x)); + out_store_data.SetEyebrowY(static_cast<u8>(appearance_bits5.eyebrow_y)); + + out_store_data.SetNoseType(static_cast<NoseType>(appearance_bits6.nose_type.Value())); + out_store_data.SetNoseScale(static_cast<u8>(appearance_bits6.nose_scale)); + out_store_data.SetNoseY(static_cast<u8>(appearance_bits6.nose_y)); + + out_store_data.SetMouthType(static_cast<u8>(appearance_bits7.mouth_type)); + out_store_data.SetMouthColor(static_cast<CommonColor>(appearance_bits7.mouth_color.Value())); + out_store_data.SetMouthScale(static_cast<u8>(appearance_bits7.mouth_scale)); + out_store_data.SetMouthAspect(static_cast<u8>(appearance_bits7.mouth_aspect)); + out_store_data.SetMouthY(static_cast<u8>(appearance_bits8.mouth_y)); + + out_store_data.SetMustacheType( + static_cast<MustacheType>(appearance_bits8.mustache_type.Value())); + out_store_data.SetMustacheScale(static_cast<u8>(appearance_bits9.mustache_scale)); + out_store_data.SetMustacheY(static_cast<u8>(appearance_bits9.mustache_y)); + + out_store_data.SetBeardType(static_cast<BeardType>(appearance_bits9.beard_type.Value())); + out_store_data.SetBeardColor(static_cast<CommonColor>(appearance_bits9.beard_color.Value())); + + out_store_data.SetGlassType(static_cast<GlassType>(appearance_bits10.glass_type.Value())); + out_store_data.SetGlassColor(static_cast<CommonColor>(appearance_bits10.glass_color.Value())); + out_store_data.SetGlassScale(static_cast<u8>(appearance_bits10.glass_scale)); + out_store_data.SetGlassY(static_cast<u8>(appearance_bits10.glass_y)); + + out_store_data.SetMoleType(static_cast<MoleType>(appearance_bits11.mole_type.Value())); + out_store_data.SetMoleScale(static_cast<u8>(appearance_bits11.mole_scale)); + out_store_data.SetMoleX(static_cast<u8>(appearance_bits11.mole_x)); + out_store_data.SetMoleY(static_cast<u8>(appearance_bits11.mole_y)); +} + +void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { + version = 1; + mii_information.gender.Assign(static_cast<u8>(store_data.GetGender())); + mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor())); + height = store_data.GetHeight(); + build = store_data.GetBuild(); + + mii_name = store_data.GetNickname(); + region_information.font_region.Assign(static_cast<u8>(store_data.GetFontRegion())); + + appearance_bits1.faceline_type.Assign(static_cast<u8>(store_data.GetFacelineType())); + appearance_bits2.faceline_wrinkle.Assign(static_cast<u8>(store_data.GetFacelineWrinkle())); + appearance_bits2.faceline_make.Assign(static_cast<u8>(store_data.GetFacelineMake())); + + hair_type = static_cast<u8>(store_data.GetHairType()); + appearance_bits3.hair_flip.Assign(static_cast<u8>(store_data.GetHairFlip())); + + appearance_bits4.eye_type.Assign(static_cast<u8>(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_type.Assign(static_cast<u8>(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(static_cast<u8>(store_data.GetNoseType())); + appearance_bits6.nose_scale.Assign(store_data.GetNoseScale()); + appearance_bits6.nose_y.Assign(store_data.GetNoseY()); + + appearance_bits7.mouth_type.Assign(static_cast<u8>(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(static_cast<u8>(store_data.GetMustacheType())); + appearance_bits9.mustache_scale.Assign(store_data.GetMustacheScale()); + appearance_bits9.mustache_y.Assign(store_data.GetMustacheY()); + + appearance_bits9.beard_type.Assign(static_cast<u8>(store_data.GetBeardType())); + + appearance_bits10.glass_scale.Assign(store_data.GetGlassScale()); + appearance_bits10.glass_y.Assign(store_data.GetGlassY()); + + appearance_bits11.mole_type.Assign(static_cast<u8>(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.faceline_color.Assign( + RawData::FromVer3GetFacelineColor(static_cast<u8>(store_data.GetFacelineColor()))); + appearance_bits3.hair_color.Assign( + RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetHairColor()))); + appearance_bits4.eye_color.Assign( + RawData::FromVer3GetEyeColor(static_cast<u8>(store_data.GetEyeColor()))); + appearance_bits5.eyebrow_color.Assign( + RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetEyebrowColor()))); + appearance_bits7.mouth_color.Assign( + RawData::FromVer3GetMouthlineColor(static_cast<u8>(store_data.GetMouthColor()))); + appearance_bits9.beard_color.Assign( + RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetBeardColor()))); + appearance_bits10.glass_color.Assign( + RawData::FromVer3GetGlassColor(static_cast<u8>(store_data.GetGlassColor()))); + appearance_bits10.glass_type.Assign( + RawData::FromVer3GetGlassType(static_cast<u8>(store_data.GetGlassType()))); + + 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.data[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 <= static_cast<u8>(FavoriteColor::Max)); + is_valid = is_valid && (height <= MaxHeight); + is_valid = is_valid && (build <= MaxBuild); + + is_valid = is_valid && (appearance_bits1.faceline_type <= static_cast<u8>(FacelineType::Max)); + is_valid = is_valid && (appearance_bits1.faceline_color <= MaxVer3CommonColor - 2); + is_valid = + is_valid && (appearance_bits2.faceline_wrinkle <= static_cast<u8>(FacelineWrinkle::Max)); + is_valid = is_valid && (appearance_bits2.faceline_make <= static_cast<u8>(FacelineMake::Max)); + + is_valid = is_valid && (hair_type <= static_cast<u8>(HairType::Max)); + is_valid = is_valid && (appearance_bits3.hair_color <= MaxVer3CommonColor); + + is_valid = is_valid && (appearance_bits4.eye_type <= static_cast<u8>(EyeType::Max)); + is_valid = is_valid && (appearance_bits4.eye_color <= MaxVer3CommonColor - 2); + is_valid = is_valid && (appearance_bits4.eye_scale <= MaxEyeScale); + is_valid = is_valid && (appearance_bits4.eye_aspect <= MaxEyeAspect); + is_valid = is_valid && (appearance_bits4.eye_rotate <= MaxEyeRotate); + is_valid = is_valid && (appearance_bits4.eye_x <= MaxEyeX); + is_valid = is_valid && (appearance_bits4.eye_y <= MaxEyeY); + + is_valid = is_valid && (appearance_bits5.eyebrow_type <= static_cast<u8>(EyebrowType::Max)); + is_valid = is_valid && (appearance_bits5.eyebrow_color <= MaxVer3CommonColor); + is_valid = is_valid && (appearance_bits5.eyebrow_scale <= MaxEyebrowScale); + is_valid = is_valid && (appearance_bits5.eyebrow_aspect <= MaxEyebrowAspect); + is_valid = is_valid && (appearance_bits5.eyebrow_rotate <= MaxEyebrowRotate); + is_valid = is_valid && (appearance_bits5.eyebrow_x <= MaxEyebrowX); + is_valid = is_valid && (appearance_bits5.eyebrow_y <= MaxEyebrowY); + + is_valid = is_valid && (appearance_bits6.nose_type <= static_cast<u8>(NoseType::Max)); + is_valid = is_valid && (appearance_bits6.nose_scale <= MaxNoseScale); + is_valid = is_valid && (appearance_bits6.nose_y <= MaxNoseY); + + is_valid = is_valid && (appearance_bits7.mouth_type <= static_cast<u8>(MouthType::Max)); + is_valid = is_valid && (appearance_bits7.mouth_color <= MaxVer3CommonColor - 3); + is_valid = is_valid && (appearance_bits7.mouth_scale <= MaxMouthScale); + is_valid = is_valid && (appearance_bits7.mouth_aspect <= MaxMoutAspect); + is_valid = is_valid && (appearance_bits8.mouth_y <= MaxMouthY); + + is_valid = is_valid && (appearance_bits8.mustache_type <= static_cast<u8>(MustacheType::Max)); + is_valid = is_valid && (appearance_bits9.mustache_scale < MaxMustacheScale); + is_valid = is_valid && (appearance_bits9.mustache_y <= MasMustacheY); + + is_valid = is_valid && (appearance_bits9.beard_type <= static_cast<u8>(BeardType::Max)); + is_valid = is_valid && (appearance_bits9.beard_color <= MaxVer3CommonColor); + + is_valid = is_valid && (appearance_bits10.glass_type <= MaxVer3GlassType); + is_valid = is_valid && (appearance_bits10.glass_color <= MaxVer3CommonColor - 2); + is_valid = is_valid && (appearance_bits10.glass_scale <= MaxGlassScale); + is_valid = is_valid && (appearance_bits10.glass_y <= MaxGlassScale); + + is_valid = is_valid && (appearance_bits11.mole_type <= static_cast<u8>(MoleType::Max)); + is_valid = is_valid && (appearance_bits11.mole_scale <= MaxMoleScale); + is_valid = is_valid && (appearance_bits11.mole_x <= MaxMoleX); + is_valid = is_valid && (appearance_bits11.mole_y <= MaxMoleY); + + return is_valid; +} + +} // namespace Service::Mii diff --git a/src/core/hle/service/mii/types/ver3_store_data.h b/src/core/hle/service/mii/types/ver3_store_data.h new file mode 100644 index 000000000..47907bf7d --- /dev/null +++ b/src/core/hle/service/mii/types/ver3_store_data.h @@ -0,0 +1,160 @@ +// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/mii/mii_types.h" + +namespace Service::Mii { +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: + void BuildToStoreData(StoreData& out_store_data) const; + void BuildFromStoreData(const StoreData& store_data); + + u32 IsValid() const; + + u8 version; + union { + u8 raw; + + BitField<0, 1, u8> allow_copying; + BitField<1, 1, u8> profanity_flag; + BitField<2, 2, u8> region_lock; + BitField<4, 2, u8> font_region; + } region_information; + u16_be mii_id; + u64_be system_id; + u32_be specialness_and_creation_date; + std::array<u8, 6> creator_mac; + u16_be padding; + union { + u16 raw; + + BitField<0, 1, u16> gender; + BitField<1, 4, u16> birth_month; + BitField<5, 5, u16> birth_day; + BitField<10, 4, u16> favorite_color; + BitField<14, 1, u16> favorite; + } mii_information; + Nickname mii_name; + u8 height; + u8 build; + union { + u8 raw; + + BitField<0, 1, u8> disable_sharing; + BitField<1, 4, u8> faceline_type; + BitField<5, 3, u8> faceline_color; + } appearance_bits1; + union { + u8 raw; + + BitField<0, 4, u8> faceline_wrinkle; + BitField<4, 4, u8> faceline_make; + } appearance_bits2; + u8 hair_type; + union { + u8 raw; + + BitField<0, 3, u8> hair_color; + BitField<3, 1, u8> hair_flip; + } appearance_bits3; + union { + u32 raw; + + BitField<0, 6, u32> eye_type; + BitField<6, 3, u32> eye_color; + BitField<9, 4, u32> eye_scale; + 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_type; + BitField<5, 3, u32> eyebrow_color; + BitField<8, 4, u32> eyebrow_scale; + 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; + } appearance_bits6; + union { + u16 raw; + + BitField<0, 6, u16> mouth_type; + BitField<6, 3, u16> mouth_color; + BitField<9, 4, u16> mouth_scale; + BitField<13, 3, u16> mouth_aspect; + } appearance_bits7; + union { + u8 raw; + + BitField<0, 5, u8> mouth_y; + BitField<5, 3, u8> mustache_type; + } appearance_bits8; + u8 allow_copying; + union { + u16 raw; + + BitField<0, 3, u16> beard_type; + BitField<3, 3, u16> beard_color; + BitField<6, 4, u16> mustache_scale; + BitField<10, 5, u16> mustache_y; + } appearance_bits9; + union { + u16 raw; + + 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_type; + BitField<1, 4, u16> mole_scale; + BitField<5, 5, u16> mole_x; + BitField<10, 5, u16> mole_y; + } appearance_bits11; + + Nickname author_name; + INSERT_PADDING_BYTES(0x2); + u16_be crc; +}; +static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size"); +#pragma pack(pop) + +}; // namespace Service::Mii |