mii: service: Address review

master
german77 2023-09-11 08:53:23 +07:00
parent bd169f417f
commit ec25f847d8
13 changed files with 135 additions and 104 deletions

@ -210,7 +210,7 @@ private:
LOG_DEBUG(Service_Mii, "called"); LOG_DEBUG(Service_Mii, "called");
s32 index{}; s32 index{};
const Result result = manager.GetIndex(metadata, info, index); const auto result = manager.GetIndex(metadata, info, index);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result); rb.Push(result);

@ -37,10 +37,10 @@ bool MiiManager::IsFullDatabase() const {
u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const { u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
u32 mii_count{}; u32 mii_count{};
if ((source_flag & SourceFlag::Default) == SourceFlag::None) { if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
mii_count += DefaultMiiCount; mii_count += DefaultMiiCount;
} }
if ((source_flag & SourceFlag::Database) == SourceFlag::None) { if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
// TODO(bunnei): We don't implement the Mii database, but when we do, update this // TODO(bunnei): We don't implement the Mii database, but when we do, update this
} }
return mii_count; return mii_count;
@ -153,7 +153,7 @@ Result MiiManager::BuildDefault(std::span<CharInfo> out_char_info, u32& out_coun
Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info, Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
s32& out_index) { s32& out_index) {
if (char_info.Verify() != 0) { if (char_info.Verify() != ValidationResult::NoErrors) {
return ResultInvalidCharInfo; return ResultInvalidCharInfo;
} }

@ -38,15 +38,6 @@ public:
s32& out_index); s32& out_index);
void SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version); void SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version);
struct MiiDatabase {
u32 magic{}; // 'NFDB'
std::array<StoreData, 0x64> miis{};
INSERT_PADDING_BYTES(1);
u8 count{};
u16 crc{};
};
static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
private: private:
Result BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count, Result BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
SourceFlag source_flag); SourceFlag source_flag);

@ -86,6 +86,61 @@ enum class SourceFlag : u32 {
}; };
DECLARE_ENUM_FLAG_OPERATORS(SourceFlag); DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
enum class ValidationResult : u32 {
NoErrors = 0x0,
InvalidBeardColor = 0x1,
InvalidBeardType = 0x2,
InvalidBuild = 0x3,
InvalidEyeAspect = 0x4,
InvalidEyeColor = 0x5,
InvalidEyeRotate = 0x6,
InvalidEyeScale = 0x7,
InvalidEyeType = 0x8,
InvalidEyeX = 0x9,
InvalidEyeY = 0xa,
InvalidEyebrowAspect = 0xb,
InvalidEyebrowColor = 0xc,
InvalidEyebrowRotate = 0xd,
InvalidEyebrowScale = 0xe,
InvalidEyebrowType = 0xf,
InvalidEyebrowX = 0x10,
InvalidEyebrowY = 0x11,
InvalidFacelineColor = 0x12,
InvalidFacelineMake = 0x13,
InvalidFacelineWrinkle = 0x14,
InvalidFacelineType = 0x15,
InvalidColor = 0x16,
InvalidFont = 0x17,
InvalidGender = 0x18,
InvalidGlassColor = 0x19,
InvalidGlassScale = 0x1a,
InvalidGlassType = 0x1b,
InvalidGlassY = 0x1c,
InvalidHairColor = 0x1d,
InvalidHairFlip = 0x1e,
InvalidHairType = 0x1f,
InvalidHeight = 0x20,
InvalidMoleScale = 0x21,
InvalidMoleType = 0x22,
InvalidMoleX = 0x23,
InvalidMoleY = 0x24,
InvalidMouthAspect = 0x25,
InvalidMouthColor = 0x26,
InvalidMouthScale = 0x27,
InvalidMouthType = 0x28,
InvalidMouthY = 0x29,
InvalidMustacheScale = 0x2a,
InvalidMustacheType = 0x2b,
InvalidMustacheY = 0x2c,
InvalidNoseScale = 0x2e,
InvalidNoseType = 0x2f,
InvalidNoseY = 0x30,
InvalidRegionMove = 0x31,
InvalidCreateId = 0x32,
InvalidName = 0x33,
InvalidType = 0x35,
};
struct Nickname { struct Nickname {
static constexpr std::size_t MaxNameSize = 10; static constexpr std::size_t MaxNameSize = 10;
std::array<char16_t, MaxNameSize> data; std::array<char16_t, MaxNameSize> data;
@ -163,7 +218,7 @@ struct DefaultMii {
u32 type{}; u32 type{};
Nickname nickname; Nickname nickname;
}; };
static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size."); static_assert(sizeof(DefaultMii) == 0xd8, "DefaultMii has incorrect size.");
struct DatabaseSessionMetadata { struct DatabaseSessionMetadata {
u32 interface_version; u32 interface_version;

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <random> #include <random>
#include <span>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h" #include "common/swap.h"
@ -51,7 +52,7 @@ public:
} }
static bool IsFontRegionValid(FontRegion font, std::span<const char16_t> text) { static bool IsFontRegionValid(FontRegion font, std::span<const char16_t> text) {
// Todo:: This function needs to check against the font tables // TODO: This function needs to check against the font tables
return true; return true;
} }
}; };

