From 1e8616bd012c91764ed83a6eac3d8334e192af5f Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 17 Sep 2023 10:41:57 -0600 Subject: service: mii: Complete structs and fix mistakes --- src/core/hle/service/mii/mii_result.h | 9 +- src/core/hle/service/mii/mii_types.h | 7 +- src/core/hle/service/mii/types/char_info.cpp | 6 +- src/core/hle/service/mii/types/char_info.h | 106 +++++----- src/core/hle/service/mii/types/core_data.cpp | 213 ++++++++++++++++++++- src/core/hle/service/mii/types/core_data.h | 6 +- src/core/hle/service/mii/types/store_data.cpp | 83 +++++--- src/core/hle/service/mii/types/store_data.h | 17 +- src/core/hle/service/mii/types/ver3_store_data.cpp | 78 ++++---- 9 files changed, 387 insertions(+), 138 deletions(-) diff --git a/src/core/hle/service/mii/mii_result.h b/src/core/hle/service/mii/mii_result.h index 021cb76da..e2c36e556 100644 --- a/src/core/hle/service/mii/mii_result.h +++ b/src/core/hle/service/mii/mii_result.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -13,8 +13,15 @@ constexpr Result ResultNotUpdated{ErrorModule::Mii, 3}; constexpr Result ResultNotFound{ErrorModule::Mii, 4}; constexpr Result ResultDatabaseFull{ErrorModule::Mii, 5}; constexpr Result ResultInvalidCharInfo{ErrorModule::Mii, 100}; +constexpr Result ResultInvalidDatabaseChecksum{ErrorModule::Mii, 101}; +constexpr Result ResultInvalidDatabaseSignature{ErrorModule::Mii, 103}; +constexpr Result ResultInvalidDatabaseVersion{ErrorModule::Mii, 104}; +constexpr Result ResultInvalidDatabaseLength{ErrorModule::Mii, 105}; +constexpr Result ResultInvalidCharInfo2{ErrorModule::Mii, 107}; constexpr Result ResultInvalidStoreData{ErrorModule::Mii, 109}; constexpr Result ResultInvalidOperation{ErrorModule::Mii, 202}; constexpr Result ResultPermissionDenied{ErrorModule::Mii, 203}; +constexpr Result ResultTestModeOnly{ErrorModule::Mii, 204}; +constexpr Result ResultInvalidCharInfoType{ErrorModule::Mii, 205}; }; // namespace Service::Mii diff --git a/src/core/hle/service/mii/mii_types.h b/src/core/hle/service/mii/mii_types.h index 611ff4f81..9efe6c915 100644 --- a/src/core/hle/service/mii/mii_types.h +++ b/src/core/hle/service/mii/mii_types.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -26,14 +26,14 @@ constexpr u8 MaxEyebrowScale = 8; constexpr u8 MaxEyebrowAspect = 6; constexpr u8 MaxEyebrowRotate = 11; constexpr u8 MaxEyebrowX = 12; -constexpr u8 MaxEyebrowY = 18; +constexpr u8 MaxEyebrowY = 15; constexpr u8 MaxNoseScale = 8; constexpr u8 MaxNoseY = 18; constexpr u8 MaxMouthScale = 8; constexpr u8 MaxMoutAspect = 6; constexpr u8 MaxMouthY = 18; constexpr u8 MaxMustacheScale = 8; -constexpr u8 MasMustacheY = 16; +constexpr u8 MaxMustacheY = 16; constexpr u8 MaxGlassScale = 7; constexpr u8 MaxGlassY = 20; constexpr u8 MaxMoleScale = 8; @@ -599,6 +599,7 @@ enum class ValidationResult : u32 { InvalidRegionMove = 0x31, InvalidCreateId = 0x32, InvalidName = 0x33, + InvalidChecksum = 0x34, InvalidType = 0x35, }; diff --git a/src/core/hle/service/mii/types/char_info.cpp b/src/core/hle/service/mii/types/char_info.cpp index bb948c628..e90124af4 100644 --- a/src/core/hle/service/mii/types/char_info.cpp +++ b/src/core/hle/service/mii/types/char_info.cpp @@ -37,7 +37,7 @@ void CharInfo::SetFromStoreData(const StoreData& store_data) { eyebrow_aspect = store_data.GetEyebrowAspect(); eyebrow_rotate = store_data.GetEyebrowRotate(); eyebrow_x = store_data.GetEyebrowX(); - eyebrow_y = store_data.GetEyebrowY(); + eyebrow_y = store_data.GetEyebrowY() + 3; nose_type = store_data.GetNoseType(); nose_scale = store_data.GetNoseScale(); nose_y = store_data.GetNoseY(); @@ -150,7 +150,7 @@ ValidationResult CharInfo::Verify() const { if (eyebrow_x > MaxEyebrowX) { return ValidationResult::InvalidEyebrowX; } - if (eyebrow_y > MaxEyebrowY) { + if (eyebrow_y - 3 > MaxEyebrowY) { return ValidationResult::InvalidEyebrowY; } if (nose_type > NoseType::Max) { @@ -189,7 +189,7 @@ ValidationResult CharInfo::Verify() const { if (mustache_scale > MaxMustacheScale) { return ValidationResult::InvalidMustacheScale; } - if (mustache_y > MasMustacheY) { + if (mustache_y > MaxMustacheY) { return ValidationResult::InvalidMustacheY; } if (glass_type > GlassType::Max) { diff --git a/src/core/hle/service/mii/types/char_info.h b/src/core/hle/service/mii/types/char_info.h index d069b221f..d0c457fd5 100644 --- a/src/core/hle/service/mii/types/char_info.h +++ b/src/core/hle/service/mii/types/char_info.h @@ -70,59 +70,59 @@ public: 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; + 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, diff --git a/src/core/hle/service/mii/types/core_data.cpp b/src/core/hle/service/mii/types/core_data.cpp index 659288b51..465c6293a 100644 --- a/src/core/hle/service/mii/types/core_data.cpp +++ b/src/core/hle/service/mii/types/core_data.cpp @@ -3,6 +3,7 @@ #include "common/assert.h" #include "core/hle/service/mii/mii_util.h" +#include "core/hle/service/mii/types/char_info.h" #include "core/hle/service/mii/types/core_data.h" #include "core/hle/service/mii/types/raw_data.h" @@ -185,9 +186,211 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) { SetMoleY(20); } -u32 CoreData::IsValid() const { - // TODO: Complete this - return 0; +void CoreData::BuildFromCharInfo(const CharInfo& char_info) { + name = char_info.GetNickname(); + SetFontRegion(char_info.GetFontRegion()); + SetFavoriteColor(char_info.GetFavoriteColor()); + SetGender(char_info.GetGender()); + SetHeight(char_info.GetHeight()); + SetBuild(char_info.GetBuild()); + SetType(char_info.GetType()); + SetRegionMove(char_info.GetRegionMove()); + SetFacelineType(char_info.GetFacelineType()); + SetFacelineColor(char_info.GetFacelineColor()); + SetFacelineWrinkle(char_info.GetFacelineWrinkle()); + SetFacelineMake(char_info.GetFacelineMake()); + SetHairType(char_info.GetHairType()); + SetHairColor(char_info.GetHairColor()); + SetHairFlip(char_info.GetHairFlip()); + SetEyeType(char_info.GetEyeType()); + SetEyeColor(char_info.GetEyeColor()); + SetEyeScale(char_info.GetEyeScale()); + SetEyeAspect(char_info.GetEyeAspect()); + SetEyeRotate(char_info.GetEyeRotate()); + SetEyeX(char_info.GetEyeX()); + SetEyeY(char_info.GetEyeY()); + SetEyebrowType(char_info.GetEyebrowType()); + SetEyebrowColor(char_info.GetEyebrowColor()); + SetEyebrowScale(char_info.GetEyebrowScale()); + SetEyebrowAspect(char_info.GetEyebrowAspect()); + SetEyebrowRotate(char_info.GetEyebrowRotate()); + SetEyebrowX(char_info.GetEyebrowX()); + SetEyebrowY(char_info.GetEyebrowY() - 3); + SetNoseType(char_info.GetNoseType()); + SetNoseScale(char_info.GetNoseScale()); + SetNoseY(char_info.GetNoseY()); + SetMouthType(char_info.GetMouthType()); + SetMouthColor(char_info.GetMouthColor()); + SetMouthScale(char_info.GetMouthScale()); + SetMouthAspect(char_info.GetMouthAspect()); + SetMouthY(char_info.GetMouthY()); + SetBeardColor(char_info.GetBeardColor()); + SetBeardType(char_info.GetBeardType()); + SetMustacheType(char_info.GetMustacheType()); + SetMustacheScale(char_info.GetMustacheScale()); + SetMustacheY(char_info.GetMustacheY()); + SetGlassType(char_info.GetGlassType()); + SetGlassColor(char_info.GetGlassColor()); + SetGlassScale(char_info.GetGlassScale()); + SetGlassY(char_info.GetGlassY()); + SetMoleType(char_info.GetMoleType()); + SetMoleScale(char_info.GetMoleScale()); + SetMoleX(char_info.GetMoleX()); + SetMoleY(char_info.GetMoleY()); +} + +ValidationResult CoreData::IsValid() const { + if (!name.IsValid()) { + return ValidationResult::InvalidName; + } + if (GetFontRegion() > FontRegion::Max) { + return ValidationResult::InvalidFont; + } + if (GetFavoriteColor() > FavoriteColor::Max) { + return ValidationResult::InvalidColor; + } + if (GetGender() > Gender::Max) { + return ValidationResult::InvalidGender; + } + if (GetHeight() > MaxHeight) { + return ValidationResult::InvalidHeight; + } + if (GetBuild() > MaxBuild) { + return ValidationResult::InvalidBuild; + } + if (GetType() > MaxType) { + return ValidationResult::InvalidType; + } + if (GetRegionMove() > MaxRegionMove) { + return ValidationResult::InvalidRegionMove; + } + if (GetFacelineType() > FacelineType::Max) { + return ValidationResult::InvalidFacelineType; + } + if (GetFacelineColor() > FacelineColor::Max) { + return ValidationResult::InvalidFacelineColor; + } + if (GetFacelineWrinkle() > FacelineWrinkle::Max) { + return ValidationResult::InvalidFacelineWrinkle; + } + if (GetFacelineMake() > FacelineMake::Max) { + return ValidationResult::InvalidFacelineMake; + } + if (GetHairType() > HairType::Max) { + return ValidationResult::InvalidHairType; + } + if (GetHairColor() > CommonColor::Max) { + return ValidationResult::InvalidHairColor; + } + if (GetHairFlip() > HairFlip::Max) { + return ValidationResult::InvalidHairFlip; + } + if (GetEyeType() > EyeType::Max) { + return ValidationResult::InvalidEyeType; + } + if (GetEyeColor() > CommonColor::Max) { + return ValidationResult::InvalidEyeColor; + } + if (GetEyeScale() > MaxEyeScale) { + return ValidationResult::InvalidEyeScale; + } + if (GetEyeAspect() > MaxEyeAspect) { + return ValidationResult::InvalidEyeAspect; + } + if (GetEyeRotate() > MaxEyeRotate) { + return ValidationResult::InvalidEyeRotate; + } + if (GetEyeX() > MaxEyeX) { + return ValidationResult::InvalidEyeX; + } + if (GetEyeY() > MaxEyeY) { + return ValidationResult::InvalidEyeY; + } + if (GetEyebrowType() > EyebrowType::Max) { + return ValidationResult::InvalidEyebrowType; + } + if (GetEyebrowColor() > CommonColor::Max) { + return ValidationResult::InvalidEyebrowColor; + } + if (GetEyebrowScale() > MaxEyebrowScale) { + return ValidationResult::InvalidEyebrowScale; + } + if (GetEyebrowAspect() > MaxEyebrowAspect) { + return ValidationResult::InvalidEyebrowAspect; + } + if (GetEyebrowRotate() > MaxEyebrowRotate) { + return ValidationResult::InvalidEyebrowRotate; + } + if (GetEyebrowX() > MaxEyebrowX) { + return ValidationResult::InvalidEyebrowX; + } + if (GetEyebrowY() > MaxEyebrowY) { + return ValidationResult::InvalidEyebrowY; + } + if (GetNoseType() > NoseType::Max) { + return ValidationResult::InvalidNoseType; + } + if (GetNoseScale() > MaxNoseScale) { + return ValidationResult::InvalidNoseScale; + } + if (GetNoseY() > MaxNoseY) { + return ValidationResult::InvalidNoseY; + } + if (GetMouthType() > MouthType::Max) { + return ValidationResult::InvalidMouthType; + } + if (GetMouthColor() > CommonColor::Max) { + return ValidationResult::InvalidMouthColor; + } + if (GetMouthScale() > MaxMouthScale) { + return ValidationResult::InvalidMouthScale; + } + if (GetMouthAspect() > MaxMoutAspect) { + return ValidationResult::InvalidMouthAspect; + } + if (GetMouthY() > MaxMouthY) { + return ValidationResult::InvalidMouthY; + } + if (GetBeardColor() > CommonColor::Max) { + return ValidationResult::InvalidBeardColor; + } + if (GetBeardType() > BeardType::Max) { + return ValidationResult::InvalidBeardType; + } + if (GetMustacheType() > MustacheType::Max) { + return ValidationResult::InvalidMustacheType; + } + if (GetMustacheScale() > MaxMustacheScale) { + return ValidationResult::InvalidMustacheScale; + } + if (GetMustacheY() > MaxMustacheY) { + return ValidationResult::InvalidMustacheY; + } + if (GetGlassType() > GlassType::Max) { + return ValidationResult::InvalidGlassType; + } + if (GetGlassColor() > CommonColor::Max) { + return ValidationResult::InvalidGlassColor; + } + if (GetGlassScale() > MaxGlassScale) { + return ValidationResult::InvalidGlassScale; + } + if (GetGlassY() > MaxGlassY) { + return ValidationResult::InvalidGlassY; + } + if (GetMoleType() > MoleType::Max) { + return ValidationResult::InvalidMoleType; + } + if (GetMoleScale() > MaxMoleScale) { + return ValidationResult::InvalidMoleScale; + } + if (GetMoleX() > MaxMoleX) { + return ValidationResult::InvalidMoleX; + } + if (GetMoleY() > MaxMoleY) { + return ValidationResult::InvalidMoleY; + } + return ValidationResult::NoErrors; } void CoreData::SetFontRegion(FontRegion value) { @@ -314,8 +517,8 @@ void CoreData::SetNoseY(u8 value) { data.nose_y.Assign(value); } -void CoreData::SetMouthType(u8 value) { - data.mouth_type.Assign(value); +void CoreData::SetMouthType(MouthType value) { + data.mouth_type.Assign(static_cast(value)); } void CoreData::SetMouthColor(CommonColor value) { diff --git a/src/core/hle/service/mii/types/core_data.h b/src/core/hle/service/mii/types/core_data.h index cebcd2ee4..e6398f68f 100644 --- a/src/core/hle/service/mii/types/core_data.h +++ b/src/core/hle/service/mii/types/core_data.h @@ -6,6 +6,7 @@ #include "core/hle/service/mii/mii_types.h" namespace Service::Mii { +class CharInfo; struct StoreDataBitFields { union { @@ -100,8 +101,9 @@ class CoreData { public: void SetDefault(); void BuildRandom(Age age, Gender gender, Race race); + void BuildFromCharInfo(const CharInfo& char_info); - u32 IsValid() const; + ValidationResult IsValid() const; void SetFontRegion(FontRegion value); void SetFavoriteColor(FavoriteColor value); @@ -134,7 +136,7 @@ public: void SetNoseType(NoseType value); void SetNoseScale(u8 value); void SetNoseY(u8 value); - void SetMouthType(u8 value); + void SetMouthType(MouthType value); void SetMouthColor(CommonColor value); void SetMouthScale(u8 value); void SetMouthAspect(u8 value); diff --git a/src/core/hle/service/mii/types/store_data.cpp b/src/core/hle/service/mii/types/store_data.cpp index 8fce636c7..127221fdb 100644 --- a/src/core/hle/service/mii/types/store_data.cpp +++ b/src/core/hle/service/mii/types/store_data.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/mii/mii_result.h" #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" @@ -35,13 +36,13 @@ void StoreData::BuildDefault(u32 mii_index) { core_data.SetEyebrowAspect(static_cast(default_mii.eyebrow_aspect)); core_data.SetEyebrowRotate(static_cast(default_mii.eyebrow_rotate)); core_data.SetEyebrowX(static_cast(default_mii.eyebrow_x)); - core_data.SetEyebrowY(static_cast(default_mii.eyebrow_y)); + core_data.SetEyebrowY(static_cast(default_mii.eyebrow_y - 3)); core_data.SetNoseType(static_cast(default_mii.nose_type)); core_data.SetNoseScale(static_cast(default_mii.nose_scale)); core_data.SetNoseY(static_cast(default_mii.nose_y)); - core_data.SetMouthType(static_cast(default_mii.mouth_type)); + core_data.SetMouthType(static_cast(default_mii.mouth_type)); core_data.SetMouthColor( RawData::GetMouthColorFromVer3(static_cast(default_mii.mouth_color))); core_data.SetMouthScale(static_cast(default_mii.mouth_scale)); @@ -75,10 +76,8 @@ void StoreData::BuildDefault(u32 mii_index) { core_data.SetType(static_cast(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)); + SetChecksum(); } void StoreData::BuildBase(Gender gender) { @@ -109,13 +108,13 @@ void StoreData::BuildBase(Gender gender) { core_data.SetEyebrowAspect(static_cast(default_mii.eyebrow_aspect)); core_data.SetEyebrowRotate(static_cast(default_mii.eyebrow_rotate)); core_data.SetEyebrowX(static_cast(default_mii.eyebrow_x)); - core_data.SetEyebrowY(static_cast(default_mii.eyebrow_y)); + core_data.SetEyebrowY(static_cast(default_mii.eyebrow_y - 3)); core_data.SetNoseType(static_cast(default_mii.nose_type)); core_data.SetNoseScale(static_cast(default_mii.nose_scale)); core_data.SetNoseY(static_cast(default_mii.nose_y)); - core_data.SetMouthType(static_cast(default_mii.mouth_type)); + core_data.SetMouthType(static_cast(default_mii.mouth_type)); core_data.SetMouthColor( RawData::GetMouthColorFromVer3(static_cast(default_mii.mouth_color))); core_data.SetMouthScale(static_cast(default_mii.mouth_scale)); @@ -149,37 +148,51 @@ void StoreData::BuildBase(Gender gender) { core_data.SetType(static_cast(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)); + SetChecksum(); } 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)); + SetChecksum(); } -void StoreData::SetInvalidName() { - const auto& invalid_name = core_data.GetInvalidNickname(); +void StoreData::BuildWithCharInfo(const CharInfo& char_info) { + core_data.BuildFromCharInfo(char_info); + create_id = MiiUtil::MakeCreateId(); + SetChecksum(); +} + +void StoreData::BuildWithCoreData(const CoreData& in_core_data) { + core_data = in_core_data; + create_id = MiiUtil::MakeCreateId(); + SetChecksum(); +} + +Result StoreData::Restore() { + // TODO: Implement this + return ResultNotUpdated; +} + +ValidationResult StoreData::IsValid() const { + if (core_data.IsValid() != ValidationResult::NoErrors) { + return core_data.IsValid(); + } + if (data_crc != MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData) + sizeof(Common::UUID))) { + return ValidationResult::InvalidChecksum; + } 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)); + if (device_crc != MiiUtil::CalculateDeviceCrc16(device_id, sizeof(StoreData))) { + return ValidationResult::InvalidChecksum; + } + return ValidationResult::NoErrors; } 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); } @@ -304,7 +317,7 @@ void StoreData::SetNoseY(u8 value) { core_data.SetNoseY(value); } -void StoreData::SetMouthType(u8 value) { +void StoreData::SetMouthType(MouthType value) { core_data.SetMouthType(value); } @@ -380,6 +393,26 @@ void StoreData::SetNickname(Nickname value) { core_data.SetNickname(value); } +void StoreData::SetInvalidName() { + const auto& invalid_name = core_data.GetInvalidNickname(); + core_data.SetNickname(invalid_name); + SetChecksum(); +} + +void StoreData::SetChecksum() { + SetDataChecksum(); + SetDeviceChecksum(); +} + +void StoreData::SetDataChecksum() { + data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData) + sizeof(Common::UUID)); +} + +void StoreData::SetDeviceChecksum() { + const auto device_id = MiiUtil::GetDeviceId(); + device_crc = MiiUtil::CalculateDeviceCrc16(device_id, sizeof(StoreData)); +} + Common::UUID StoreData::GetCreateId() const { return create_id; } @@ -585,7 +618,7 @@ Nickname StoreData::GetNickname() const { } bool StoreData::operator==(const StoreData& data) { - bool is_identical = data.core_data.IsValid() == 0; + bool is_identical = data.core_data.IsValid() == ValidationResult::NoErrors; is_identical &= core_data.GetNickname().data == data.core_data.GetNickname().data; is_identical &= GetCreateId() == data.GetCreateId(); is_identical &= GetFontRegion() == data.GetFontRegion(); diff --git a/src/core/hle/service/mii/types/store_data.h b/src/core/hle/service/mii/types/store_data.h index 224c32cf8..38f534d26 100644 --- a/src/core/hle/service/mii/types/store_data.h +++ b/src/core/hle/service/mii/types/store_data.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/result.h" #include "core/hle/service/mii/mii_types.h" #include "core/hle/service/mii/types/core_data.h" @@ -10,17 +11,16 @@ 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); + void BuildWithCharInfo(const CharInfo& char_info); + void BuildWithCoreData(const CoreData& in_core_data); + Result Restore(); - bool IsSpecial() const; + ValidationResult IsValid() const; - u32 IsValid() const; + bool IsSpecial() const; void SetFontRegion(FontRegion value); void SetFavoriteColor(FavoriteColor value); @@ -53,7 +53,7 @@ public: void SetNoseType(NoseType value); void SetNoseScale(u8 value); void SetNoseY(u8 value); - void SetMouthType(u8 value); + void SetMouthType(MouthType value); void SetMouthColor(CommonColor value); void SetMouthScale(u8 value); void SetMouthAspect(u8 value); @@ -73,6 +73,9 @@ public: void SetMoleY(u8 value); void SetNickname(Nickname nickname); void SetInvalidName(); + void SetChecksum(); + void SetDataChecksum(); + void SetDeviceChecksum(); Common::UUID GetCreateId() const; FontRegion GetFontRegion() const; diff --git a/src/core/hle/service/mii/types/ver3_store_data.cpp b/src/core/hle/service/mii/types/ver3_store_data.cpp index 1c28e0b1b..a019cc9f7 100644 --- a/src/core/hle/service/mii/types/ver3_store_data.cpp +++ b/src/core/hle/service/mii/types/ver3_store_data.cpp @@ -22,12 +22,6 @@ void NfpStoreDataExtension::SetFromStoreData(const StoreData& store_data) { 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(mii_information.gender.Value())); out_store_data.SetFavoriteColor( static_cast(mii_information.favorite_color.Value())); @@ -36,65 +30,71 @@ void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const { out_store_data.SetNickname(mii_name); out_store_data.SetFontRegion( - static_cast(static_cast(region_information.font_region))); + static_cast(static_cast(region_information.font_region.Value()))); out_store_data.SetFacelineType( static_cast(appearance_bits1.faceline_type.Value())); out_store_data.SetFacelineColor( - static_cast(appearance_bits1.faceline_color.Value())); + RawData::GetFacelineColorFromVer3(appearance_bits1.faceline_color.Value())); out_store_data.SetFacelineWrinkle( static_cast(appearance_bits2.faceline_wrinkle.Value())); out_store_data.SetFacelineMake( static_cast(appearance_bits2.faceline_make.Value())); out_store_data.SetHairType(static_cast(hair_type)); - out_store_data.SetHairColor(static_cast(appearance_bits3.hair_color.Value())); + out_store_data.SetHairColor(RawData::GetHairColorFromVer3(appearance_bits3.hair_color.Value())); out_store_data.SetHairFlip(static_cast(appearance_bits3.hair_flip.Value())); out_store_data.SetEyeType(static_cast(appearance_bits4.eye_type.Value())); - out_store_data.SetEyeColor(static_cast(appearance_bits4.eye_color.Value())); - out_store_data.SetEyeScale(static_cast(appearance_bits4.eye_scale)); - out_store_data.SetEyeAspect(static_cast(appearance_bits4.eye_aspect)); - out_store_data.SetEyeRotate(static_cast(appearance_bits4.eye_rotate)); - out_store_data.SetEyeX(static_cast(appearance_bits4.eye_x)); - out_store_data.SetEyeY(static_cast(appearance_bits4.eye_y)); + out_store_data.SetEyeColor(RawData::GetEyeColorFromVer3(appearance_bits4.eye_color.Value())); + out_store_data.SetEyeScale(static_cast(appearance_bits4.eye_scale.Value())); + out_store_data.SetEyeAspect(static_cast(appearance_bits4.eye_aspect.Value())); + out_store_data.SetEyeRotate(static_cast(appearance_bits4.eye_rotate.Value())); + out_store_data.SetEyeX(static_cast(appearance_bits4.eye_x.Value())); + out_store_data.SetEyeY(static_cast(appearance_bits4.eye_y.Value())); out_store_data.SetEyebrowType(static_cast(appearance_bits5.eyebrow_type.Value())); out_store_data.SetEyebrowColor( - static_cast(appearance_bits5.eyebrow_color.Value())); - out_store_data.SetEyebrowScale(static_cast(appearance_bits5.eyebrow_scale)); - out_store_data.SetEyebrowAspect(static_cast(appearance_bits5.eyebrow_aspect)); - out_store_data.SetEyebrowRotate(static_cast(appearance_bits5.eyebrow_rotate)); - out_store_data.SetEyebrowX(static_cast(appearance_bits5.eyebrow_x)); - out_store_data.SetEyebrowY(static_cast(appearance_bits5.eyebrow_y)); + RawData::GetHairColorFromVer3(appearance_bits5.eyebrow_color.Value())); + out_store_data.SetEyebrowScale(static_cast(appearance_bits5.eyebrow_scale.Value())); + out_store_data.SetEyebrowAspect(static_cast(appearance_bits5.eyebrow_aspect.Value())); + out_store_data.SetEyebrowRotate(static_cast(appearance_bits5.eyebrow_rotate.Value())); + out_store_data.SetEyebrowX(static_cast(appearance_bits5.eyebrow_x.Value())); + out_store_data.SetEyebrowY(static_cast(appearance_bits5.eyebrow_y.Value() - 3)); out_store_data.SetNoseType(static_cast(appearance_bits6.nose_type.Value())); - out_store_data.SetNoseScale(static_cast(appearance_bits6.nose_scale)); - out_store_data.SetNoseY(static_cast(appearance_bits6.nose_y)); + out_store_data.SetNoseScale(static_cast(appearance_bits6.nose_scale.Value())); + out_store_data.SetNoseY(static_cast(appearance_bits6.nose_y.Value())); - out_store_data.SetMouthType(static_cast(appearance_bits7.mouth_type)); - out_store_data.SetMouthColor(static_cast(appearance_bits7.mouth_color.Value())); - out_store_data.SetMouthScale(static_cast(appearance_bits7.mouth_scale)); - out_store_data.SetMouthAspect(static_cast(appearance_bits7.mouth_aspect)); - out_store_data.SetMouthY(static_cast(appearance_bits8.mouth_y)); + out_store_data.SetMouthType(static_cast(appearance_bits7.mouth_type.Value())); + out_store_data.SetMouthColor( + RawData::GetMouthColorFromVer3(appearance_bits7.mouth_color.Value())); + out_store_data.SetMouthScale(static_cast(appearance_bits7.mouth_scale.Value())); + out_store_data.SetMouthAspect(static_cast(appearance_bits7.mouth_aspect.Value())); + out_store_data.SetMouthY(static_cast(appearance_bits8.mouth_y.Value())); out_store_data.SetMustacheType( static_cast(appearance_bits8.mustache_type.Value())); - out_store_data.SetMustacheScale(static_cast(appearance_bits9.mustache_scale)); - out_store_data.SetMustacheY(static_cast(appearance_bits9.mustache_y)); + out_store_data.SetMustacheScale(static_cast(appearance_bits9.mustache_scale.Value())); + out_store_data.SetMustacheY(static_cast(appearance_bits9.mustache_y.Value())); out_store_data.SetBeardType(static_cast(appearance_bits9.beard_type.Value())); - out_store_data.SetBeardColor(static_cast(appearance_bits9.beard_color.Value())); + out_store_data.SetBeardColor( + RawData::GetHairColorFromVer3(appearance_bits9.beard_color.Value())); + // Glass type is compatible as it is. It doesn't need a table out_store_data.SetGlassType(static_cast(appearance_bits10.glass_type.Value())); - out_store_data.SetGlassColor(static_cast(appearance_bits10.glass_color.Value())); - out_store_data.SetGlassScale(static_cast(appearance_bits10.glass_scale)); - out_store_data.SetGlassY(static_cast(appearance_bits10.glass_y)); + out_store_data.SetGlassColor( + RawData::GetGlassColorFromVer3(appearance_bits10.glass_color.Value())); + out_store_data.SetGlassScale(static_cast(appearance_bits10.glass_scale.Value())); + out_store_data.SetGlassY(static_cast(appearance_bits10.glass_y.Value())); out_store_data.SetMoleType(static_cast(appearance_bits11.mole_type.Value())); - out_store_data.SetMoleScale(static_cast(appearance_bits11.mole_scale)); - out_store_data.SetMoleX(static_cast(appearance_bits11.mole_x)); - out_store_data.SetMoleY(static_cast(appearance_bits11.mole_y)); + out_store_data.SetMoleScale(static_cast(appearance_bits11.mole_scale.Value())); + out_store_data.SetMoleX(static_cast(appearance_bits11.mole_x.Value())); + out_store_data.SetMoleY(static_cast(appearance_bits11.mole_y.Value())); + + out_store_data.SetChecksum(); } void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { @@ -220,7 +220,7 @@ u32 Ver3StoreData::IsValid() const { is_valid = is_valid && (appearance_bits8.mustache_type <= static_cast(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.mustache_y <= MaxMustacheY); is_valid = is_valid && (appearance_bits9.beard_type <= static_cast(BeardType::Max)); is_valid = is_valid && (appearance_bits9.beard_color <= MaxVer3CommonColor); @@ -228,7 +228,7 @@ u32 Ver3StoreData::IsValid() const { 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_bits10.glass_y <= MaxGlassY); is_valid = is_valid && (appearance_bits11.mole_type <= static_cast(MoleType::Max)); is_valid = is_valid && (appearance_bits11.mole_scale <= MaxMoleScale); -- cgit v1.2.3