summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/mii/mii_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp250
1 files changed, 238 insertions, 12 deletions
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 0a57c3cde..3a2fe938f 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstring>
#include <random>
@@ -12,13 +11,12 @@
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/mii/raw_data.h"
-#include "core/hle/service/mii/types.h"
namespace Service::Mii {
namespace {
-constexpr ResultCode ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
+constexpr Result ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
constexpr std::size_t BaseMiiCount{2};
constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
@@ -44,7 +42,7 @@ std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& i
return out;
}
-MiiInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
+CharInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
MiiStoreBitFields bf;
std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields));
@@ -292,7 +290,7 @@ MiiStoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Commo
u8 glasses_type{};
while (glasses_type_start < glasses_type_info.values[glasses_type]) {
if (++glasses_type >= glasses_type_info.values_count) {
- UNREACHABLE();
+ ASSERT(false);
break;
}
}
@@ -411,8 +409,8 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const {
return static_cast<u32>(count);
}
-ResultVal<MiiInfo> MiiManager::UpdateLatest([[maybe_unused]] const MiiInfo& info,
- SourceFlag source_flag) {
+ResultVal<CharInfo> MiiManager::UpdateLatest([[maybe_unused]] const CharInfo& info,
+ SourceFlag source_flag) {
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
return ERROR_CANNOT_FIND_ENTRY;
}
@@ -421,14 +419,242 @@ ResultVal<MiiInfo> MiiManager::UpdateLatest([[maybe_unused]] const MiiInfo& info
return ERROR_CANNOT_FIND_ENTRY;
}
-MiiInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) {
+CharInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) {
return ConvertStoreDataToInfo(BuildRandomStoreData(age, gender, race, user_id));
}
-MiiInfo MiiManager::BuildDefault(std::size_t index) {
+CharInfo MiiManager::BuildDefault(std::size_t index) {
return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::DefaultMii.at(index), user_id));
}
+CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const {
+ Service::Mii::MiiManager manager;
+ auto mii = manager.BuildDefault(0);
+
+ if (!ValidateV3Info(mii_v3)) {
+ return mii;
+ }
+
+ // TODO: We are ignoring a bunch of data from the mii_v3
+
+ mii.gender = static_cast<u8>(mii_v3.mii_information.gender);
+ mii.favorite_color = static_cast<u8>(mii_v3.mii_information.favorite_color);
+ mii.height = mii_v3.height;
+ mii.build = mii_v3.build;
+
+ // Copy name until string terminator
+ mii.name = {};
+ for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
+ mii.name[index] = mii_v3.mii_name[index];
+ if (mii.name[index] == 0) {
+ break;
+ }
+ }
+
+ mii.font_region = mii_v3.region_information.character_set;
+
+ mii.faceline_type = mii_v3.appearance_bits1.face_shape;
+ mii.faceline_color = mii_v3.appearance_bits1.skin_color;
+ mii.faceline_wrinkle = mii_v3.appearance_bits2.wrinkles;
+ mii.faceline_make = mii_v3.appearance_bits2.makeup;
+
+ mii.hair_type = mii_v3.hair_style;
+ mii.hair_color = mii_v3.appearance_bits3.hair_color;
+ mii.hair_flip = mii_v3.appearance_bits3.flip_hair;
+
+ mii.eye_type = static_cast<u8>(mii_v3.appearance_bits4.eye_type);
+ mii.eye_color = static_cast<u8>(mii_v3.appearance_bits4.eye_color);
+ mii.eye_scale = static_cast<u8>(mii_v3.appearance_bits4.eye_scale);
+ mii.eye_aspect = static_cast<u8>(mii_v3.appearance_bits4.eye_vertical_stretch);
+ mii.eye_rotate = static_cast<u8>(mii_v3.appearance_bits4.eye_rotation);
+ mii.eye_x = static_cast<u8>(mii_v3.appearance_bits4.eye_spacing);
+ mii.eye_y = static_cast<u8>(mii_v3.appearance_bits4.eye_y_position);
+
+ mii.eyebrow_type = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_style);
+ mii.eyebrow_color = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_color);
+ mii.eyebrow_scale = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_scale);
+ mii.eyebrow_aspect = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_yscale);
+ mii.eyebrow_rotate = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_rotation);
+ mii.eyebrow_x = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_spacing);
+ mii.eyebrow_y = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_y_position);
+
+ mii.nose_type = static_cast<u8>(mii_v3.appearance_bits6.nose_type);
+ mii.nose_scale = static_cast<u8>(mii_v3.appearance_bits6.nose_scale);
+ mii.nose_y = static_cast<u8>(mii_v3.appearance_bits6.nose_y_position);
+
+ mii.mouth_type = static_cast<u8>(mii_v3.appearance_bits7.mouth_type);
+ mii.mouth_color = static_cast<u8>(mii_v3.appearance_bits7.mouth_color);
+ mii.mouth_scale = static_cast<u8>(mii_v3.appearance_bits7.mouth_scale);
+ mii.mouth_aspect = static_cast<u8>(mii_v3.appearance_bits7.mouth_horizontal_stretch);
+ mii.mouth_y = static_cast<u8>(mii_v3.appearance_bits8.mouth_y_position);
+
+ mii.mustache_type = static_cast<u8>(mii_v3.appearance_bits8.mustache_type);
+ mii.mustache_scale = static_cast<u8>(mii_v3.appearance_bits9.mustache_scale);
+ mii.mustache_y = static_cast<u8>(mii_v3.appearance_bits9.mustache_y_position);
+
+ mii.beard_type = static_cast<u8>(mii_v3.appearance_bits9.bear_type);
+ mii.beard_color = static_cast<u8>(mii_v3.appearance_bits9.facial_hair_color);
+
+ mii.glasses_type = static_cast<u8>(mii_v3.appearance_bits10.glasses_type);
+ mii.glasses_color = static_cast<u8>(mii_v3.appearance_bits10.glasses_color);
+ mii.glasses_scale = static_cast<u8>(mii_v3.appearance_bits10.glasses_scale);
+ mii.glasses_y = static_cast<u8>(mii_v3.appearance_bits10.glasses_y_position);
+
+ mii.mole_type = static_cast<u8>(mii_v3.appearance_bits11.mole_enabled);
+ mii.mole_scale = static_cast<u8>(mii_v3.appearance_bits11.mole_scale);
+ mii.mole_x = static_cast<u8>(mii_v3.appearance_bits11.mole_x_position);
+ mii.mole_y = static_cast<u8>(mii_v3.appearance_bits11.mole_y_position);
+
+ // TODO: Validate mii data
+
+ return mii;
+}
+
+Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const {
+ Service::Mii::MiiManager manager;
+ Ver3StoreData mii_v3{};
+
+ // TODO: We are ignoring a bunch of data from the mii_v3
+
+ mii_v3.version = 1;
+ mii_v3.mii_information.gender.Assign(mii.gender);
+ mii_v3.mii_information.favorite_color.Assign(mii.favorite_color);
+ mii_v3.height = mii.height;
+ mii_v3.build = mii.build;
+
+ // Copy name until string terminator
+ mii_v3.mii_name = {};
+ for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
+ mii_v3.mii_name[index] = mii.name[index];
+ if (mii_v3.mii_name[index] == 0) {
+ break;
+ }
+ }
+
+ mii_v3.region_information.character_set.Assign(mii.font_region);
+
+ mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type);
+ mii_v3.appearance_bits1.skin_color.Assign(mii.faceline_color);
+ mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle);
+ mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make);
+
+ mii_v3.hair_style = mii.hair_type;
+ mii_v3.appearance_bits3.hair_color.Assign(mii.hair_color);
+ mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip);
+
+ mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type);
+ mii_v3.appearance_bits4.eye_color.Assign(mii.eye_color);
+ mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale);
+ mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect);
+ mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate);
+ mii_v3.appearance_bits4.eye_spacing.Assign(mii.eye_x);
+ mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y);
+
+ mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type);
+ mii_v3.appearance_bits5.eyebrow_color.Assign(mii.eyebrow_color);
+ mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale);
+ mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect);
+ mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate);
+ mii_v3.appearance_bits5.eyebrow_spacing.Assign(mii.eyebrow_x);
+ mii_v3.appearance_bits5.eyebrow_y_position.Assign(mii.eyebrow_y);
+
+ mii_v3.appearance_bits6.nose_type.Assign(mii.nose_type);
+ mii_v3.appearance_bits6.nose_scale.Assign(mii.nose_scale);
+ mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y);
+
+ mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type);
+ mii_v3.appearance_bits7.mouth_color.Assign(mii.mouth_color);
+ mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale);
+ mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect);
+ mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y);
+
+ mii_v3.appearance_bits8.mustache_type.Assign(mii.mustache_type);
+ mii_v3.appearance_bits9.mustache_scale.Assign(mii.mustache_scale);
+ mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y);
+
+ mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type);
+ mii_v3.appearance_bits9.facial_hair_color.Assign(mii.beard_color);
+
+ mii_v3.appearance_bits10.glasses_type.Assign(mii.glasses_type);
+ mii_v3.appearance_bits10.glasses_color.Assign(mii.glasses_color);
+ mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale);
+ mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y);
+
+ mii_v3.appearance_bits11.mole_enabled.Assign(mii.mole_type);
+ mii_v3.appearance_bits11.mole_scale.Assign(mii.mole_scale);
+ mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x);
+ mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y);
+
+ // TODO: Validate mii_v3 data
+
+ return mii_v3;
+}
+
+bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
+ bool is_valid = mii_v3.version == 0 || mii_v3.version == 3;
+
+ is_valid = is_valid && (mii_v3.mii_name[0] != 0);
+
+ is_valid = is_valid && (mii_v3.mii_information.birth_month < 13);
+ is_valid = is_valid && (mii_v3.mii_information.birth_day < 32);
+ is_valid = is_valid && (mii_v3.mii_information.favorite_color < 12);
+ is_valid = is_valid && (mii_v3.height < 128);
+ is_valid = is_valid && (mii_v3.build < 128);
+
+ is_valid = is_valid && (mii_v3.appearance_bits1.face_shape < 12);
+ is_valid = is_valid && (mii_v3.appearance_bits1.skin_color < 7);
+ is_valid = is_valid && (mii_v3.appearance_bits2.wrinkles < 12);
+ is_valid = is_valid && (mii_v3.appearance_bits2.makeup < 12);
+
+ is_valid = is_valid && (mii_v3.hair_style < 132);
+ is_valid = is_valid && (mii_v3.appearance_bits3.hair_color < 8);
+
+ is_valid = is_valid && (mii_v3.appearance_bits4.eye_type < 60);
+ is_valid = is_valid && (mii_v3.appearance_bits4.eye_color < 6);
+ is_valid = is_valid && (mii_v3.appearance_bits4.eye_scale < 8);
+ is_valid = is_valid && (mii_v3.appearance_bits4.eye_vertical_stretch < 7);
+ is_valid = is_valid && (mii_v3.appearance_bits4.eye_rotation < 8);
+ is_valid = is_valid && (mii_v3.appearance_bits4.eye_spacing < 13);
+ is_valid = is_valid && (mii_v3.appearance_bits4.eye_y_position < 19);
+
+ is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_style < 25);
+ is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_color < 8);
+ is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_scale < 9);
+ is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_yscale < 7);
+ is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_rotation < 12);
+ is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_spacing < 12);
+ is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_y_position < 19);
+
+ is_valid = is_valid && (mii_v3.appearance_bits6.nose_type < 18);
+ is_valid = is_valid && (mii_v3.appearance_bits6.nose_scale < 9);
+ is_valid = is_valid && (mii_v3.appearance_bits6.nose_y_position < 19);
+
+ is_valid = is_valid && (mii_v3.appearance_bits7.mouth_type < 36);
+ is_valid = is_valid && (mii_v3.appearance_bits7.mouth_color < 5);
+ is_valid = is_valid && (mii_v3.appearance_bits7.mouth_scale < 9);
+ is_valid = is_valid && (mii_v3.appearance_bits7.mouth_horizontal_stretch < 7);
+ is_valid = is_valid && (mii_v3.appearance_bits8.mouth_y_position < 19);
+
+ is_valid = is_valid && (mii_v3.appearance_bits8.mustache_type < 6);
+ is_valid = is_valid && (mii_v3.appearance_bits9.mustache_scale < 7);
+ is_valid = is_valid && (mii_v3.appearance_bits9.mustache_y_position < 17);
+
+ is_valid = is_valid && (mii_v3.appearance_bits9.bear_type < 6);
+ is_valid = is_valid && (mii_v3.appearance_bits9.facial_hair_color < 8);
+
+ is_valid = is_valid && (mii_v3.appearance_bits10.glasses_type < 9);
+ is_valid = is_valid && (mii_v3.appearance_bits10.glasses_color < 6);
+ is_valid = is_valid && (mii_v3.appearance_bits10.glasses_scale < 8);
+ is_valid = is_valid && (mii_v3.appearance_bits10.glasses_y_position < 21);
+
+ is_valid = is_valid && (mii_v3.appearance_bits11.mole_enabled < 2);
+ is_valid = is_valid && (mii_v3.appearance_bits11.mole_scale < 9);
+ is_valid = is_valid && (mii_v3.appearance_bits11.mole_x_position < 17);
+ is_valid = is_valid && (mii_v3.appearance_bits11.mole_y_position < 31);
+
+ return is_valid;
+}
+
ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) {
std::vector<MiiInfoElement> result;
@@ -443,7 +669,7 @@ ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_
return result;
}
-ResultCode MiiManager::GetIndex([[maybe_unused]] const MiiInfo& info, u32& index) {
+Result MiiManager::GetIndex([[maybe_unused]] const CharInfo& info, u32& index) {
constexpr u32 INVALID_INDEX{0xFFFFFFFF};
index = INVALID_INDEX;