@ -62,161 +62,161 @@ void CharInfo::SetFromStoreData(const StoreData& store_data) {
padding = '\0'; padding = '\0';
} }
u32 CharInfo::Verify() const { ValidationResult CharInfo::Verify() const {
if (!create_id.IsValid()) { if (!create_id.IsValid()) {
return 0x32; return ValidationResult::InvalidCreateId;
} }
if (!name.IsValid()) { if (!name.IsValid()) {
return 0x33; return ValidationResult::InvalidName;
} }
if (3 < font_region) { if (3 < font_region) {
return 0x17; return ValidationResult::InvalidFont;
} }
if (0xb < favorite_color) { if (0xb < favorite_color) {
return 0x16; return ValidationResult::InvalidColor;
} }
if (1 < gender) { if (1 < gender) {
return 0x18; return ValidationResult::InvalidGender;
} }
if (height < 0) { if (height > 0x7f) {
return 0x20; return ValidationResult::InvalidHeight;
} }
if (build < 0) { if (build > 0x7f) {
return 3; return ValidationResult::InvalidBuild;
} }
if (1 < type) { if (1 < type) {
return 0x35; return ValidationResult::InvalidType;
} }
if (3 < region_move) { if (3 < region_move) {
return 0x31; return ValidationResult::InvalidRegionMove;
} }
if (0xb < faceline_type) { if (0xb < faceline_type) {
return 0x15; return ValidationResult::InvalidFacelineType;
} }
if (9 < faceline_color) { if (9 < faceline_color) {
return 0x12; return ValidationResult::InvalidFacelineColor;
} }
if (0xb < faceline_wrinkle) { if (0xb < faceline_wrinkle) {
return 0x14; return ValidationResult::InvalidFacelineWrinkle;
} }
if (0xb < faceline_make) { if (0xb < faceline_make) {
return 0x13; return ValidationResult::InvalidFacelineMake;
} }
if (0x83 < hair_type) { if (0x83 < hair_type) {
return 0x1f; return ValidationResult::InvalidHairType;
} }
if (99 < hair_color) { if (99 < hair_color) {
return 0x1d; return ValidationResult::InvalidHairColor;
} }
if (1 < hair_flip) { if (1 < hair_flip) {
return 0x1e; return ValidationResult::InvalidHairFlip;
} }
if (0x3b < eye_type) { if (0x3b < eye_type) {
return 8; return ValidationResult::InvalidEyeType;
} }
if (99 < eye_color) { if (99 < eye_color) {
return 5; return ValidationResult::InvalidEyeColor;
} }
if (7 < eye_scale) { if (7 < eye_scale) {
return 7; return ValidationResult::InvalidEyeScale;
} }
if (6 < eye_aspect) { if (6 < eye_aspect) {
return 4; return ValidationResult::InvalidEyeAspect;
} }
if (7 < eye_rotate) { if (7 < eye_rotate) {
return 6; return ValidationResult::InvalidEyeRotate;
} }
if (0xc < eye_x) { if (0xc < eye_x) {
return 9; return ValidationResult::InvalidEyeX;
} }
if (0x12 < eye_y) { if (0x12 < eye_y) {
return 10; return ValidationResult::InvalidEyeY;
} }
if (0x17 < eyebrow_type) { if (0x17 < eyebrow_type) {
return 0xf; return ValidationResult::InvalidEyebrowType;
} }
if (99 < eyebrow_color) { if (99 < eyebrow_color) {
return 0xc; return ValidationResult::InvalidEyebrowColor;
} }
if (8 < eyebrow_scale) { if (8 < eyebrow_scale) {
return 0xe; return ValidationResult::InvalidEyebrowScale;
} }
if (6 < eyebrow_aspect) { if (6 < eyebrow_aspect) {
return 0xb; return ValidationResult::InvalidEyebrowAspect;
} }
if (0xb < eyebrow_rotate) { if (0xb < eyebrow_rotate) {
return 0xd; return ValidationResult::InvalidEyebrowRotate;
} }
if (0xc < eyebrow_x) { if (0xc < eyebrow_x) {
return 0x10; return ValidationResult::InvalidEyebrowX;
} }
if (0xf < eyebrow_y - 3) { if (0xf < eyebrow_y - 3) {
return 0x11; return ValidationResult::InvalidEyebrowY;
} }
if (0x11 < nose_type) { if (0x11 < nose_type) {
return 0x2f; return ValidationResult::InvalidNoseType;
} }
if (nose_scale >= 9) { if (nose_scale >= 9) {
return 0x2e; return ValidationResult::InvalidNoseScale;
} }
if (0x12 < nose_y) { if (0x12 < nose_y) {
return 0x30; return ValidationResult::InvalidNoseY;
} }
if (0x23 < mouth_type) { if (0x23 < mouth_type) {
return 0x28; return ValidationResult::InvalidMouthType;
} }
if (99 < mouth_color) { if (99 < mouth_color) {
return 0x26; return ValidationResult::InvalidMouthColor;
} }
if (8 < mouth_scale) { if (8 < mouth_scale) {
return 0x27; return ValidationResult::InvalidMouthScale;
} }
if (6 < mouth_aspect) { if (6 < mouth_aspect) {
return 0x25; return ValidationResult::InvalidMouthAspect;
} }
if (0x12 < mouth_y) { if (0x12 < mouth_y) {
return 0x29; return ValidationResult::InvalidMoleY;
} }
if (99 < beard_color) { if (99 < beard_color) {
return 1; return ValidationResult::InvalidBeardColor;
} }
if (5 < beard_type) { if (5 < beard_type) {
return 2; return ValidationResult::InvalidBeardType;
} }
if (5 < mustache_type) { if (5 < mustache_type) {
return 0x2b; return ValidationResult::InvalidMustacheType;
} }
if (8 < mustache_scale) { if (8 < mustache_scale) {
return 0x2a; return ValidationResult::InvalidMustacheScale;
} }
if (0x10 < mustache_y) { if (0x10 < mustache_y) {
return 0x2c; return ValidationResult::InvalidMustacheY;
} }
if (0x13 < glasses_type) { if (0x13 < glasses_type) {
return 0x1b; return ValidationResult::InvalidGlassType;
} }
if (99 < glasses_color) { if (99 < glasses_color) {
return 0x19; return ValidationResult::InvalidGlassColor;
} }
if (7 < glasses_scale) { if (7 < glasses_scale) {
return 0x1a; return ValidationResult::InvalidGlassScale;
} }
if (0x14 < glasses_y) { if (0x14 < glasses_y) {
return 0x1c; return ValidationResult::InvalidGlassY;
} }
if (mole_type >= 2) { if (mole_type >= 2) {
return 0x22; return ValidationResult::InvalidMoleType;
} }
if (8 < mole_scale) { if (8 < mole_scale) {
return 0x21; return ValidationResult::InvalidMoleScale;
} }
if (mole_x >= 0x11) { if (mole_x >= 0x11) {
return 0x23; return ValidationResult::InvalidMoleX;
} }
if (0x1e < mole_y) { if (0x1e < mole_y) {
return 0x24; return ValidationResult::InvalidMoleY;
} }
return 0; return ValidationResult::NoErrors;
} }
Common::UUID CharInfo::GetCreateId() const { Common::UUID CharInfo::GetCreateId() const {
@ -424,7 +424,7 @@ u8 CharInfo::GetMoleY() const {
} }
bool CharInfo::operator==(const CharInfo& info) { bool CharInfo::operator==(const CharInfo& info) {
bool is_identical = info.Verify() == 0; bool is_identical = info.Verify() == ValidationResult::NoErrors;
is_identical &= name.data == info.GetNickname().data; is_identical &= name.data == info.GetNickname().data;
is_identical &= create_id == info.GetCreateId(); is_identical &= create_id == info.GetCreateId();
is_identical &= font_region == info.GetFontRegion(); is_identical &= font_region == info.GetFontRegion();

@ -13,7 +13,7 @@ class CharInfo {
public: public:
void SetFromStoreData(const StoreData& store_data_raw); void SetFromStoreData(const StoreData& store_data_raw);
u32 Verify() const; ValidationResult Verify() const;
Common::UUID GetCreateId() const; Common::UUID GetCreateId() const;
Nickname GetNickname() const; Nickname GetNickname() const;

@ -26,10 +26,10 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) {
data.build.Assign(64); data.build.Assign(64);
if (age == Age::All) { if (age == Age::All) {
const auto temp{MiiUtil::GetRandomValue<int>(10)}; const auto random{MiiUtil::GetRandomValue<int>(10)};
if (temp >= 8) { if (random >= 8) {
age = Age::Old; age = Age::Old;
} else if (temp >= 4) { } else if (random >= 4) {
age = Age::Normal; age = Age::Normal;
} else { } else {
age = Age::Young; age = Age::Young;
@ -37,10 +37,10 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) {
} }
if (race == Race::All) { if (race == Race::All) {
const auto temp{MiiUtil::GetRandomValue<int>(10)}; const auto random{MiiUtil::GetRandomValue<int>(10)};
if (temp >= 8) { if (random >= 8) {
race = Race::Black; race = Race::Black;
} else if (temp >= 4) { } else if (random >= 4) {
race = Race::White; race = Race::White;
} else { } else {
race = Race::Asian; race = Race::Asian;

@ -5,7 +5,7 @@
namespace Service::Mii::RawData { namespace Service::Mii::RawData {
constexpr std::array<u8, 0x10> FromVer3FacelineColorTable{ constexpr std::array<u8, 16> FromVer3FacelineColorTable{
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5,
}; };

@ -10,7 +10,7 @@
namespace Service::Mii::RawData { namespace Service::Mii::RawData {
struct RandomMiiValues { struct RandomMiiValues {
std::array<u8, 0xbc> values{}; std::array<u8, 188> values{};
}; };
static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size."); static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");

@ -33,16 +33,7 @@ void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const {
out_store_data.SetHeight(height); out_store_data.SetHeight(height);
out_store_data.SetBuild(build); out_store_data.SetBuild(build);
// Copy name until string terminator out_store_data.SetNickname(mii_name);
Nickname name = {};
for (std::size_t index = 0; index < name.data.size() - 1; index++) {
name.data[index] = mii_name[index];
if (name.data[index] == 0) {
break;
}
}
out_store_data.SetNickname(name);
out_store_data.SetFontRegion( out_store_data.SetFontRegion(
static_cast<FontRegion>(static_cast<u8>(region_information.font_region))); static_cast<FontRegion>(static_cast<u8>(region_information.font_region)));
@ -108,15 +99,7 @@ void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) {
height = store_data.GetHeight(); height = store_data.GetHeight();
build = store_data.GetBuild(); build = store_data.GetBuild();
// Copy name until string terminator mii_name = store_data.GetNickname();
mii_name = {};
for (std::size_t index = 0; index < store_data.GetNickname().data.size() - 1; index++) {
mii_name[index] = store_data.GetNickname().data[index];
if (mii_name[index] == 0) {
break;
}
}
region_information.font_region.Assign(static_cast<u8>(store_data.GetFontRegion())); region_information.font_region.Assign(static_cast<u8>(store_data.GetFontRegion()));
appearance_bits1.faceline_type.Assign(store_data.GetFacelineType()); appearance_bits1.faceline_type.Assign(store_data.GetFacelineType());
@ -183,7 +166,7 @@ void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) {
u32 Ver3StoreData::IsValid() const { u32 Ver3StoreData::IsValid() const {
bool is_valid = version == 0 || version == 3; bool is_valid = version == 0 || version == 3;
is_valid = is_valid && (mii_name[0] != 0); 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_month < 13);
is_valid = is_valid && (mii_information.birth_day < 32); is_valid = is_valid && (mii_information.birth_day < 32);

@ -47,7 +47,7 @@ public:
u16_be mii_id; u16_be mii_id;
u64_be system_id; u64_be system_id;
u32_be specialness_and_creation_date; u32_be specialness_and_creation_date;
std::array<u8, 0x6> creator_mac; std::array<u8, 6> creator_mac;
u16_be padding; u16_be padding;
union { union {
u16 raw; u16 raw;
@ -58,7 +58,7 @@ public:
BitField<10, 4, u16> favorite_color; BitField<10, 4, u16> favorite_color;
BitField<14, 1, u16> favorite; BitField<14, 1, u16> favorite;
} mii_information; } mii_information;
std::array<char16_t, 0xA> mii_name; Nickname mii_name;
u8 height; u8 height;
u8 build; u8 build;
union { union {
@ -150,7 +150,7 @@ public:
BitField<10, 5, u16> mole_y; BitField<10, 5, u16> mole_y;
} appearance_bits11; } appearance_bits11;
std::array<u16_le, 0xA> author_name; Nickname author_name;
INSERT_PADDING_BYTES(0x2); INSERT_PADDING_BYTES(0x2);
u16_be crc; u16_be crc;
}; };

@ -160,7 +160,8 @@ void QtAmiiboSettingsDialog::LoadAmiiboData() {
} }
const auto amiibo_name = std::string(register_info.amiibo_name.data()); const auto amiibo_name = std::string(register_info.amiibo_name.data());
const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data()); const auto owner_name =
Common::UTF16ToUTF8(register_info.mii_char_info.GetNickname().data.data());
const auto creation_date = const auto creation_date =
QDate(register_info.creation_date.year, register_info.creation_date.month, QDate(register_info.creation_date.year, register_info.creation_date.month,
register_info.creation_date.day); register_info.creation_date.day);