summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar liamwhite2023-09-13 09:39:16 -0400
committerGravatar GitHub2023-09-13 09:39:16 -0400
commit5b5c69b8f61fbcff2ac72441857750068d585816 (patch)
tree071d9db0793abfa5e7cf2f1544d81a10f66596d3 /src
parentMerge pull request #11473 from liamwhite/fix-launch-param (diff)
parentservice: mii: Remove most magic values (diff)
downloadyuzu-5b5c69b8f61fbcff2ac72441857750068d585816.tar.gz
yuzu-5b5c69b8f61fbcff2ac72441857750068d585816.tar.xz
yuzu-5b5c69b8f61fbcff2ac72441857750068d585816.zip
Merge pull request #11480 from german77/mii_service
service: mii: Update implementation Part1
Diffstat (limited to '')
-rw-r--r--src/core/CMakeLists.txt16
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp11
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit_types.h3
-rw-r--r--src/core/hle/service/mii/mii.cpp139
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp717
-rw-r--r--src/core/hle/service/mii/mii_manager.h43
-rw-r--r--src/core/hle/service/mii/mii_result.h20
-rw-r--r--src/core/hle/service/mii/mii_types.h694
-rw-r--r--src/core/hle/service/mii/mii_util.h59
-rw-r--r--src/core/hle/service/mii/raw_data.h27
-rw-r--r--src/core/hle/service/mii/types.h553
-rw-r--r--src/core/hle/service/mii/types/char_info.cpp482
-rw-r--r--src/core/hle/service/mii/types/char_info.h137
-rw-r--r--src/core/hle/service/mii/types/core_data.cpp601
-rw-r--r--src/core/hle/service/mii/types/core_data.h216
-rw-r--r--src/core/hle/service/mii/types/raw_data.cpp (renamed from src/core/hle/service/mii/raw_data.cpp)1395
-rw-r--r--src/core/hle/service/mii/types/raw_data.h73
-rw-r--r--src/core/hle/service/mii/types/store_data.cpp643
-rw-r--r--src/core/hle/service/mii/types/store_data.h145
-rw-r--r--src/core/hle/service/mii/types/ver3_store_data.cpp241
-rw-r--r--src/core/hle/service/mii/types/ver3_store_data.h160
-rw-r--r--src/core/hle/service/nfc/common/device.cpp25
-rw-r--r--src/core/hle/service/nfp/nfp_types.h6
-rw-r--r--src/yuzu/applets/qt_amiibo_settings.cpp3
24 files changed, 4466 insertions, 1943 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 012648d69..c33910ade 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -584,13 +584,23 @@ add_library(core STATIC
584 hle/service/lm/lm.h 584 hle/service/lm/lm.h
585 hle/service/mig/mig.cpp 585 hle/service/mig/mig.cpp
586 hle/service/mig/mig.h 586 hle/service/mig/mig.h
587 hle/service/mii/types/char_info.cpp
588 hle/service/mii/types/char_info.h
589 hle/service/mii/types/core_data.cpp
590 hle/service/mii/types/core_data.h
591 hle/service/mii/types/raw_data.cpp
592 hle/service/mii/types/raw_data.h
593 hle/service/mii/types/store_data.cpp
594 hle/service/mii/types/store_data.h
595 hle/service/mii/types/ver3_store_data.cpp
596 hle/service/mii/types/ver3_store_data.h
587 hle/service/mii/mii.cpp 597 hle/service/mii/mii.cpp
588 hle/service/mii/mii.h 598 hle/service/mii/mii.h
589 hle/service/mii/mii_manager.cpp 599 hle/service/mii/mii_manager.cpp
590 hle/service/mii/mii_manager.h 600 hle/service/mii/mii_manager.h
591 hle/service/mii/raw_data.cpp 601 hle/service/mii/mii_result.h
592 hle/service/mii/raw_data.h 602 hle/service/mii/mii_types.h
593 hle/service/mii/types.h 603 hle/service/mii/mii_util.h
594 hle/service/mm/mm_u.cpp 604 hle/service/mm/mm_u.cpp
595 hle/service/mm/mm_u.h 605 hle/service/mm/mm_u.h
596 hle/service/mnpp/mnpp_app.cpp 606 hle/service/mnpp/mnpp_app.cpp
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
index f8e2bac32..350a90818 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -85,15 +85,18 @@ void MiiEdit::Execute() {
85 break; 85 break;
86 case MiiEditAppletMode::CreateMii: 86 case MiiEditAppletMode::CreateMii:
87 case MiiEditAppletMode::EditMii: { 87 case MiiEditAppletMode::EditMii: {
88 Service::Mii::MiiManager mii_manager; 88 Mii::CharInfo char_info{};
89 Mii::StoreData store_data{};
90 store_data.BuildBase(Mii::Gender::Male);
91 char_info.SetFromStoreData(store_data);
89 92
90 const MiiEditCharInfo char_info{ 93 const MiiEditCharInfo edit_char_info{
91 .mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii 94 .mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
92 ? applet_input_v4.char_info.mii_info 95 ? applet_input_v4.char_info.mii_info
93 : mii_manager.BuildBase(Mii::Gender::Male)}, 96 : char_info},
94 }; 97 };
95 98
96 MiiEditOutputForCharInfoEditing(MiiEditResult::Success, char_info); 99 MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info);
97 break; 100 break;
98 } 101 }
99 default: 102 default:
diff --git a/src/core/hle/service/am/applets/applet_mii_edit_types.h b/src/core/hle/service/am/applets/applet_mii_edit_types.h
index 4705d019f..f3d764073 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit_types.h
+++ b/src/core/hle/service/am/applets/applet_mii_edit_types.h
@@ -7,7 +7,8 @@
7 7
8#include "common/common_funcs.h" 8#include "common/common_funcs.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/hle/service/mii/types.h" 10#include "common/uuid.h"
11#include "core/hle/service/mii/types/char_info.h"
11 12
12namespace Service::AM::Applets { 13namespace Service::AM::Applets {
13 14
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index 65c11a2f3..3b83c5ed7 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -7,17 +7,16 @@
7#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
8#include "core/hle/service/mii/mii.h" 8#include "core/hle/service/mii/mii.h"
9#include "core/hle/service/mii/mii_manager.h" 9#include "core/hle/service/mii/mii_manager.h"
10#include "core/hle/service/mii/mii_result.h"
10#include "core/hle/service/server_manager.h" 11#include "core/hle/service/server_manager.h"
11#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
12 13
13namespace Service::Mii { 14namespace Service::Mii {
14 15
15constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1};
16
17class IDatabaseService final : public ServiceFramework<IDatabaseService> { 16class IDatabaseService final : public ServiceFramework<IDatabaseService> {
18public: 17public:
19 explicit IDatabaseService(Core::System& system_) 18 explicit IDatabaseService(Core::System& system_, bool is_system_)
20 : ServiceFramework{system_, "IDatabaseService"} { 19 : ServiceFramework{system_, "IDatabaseService"}, is_system{is_system_} {
21 // clang-format off 20 // clang-format off
22 static const FunctionInfo functions[] = { 21 static const FunctionInfo functions[] = {
23 {0, &IDatabaseService::IsUpdated, "IsUpdated"}, 22 {0, &IDatabaseService::IsUpdated, "IsUpdated"},
@@ -54,34 +53,27 @@ public:
54 } 53 }
55 54
56private: 55private:
57 template <typename T>
58 std::vector<u8> SerializeArray(const std::vector<T>& values) {
59 std::vector<u8> out(values.size() * sizeof(T));
60 std::size_t offset{};
61 for (const auto& value : values) {
62 std::memcpy(out.data() + offset, &value, sizeof(T));
63 offset += sizeof(T);
64 }
65 return out;
66 }
67
68 void IsUpdated(HLERequestContext& ctx) { 56 void IsUpdated(HLERequestContext& ctx) {
69 IPC::RequestParser rp{ctx}; 57 IPC::RequestParser rp{ctx};
70 const auto source_flag{rp.PopRaw<SourceFlag>()}; 58 const auto source_flag{rp.PopRaw<SourceFlag>()};
71 59
72 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); 60 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
73 61
62 const bool is_updated = manager.IsUpdated(metadata, source_flag);
63
74 IPC::ResponseBuilder rb{ctx, 3}; 64 IPC::ResponseBuilder rb{ctx, 3};
75 rb.Push(ResultSuccess); 65 rb.Push(ResultSuccess);
76 rb.Push(manager.CheckAndResetUpdateCounter(source_flag, current_update_counter)); 66 rb.Push<u8>(is_updated);
77 } 67 }
78 68
79 void IsFullDatabase(HLERequestContext& ctx) { 69 void IsFullDatabase(HLERequestContext& ctx) {
80 LOG_DEBUG(Service_Mii, "called"); 70 LOG_DEBUG(Service_Mii, "called");
81 71
72 const bool is_full_database = manager.IsFullDatabase();
73
82 IPC::ResponseBuilder rb{ctx, 3}; 74 IPC::ResponseBuilder rb{ctx, 3};
83 rb.Push(ResultSuccess); 75 rb.Push(ResultSuccess);
84 rb.Push(manager.IsFullDatabase()); 76 rb.Push<u8>(is_full_database);
85 } 77 }
86 78
87 void GetCount(HLERequestContext& ctx) { 79 void GetCount(HLERequestContext& ctx) {
@@ -90,57 +82,63 @@ private:
90 82
91 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); 83 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
92 84
85 const u32 mii_count = manager.GetCount(metadata, source_flag);
86
93 IPC::ResponseBuilder rb{ctx, 3}; 87 IPC::ResponseBuilder rb{ctx, 3};
94 rb.Push(ResultSuccess); 88 rb.Push(ResultSuccess);
95 rb.Push<u32>(manager.GetCount(source_flag)); 89 rb.Push(mii_count);
96 } 90 }
97 91
98 void Get(HLERequestContext& ctx) { 92 void Get(HLERequestContext& ctx) {
99 IPC::RequestParser rp{ctx}; 93 IPC::RequestParser rp{ctx};
100 const auto source_flag{rp.PopRaw<SourceFlag>()}; 94 const auto source_flag{rp.PopRaw<SourceFlag>()};
95 const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()};
101 96
102 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); 97 LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
98
99 u32 mii_count{};
100 std::vector<CharInfoElement> char_info_elements(output_size);
101 Result result = manager.Get(metadata, char_info_elements, mii_count, source_flag);
103 102
104 const auto default_miis{manager.GetDefault(source_flag)}; 103 if (mii_count != 0) {
105 if (default_miis.size() > 0) { 104 ctx.WriteBuffer(char_info_elements);
106 ctx.WriteBuffer(SerializeArray(default_miis));
107 } 105 }
108 106
109 IPC::ResponseBuilder rb{ctx, 3}; 107 IPC::ResponseBuilder rb{ctx, 3};
110 rb.Push(ResultSuccess); 108 rb.Push(result);
111 rb.Push<u32>(static_cast<u32>(default_miis.size())); 109 rb.Push(mii_count);
112 } 110 }
113 111
114 void Get1(HLERequestContext& ctx) { 112 void Get1(HLERequestContext& ctx) {
115 IPC::RequestParser rp{ctx}; 113 IPC::RequestParser rp{ctx};
116 const auto source_flag{rp.PopRaw<SourceFlag>()}; 114 const auto source_flag{rp.PopRaw<SourceFlag>()};
115 const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()};
117 116
118 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); 117 LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
119 118
120 const auto default_miis{manager.GetDefault(source_flag)}; 119 u32 mii_count{};
120 std::vector<CharInfo> char_info(output_size);
121 Result result = manager.Get(metadata, char_info, mii_count, source_flag);
121 122
122 std::vector<CharInfo> values; 123 if (mii_count != 0) {
123 for (const auto& element : default_miis) { 124 ctx.WriteBuffer(char_info);
124 values.emplace_back(element.info);
125 } 125 }
126 126
127 ctx.WriteBuffer(SerializeArray(values));
128
129 IPC::ResponseBuilder rb{ctx, 3}; 127 IPC::ResponseBuilder rb{ctx, 3};
130 rb.Push(ResultSuccess); 128 rb.Push(result);
131 rb.Push<u32>(static_cast<u32>(default_miis.size())); 129 rb.Push(mii_count);
132 } 130 }
133 131
134 void UpdateLatest(HLERequestContext& ctx) { 132 void UpdateLatest(HLERequestContext& ctx) {
135 IPC::RequestParser rp{ctx}; 133 IPC::RequestParser rp{ctx};
136 const auto info{rp.PopRaw<CharInfo>()}; 134 const auto char_info{rp.PopRaw<CharInfo>()};
137 const auto source_flag{rp.PopRaw<SourceFlag>()}; 135 const auto source_flag{rp.PopRaw<SourceFlag>()};
138 136
139 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); 137 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
140 138
141 CharInfo new_char_info{}; 139 CharInfo new_char_info{};
142 const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)}; 140 const auto result = manager.UpdateLatest(metadata, new_char_info, char_info, source_flag);
143 if (result != ResultSuccess) { 141 if (result.IsFailure()) {
144 IPC::ResponseBuilder rb{ctx, 2}; 142 IPC::ResponseBuilder rb{ctx, 2};
145 rb.Push(result); 143 rb.Push(result);
146 return; 144 return;
@@ -153,7 +151,6 @@ private:
153 151
154 void BuildRandom(HLERequestContext& ctx) { 152 void BuildRandom(HLERequestContext& ctx) {
155 IPC::RequestParser rp{ctx}; 153 IPC::RequestParser rp{ctx};
156
157 const auto age{rp.PopRaw<Age>()}; 154 const auto age{rp.PopRaw<Age>()};
158 const auto gender{rp.PopRaw<Gender>()}; 155 const auto gender{rp.PopRaw<Gender>()};
159 const auto race{rp.PopRaw<Race>()}; 156 const auto race{rp.PopRaw<Race>()};
@@ -162,47 +159,48 @@ private:
162 159
163 if (age > Age::All) { 160 if (age > Age::All) {
164 IPC::ResponseBuilder rb{ctx, 2}; 161 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(ERROR_INVALID_ARGUMENT); 162 rb.Push(ResultInvalidArgument);
166 LOG_ERROR(Service_Mii, "invalid age={}", age);
167 return; 163 return;
168 } 164 }
169 165
170 if (gender > Gender::All) { 166 if (gender > Gender::All) {
171 IPC::ResponseBuilder rb{ctx, 2}; 167 IPC::ResponseBuilder rb{ctx, 2};
172 rb.Push(ERROR_INVALID_ARGUMENT); 168 rb.Push(ResultInvalidArgument);
173 LOG_ERROR(Service_Mii, "invalid gender={}", gender);
174 return; 169 return;
175 } 170 }
176 171
177 if (race > Race::All) { 172 if (race > Race::All) {
178 IPC::ResponseBuilder rb{ctx, 2}; 173 IPC::ResponseBuilder rb{ctx, 2};
179 rb.Push(ERROR_INVALID_ARGUMENT); 174 rb.Push(ResultInvalidArgument);
180 LOG_ERROR(Service_Mii, "invalid race={}", race);
181 return; 175 return;
182 } 176 }
183 177
178 CharInfo char_info{};
179 manager.BuildRandom(char_info, age, gender, race);
180
184 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; 181 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
185 rb.Push(ResultSuccess); 182 rb.Push(ResultSuccess);
186 rb.PushRaw<CharInfo>(manager.BuildRandom(age, gender, race)); 183 rb.PushRaw<CharInfo>(char_info);
187 } 184 }
188 185
189 void BuildDefault(HLERequestContext& ctx) { 186 void BuildDefault(HLERequestContext& ctx) {
190 IPC::RequestParser rp{ctx}; 187 IPC::RequestParser rp{ctx};
191 const auto index{rp.Pop<u32>()}; 188 const auto index{rp.Pop<u32>()};
192 189
193 LOG_DEBUG(Service_Mii, "called with index={}", index); 190 LOG_INFO(Service_Mii, "called with index={}", index);
194 191
195 if (index > 5) { 192 if (index > 5) {
196 LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}",
197 index);
198 IPC::ResponseBuilder rb{ctx, 2}; 193 IPC::ResponseBuilder rb{ctx, 2};
199 rb.Push(ERROR_INVALID_ARGUMENT); 194 rb.Push(ResultInvalidArgument);
200 return; 195 return;
201 } 196 }
202 197
198 CharInfo char_info{};
199 manager.BuildDefault(char_info, index);
200
203 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; 201 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
204 rb.Push(ResultSuccess); 202 rb.Push(ResultSuccess);
205 rb.PushRaw<CharInfo>(manager.BuildDefault(index)); 203 rb.PushRaw<CharInfo>(char_info);
206 } 204 }
207 205
208 void GetIndex(HLERequestContext& ctx) { 206 void GetIndex(HLERequestContext& ctx) {
@@ -211,19 +209,21 @@ private:
211 209
212 LOG_DEBUG(Service_Mii, "called"); 210 LOG_DEBUG(Service_Mii, "called");
213 211
214 u32 index{}; 212 s32 index{};
213 const auto result = manager.GetIndex(metadata, info, index);
214
215 IPC::ResponseBuilder rb{ctx, 3}; 215 IPC::ResponseBuilder rb{ctx, 3};
216 rb.Push(manager.GetIndex(info, index)); 216 rb.Push(result);
217 rb.Push(index); 217 rb.Push(index);
218 } 218 }
219 219
220 void SetInterfaceVersion(HLERequestContext& ctx) { 220 void SetInterfaceVersion(HLERequestContext& ctx) {
221 IPC::RequestParser rp{ctx}; 221 IPC::RequestParser rp{ctx};
222 current_interface_version = rp.PopRaw<u32>(); 222 const auto interface_version{rp.PopRaw<u32>()};
223 223
224 LOG_DEBUG(Service_Mii, "called, interface_version={:08X}", current_interface_version); 224 LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
225 225
226 UNIMPLEMENTED_IF(current_interface_version != 1); 226 manager.SetInterfaceVersion(metadata, interface_version);
227 227
228 IPC::ResponseBuilder rb{ctx, 2}; 228 IPC::ResponseBuilder rb{ctx, 2};
229 rb.Push(ResultSuccess); 229 rb.Push(ResultSuccess);
@@ -231,30 +231,27 @@ private:
231 231
232 void Convert(HLERequestContext& ctx) { 232 void Convert(HLERequestContext& ctx) {
233 IPC::RequestParser rp{ctx}; 233 IPC::RequestParser rp{ctx};
234
235 const auto mii_v3{rp.PopRaw<Ver3StoreData>()}; 234 const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
236 235
237 LOG_INFO(Service_Mii, "called"); 236 LOG_INFO(Service_Mii, "called");
238 237
238 CharInfo char_info{};
239 manager.ConvertV3ToCharInfo(char_info, mii_v3);
240
239 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; 241 IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
240 rb.Push(ResultSuccess); 242 rb.Push(ResultSuccess);
241 rb.PushRaw<CharInfo>(manager.ConvertV3ToCharInfo(mii_v3)); 243 rb.PushRaw<CharInfo>(char_info);
242 }
243
244 constexpr bool IsInterfaceVersionSupported(u32 interface_version) const {
245 return current_interface_version >= interface_version;
246 } 244 }
247 245
248 MiiManager manager; 246 MiiManager manager{};
249 247 DatabaseSessionMetadata metadata{};
250 u32 current_interface_version{}; 248 bool is_system{};
251 u64 current_update_counter{};
252}; 249};
253 250
254class MiiDBModule final : public ServiceFramework<MiiDBModule> { 251class MiiDBModule final : public ServiceFramework<MiiDBModule> {
255public: 252public:
256 explicit MiiDBModule(Core::System& system_, const char* name_) 253 explicit MiiDBModule(Core::System& system_, const char* name_, bool is_system_)
257 : ServiceFramework{system_, name_} { 254 : ServiceFramework{system_, name_}, is_system{is_system_} {
258 // clang-format off 255 // clang-format off
259 static const FunctionInfo functions[] = { 256 static const FunctionInfo functions[] = {
260 {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, 257 {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
@@ -268,10 +265,12 @@ private:
268 void GetDatabaseService(HLERequestContext& ctx) { 265 void GetDatabaseService(HLERequestContext& ctx) {
269 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 266 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
270 rb.Push(ResultSuccess); 267 rb.Push(ResultSuccess);
271 rb.PushIpcInterface<IDatabaseService>(system); 268 rb.PushIpcInterface<IDatabaseService>(system, is_system);
272 269
273 LOG_DEBUG(Service_Mii, "called"); 270 LOG_DEBUG(Service_Mii, "called");
274 } 271 }
272
273 bool is_system{};
275}; 274};
276 275
277class MiiImg final : public ServiceFramework<MiiImg> { 276class MiiImg final : public ServiceFramework<MiiImg> {
@@ -303,8 +302,10 @@ public:
303void LoopProcess(Core::System& system) { 302void LoopProcess(Core::System& system) {
304 auto server_manager = std::make_unique<ServerManager>(system); 303 auto server_manager = std::make_unique<ServerManager>(system);
305 304
306 server_manager->RegisterNamedService("mii:e", std::make_shared<MiiDBModule>(system, "mii:e")); 305 server_manager->RegisterNamedService("mii:e",
307 server_manager->RegisterNamedService("mii:u", std::make_shared<MiiDBModule>(system, "mii:u")); 306 std::make_shared<MiiDBModule>(system, "mii:e", true));
307 server_manager->RegisterNamedService("mii:u",
308 std::make_shared<MiiDBModule>(system, "mii:u", false));
308 server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system)); 309 server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
309 ServerManager::RunServer(std::move(server_manager)); 310 ServerManager::RunServer(std::move(server_manager));
310} 311}
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index dd632df50..292d63777 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -10,385 +10,24 @@
10 10
11#include "core/hle/service/acc/profile_manager.h" 11#include "core/hle/service/acc/profile_manager.h"
12#include "core/hle/service/mii/mii_manager.h" 12#include "core/hle/service/mii/mii_manager.h"
13#include "core/hle/service/mii/raw_data.h" 13#include "core/hle/service/mii/mii_result.h"
14#include "core/hle/service/mii/mii_util.h"
15#include "core/hle/service/mii/types/core_data.h"
16#include "core/hle/service/mii/types/raw_data.h"
14 17
15namespace Service::Mii { 18namespace Service::Mii {
16
17namespace {
18
19constexpr Result ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
20
21constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()}; 19constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
22 20
23constexpr MiiStoreData::Name DefaultMiiName{u'n', u'o', u' ', u'n', u'a', u'm', u'e'}; 21MiiManager::MiiManager() {}
24constexpr std::array<u8, 8> HairColorLookup{8, 1, 2, 3, 4, 5, 6, 7};
25constexpr std::array<u8, 6> EyeColorLookup{8, 9, 10, 11, 12, 13};
26constexpr std::array<u8, 5> MouthColorLookup{19, 20, 21, 22, 23};
27constexpr std::array<u8, 7> GlassesColorLookup{8, 14, 15, 16, 17, 18, 0};
28constexpr std::array<u8, 62> EyeRotateLookup{
29 {0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
30 0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
31 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
32 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04}};
33constexpr std::array<u8, 24> EyebrowRotateLookup{{0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07,
34 0x04, 0x07, 0x06, 0x08, 0x05, 0x05, 0x06, 0x06,
35 0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05}};
36
37template <typename T, std::size_t SourceArraySize, std::size_t DestArraySize>
38std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& in) {
39 std::array<T, DestArraySize> out{};
40 std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize));
41 return out;
42}
43
44CharInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
45 MiiStoreBitFields bf;
46 std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields));
47
48 return {
49 .uuid = data.data.uuid,
50 .name = ResizeArray<char16_t, 10, 11>(data.data.name),
51 .font_region = static_cast<u8>(bf.font_region.Value()),
52 .favorite_color = static_cast<u8>(bf.favorite_color.Value()),
53 .gender = static_cast<u8>(bf.gender.Value()),
54 .height = static_cast<u8>(bf.height.Value()),
55 .build = static_cast<u8>(bf.build.Value()),
56 .type = static_cast<u8>(bf.type.Value()),
57 .region_move = static_cast<u8>(bf.region_move.Value()),
58 .faceline_type = static_cast<u8>(bf.faceline_type.Value()),
59 .faceline_color = static_cast<u8>(bf.faceline_color.Value()),
60 .faceline_wrinkle = static_cast<u8>(bf.faceline_wrinkle.Value()),
61 .faceline_make = static_cast<u8>(bf.faceline_makeup.Value()),
62 .hair_type = static_cast<u8>(bf.hair_type.Value()),
63 .hair_color = static_cast<u8>(bf.hair_color.Value()),
64 .hair_flip = static_cast<u8>(bf.hair_flip.Value()),
65 .eye_type = static_cast<u8>(bf.eye_type.Value()),
66 .eye_color = static_cast<u8>(bf.eye_color.Value()),
67 .eye_scale = static_cast<u8>(bf.eye_scale.Value()),
68 .eye_aspect = static_cast<u8>(bf.eye_aspect.Value()),
69 .eye_rotate = static_cast<u8>(bf.eye_rotate.Value()),
70 .eye_x = static_cast<u8>(bf.eye_x.Value()),
71 .eye_y = static_cast<u8>(bf.eye_y.Value()),
72 .eyebrow_type = static_cast<u8>(bf.eyebrow_type.Value()),
73 .eyebrow_color = static_cast<u8>(bf.eyebrow_color.Value()),
74 .eyebrow_scale = static_cast<u8>(bf.eyebrow_scale.Value()),
75 .eyebrow_aspect = static_cast<u8>(bf.eyebrow_aspect.Value()),
76 .eyebrow_rotate = static_cast<u8>(bf.eyebrow_rotate.Value()),
77 .eyebrow_x = static_cast<u8>(bf.eyebrow_x.Value()),
78 .eyebrow_y = static_cast<u8>(bf.eyebrow_y.Value() + 3),
79 .nose_type = static_cast<u8>(bf.nose_type.Value()),
80 .nose_scale = static_cast<u8>(bf.nose_scale.Value()),
81 .nose_y = static_cast<u8>(bf.nose_y.Value()),
82 .mouth_type = static_cast<u8>(bf.mouth_type.Value()),
83 .mouth_color = static_cast<u8>(bf.mouth_color.Value()),
84 .mouth_scale = static_cast<u8>(bf.mouth_scale.Value()),
85 .mouth_aspect = static_cast<u8>(bf.mouth_aspect.Value()),
86 .mouth_y = static_cast<u8>(bf.mouth_y.Value()),
87 .beard_color = static_cast<u8>(bf.beard_color.Value()),
88 .beard_type = static_cast<u8>(bf.beard_type.Value()),
89 .mustache_type = static_cast<u8>(bf.mustache_type.Value()),
90 .mustache_scale = static_cast<u8>(bf.mustache_scale.Value()),
91 .mustache_y = static_cast<u8>(bf.mustache_y.Value()),
92 .glasses_type = static_cast<u8>(bf.glasses_type.Value()),
93 .glasses_color = static_cast<u8>(bf.glasses_color.Value()),
94 .glasses_scale = static_cast<u8>(bf.glasses_scale.Value()),
95 .glasses_y = static_cast<u8>(bf.glasses_y.Value()),
96 .mole_type = static_cast<u8>(bf.mole_type.Value()),
97 .mole_scale = static_cast<u8>(bf.mole_scale.Value()),
98 .mole_x = static_cast<u8>(bf.mole_x.Value()),
99 .mole_y = static_cast<u8>(bf.mole_y.Value()),
100 .padding = 0,
101 };
102}
103
104u16 GenerateCrc16(const void* data, std::size_t size) {
105 s32 crc{};
106 for (std::size_t i = 0; i < size; i++) {
107 crc ^= static_cast<const u8*>(data)[i] << 8;
108 for (std::size_t j = 0; j < 8; j++) {
109 crc <<= 1;
110 if ((crc & 0x10000) != 0) {
111 crc = (crc ^ 0x1021) & 0xFFFF;
112 }
113 }
114 }
115 return Common::swap16(static_cast<u16>(crc));
116}
117
118template <typename T>
119T GetRandomValue(T min, T max) {
120 std::random_device device;
121 std::mt19937 gen(device());
122 std::uniform_int_distribution<u64> distribution(static_cast<u64>(min), static_cast<u64>(max));
123 return static_cast<T>(distribution(gen));
124}
125
126template <typename T>
127T GetRandomValue(T max) {
128 return GetRandomValue<T>({}, max);
129}
130
131MiiStoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Common::UUID& user_id) {
132 MiiStoreBitFields bf{};
133
134 if (gender == Gender::All) {
135 gender = GetRandomValue<Gender>(Gender::Maximum);
136 }
137
138 bf.gender.Assign(gender);
139 bf.favorite_color.Assign(GetRandomValue<u8>(11));
140 bf.region_move.Assign(0);
141 bf.font_region.Assign(FontRegion::Standard);
142 bf.type.Assign(0);
143 bf.height.Assign(64);
144 bf.build.Assign(64);
145
146 if (age == Age::All) {
147 const auto temp{GetRandomValue<int>(10)};
148 if (temp >= 8) {
149 age = Age::Old;
150 } else if (temp >= 4) {
151 age = Age::Normal;
152 } else {
153 age = Age::Young;
154 }
155 }
156
157 if (race == Race::All) {
158 const auto temp{GetRandomValue<int>(10)};
159 if (temp >= 8) {
160 race = Race::Black;
161 } else if (temp >= 4) {
162 race = Race::White;
163 } else {
164 race = Race::Asian;
165 }
166 }
167
168 u32 axis_y{};
169 if (gender == Gender::Female && age == Age::Young) {
170 axis_y = GetRandomValue<u32>(3);
171 }
172
173 const std::size_t index{3 * static_cast<std::size_t>(age) +
174 9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
175
176 const auto faceline_type_info{RawData::RandomMiiFaceline.at(index)};
177 const auto faceline_color_info{RawData::RandomMiiFacelineColor.at(
178 3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
179 const auto faceline_wrinkle_info{RawData::RandomMiiFacelineWrinkle.at(index)};
180 const auto faceline_makeup_info{RawData::RandomMiiFacelineMakeup.at(index)};
181 const auto hair_type_info{RawData::RandomMiiHairType.at(index)};
182 const auto hair_color_info{RawData::RandomMiiHairColor.at(3 * static_cast<std::size_t>(race) +
183 static_cast<std::size_t>(age))};
184 const auto eye_type_info{RawData::RandomMiiEyeType.at(index)};
185 const auto eye_color_info{RawData::RandomMiiEyeColor.at(static_cast<std::size_t>(race))};
186 const auto eyebrow_type_info{RawData::RandomMiiEyebrowType.at(index)};
187 const auto nose_type_info{RawData::RandomMiiNoseType.at(index)};
188 const auto mouth_type_info{RawData::RandomMiiMouthType.at(index)};
189 const auto glasses_type_info{RawData::RandomMiiGlassType.at(static_cast<std::size_t>(age))};
190
191 bf.faceline_type.Assign(
192 faceline_type_info.values[GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
193 bf.faceline_color.Assign(
194 faceline_color_info.values[GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
195 bf.faceline_wrinkle.Assign(
196 faceline_wrinkle_info
197 .values[GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
198 bf.faceline_makeup.Assign(
199 faceline_makeup_info
200 .values[GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
201
202 bf.hair_type.Assign(
203 hair_type_info.values[GetRandomValue<std::size_t>(hair_type_info.values_count)]);
204 bf.hair_color.Assign(
205 HairColorLookup[hair_color_info
206 .values[GetRandomValue<std::size_t>(hair_color_info.values_count)]]);
207 bf.hair_flip.Assign(GetRandomValue<HairFlip>(HairFlip::Maximum));
208
209 bf.eye_type.Assign(
210 eye_type_info.values[GetRandomValue<std::size_t>(eye_type_info.values_count)]);
211
212 const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
213 const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
214 const auto eye_rotate_offset{32 - EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
215 const auto eye_rotate{32 - EyeRotateLookup[bf.eye_type]};
216
217 bf.eye_color.Assign(
218 EyeColorLookup[eye_color_info
219 .values[GetRandomValue<std::size_t>(eye_color_info.values_count)]]);
220 bf.eye_scale.Assign(4);
221 bf.eye_aspect.Assign(3);
222 bf.eye_rotate.Assign(eye_rotate_offset - eye_rotate);
223 bf.eye_x.Assign(2);
224 bf.eye_y.Assign(axis_y + 12);
225
226 bf.eyebrow_type.Assign(
227 eyebrow_type_info.values[GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
228
229 const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
230 const auto eyebrow_y{race == Race::Asian ? 9 : 10};
231 const auto eyebrow_rotate_offset{32 - EyebrowRotateLookup[eyebrow_rotate_1] + 6};
232 const auto eyebrow_rotate{
233 32 - EyebrowRotateLookup[static_cast<std::size_t>(bf.eyebrow_type.Value())]};
234
235 bf.eyebrow_color.Assign(bf.hair_color);
236 bf.eyebrow_scale.Assign(4);
237 bf.eyebrow_aspect.Assign(3);
238 bf.eyebrow_rotate.Assign(eyebrow_rotate_offset - eyebrow_rotate);
239 bf.eyebrow_x.Assign(2);
240 bf.eyebrow_y.Assign(axis_y + eyebrow_y);
241
242 const auto nose_scale{gender == Gender::Female ? 3 : 4};
243
244 bf.nose_type.Assign(
245 nose_type_info.values[GetRandomValue<std::size_t>(nose_type_info.values_count)]);
246 bf.nose_scale.Assign(nose_scale);
247 bf.nose_y.Assign(axis_y + 9);
248
249 const auto mouth_color{gender == Gender::Female ? GetRandomValue<int>(4) : 0};
250
251 bf.mouth_type.Assign(
252 mouth_type_info.values[GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
253 bf.mouth_color.Assign(MouthColorLookup[mouth_color]);
254 bf.mouth_scale.Assign(4);
255 bf.mouth_aspect.Assign(3);
256 bf.mouth_y.Assign(axis_y + 13);
257
258 bf.beard_color.Assign(bf.hair_color);
259 bf.mustache_scale.Assign(4);
260
261 if (gender == Gender::Male && age != Age::Young && GetRandomValue<int>(10) < 2) {
262 const auto mustache_and_beard_flag{
263 GetRandomValue<BeardAndMustacheFlag>(BeardAndMustacheFlag::All)};
264
265 auto beard_type{BeardType::None};
266 auto mustache_type{MustacheType::None};
267
268 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
269 BeardAndMustacheFlag::Beard) {
270 beard_type = GetRandomValue<BeardType>(BeardType::Beard1, BeardType::Beard5);
271 }
272
273 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
274 BeardAndMustacheFlag::Mustache) {
275 mustache_type =
276 GetRandomValue<MustacheType>(MustacheType::Mustache1, MustacheType::Mustache5);
277 }
278
279 bf.mustache_type.Assign(mustache_type);
280 bf.beard_type.Assign(beard_type);
281 bf.mustache_y.Assign(10);
282 } else {
283 bf.mustache_type.Assign(MustacheType::None);
284 bf.beard_type.Assign(BeardType::None);
285 bf.mustache_y.Assign(axis_y + 10);
286 }
287
288 const auto glasses_type_start{GetRandomValue<std::size_t>(100)};
289 u8 glasses_type{};
290 while (glasses_type_start < glasses_type_info.values[glasses_type]) {
291 if (++glasses_type >= glasses_type_info.values_count) {
292 ASSERT(false);
293 break;
294 }
295 }
296
297 bf.glasses_type.Assign(glasses_type);
298 bf.glasses_color.Assign(GlassesColorLookup[0]);
299 bf.glasses_scale.Assign(4);
300 bf.glasses_y.Assign(axis_y + 10);
301
302 bf.mole_type.Assign(0);
303 bf.mole_scale.Assign(4);
304 bf.mole_x.Assign(2);
305 bf.mole_y.Assign(20);
306 22
307 return {DefaultMiiName, bf, user_id}; 23bool MiiManager::IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
308}
309
310MiiStoreData BuildDefaultStoreData(const DefaultMii& info, const Common::UUID& user_id) {
311 MiiStoreBitFields bf{};
312
313 bf.font_region.Assign(info.font_region);
314 bf.favorite_color.Assign(info.favorite_color);
315 bf.gender.Assign(info.gender);
316 bf.height.Assign(info.height);
317 bf.build.Assign(info.weight);
318 bf.type.Assign(info.type);
319 bf.region_move.Assign(info.region);
320 bf.faceline_type.Assign(info.face_type);
321 bf.faceline_color.Assign(info.face_color);
322 bf.faceline_wrinkle.Assign(info.face_wrinkle);
323 bf.faceline_makeup.Assign(info.face_makeup);
324 bf.hair_type.Assign(info.hair_type);
325 bf.hair_color.Assign(HairColorLookup[info.hair_color]);
326 bf.hair_flip.Assign(static_cast<HairFlip>(info.hair_flip));
327 bf.eye_type.Assign(info.eye_type);
328 bf.eye_color.Assign(EyeColorLookup[info.eye_color]);
329 bf.eye_scale.Assign(info.eye_scale);
330 bf.eye_aspect.Assign(info.eye_aspect);
331 bf.eye_rotate.Assign(info.eye_rotate);
332 bf.eye_x.Assign(info.eye_x);
333 bf.eye_y.Assign(info.eye_y);
334 bf.eyebrow_type.Assign(info.eyebrow_type);
335 bf.eyebrow_color.Assign(HairColorLookup[info.eyebrow_color]);
336 bf.eyebrow_scale.Assign(info.eyebrow_scale);
337 bf.eyebrow_aspect.Assign(info.eyebrow_aspect);
338 bf.eyebrow_rotate.Assign(info.eyebrow_rotate);
339 bf.eyebrow_x.Assign(info.eyebrow_x);
340 bf.eyebrow_y.Assign(info.eyebrow_y - 3);
341 bf.nose_type.Assign(info.nose_type);
342 bf.nose_scale.Assign(info.nose_scale);
343 bf.nose_y.Assign(info.nose_y);
344 bf.mouth_type.Assign(info.mouth_type);
345 bf.mouth_color.Assign(MouthColorLookup[info.mouth_color]);
346 bf.mouth_scale.Assign(info.mouth_scale);
347 bf.mouth_aspect.Assign(info.mouth_aspect);
348 bf.mouth_y.Assign(info.mouth_y);
349 bf.beard_color.Assign(HairColorLookup[info.beard_color]);
350 bf.beard_type.Assign(static_cast<BeardType>(info.beard_type));
351 bf.mustache_type.Assign(static_cast<MustacheType>(info.mustache_type));
352 bf.mustache_scale.Assign(info.mustache_scale);
353 bf.mustache_y.Assign(info.mustache_y);
354 bf.glasses_type.Assign(info.glasses_type);
355 bf.glasses_color.Assign(GlassesColorLookup[info.glasses_color]);
356 bf.glasses_scale.Assign(info.glasses_scale);
357 bf.glasses_y.Assign(info.glasses_y);
358 bf.mole_type.Assign(info.mole_type);
359 bf.mole_scale.Assign(info.mole_scale);
360 bf.mole_x.Assign(info.mole_x);
361 bf.mole_y.Assign(info.mole_y);
362
363 return {DefaultMiiName, bf, user_id};
364}
365
366} // namespace
367
368MiiStoreData::MiiStoreData() = default;
369
370MiiStoreData::MiiStoreData(const MiiStoreData::Name& name, const MiiStoreBitFields& bit_fields,
371 const Common::UUID& user_id) {
372 data.name = name;
373 data.uuid = Common::UUID::MakeRandomRFC4122V4();
374
375 std::memcpy(data.data.data(), &bit_fields, sizeof(MiiStoreBitFields));
376 data_crc = GenerateCrc16(data.data.data(), sizeof(data));
377 device_crc = GenerateCrc16(&user_id, sizeof(Common::UUID));
378}
379
380MiiManager::MiiManager() : user_id{Service::Account::ProfileManager().GetLastOpenedUser()} {}
381
382bool MiiManager::CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter) {
383 if ((source_flag & SourceFlag::Database) == SourceFlag::None) { 24 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
384 return false; 25 return false;
385 } 26 }
386 27
387 const bool result{current_update_counter != update_counter}; 28 const auto metadata_update_counter = metadata.update_counter;
388 29 metadata.update_counter = update_counter;
389 current_update_counter = update_counter; 30 return metadata_update_counter != update_counter;
390
391 return result;
392} 31}
393 32
394bool MiiManager::IsFullDatabase() const { 33bool MiiManager::IsFullDatabase() const {
@@ -396,306 +35,138 @@ bool MiiManager::IsFullDatabase() const {
396 return false; 35 return false;
397} 36}
398 37
399u32 MiiManager::GetCount(SourceFlag source_flag) const { 38u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
400 std::size_t count{}; 39 u32 mii_count{};
40 if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
41 mii_count += DefaultMiiCount;
42 }
401 if ((source_flag & SourceFlag::Database) != SourceFlag::None) { 43 if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
402 // TODO(bunnei): We don't implement the Mii database, but when we do, update this 44 // TODO(bunnei): We don't implement the Mii database, but when we do, update this
403 count += 0;
404 } 45 }
405 if ((source_flag & SourceFlag::Default) != SourceFlag::None) { 46 return mii_count;
406 count += DefaultMiiCount;
407 }
408 return static_cast<u32>(count);
409} 47}
410 48
411Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) { 49Result MiiManager::UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
50 const CharInfo& char_info, SourceFlag source_flag) {
412 if ((source_flag & SourceFlag::Database) == SourceFlag::None) { 51 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
413 return ERROR_CANNOT_FIND_ENTRY; 52 return ResultNotFound;
414 } 53 }
415 54
416 // TODO(bunnei): We don't implement the Mii database, so we can't have an entry 55 // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
417 return ERROR_CANNOT_FIND_ENTRY; 56 return ResultNotFound;
418} 57}
419 58
420CharInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) { 59void MiiManager::BuildDefault(CharInfo& out_char_info, u32 index) const {
421 return ConvertStoreDataToInfo(BuildRandomStoreData(age, gender, race, user_id)); 60 StoreData store_data{};
61 store_data.BuildDefault(index);
62 out_char_info.SetFromStoreData(store_data);
422} 63}
423 64
424CharInfo MiiManager::BuildBase(Gender gender) { 65void MiiManager::BuildBase(CharInfo& out_char_info, Gender gender) const {
425 const std::size_t index = gender == Gender::Female ? 1 : 0; 66 StoreData store_data{};
426 return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::BaseMii.at(index), user_id)); 67 store_data.BuildBase(gender);
68 out_char_info.SetFromStoreData(store_data);
427} 69}
428 70
429CharInfo MiiManager::BuildDefault(std::size_t index) { 71void MiiManager::BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const {
430 return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::DefaultMii.at(index), user_id)); 72 StoreData store_data{};
73 store_data.BuildRandom(age, gender, race);
74 out_char_info.SetFromStoreData(store_data);
431} 75}
432 76
433CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const { 77void MiiManager::ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const {
434 Service::Mii::MiiManager manager; 78 StoreData store_data{};
435 auto mii = manager.BuildBase(Mii::Gender::Male); 79 mii_v3.BuildToStoreData(store_data);
80 out_char_info.SetFromStoreData(store_data);
81}
436 82
437 if (!ValidateV3Info(mii_v3)) { 83Result MiiManager::Get(const DatabaseSessionMetadata& metadata,
438 return mii; 84 std::span<CharInfoElement> out_elements, u32& out_count,
85 SourceFlag source_flag) {
86 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
87 return BuildDefault(out_elements, out_count, source_flag);
439 } 88 }
440 89
441 // TODO: We are ignoring a bunch of data from the mii_v3 90 // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
442
443 mii.gender = static_cast<u8>(mii_v3.mii_information.gender);
444 mii.favorite_color = static_cast<u8>(mii_v3.mii_information.favorite_color);
445 mii.height = mii_v3.height;
446 mii.build = mii_v3.build;
447
448 // Copy name until string terminator
449 mii.name = {};
450 for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
451 mii.name[index] = mii_v3.mii_name[index];
452 if (mii.name[index] == 0) {
453 break;
454 }
455 }
456 91
457 mii.font_region = mii_v3.region_information.character_set; 92 // Include default Mii at the end of the list
458 93 return BuildDefault(out_elements, out_count, source_flag);
459 mii.faceline_type = mii_v3.appearance_bits1.face_shape;
460 mii.faceline_color = mii_v3.appearance_bits1.skin_color;
461 mii.faceline_wrinkle = mii_v3.appearance_bits2.wrinkles;
462 mii.faceline_make = mii_v3.appearance_bits2.makeup;
463
464 mii.hair_type = mii_v3.hair_style;
465 mii.hair_color = mii_v3.appearance_bits3.hair_color;
466 mii.hair_flip = mii_v3.appearance_bits3.flip_hair;
467
468 mii.eye_type = static_cast<u8>(mii_v3.appearance_bits4.eye_type);
469 mii.eye_color = static_cast<u8>(mii_v3.appearance_bits4.eye_color);
470 mii.eye_scale = static_cast<u8>(mii_v3.appearance_bits4.eye_scale);
471 mii.eye_aspect = static_cast<u8>(mii_v3.appearance_bits4.eye_vertical_stretch);
472 mii.eye_rotate = static_cast<u8>(mii_v3.appearance_bits4.eye_rotation);
473 mii.eye_x = static_cast<u8>(mii_v3.appearance_bits4.eye_spacing);
474 mii.eye_y = static_cast<u8>(mii_v3.appearance_bits4.eye_y_position);
475
476 mii.eyebrow_type = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_style);
477 mii.eyebrow_color = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_color);
478 mii.eyebrow_scale = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_scale);
479 mii.eyebrow_aspect = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_yscale);
480 mii.eyebrow_rotate = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_rotation);
481 mii.eyebrow_x = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_spacing);
482 mii.eyebrow_y = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_y_position);
483
484 mii.nose_type = static_cast<u8>(mii_v3.appearance_bits6.nose_type);
485 mii.nose_scale = static_cast<u8>(mii_v3.appearance_bits6.nose_scale);
486 mii.nose_y = static_cast<u8>(mii_v3.appearance_bits6.nose_y_position);
487
488 mii.mouth_type = static_cast<u8>(mii_v3.appearance_bits7.mouth_type);
489 mii.mouth_color = static_cast<u8>(mii_v3.appearance_bits7.mouth_color);
490 mii.mouth_scale = static_cast<u8>(mii_v3.appearance_bits7.mouth_scale);
491 mii.mouth_aspect = static_cast<u8>(mii_v3.appearance_bits7.mouth_horizontal_stretch);
492 mii.mouth_y = static_cast<u8>(mii_v3.appearance_bits8.mouth_y_position);
493
494 mii.mustache_type = static_cast<u8>(mii_v3.appearance_bits8.mustache_type);
495 mii.mustache_scale = static_cast<u8>(mii_v3.appearance_bits9.mustache_scale);
496 mii.mustache_y = static_cast<u8>(mii_v3.appearance_bits9.mustache_y_position);
497
498 mii.beard_type = static_cast<u8>(mii_v3.appearance_bits9.bear_type);
499 mii.beard_color = static_cast<u8>(mii_v3.appearance_bits9.facial_hair_color);
500
501 mii.glasses_type = static_cast<u8>(mii_v3.appearance_bits10.glasses_type);
502 mii.glasses_color = static_cast<u8>(mii_v3.appearance_bits10.glasses_color);
503 mii.glasses_scale = static_cast<u8>(mii_v3.appearance_bits10.glasses_scale);
504 mii.glasses_y = static_cast<u8>(mii_v3.appearance_bits10.glasses_y_position);
505
506 mii.mole_type = static_cast<u8>(mii_v3.appearance_bits11.mole_enabled);
507 mii.mole_scale = static_cast<u8>(mii_v3.appearance_bits11.mole_scale);
508 mii.mole_x = static_cast<u8>(mii_v3.appearance_bits11.mole_x_position);
509 mii.mole_y = static_cast<u8>(mii_v3.appearance_bits11.mole_y_position);
510
511 // TODO: Validate mii data
512
513 return mii;
514} 94}
515 95
516Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const { 96Result MiiManager::Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
517 Service::Mii::MiiManager manager; 97 u32& out_count, SourceFlag source_flag) {
518 Ver3StoreData mii_v3{}; 98 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
519 99 return BuildDefault(out_char_info, out_count, source_flag);
520 // TODO: We are ignoring a bunch of data from the mii_v3
521
522 mii_v3.version = 1;
523 mii_v3.mii_information.gender.Assign(mii.gender);
524 mii_v3.mii_information.favorite_color.Assign(mii.favorite_color);
525 mii_v3.height = mii.height;
526 mii_v3.build = mii.build;
527
528 // Copy name until string terminator
529 mii_v3.mii_name = {};
530 for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
531 mii_v3.mii_name[index] = mii.name[index];
532 if (mii_v3.mii_name[index] == 0) {
533 break;
534 }
535 } 100 }
536 101
537 mii_v3.region_information.character_set.Assign(mii.font_region); 102 // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
538
539 mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type);
540 mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle);
541 mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make);
542
543 mii_v3.hair_style = mii.hair_type;
544 mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip);
545 103
546 mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type); 104 // Include default Mii at the end of the list
547 mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale); 105 return BuildDefault(out_char_info, out_count, source_flag);
548 mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect); 106}
549 mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate);
550 mii_v3.appearance_bits4.eye_spacing.Assign(mii.eye_x);
551 mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y);
552 107
553 mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type); 108Result MiiManager::BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
554 mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale); 109 SourceFlag source_flag) {
555 mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect); 110 if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
556 mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate); 111 return ResultSuccess;
557 mii_v3.appearance_bits5.eyebrow_spacing.Assign(mii.eyebrow_x); 112 }
558 mii_v3.appearance_bits5.eyebrow_y_position.Assign(mii.eyebrow_y);
559 113
560 mii_v3.appearance_bits6.nose_type.Assign(mii.nose_type); 114 StoreData store_data{};
561 mii_v3.appearance_bits6.nose_scale.Assign(mii.nose_scale);
562 mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y);
563 115
564 mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type); 116 for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
565 mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale); 117 if (out_elements.size() <= static_cast<std::size_t>(out_count)) {
566 mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect); 118 return ResultInvalidArgumentSize;
567 mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y); 119 }
568 120
569 mii_v3.appearance_bits8.mustache_type.Assign(mii.mustache_type); 121 store_data.BuildDefault(static_cast<u32>(index));
570 mii_v3.appearance_bits9.mustache_scale.Assign(mii.mustache_scale);
571 mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y);
572 122
573 mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type); 123 out_elements[out_count].source = Source::Default;
124 out_elements[out_count].char_info.SetFromStoreData(store_data);
125 out_count++;
126 }
574 127
575 mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale); 128 return ResultSuccess;
576 mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y); 129}
577 130
578 mii_v3.appearance_bits11.mole_enabled.Assign(mii.mole_type); 131Result MiiManager::BuildDefault(std::span<CharInfo> out_char_info, u32& out_count,
579 mii_v3.appearance_bits11.mole_scale.Assign(mii.mole_scale); 132 SourceFlag source_flag) {
580 mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x); 133 if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
581 mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y); 134 return ResultSuccess;
135 }
582 136
583 // These types are converted to V3 from a table 137 StoreData store_data{};
584 mii_v3.appearance_bits1.skin_color.Assign(Ver3FacelineColorTable[mii.faceline_color]);
585 mii_v3.appearance_bits3.hair_color.Assign(Ver3HairColorTable[mii.hair_color]);
586 mii_v3.appearance_bits4.eye_color.Assign(Ver3EyeColorTable[mii.eye_color]);
587 mii_v3.appearance_bits5.eyebrow_color.Assign(Ver3HairColorTable[mii.eyebrow_color]);
588 mii_v3.appearance_bits7.mouth_color.Assign(Ver3MouthlineColorTable[mii.mouth_color]);
589 mii_v3.appearance_bits9.facial_hair_color.Assign(Ver3HairColorTable[mii.beard_color]);
590 mii_v3.appearance_bits10.glasses_color.Assign(Ver3GlassColorTable[mii.glasses_color]);
591 mii_v3.appearance_bits10.glasses_type.Assign(Ver3GlassTypeTable[mii.glasses_type]);
592 138
593 mii_v3.crc = GenerateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16)); 139 for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
140 if (out_char_info.size() <= static_cast<std::size_t>(out_count)) {
141 return ResultInvalidArgumentSize;
142 }
594 143
595 // TODO: Validate mii_v3 data 144 store_data.BuildDefault(static_cast<u32>(index));
596 145
597 return mii_v3; 146 out_char_info[out_count].SetFromStoreData(store_data);
598} 147 out_count++;
599 148 }
600NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const {
601 return {
602 .faceline_color = static_cast<u8>(mii.faceline_color & 0xf),
603 .hair_color = static_cast<u8>(mii.hair_color & 0x7f),
604 .eye_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
605 .eyebrow_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
606 .mouth_color = static_cast<u8>(mii.mouth_color & 0x7f),
607 .beard_color = static_cast<u8>(mii.beard_color & 0x7f),
608 .glass_color = static_cast<u8>(mii.glasses_color & 0x7f),
609 .glass_type = static_cast<u8>(mii.glasses_type & 0x1f),
610 };
611}
612 149
613bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { 150 return ResultSuccess;
614 bool is_valid = mii_v3.version == 0 || mii_v3.version == 3;
615
616 is_valid = is_valid && (mii_v3.mii_name[0] != 0);
617
618 is_valid = is_valid && (mii_v3.mii_information.birth_month < 13);
619 is_valid = is_valid && (mii_v3.mii_information.birth_day < 32);
620 is_valid = is_valid && (mii_v3.mii_information.favorite_color < 12);
621 is_valid = is_valid && (mii_v3.height < 128);
622 is_valid = is_valid && (mii_v3.build < 128);
623
624 is_valid = is_valid && (mii_v3.appearance_bits1.face_shape < 12);
625 is_valid = is_valid && (mii_v3.appearance_bits1.skin_color < 7);
626 is_valid = is_valid && (mii_v3.appearance_bits2.wrinkles < 12);
627 is_valid = is_valid && (mii_v3.appearance_bits2.makeup < 12);
628
629 is_valid = is_valid && (mii_v3.hair_style < 132);
630 is_valid = is_valid && (mii_v3.appearance_bits3.hair_color < 8);
631
632 is_valid = is_valid && (mii_v3.appearance_bits4.eye_type < 60);
633 is_valid = is_valid && (mii_v3.appearance_bits4.eye_color < 6);
634 is_valid = is_valid && (mii_v3.appearance_bits4.eye_scale < 8);
635 is_valid = is_valid && (mii_v3.appearance_bits4.eye_vertical_stretch < 7);
636 is_valid = is_valid && (mii_v3.appearance_bits4.eye_rotation < 8);
637 is_valid = is_valid && (mii_v3.appearance_bits4.eye_spacing < 13);
638 is_valid = is_valid && (mii_v3.appearance_bits4.eye_y_position < 19);
639
640 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_style < 25);
641 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_color < 8);
642 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_scale < 9);
643 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_yscale < 7);
644 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_rotation < 12);
645 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_spacing < 12);
646 is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_y_position < 19);
647
648 is_valid = is_valid && (mii_v3.appearance_bits6.nose_type < 18);
649 is_valid = is_valid && (mii_v3.appearance_bits6.nose_scale < 9);
650 is_valid = is_valid && (mii_v3.appearance_bits6.nose_y_position < 19);
651
652 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_type < 36);
653 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_color < 5);
654 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_scale < 9);
655 is_valid = is_valid && (mii_v3.appearance_bits7.mouth_horizontal_stretch < 7);
656 is_valid = is_valid && (mii_v3.appearance_bits8.mouth_y_position < 19);
657
658 is_valid = is_valid && (mii_v3.appearance_bits8.mustache_type < 6);
659 is_valid = is_valid && (mii_v3.appearance_bits9.mustache_scale < 7);
660 is_valid = is_valid && (mii_v3.appearance_bits9.mustache_y_position < 17);
661
662 is_valid = is_valid && (mii_v3.appearance_bits9.bear_type < 6);
663 is_valid = is_valid && (mii_v3.appearance_bits9.facial_hair_color < 8);
664
665 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_type < 9);
666 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_color < 6);
667 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_scale < 8);
668 is_valid = is_valid && (mii_v3.appearance_bits10.glasses_y_position < 21);
669
670 is_valid = is_valid && (mii_v3.appearance_bits11.mole_enabled < 2);
671 is_valid = is_valid && (mii_v3.appearance_bits11.mole_scale < 9);
672 is_valid = is_valid && (mii_v3.appearance_bits11.mole_x_position < 17);
673 is_valid = is_valid && (mii_v3.appearance_bits11.mole_y_position < 31);
674
675 return is_valid;
676} 151}
677 152
678std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) { 153Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
679 std::vector<MiiInfoElement> result; 154 s32& out_index) {
680
681 if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
682 return result;
683 }
684 155
685 for (std::size_t index = 0; index < DefaultMiiCount; index++) { 156 if (char_info.Verify() != ValidationResult::NoErrors) {
686 result.emplace_back(BuildDefault(index), Source::Default); 157 return ResultInvalidCharInfo;
687 } 158 }
688 159
689 return result;
690}
691
692Result MiiManager::GetIndex([[maybe_unused]] const CharInfo& info, u32& index) {
693 constexpr u32 INVALID_INDEX{0xFFFFFFFF}; 160 constexpr u32 INVALID_INDEX{0xFFFFFFFF};
694 161
695 index = INVALID_INDEX; 162 out_index = INVALID_INDEX;
696 163
697 // TODO(bunnei): We don't implement the Mii database, so we can't have an index 164 // TODO(bunnei): We don't implement the Mii database, so we can't have an index
698 return ERROR_CANNOT_FIND_ENTRY; 165 return ResultNotFound;
166}
167
168void MiiManager::SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version) {
169 metadata.interface_version = version;
699} 170}
700 171
701} // namespace Service::Mii 172} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
index 0c8295ebe..a2e7a6d73 100644
--- a/src/core/hle/service/mii/mii_manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
@@ -6,7 +6,10 @@
6#include <vector> 6#include <vector>
7 7
8#include "core/hle/result.h" 8#include "core/hle/result.h"
9#include "core/hle/service/mii/types.h" 9#include "core/hle/service/mii/mii_types.h"
10#include "core/hle/service/mii/types/char_info.h"
11#include "core/hle/service/mii/types/store_data.h"
12#include "core/hle/service/mii/types/ver3_store_data.h"
10 13
11namespace Service::Mii { 14namespace Service::Mii {
12 15
@@ -16,26 +19,30 @@ class MiiManager {
16public: 19public:
17 MiiManager(); 20 MiiManager();
18 21
19 bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter); 22 bool IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
23
20 bool IsFullDatabase() const; 24 bool IsFullDatabase() const;
21 u32 GetCount(SourceFlag source_flag) const; 25 u32 GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
22 Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag); 26 Result UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
23 CharInfo BuildRandom(Age age, Gender gender, Race race); 27 const CharInfo& char_info, SourceFlag source_flag);
24 CharInfo BuildBase(Gender gender); 28 Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfoElement> out_elements,
25 CharInfo BuildDefault(std::size_t index); 29 u32& out_count, SourceFlag source_flag);
26 CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; 30 Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
27 bool ValidateV3Info(const Ver3StoreData& mii_v3) const; 31 u32& out_count, SourceFlag source_flag);
28 std::vector<MiiInfoElement> GetDefault(SourceFlag source_flag); 32 void BuildDefault(CharInfo& out_char_info, u32 index) const;
29 Result GetIndex(const CharInfo& info, u32& index); 33 void BuildBase(CharInfo& out_char_info, Gender gender) const;
30 34 void BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const;
31 // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData 35 void ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const;
32 Ver3StoreData BuildFromStoreData(const CharInfo& mii) const; 36 std::vector<CharInfoElement> GetDefault(SourceFlag source_flag);
33 37 Result GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
34 // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData 38 s32& out_index);
35 NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const; 39 void SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version);
36 40
37private: 41private:
38 const Common::UUID user_id{}; 42 Result BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
43 SourceFlag source_flag);
44 Result BuildDefault(std::span<CharInfo> out_char_info, u32& out_count, SourceFlag source_flag);
45
39 u64 update_counter{}; 46 u64 update_counter{};
40}; 47};
41 48
diff --git a/src/core/hle/service/mii/mii_result.h b/src/core/hle/service/mii/mii_result.h
new file mode 100644
index 000000000..021cb76da
--- /dev/null
+++ b/src/core/hle/service/mii/mii_result.h
@@ -0,0 +1,20 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Service::Mii {
9
10constexpr Result ResultInvalidArgument{ErrorModule::Mii, 1};
11constexpr Result ResultInvalidArgumentSize{ErrorModule::Mii, 2};
12constexpr Result ResultNotUpdated{ErrorModule::Mii, 3};
13constexpr Result ResultNotFound{ErrorModule::Mii, 4};
14constexpr Result ResultDatabaseFull{ErrorModule::Mii, 5};
15constexpr Result ResultInvalidCharInfo{ErrorModule::Mii, 100};
16constexpr Result ResultInvalidStoreData{ErrorModule::Mii, 109};
17constexpr Result ResultInvalidOperation{ErrorModule::Mii, 202};
18constexpr Result ResultPermissionDenied{ErrorModule::Mii, 203};
19
20}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_types.h b/src/core/hle/service/mii/mii_types.h
new file mode 100644
index 000000000..95476f745
--- /dev/null
+++ b/src/core/hle/service/mii/mii_types.h
@@ -0,0 +1,694 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <type_traits>
8
9#include "common/bit_field.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "common/uuid.h"
13
14namespace Service::Mii {
15
16constexpr u8 MaxHeight = 127;
17constexpr u8 MaxBuild = 127;
18constexpr u8 MaxType = 1;
19constexpr u8 MaxRegionMove = 3;
20constexpr u8 MaxEyeScale = 7;
21constexpr u8 MaxEyeAspect = 6;
22constexpr u8 MaxEyeRotate = 7;
23constexpr u8 MaxEyeX = 12;
24constexpr u8 MaxEyeY = 18;
25constexpr u8 MaxEyebrowScale = 8;
26constexpr u8 MaxEyebrowAspect = 6;
27constexpr u8 MaxEyebrowRotate = 11;
28constexpr u8 MaxEyebrowX = 12;
29constexpr u8 MaxEyebrowY = 18;
30constexpr u8 MaxNoseScale = 8;
31constexpr u8 MaxNoseY = 18;
32constexpr u8 MaxMouthScale = 8;
33constexpr u8 MaxMoutAspect = 6;
34constexpr u8 MaxMouthY = 18;
35constexpr u8 MaxMustacheScale = 8;
36constexpr u8 MasMustacheY = 16;
37constexpr u8 MaxGlassScale = 7;
38constexpr u8 MaxGlassY = 20;
39constexpr u8 MaxMoleScale = 8;
40constexpr u8 MaxMoleX = 16;
41constexpr u8 MaxMoleY = 30;
42constexpr u8 MaxVer3CommonColor = 7;
43constexpr u8 MaxVer3GlassType = 8;
44
45enum class Age : u8 {
46 Young,
47 Normal,
48 Old,
49 All, // Default
50
51 Max = All,
52};
53
54enum class Gender : u8 {
55 Male,
56 Female,
57 All, // Default
58
59 Max = Female,
60};
61
62enum class Race : u8 {
63 Black,
64 White,
65 Asian,
66 All, // Default
67
68 Max = All,
69};
70
71enum class HairType : u8 {
72 NormalLong, // Default
73 NormalShort,
74 NormalMedium,
75 NormalExtraLong,
76 NormalLongBottom,
77 NormalTwoPeaks,
78 PartingLong,
79 FrontLock,
80 PartingShort,
81 PartingExtraLongCurved,
82 PartingExtraLong,
83 PartingMiddleLong,
84 PartingSquared,
85 PartingLongBottom,
86 PeaksTop,
87 PeaksSquared,
88 PartingPeaks,
89 PeaksLongBottom,
90 Peaks,
91 PeaksRounded,
92 PeaksSide,
93 PeaksMedium,
94 PeaksLong,
95 PeaksRoundedLong,
96 PartingFrontPeaks,
97 PartingLongFront,
98 PartingLongRounded,
99 PartingFrontPeaksLong,
100 PartingExtraLongRounded,
101 LongRounded,
102 NormalUnknown1,
103 NormalUnknown2,
104 NormalUnknown3,
105 NormalUnknown4,
106 NormalUnknown5,
107 NormalUnknown6,
108 DreadLocks,
109 PlatedMats,
110 Caps,
111 Afro,
112 PlatedMatsLong,
113 Beanie,
114 Short,
115 ShortTopLongSide,
116 ShortUnknown1,
117 ShortUnknown2,
118 MilitaryParting,
119 Military,
120 ShortUnknown3,
121 ShortUnknown4,
122 ShortUnknown5,
123 ShortUnknown6,
124 NoneTop,
125 None,
126 LongUnknown1,
127 LongUnknown2,
128 LongUnknown3,
129 LongUnknown4,
130 LongUnknown5,
131 LongUnknown6,
132 LongUnknown7,
133 LongUnknown8,
134 LongUnknown9,
135 LongUnknown10,
136 LongUnknown11,
137 LongUnknown12,
138 LongUnknown13,
139 LongUnknown14,
140 LongUnknown15,
141 LongUnknown16,
142 LongUnknown17,
143 LongUnknown18,
144 LongUnknown19,
145 LongUnknown20,
146 LongUnknown21,
147 LongUnknown22,
148 LongUnknown23,
149 LongUnknown24,
150 LongUnknown25,
151 LongUnknown26,
152 LongUnknown27,
153 LongUnknown28,
154 LongUnknown29,
155 LongUnknown30,
156 LongUnknown31,
157 LongUnknown32,
158 LongUnknown33,
159 LongUnknown34,
160 LongUnknown35,
161 LongUnknown36,
162 LongUnknown37,
163 LongUnknown38,
164 LongUnknown39,
165 LongUnknown40,
166 LongUnknown41,
167 LongUnknown42,
168 LongUnknown43,
169 LongUnknown44,
170 LongUnknown45,
171 LongUnknown46,
172 LongUnknown47,
173 LongUnknown48,
174 LongUnknown49,
175 LongUnknown50,
176 LongUnknown51,
177 LongUnknown52,
178 LongUnknown53,
179 LongUnknown54,
180 LongUnknown55,
181 LongUnknown56,
182 LongUnknown57,
183 LongUnknown58,
184 LongUnknown59,
185 LongUnknown60,
186 LongUnknown61,
187 LongUnknown62,
188 LongUnknown63,
189 LongUnknown64,
190 LongUnknown65,
191 LongUnknown66,
192 TwoMediumFrontStrandsOneLongBackPonyTail,
193 TwoFrontStrandsLongBackPonyTail,
194 PartingFrontTwoLongBackPonyTails,
195 TwoFrontStrandsOneLongBackPonyTail,
196 LongBackPonyTail,
197 LongFrontTwoLongBackPonyTails,
198 StrandsTwoShortSidedPonyTails,
199 TwoMediumSidedPonyTails,
200 ShortFrontTwoBackPonyTails,
201 TwoShortSidedPonyTails,
202 TwoLongSidedPonyTails,
203 LongFrontTwoBackPonyTails,
204
205 Max = LongFrontTwoBackPonyTails,
206};
207
208enum class MoleType : u8 {
209 None, // Default
210 OneDot,
211
212 Max = OneDot,
213};
214
215enum class HairFlip : u8 {
216 Left, // Default
217 Right,
218
219 Max = Right,
220};
221
222enum class CommonColor : u8 {
223 // For simplicity common colors aren't listed
224 Max = 99,
225 Count = 100,
226};
227
228enum class FavoriteColor : u8 {
229 Red, // Default
230 Orange,
231 Yellow,
232 LimeGreen,
233 Green,
234 Blue,
235 LightBlue,
236 Pink,
237 Purple,
238 Brown,
239 White,
240 Black,
241
242 Max = Black,
243};
244
245enum class EyeType : u8 {
246 Normal, // Default
247 NormalLash,
248 WhiteLash,
249 WhiteNoBottom,
250 OvalAngledWhite,
251 AngryWhite,
252 DotLashType1,
253 Line,
254 DotLine,
255 OvalWhite,
256 RoundedWhite,
257 NormalShadow,
258 CircleWhite,
259 Circle,
260 CircleWhiteStroke,
261 NormalOvalNoBottom,
262 NormalOvalLarge,
263 NormalRoundedNoBottom,
264 SmallLash,
265 Small,
266 TwoSmall,
267 NormalLongLash,
268 WhiteTwoLashes,
269 WhiteThreeLashes,
270 DotAngry,
271 DotAngled,
272 Oval,
273 SmallWhite,
274 WhiteAngledNoBottom,
275 WhiteAngledNoLeft,
276 SmallWhiteTwoLashes,
277 LeafWhiteLash,
278 WhiteLargeNoBottom,
279 Dot,
280 DotLashType2,
281 DotThreeLashes,
282 WhiteOvalTop,
283 WhiteOvalBottom,
284 WhiteOvalBottomFlat,
285 WhiteOvalTwoLashes,
286 WhiteOvalThreeLashes,
287 WhiteOvalNoBottomTwoLashes,
288 DotWhite,
289 WhiteOvalTopFlat,
290 WhiteThinLeaf,
291 StarThreeLashes,
292 LineTwoLashes,
293 CrowsFeet,
294 WhiteNoBottomFlat,
295 WhiteNoBottomRounded,
296 WhiteSmallBottomLine,
297 WhiteNoBottomLash,
298 WhiteNoPartialBottomLash,
299 WhiteOvalBottomLine,
300 WhiteNoBottomLashTopLine,
301 WhiteNoPartialBottomTwoLashes,
302 NormalTopLine,
303 WhiteOvalLash,
304 RoundTired,
305 WhiteLarge,
306
307 Max = WhiteLarge,
308};
309
310enum class MouthType : u8 {
311 Neutral, // Default
312 NeutralLips,
313 Smile,
314 SmileStroke,
315 SmileTeeth,
316 LipsSmall,
317 LipsLarge,
318 Wave,
319 WaveAngrySmall,
320 NeutralStrokeLarge,
321 TeethSurprised,
322 LipsExtraLarge,
323 LipsUp,
324 NeutralDown,
325 Surprised,
326 TeethMiddle,
327 NeutralStroke,
328 LipsExtraSmall,
329 Malicious,
330 LipsDual,
331 NeutralComma,
332 NeutralUp,
333 TeethLarge,
334 WaveAngry,
335 LipsSexy,
336 SmileInverted,
337 LipsSexyOutline,
338 SmileRounded,
339 LipsTeeth,
340 NeutralOpen,
341 TeethRounded,
342 WaveAngrySmallInverted,
343 NeutralCommaInverted,
344 TeethFull,
345 SmileDownLine,
346 Kiss,
347
348 Max = Kiss,
349};
350
351enum class FontRegion : u8 {
352 Standard, // Default
353 China,
354 Korea,
355 Taiwan,
356
357 Max = Taiwan,
358};
359
360enum class FacelineType : u8 {
361 Sharp, // Default
362 Rounded,
363 SharpRounded,
364 SharpRoundedSmall,
365 Large,
366 LargeRounded,
367 SharpSmall,
368 Flat,
369 Bump,
370 Angular,
371 FlatRounded,
372 AngularSmall,
373
374 Max = AngularSmall,
375};
376
377enum class FacelineColor : u8 {
378 Beige, // Default
379 WarmBeige,
380 Natural,
381 Honey,
382 Chestnut,
383 Porcelain,
384 Ivory,
385 WarmIvory,
386 Almond,
387 Espresso,
388
389 Max = Espresso,
390 Count = Max + 1,
391};
392
393enum class FacelineWrinkle : u8 {
394 None, // Default
395 TearTroughs,
396 FacialPain,
397 Cheeks,
398 Folds,
399 UnderTheEyes,
400 SplitChin,
401 Chin,
402 BrowDroop,
403 MouthFrown,
404 CrowsFeet,
405 FoldsCrowsFrown,
406
407 Max = FoldsCrowsFrown,
408};
409
410enum class FacelineMake : u8 {
411 None, // Default
412 CheekPorcelain,
413 CheekNatural,
414 EyeShadowBlue,
415 CheekBlushPorcelain,
416 CheekBlushNatural,
417 CheekPorcelainEyeShadowBlue,
418 CheekPorcelainEyeShadowNatural,
419 CheekBlushPorcelainEyeShadowEspresso,
420 Freckles,
421 LionsManeBeard,
422 StubbleBeard,
423
424 Max = StubbleBeard,
425};
426
427enum class EyebrowType : u8 {
428 FlatAngledLarge, // Default
429 LowArchRoundedThin,
430 SoftAngledLarge,
431 MediumArchRoundedThin,
432 RoundedMedium,
433 LowArchMedium,
434 RoundedThin,
435 UpThin,
436 MediumArchRoundedMedium,
437 RoundedLarge,
438 UpLarge,
439 FlatAngledLargeInverted,
440 MediumArchFlat,
441 AngledThin,
442 HorizontalLarge,
443 HighArchFlat,
444 Flat,
445 MediumArchLarge,
446 LowArchThin,
447 RoundedThinInverted,
448 HighArchLarge,
449 Hairy,
450 Dotted,
451 None,
452
453 Max = None,
454};
455
456enum class NoseType : u8 {
457 Normal, // Default
458 Rounded,
459 Dot,
460 Arrow,
461 Roman,
462 Triangle,
463 Button,
464 RoundedInverted,
465 Potato,
466 Grecian,
467 Snub,
468 Aquiline,
469 ArrowLeft,
470 RoundedLarge,
471 Hooked,
472 Fat,
473 Droopy,
474 ArrowLarge,
475
476 Max = ArrowLarge,
477};
478
479enum class BeardType : u8 {
480 None,
481 Goatee,
482 GoateeLong,
483 LionsManeLong,
484 LionsMane,
485 Full,
486
487 Min = Goatee,
488 Max = Full,
489};
490
491enum class MustacheType : u8 {
492 None,
493 Walrus,
494 Pencil,
495 Horseshoe,
496 Normal,
497 Toothbrush,
498
499 Min = Walrus,
500 Max = Toothbrush,
501};
502
503enum class GlassType : u8 {
504 None,
505 Oval,
506 Wayfarer,
507 Rectangle,
508 TopRimless,
509 Rounded,
510 Oversized,
511 CatEye,
512 Square,
513 BottomRimless,
514 SemiOpaqueRounded,
515 SemiOpaqueCatEye,
516 SemiOpaqueOval,
517 SemiOpaqueRectangle,
518 SemiOpaqueAviator,
519 OpaqueRounded,
520 OpaqueCatEye,
521 OpaqueOval,
522 OpaqueRectangle,
523 OpaqueAviator,
524
525 Max = OpaqueAviator,
526 Count = Max + 1,
527};
528
529enum class BeardAndMustacheFlag : u32 {
530 Beard = 1,
531 Mustache,
532 All = Beard | Mustache,
533};
534DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
535
536enum class Source : u32 {
537 Database = 0,
538 Default = 1,
539 Account = 2,
540 Friend = 3,
541};
542
543enum class SourceFlag : u32 {
544 None = 0,
545 Database = 1 << 0,
546 Default = 1 << 1,
547};
548DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
549
550enum class ValidationResult : u32 {
551 NoErrors = 0x0,
552 InvalidBeardColor = 0x1,
553 InvalidBeardType = 0x2,
554 InvalidBuild = 0x3,
555 InvalidEyeAspect = 0x4,
556 InvalidEyeColor = 0x5,
557 InvalidEyeRotate = 0x6,
558 InvalidEyeScale = 0x7,
559 InvalidEyeType = 0x8,
560 InvalidEyeX = 0x9,
561 InvalidEyeY = 0xa,
562 InvalidEyebrowAspect = 0xb,
563 InvalidEyebrowColor = 0xc,
564 InvalidEyebrowRotate = 0xd,
565 InvalidEyebrowScale = 0xe,
566 InvalidEyebrowType = 0xf,
567 InvalidEyebrowX = 0x10,
568 InvalidEyebrowY = 0x11,
569 InvalidFacelineColor = 0x12,
570 InvalidFacelineMake = 0x13,
571 InvalidFacelineWrinkle = 0x14,
572 InvalidFacelineType = 0x15,
573 InvalidColor = 0x16,
574 InvalidFont = 0x17,
575 InvalidGender = 0x18,
576 InvalidGlassColor = 0x19,
577 InvalidGlassScale = 0x1a,
578 InvalidGlassType = 0x1b,
579 InvalidGlassY = 0x1c,
580 InvalidHairColor = 0x1d,
581 InvalidHairFlip = 0x1e,
582 InvalidHairType = 0x1f,
583 InvalidHeight = 0x20,
584 InvalidMoleScale = 0x21,
585 InvalidMoleType = 0x22,
586 InvalidMoleX = 0x23,
587 InvalidMoleY = 0x24,
588 InvalidMouthAspect = 0x25,
589 InvalidMouthColor = 0x26,
590 InvalidMouthScale = 0x27,
591 InvalidMouthType = 0x28,
592 InvalidMouthY = 0x29,
593 InvalidMustacheScale = 0x2a,
594 InvalidMustacheType = 0x2b,
595 InvalidMustacheY = 0x2c,
596 InvalidNoseScale = 0x2e,
597 InvalidNoseType = 0x2f,
598 InvalidNoseY = 0x30,
599 InvalidRegionMove = 0x31,
600 InvalidCreateId = 0x32,
601 InvalidName = 0x33,
602 InvalidType = 0x35,
603};
604
605struct Nickname {
606 static constexpr std::size_t MaxNameSize = 10;
607 std::array<char16_t, MaxNameSize> data;
608
609 // Checks for null, non-zero terminated or dirty strings
610 bool IsValid() const {
611 if (data[0] == 0) {
612 return false;
613 }
614
615 if (data[MaxNameSize] != 0) {
616 return false;
617 }
618 std::size_t index = 1;
619 while (data[index] != 0) {
620 index++;
621 }
622 while (index < MaxNameSize && data[index] == 0) {
623 index++;
624 }
625 return index == MaxNameSize;
626 }
627};
628static_assert(sizeof(Nickname) == 0x14, "Nickname is an invalid size");
629
630struct DefaultMii {
631 u32 face_type{};
632 u32 face_color{};
633 u32 face_wrinkle{};
634 u32 face_makeup{};
635 u32 hair_type{};
636 u32 hair_color{};
637 u32 hair_flip{};
638 u32 eye_type{};
639 u32 eye_color{};
640 u32 eye_scale{};
641 u32 eye_aspect{};
642 u32 eye_rotate{};
643 u32 eye_x{};
644 u32 eye_y{};
645 u32 eyebrow_type{};
646 u32 eyebrow_color{};
647 u32 eyebrow_scale{};
648 u32 eyebrow_aspect{};
649 u32 eyebrow_rotate{};
650 u32 eyebrow_x{};
651 u32 eyebrow_y{};
652 u32 nose_type{};
653 u32 nose_scale{};
654 u32 nose_y{};
655 u32 mouth_type{};
656 u32 mouth_color{};
657 u32 mouth_scale{};
658 u32 mouth_aspect{};
659 u32 mouth_y{};
660 u32 mustache_type{};
661 u32 beard_type{};
662 u32 beard_color{};
663 u32 mustache_scale{};
664 u32 mustache_y{};
665 u32 glasses_type{};
666 u32 glasses_color{};
667 u32 glasses_scale{};
668 u32 glasses_y{};
669 u32 mole_type{};
670 u32 mole_scale{};
671 u32 mole_x{};
672 u32 mole_y{};
673 u32 height{};
674 u32 weight{};
675 u32 gender{};
676 u32 favorite_color{};
677 u32 region_move{};
678 u32 font_region{};
679 u32 type{};
680 Nickname nickname;
681};
682static_assert(sizeof(DefaultMii) == 0xd8, "DefaultMii has incorrect size.");
683
684struct DatabaseSessionMetadata {
685 u32 interface_version;
686 u32 magic;
687 u64 update_counter;
688
689 bool IsInterfaceVersionSupported(u32 version) const {
690 return version <= interface_version;
691 }
692};
693
694} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_util.h b/src/core/hle/service/mii/mii_util.h
new file mode 100644
index 000000000..ddb544c23
--- /dev/null
+++ b/src/core/hle/service/mii/mii_util.h
@@ -0,0 +1,59 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <random>
7#include <span>
8
9#include "common/common_types.h"
10#include "common/swap.h"
11#include "common/uuid.h"
12#include "core/hle/service/mii/mii_types.h"
13
14namespace Service::Mii {
15class MiiUtil {
16public:
17 static u16 CalculateCrc16(const void* data, std::size_t size) {
18 s32 crc{};
19 for (std::size_t i = 0; i < size; i++) {
20 crc ^= static_cast<const u8*>(data)[i] << 8;
21 for (std::size_t j = 0; j < 8; j++) {
22 crc <<= 1;
23 if ((crc & 0x10000) != 0) {
24 crc = (crc ^ 0x1021) & 0xFFFF;
25 }
26 }
27 }
28 return Common::swap16(static_cast<u16>(crc));
29 }
30
31 static Common::UUID MakeCreateId() {
32 return Common::UUID::MakeRandomRFC4122V4();
33 }
34
35 static Common::UUID GetDeviceId() {
36 // This should be nn::settings::detail::GetMiiAuthorId()
37 return Common::UUID::MakeDefault();
38 }
39
40 template <typename T>
41 static T GetRandomValue(T min, T max) {
42 std::random_device device;
43 std::mt19937 gen(device());
44 std::uniform_int_distribution<u64> distribution(static_cast<u64>(min),
45 static_cast<u64>(max));
46 return static_cast<T>(distribution(gen));
47 }
48
49 template <typename T>
50 static T GetRandomValue(T max) {
51 return GetRandomValue<T>({}, max);
52 }
53
54 static bool IsFontRegionValid(FontRegion font, std::span<const char16_t> text) {
55 // TODO: This function needs to check against the font tables
56 return true;
57 }
58};
59} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/raw_data.h b/src/core/hle/service/mii/raw_data.h
deleted file mode 100644
index cdd2337d6..000000000
--- a/src/core/hle/service/mii/raw_data.h
+++ /dev/null
@@ -1,27 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7
8#include "core/hle/service/mii/types.h"
9
10namespace Service::Mii::RawData {
11
12extern const std::array<Service::Mii::DefaultMii, 2> BaseMii;
13extern const std::array<Service::Mii::DefaultMii, 6> DefaultMii;
14extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFaceline;
15extern const std::array<Service::Mii::RandomMiiData3, 6> RandomMiiFacelineColor;
16extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineWrinkle;
17extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineMakeup;
18extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiHairType;
19extern const std::array<Service::Mii::RandomMiiData3, 9> RandomMiiHairColor;
20extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyeType;
21extern const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiEyeColor;
22extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyebrowType;
23extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiNoseType;
24extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiMouthType;
25extern const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiGlassType;
26
27} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h
deleted file mode 100644
index c48d08d79..000000000
--- a/src/core/hle/service/mii/types.h
+++ /dev/null
@@ -1,553 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <type_traits>
8
9#include "common/bit_field.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "common/uuid.h"
13
14namespace Service::Mii {
15
16enum class Age : u32 {
17 Young,
18 Normal,
19 Old,
20 All,
21};
22
23enum class BeardType : u32 {
24 None,
25 Beard1,
26 Beard2,
27 Beard3,
28 Beard4,
29 Beard5,
30};
31
32enum class BeardAndMustacheFlag : u32 {
33 Beard = 1,
34 Mustache,
35 All = Beard | Mustache,
36};
37DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
38
39enum class FontRegion : u32 {
40 Standard,
41 China,
42 Korea,
43 Taiwan,
44};
45
46enum class Gender : u32 {
47 Male,
48 Female,
49 All,
50 Maximum = Female,
51};
52
53enum class HairFlip : u32 {
54 Left,
55 Right,
56 Maximum = Right,
57};
58
59enum class MustacheType : u32 {
60 None,
61 Mustache1,
62 Mustache2,
63 Mustache3,
64 Mustache4,
65 Mustache5,
66};
67
68enum class Race : u32 {
69 Black,
70 White,
71 Asian,
72 All,
73};
74
75enum class Source : u32 {
76 Database = 0,
77 Default = 1,
78 Account = 2,
79 Friend = 3,
80};
81
82enum class SourceFlag : u32 {
83 None = 0,
84 Database = 1 << 0,
85 Default = 1 << 1,
86};
87DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
88
89// nn::mii::CharInfo
90struct CharInfo {
91 Common::UUID uuid;
92 std::array<char16_t, 11> name;
93 u8 font_region;
94 u8 favorite_color;
95 u8 gender;
96 u8 height;
97 u8 build;
98 u8 type;
99 u8 region_move;
100 u8 faceline_type;
101 u8 faceline_color;
102 u8 faceline_wrinkle;
103 u8 faceline_make;
104 u8 hair_type;
105 u8 hair_color;
106 u8 hair_flip;
107 u8 eye_type;
108 u8 eye_color;
109 u8 eye_scale;
110 u8 eye_aspect;
111 u8 eye_rotate;
112 u8 eye_x;
113 u8 eye_y;
114 u8 eyebrow_type;
115 u8 eyebrow_color;
116 u8 eyebrow_scale;
117 u8 eyebrow_aspect;
118 u8 eyebrow_rotate;
119 u8 eyebrow_x;
120 u8 eyebrow_y;
121 u8 nose_type;
122 u8 nose_scale;
123 u8 nose_y;
124 u8 mouth_type;
125 u8 mouth_color;
126 u8 mouth_scale;
127 u8 mouth_aspect;
128 u8 mouth_y;
129 u8 beard_color;
130 u8 beard_type;
131 u8 mustache_type;
132 u8 mustache_scale;
133 u8 mustache_y;
134 u8 glasses_type;
135 u8 glasses_color;
136 u8 glasses_scale;
137 u8 glasses_y;
138 u8 mole_type;
139 u8 mole_scale;
140 u8 mole_x;
141 u8 mole_y;
142 u8 padding;
143};
144static_assert(sizeof(CharInfo) == 0x58, "CharInfo has incorrect size.");
145static_assert(std::has_unique_object_representations_v<CharInfo>,
146 "All bits of CharInfo must contribute to its value.");
147
148#pragma pack(push, 4)
149
150struct MiiInfoElement {
151 MiiInfoElement(const CharInfo& info_, Source source_) : info{info_}, source{source_} {}
152
153 CharInfo info{};
154 Source source{};
155};
156static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
157
158struct MiiStoreBitFields {
159 union {
160 u32 word_0{};
161
162 BitField<0, 8, u32> hair_type;
163 BitField<8, 7, u32> height;
164 BitField<15, 1, u32> mole_type;
165 BitField<16, 7, u32> build;
166 BitField<23, 1, HairFlip> hair_flip;
167 BitField<24, 7, u32> hair_color;
168 BitField<31, 1, u32> type;
169 };
170
171 union {
172 u32 word_1{};
173
174 BitField<0, 7, u32> eye_color;
175 BitField<7, 1, Gender> gender;
176 BitField<8, 7, u32> eyebrow_color;
177 BitField<16, 7, u32> mouth_color;
178 BitField<24, 7, u32> beard_color;
179 };
180
181 union {
182 u32 word_2{};
183
184 BitField<0, 7, u32> glasses_color;
185 BitField<8, 6, u32> eye_type;
186 BitField<14, 2, u32> region_move;
187 BitField<16, 6, u32> mouth_type;
188 BitField<22, 2, FontRegion> font_region;
189 BitField<24, 5, u32> eye_y;
190 BitField<29, 3, u32> glasses_scale;
191 };
192
193 union {
194 u32 word_3{};
195
196 BitField<0, 5, u32> eyebrow_type;
197 BitField<5, 3, MustacheType> mustache_type;
198 BitField<8, 5, u32> nose_type;
199 BitField<13, 3, BeardType> beard_type;
200 BitField<16, 5, u32> nose_y;
201 BitField<21, 3, u32> mouth_aspect;
202 BitField<24, 5, u32> mouth_y;
203 BitField<29, 3, u32> eyebrow_aspect;
204 };
205
206 union {
207 u32 word_4{};
208
209 BitField<0, 5, u32> mustache_y;
210 BitField<5, 3, u32> eye_rotate;
211 BitField<8, 5, u32> glasses_y;
212 BitField<13, 3, u32> eye_aspect;
213 BitField<16, 5, u32> mole_x;
214 BitField<21, 3, u32> eye_scale;
215 BitField<24, 5, u32> mole_y;
216 };
217
218 union {
219 u32 word_5{};
220
221 BitField<0, 5, u32> glasses_type;
222 BitField<8, 4, u32> favorite_color;
223 BitField<12, 4, u32> faceline_type;
224 BitField<16, 4, u32> faceline_color;
225 BitField<20, 4, u32> faceline_wrinkle;
226 BitField<24, 4, u32> faceline_makeup;
227 BitField<28, 4, u32> eye_x;
228 };
229
230 union {
231 u32 word_6{};
232
233 BitField<0, 4, u32> eyebrow_scale;
234 BitField<4, 4, u32> eyebrow_rotate;
235 BitField<8, 4, u32> eyebrow_x;
236 BitField<12, 4, u32> eyebrow_y;
237 BitField<16, 4, u32> nose_scale;
238 BitField<20, 4, u32> mouth_scale;
239 BitField<24, 4, u32> mustache_scale;
240 BitField<28, 4, u32> mole_scale;
241 };
242};
243static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
244static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
245 "MiiStoreBitFields is not trivially copyable.");
246
247// This is nn::mii::Ver3StoreData
248// Based on citra HLE::Applets::MiiData and PretendoNetwork.
249// https://github.com/citra-emu/citra/blob/master/src/core/hle/applets/mii_selector.h#L48
250// https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299
251struct Ver3StoreData {
252 u8 version;
253 union {
254 u8 raw;
255
256 BitField<0, 1, u8> allow_copying;
257 BitField<1, 1, u8> profanity_flag;
258 BitField<2, 2, u8> region_lock;
259 BitField<4, 2, u8> character_set;
260 } region_information;
261 u16_be mii_id;
262 u64_be system_id;
263 u32_be specialness_and_creation_date;
264 std::array<u8, 0x6> creator_mac;
265 u16_be padding;
266 union {
267 u16 raw;
268
269 BitField<0, 1, u16> gender;
270 BitField<1, 4, u16> birth_month;
271 BitField<5, 5, u16> birth_day;
272 BitField<10, 4, u16> favorite_color;
273 BitField<14, 1, u16> favorite;
274 } mii_information;
275 std::array<char16_t, 0xA> mii_name;
276 u8 height;
277 u8 build;
278 union {
279 u8 raw;
280
281 BitField<0, 1, u8> disable_sharing;
282 BitField<1, 4, u8> face_shape;
283 BitField<5, 3, u8> skin_color;
284 } appearance_bits1;
285 union {
286 u8 raw;
287
288 BitField<0, 4, u8> wrinkles;
289 BitField<4, 4, u8> makeup;
290 } appearance_bits2;
291 u8 hair_style;
292 union {
293 u8 raw;
294
295 BitField<0, 3, u8> hair_color;
296 BitField<3, 1, u8> flip_hair;
297 } appearance_bits3;
298 union {
299 u32 raw;
300
301 BitField<0, 6, u32> eye_type;
302 BitField<6, 3, u32> eye_color;
303 BitField<9, 4, u32> eye_scale;
304 BitField<13, 3, u32> eye_vertical_stretch;
305 BitField<16, 5, u32> eye_rotation;
306 BitField<21, 4, u32> eye_spacing;
307 BitField<25, 5, u32> eye_y_position;
308 } appearance_bits4;
309 union {
310 u32 raw;
311
312 BitField<0, 5, u32> eyebrow_style;
313 BitField<5, 3, u32> eyebrow_color;
314 BitField<8, 4, u32> eyebrow_scale;
315 BitField<12, 3, u32> eyebrow_yscale;
316 BitField<16, 4, u32> eyebrow_rotation;
317 BitField<21, 4, u32> eyebrow_spacing;
318 BitField<25, 5, u32> eyebrow_y_position;
319 } appearance_bits5;
320 union {
321 u16 raw;
322
323 BitField<0, 5, u16> nose_type;
324 BitField<5, 4, u16> nose_scale;
325 BitField<9, 5, u16> nose_y_position;
326 } appearance_bits6;
327 union {
328 u16 raw;
329
330 BitField<0, 6, u16> mouth_type;
331 BitField<6, 3, u16> mouth_color;
332 BitField<9, 4, u16> mouth_scale;
333 BitField<13, 3, u16> mouth_horizontal_stretch;
334 } appearance_bits7;
335 union {
336 u8 raw;
337
338 BitField<0, 5, u8> mouth_y_position;
339 BitField<5, 3, u8> mustache_type;
340 } appearance_bits8;
341 u8 allow_copying;
342 union {
343 u16 raw;
344
345 BitField<0, 3, u16> bear_type;
346 BitField<3, 3, u16> facial_hair_color;
347 BitField<6, 4, u16> mustache_scale;
348 BitField<10, 5, u16> mustache_y_position;
349 } appearance_bits9;
350 union {
351 u16 raw;
352
353 BitField<0, 4, u16> glasses_type;
354 BitField<4, 3, u16> glasses_color;
355 BitField<7, 4, u16> glasses_scale;
356 BitField<11, 5, u16> glasses_y_position;
357 } appearance_bits10;
358 union {
359 u16 raw;
360
361 BitField<0, 1, u16> mole_enabled;
362 BitField<1, 4, u16> mole_scale;
363 BitField<5, 5, u16> mole_x_position;
364 BitField<10, 5, u16> mole_y_position;
365 } appearance_bits11;
366
367 std::array<u16_le, 0xA> author_name;
368 INSERT_PADDING_BYTES(0x2);
369 u16_be crc;
370};
371static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size");
372
373struct NfpStoreDataExtension {
374 u8 faceline_color;
375 u8 hair_color;
376 u8 eye_color;
377 u8 eyebrow_color;
378 u8 mouth_color;
379 u8 beard_color;
380 u8 glass_color;
381 u8 glass_type;
382};
383static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size");
384
385constexpr std::array<u8, 0x10> Ver3FacelineColorTable{
386 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5,
387};
388
389constexpr std::array<u8, 100> Ver3HairColorTable{
390 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0,
391 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
392 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4,
393 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5,
394 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7,
395 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4,
396};
397
398constexpr std::array<u8, 100> Ver3EyeColorTable{
399 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4,
400 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
401 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4,
402 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
403 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2,
404 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
405};
406
407constexpr std::array<u8, 100> Ver3MouthlineColorTable{
408 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
409 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
410 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
411 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
412 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
413 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3,
414};
415
416constexpr std::array<u8, 100> Ver3GlassColorTable{
417 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3,
418 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
419 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
420 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5,
421 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4,
422 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
423};
424
425constexpr std::array<u8, 20> Ver3GlassTypeTable{
426 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1,
427 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7,
428};
429
430struct MiiStoreData {
431 using Name = std::array<char16_t, 10>;
432
433 MiiStoreData();
434 MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
435 const Common::UUID& user_id);
436
437 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
438 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
439 // not suitable for our uses.
440 struct {
441 std::array<u8, 0x1C> data{};
442 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
443
444 Name name{};
445 Common::UUID uuid{};
446 } data;
447
448 u16 data_crc{};
449 u16 device_crc{};
450};
451static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
452
453struct MiiStoreDataElement {
454 MiiStoreData data{};
455 Source source{};
456};
457static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
458
459struct MiiDatabase {
460 u32 magic{}; // 'NFDB'
461 std::array<MiiStoreData, 0x64> miis{};
462 INSERT_PADDING_BYTES(1);
463 u8 count{};
464 u16 crc{};
465};
466static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
467
468struct RandomMiiValues {
469 std::array<u8, 0xbc> values{};
470};
471static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
472
473struct RandomMiiData4 {
474 Gender gender{};
475 Age age{};
476 Race race{};
477 u32 values_count{};
478 std::array<u32, 47> values{};
479};
480static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
481
482struct RandomMiiData3 {
483 u32 arg_1;
484 u32 arg_2;
485 u32 values_count;
486 std::array<u32, 47> values{};
487};
488static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
489
490struct RandomMiiData2 {
491 u32 arg_1;
492 u32 values_count;
493 std::array<u32, 47> values{};
494};
495static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
496
497struct DefaultMii {
498 u32 face_type{};
499 u32 face_color{};
500 u32 face_wrinkle{};
501 u32 face_makeup{};
502 u32 hair_type{};
503 u32 hair_color{};
504 u32 hair_flip{};
505 u32 eye_type{};
506 u32 eye_color{};
507 u32 eye_scale{};
508 u32 eye_aspect{};
509 u32 eye_rotate{};
510 u32 eye_x{};
511 u32 eye_y{};
512 u32 eyebrow_type{};
513 u32 eyebrow_color{};
514 u32 eyebrow_scale{};
515 u32 eyebrow_aspect{};
516 u32 eyebrow_rotate{};
517 u32 eyebrow_x{};
518 u32 eyebrow_y{};
519 u32 nose_type{};
520 u32 nose_scale{};
521 u32 nose_y{};
522 u32 mouth_type{};
523 u32 mouth_color{};
524 u32 mouth_scale{};
525 u32 mouth_aspect{};
526 u32 mouth_y{};
527 u32 mustache_type{};
528 u32 beard_type{};
529 u32 beard_color{};
530 u32 mustache_scale{};
531 u32 mustache_y{};
532 u32 glasses_type{};
533 u32 glasses_color{};
534 u32 glasses_scale{};
535 u32 glasses_y{};
536 u32 mole_type{};
537 u32 mole_scale{};
538 u32 mole_x{};
539 u32 mole_y{};
540 u32 height{};
541 u32 weight{};
542 Gender gender{};
543 u32 favorite_color{};
544 u32 region{};
545 FontRegion font_region{};
546 u32 type{};
547 INSERT_PADDING_WORDS(5);
548};
549static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
550
551#pragma pack(pop)
552
553} // namespace Service::Mii
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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/mii/types/char_info.h"
5#include "core/hle/service/mii/types/store_data.h"
6
7namespace Service::Mii {
8
9void CharInfo::SetFromStoreData(const StoreData& store_data) {
10 name = store_data.GetNickname();
11 null_terminator = '\0';
12 create_id = store_data.GetCreateId();
13 font_region = store_data.GetFontRegion();
14 favorite_color = store_data.GetFavoriteColor();
15 gender = store_data.GetGender();
16 height = store_data.GetHeight();
17 build = store_data.GetBuild();
18 type = store_data.GetType();
19 region_move = store_data.GetRegionMove();
20 faceline_type = store_data.GetFacelineType();
21 faceline_color = store_data.GetFacelineColor();
22 faceline_wrinkle = store_data.GetFacelineWrinkle();
23 faceline_make = store_data.GetFacelineMake();
24 hair_type = store_data.GetHairType();
25 hair_color = store_data.GetHairColor();
26 hair_flip = store_data.GetHairFlip();
27 eye_type = store_data.GetEyeType();
28 eye_color = store_data.GetEyeColor();
29 eye_scale = store_data.GetEyeScale();
30 eye_aspect = store_data.GetEyeAspect();
31 eye_rotate = store_data.GetEyeRotate();
32 eye_x = store_data.GetEyeX();
33 eye_y = store_data.GetEyeY();
34 eyebrow_type = store_data.GetEyebrowType();
35 eyebrow_color = store_data.GetEyebrowColor();
36 eyebrow_scale = store_data.GetEyebrowScale();
37 eyebrow_aspect = store_data.GetEyebrowAspect();
38 eyebrow_rotate = store_data.GetEyebrowRotate();
39 eyebrow_x = store_data.GetEyebrowX();
40 eyebrow_y = store_data.GetEyebrowY();
41 nose_type = store_data.GetNoseType();
42 nose_scale = store_data.GetNoseScale();
43 nose_y = store_data.GetNoseY();
44 mouth_type = store_data.GetMouthType();
45 mouth_color = store_data.GetMouthColor();
46 mouth_scale = store_data.GetMouthScale();
47 mouth_aspect = store_data.GetMouthAspect();
48 mouth_y = store_data.GetMouthY();
49 beard_color = store_data.GetBeardColor();
50 beard_type = store_data.GetBeardType();
51 mustache_type = store_data.GetMustacheType();
52 mustache_scale = store_data.GetMustacheScale();
53 mustache_y = store_data.GetMustacheY();
54 glass_type = store_data.GetGlassType();
55 glass_color = store_data.GetGlassColor();
56 glass_scale = store_data.GetGlassScale();
57 glass_y = store_data.GetGlassY();
58 mole_type = store_data.GetMoleType();
59 mole_scale = store_data.GetMoleScale();
60 mole_x = store_data.GetMoleX();
61 mole_y = store_data.GetMoleY();
62 padding = '\0';
63}
64
65ValidationResult CharInfo::Verify() const {
66 if (!create_id.IsValid()) {
67 return ValidationResult::InvalidCreateId;
68 }
69 if (!name.IsValid()) {
70 return ValidationResult::InvalidName;
71 }
72 if (font_region > FontRegion::Max) {
73 return ValidationResult::InvalidFont;
74 }
75 if (favorite_color > FavoriteColor::Max) {
76 return ValidationResult::InvalidColor;
77 }
78 if (gender > Gender::Max) {
79 return ValidationResult::InvalidGender;
80 }
81 if (height > MaxHeight) {
82 return ValidationResult::InvalidHeight;
83 }
84 if (build > MaxBuild) {
85 return ValidationResult::InvalidBuild;
86 }
87 if (type > MaxType) {
88 return ValidationResult::InvalidType;
89 }
90 if (region_move > MaxRegionMove) {
91 return ValidationResult::InvalidRegionMove;
92 }
93 if (faceline_type > FacelineType::Max) {
94 return ValidationResult::InvalidFacelineType;
95 }
96 if (faceline_color > FacelineColor::Max) {
97 return ValidationResult::InvalidFacelineColor;
98 }
99 if (faceline_wrinkle > FacelineWrinkle::Max) {
100 return ValidationResult::InvalidFacelineWrinkle;
101 }
102 if (faceline_make > FacelineMake::Max) {
103 return ValidationResult::InvalidFacelineMake;
104 }
105 if (hair_type > HairType::Max) {
106 return ValidationResult::InvalidHairType;
107 }
108 if (hair_color > CommonColor::Max) {
109 return ValidationResult::InvalidHairColor;
110 }
111 if (hair_flip > HairFlip::Max) {
112 return ValidationResult::InvalidHairFlip;
113 }
114 if (eye_type > EyeType::Max) {
115 return ValidationResult::InvalidEyeType;
116 }
117 if (eye_color > CommonColor::Max) {
118 return ValidationResult::InvalidEyeColor;
119 }
120 if (eye_scale > MaxEyeScale) {
121 return ValidationResult::InvalidEyeScale;
122 }
123 if (eye_aspect > MaxEyeAspect) {
124 return ValidationResult::InvalidEyeAspect;
125 }
126 if (eye_rotate > MaxEyeX) {
127 return ValidationResult::InvalidEyeRotate;
128 }
129 if (eye_x > MaxEyeX) {
130 return ValidationResult::InvalidEyeX;
131 }
132 if (eye_y > MaxEyeY) {
133 return ValidationResult::InvalidEyeY;
134 }
135 if (eyebrow_type > EyebrowType::Max) {
136 return ValidationResult::InvalidEyebrowType;
137 }
138 if (eyebrow_color > CommonColor::Max) {
139 return ValidationResult::InvalidEyebrowColor;
140 }
141 if (eyebrow_scale > MaxEyebrowScale) {
142 return ValidationResult::InvalidEyebrowScale;
143 }
144 if (eyebrow_aspect > MaxEyebrowAspect) {
145 return ValidationResult::InvalidEyebrowAspect;
146 }
147 if (eyebrow_rotate > MaxEyebrowRotate) {
148 return ValidationResult::InvalidEyebrowRotate;
149 }
150 if (eyebrow_x > MaxEyebrowX) {
151 return ValidationResult::InvalidEyebrowX;
152 }
153 if (eyebrow_y > MaxEyebrowY) {
154 return ValidationResult::InvalidEyebrowY;
155 }
156 if (nose_type > NoseType::Max) {
157 return ValidationResult::InvalidNoseType;
158 }
159 if (nose_scale > MaxNoseScale) {
160 return ValidationResult::InvalidNoseScale;
161 }
162 if (nose_y > MaxNoseY) {
163 return ValidationResult::InvalidNoseY;
164 }
165 if (mouth_type > MouthType::Max) {
166 return ValidationResult::InvalidMouthType;
167 }
168 if (mouth_color > CommonColor::Max) {
169 return ValidationResult::InvalidMouthColor;
170 }
171 if (mouth_scale > MaxMouthScale) {
172 return ValidationResult::InvalidMouthScale;
173 }
174 if (mouth_aspect > MaxMoutAspect) {
175 return ValidationResult::InvalidMouthAspect;
176 }
177 if (mouth_y > MaxMouthY) {
178 return ValidationResult::InvalidMoleY;
179 }
180 if (beard_color > CommonColor::Max) {
181 return ValidationResult::InvalidBeardColor;
182 }
183 if (beard_type > BeardType::Max) {
184 return ValidationResult::InvalidBeardType;
185 }
186 if (mustache_type > MustacheType::Max) {
187 return ValidationResult::InvalidMustacheType;
188 }
189 if (mustache_scale > MaxMustacheScale) {
190 return ValidationResult::InvalidMustacheScale;
191 }
192 if (mustache_y > MasMustacheY) {
193 return ValidationResult::InvalidMustacheY;
194 }
195 if (glass_type > GlassType::Max) {
196 return ValidationResult::InvalidGlassType;
197 }
198 if (glass_color > CommonColor::Max) {
199 return ValidationResult::InvalidGlassColor;
200 }
201 if (glass_scale > MaxGlassScale) {
202 return ValidationResult::InvalidGlassScale;
203 }
204 if (glass_y > MaxGlassY) {
205 return ValidationResult::InvalidGlassY;
206 }
207 if (mole_type > MoleType::Max) {
208 return ValidationResult::InvalidMoleType;
209 }
210 if (mole_scale > MaxMoleScale) {
211 return ValidationResult::InvalidMoleScale;
212 }
213 if (mole_x > MaxMoleX) {
214 return ValidationResult::InvalidMoleX;
215 }
216 if (mole_y > MaxMoleY) {
217 return ValidationResult::InvalidMoleY;
218 }
219 return ValidationResult::NoErrors;
220}
221
222Common::UUID CharInfo::GetCreateId() const {
223 return create_id;
224}
225
226Nickname CharInfo::GetNickname() const {
227 return name;
228}
229
230FontRegion CharInfo::GetFontRegion() const {
231 return font_region;
232}
233
234FavoriteColor CharInfo::GetFavoriteColor() const {
235 return favorite_color;
236}
237
238Gender CharInfo::GetGender() const {
239 return gender;
240}
241
242u8 CharInfo::GetHeight() const {
243 return height;
244}
245
246u8 CharInfo::GetBuild() const {
247 return build;
248}
249
250u8 CharInfo::GetType() const {
251 return type;
252}
253
254u8 CharInfo::GetRegionMove() const {
255 return region_move;
256}
257
258FacelineType CharInfo::GetFacelineType() const {
259 return faceline_type;
260}
261
262FacelineColor CharInfo::GetFacelineColor() const {
263 return faceline_color;
264}
265
266FacelineWrinkle CharInfo::GetFacelineWrinkle() const {
267 return faceline_wrinkle;
268}
269
270FacelineMake CharInfo::GetFacelineMake() const {
271 return faceline_make;
272}
273
274HairType CharInfo::GetHairType() const {
275 return hair_type;
276}
277
278CommonColor CharInfo::GetHairColor() const {
279 return hair_color;
280}
281
282HairFlip CharInfo::GetHairFlip() const {
283 return hair_flip;
284}
285
286EyeType CharInfo::GetEyeType() const {
287 return eye_type;
288}
289
290CommonColor CharInfo::GetEyeColor() const {
291 return eye_color;
292}
293
294u8 CharInfo::GetEyeScale() const {
295 return eye_scale;
296}
297
298u8 CharInfo::GetEyeAspect() const {
299 return eye_aspect;
300}
301
302u8 CharInfo::GetEyeRotate() const {
303 return eye_rotate;
304}
305
306u8 CharInfo::GetEyeX() const {
307 return eye_x;
308}
309
310u8 CharInfo::GetEyeY() const {
311 return eye_y;
312}
313
314EyebrowType CharInfo::GetEyebrowType() const {
315 return eyebrow_type;
316}
317
318CommonColor CharInfo::GetEyebrowColor() const {
319 return eyebrow_color;
320}
321
322u8 CharInfo::GetEyebrowScale() const {
323 return eyebrow_scale;
324}
325
326u8 CharInfo::GetEyebrowAspect() const {
327 return eyebrow_aspect;
328}
329
330u8 CharInfo::GetEyebrowRotate() const {
331 return eyebrow_rotate;
332}
333
334u8 CharInfo::GetEyebrowX() const {
335 return eyebrow_x;
336}
337
338u8 CharInfo::GetEyebrowY() const {
339 return eyebrow_y;
340}
341
342NoseType CharInfo::GetNoseType() const {
343 return nose_type;
344}
345
346u8 CharInfo::GetNoseScale() const {
347 return nose_scale;
348}
349
350u8 CharInfo::GetNoseY() const {
351 return nose_y;
352}
353
354MouthType CharInfo::GetMouthType() const {
355 return mouth_type;
356}
357
358CommonColor CharInfo::GetMouthColor() const {
359 return mouth_color;
360}
361
362u8 CharInfo::GetMouthScale() const {
363 return mouth_scale;
364}
365
366u8 CharInfo::GetMouthAspect() const {
367 return mouth_aspect;
368}
369
370u8 CharInfo::GetMouthY() const {
371 return mouth_y;
372}
373
374CommonColor CharInfo::GetBeardColor() const {
375 return beard_color;
376}
377
378BeardType CharInfo::GetBeardType() const {
379 return beard_type;
380}
381
382MustacheType CharInfo::GetMustacheType() const {
383 return mustache_type;
384}
385
386u8 CharInfo::GetMustacheScale() const {
387 return mustache_scale;
388}
389
390u8 CharInfo::GetMustacheY() const {
391 return mustache_y;
392}
393
394GlassType CharInfo::GetGlassType() const {
395 return glass_type;
396}
397
398CommonColor CharInfo::GetGlassColor() const {
399 return glass_color;
400}
401
402u8 CharInfo::GetGlassScale() const {
403 return glass_scale;
404}
405
406u8 CharInfo::GetGlassY() const {
407 return glass_y;
408}
409
410MoleType CharInfo::GetMoleType() const {
411 return mole_type;
412}
413
414u8 CharInfo::GetMoleScale() const {
415 return mole_scale;
416}
417
418u8 CharInfo::GetMoleX() const {
419 return mole_x;
420}
421
422u8 CharInfo::GetMoleY() const {
423 return mole_y;
424}
425
426bool CharInfo::operator==(const CharInfo& info) {
427 bool is_identical = info.Verify() == ValidationResult::NoErrors;
428 is_identical &= name.data == info.GetNickname().data;
429 is_identical &= create_id == info.GetCreateId();
430 is_identical &= font_region == info.GetFontRegion();
431 is_identical &= favorite_color == info.GetFavoriteColor();
432 is_identical &= gender == info.GetGender();
433 is_identical &= height == info.GetHeight();
434 is_identical &= build == info.GetBuild();
435 is_identical &= type == info.GetType();
436 is_identical &= region_move == info.GetRegionMove();
437 is_identical &= faceline_type == info.GetFacelineType();
438 is_identical &= faceline_color == info.GetFacelineColor();
439 is_identical &= faceline_wrinkle == info.GetFacelineWrinkle();
440 is_identical &= faceline_make == info.GetFacelineMake();
441 is_identical &= hair_type == info.GetHairType();
442 is_identical &= hair_color == info.GetHairColor();
443 is_identical &= hair_flip == info.GetHairFlip();
444 is_identical &= eye_type == info.GetEyeType();
445 is_identical &= eye_color == info.GetEyeColor();
446 is_identical &= eye_scale == info.GetEyeScale();
447 is_identical &= eye_aspect == info.GetEyeAspect();
448 is_identical &= eye_rotate == info.GetEyeRotate();
449 is_identical &= eye_x == info.GetEyeX();
450 is_identical &= eye_y == info.GetEyeY();
451 is_identical &= eyebrow_type == info.GetEyebrowType();
452 is_identical &= eyebrow_color == info.GetEyebrowColor();
453 is_identical &= eyebrow_scale == info.GetEyebrowScale();
454 is_identical &= eyebrow_aspect == info.GetEyebrowAspect();
455 is_identical &= eyebrow_rotate == info.GetEyebrowRotate();
456 is_identical &= eyebrow_x == info.GetEyebrowX();
457 is_identical &= eyebrow_y == info.GetEyebrowY();
458 is_identical &= nose_type == info.GetNoseType();
459 is_identical &= nose_scale == info.GetNoseScale();
460 is_identical &= nose_y == info.GetNoseY();
461 is_identical &= mouth_type == info.GetMouthType();
462 is_identical &= mouth_color == info.GetMouthColor();
463 is_identical &= mouth_scale == info.GetMouthScale();
464 is_identical &= mouth_aspect == info.GetMouthAspect();
465 is_identical &= mouth_y == info.GetMouthY();
466 is_identical &= beard_color == info.GetBeardColor();
467 is_identical &= beard_type == info.GetBeardType();
468 is_identical &= mustache_type == info.GetMustacheType();
469 is_identical &= mustache_scale == info.GetMustacheScale();
470 is_identical &= mustache_y == info.GetMustacheY();
471 is_identical &= glass_type == info.GetGlassType();
472 is_identical &= glass_color == info.GetGlassColor();
473 is_identical &= glass_scale == info.GetGlassScale();
474 is_identical &= glass_y == info.GetGlassY();
475 is_identical &= mole_type == info.GetMoleType();
476 is_identical &= mole_scale == info.GetMoleScale();
477 is_identical &= mole_x == info.GetMoleX();
478 is_identical &= mole_y == info.GetMoleY();
479 return is_identical;
480}
481
482} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/mii/mii_types.h"
7
8namespace Service::Mii {
9class StoreData;
10
11// This is nn::mii::detail::CharInfoRaw
12class CharInfo {
13public:
14 void SetFromStoreData(const StoreData& store_data_raw);
15
16 ValidationResult Verify() const;
17
18 Common::UUID GetCreateId() const;
19 Nickname GetNickname() const;
20 FontRegion GetFontRegion() const;
21 FavoriteColor GetFavoriteColor() const;
22 Gender GetGender() const;
23 u8 GetHeight() const;
24 u8 GetBuild() const;
25 u8 GetType() const;
26 u8 GetRegionMove() const;
27 FacelineType GetFacelineType() const;
28 FacelineColor GetFacelineColor() const;
29 FacelineWrinkle GetFacelineWrinkle() const;
30 FacelineMake GetFacelineMake() const;
31 HairType GetHairType() const;
32 CommonColor GetHairColor() const;
33 HairFlip GetHairFlip() const;
34 EyeType GetEyeType() const;
35 CommonColor GetEyeColor() const;
36 u8 GetEyeScale() const;
37 u8 GetEyeAspect() const;
38 u8 GetEyeRotate() const;
39 u8 GetEyeX() const;
40 u8 GetEyeY() const;
41 EyebrowType GetEyebrowType() const;
42 CommonColor GetEyebrowColor() const;
43 u8 GetEyebrowScale() const;
44 u8 GetEyebrowAspect() const;
45 u8 GetEyebrowRotate() const;
46 u8 GetEyebrowX() const;
47 u8 GetEyebrowY() const;
48 NoseType GetNoseType() const;
49 u8 GetNoseScale() const;
50 u8 GetNoseY() const;
51 MouthType GetMouthType() const;
52 CommonColor GetMouthColor() const;
53 u8 GetMouthScale() const;
54 u8 GetMouthAspect() const;
55 u8 GetMouthY() const;
56 CommonColor GetBeardColor() const;
57 BeardType GetBeardType() const;
58 MustacheType GetMustacheType() const;
59 u8 GetMustacheScale() const;
60 u8 GetMustacheY() const;
61 GlassType GetGlassType() const;
62 CommonColor GetGlassColor() const;
63 u8 GetGlassScale() const;
64 u8 GetGlassY() const;
65 MoleType GetMoleType() const;
66 u8 GetMoleScale() const;
67 u8 GetMoleX() const;
68 u8 GetMoleY() const;
69
70 bool operator==(const CharInfo& info);
71
72private:
73 Common::UUID create_id;
74 Nickname name;
75 u16 null_terminator;
76 FontRegion font_region;
77 FavoriteColor favorite_color;
78 Gender gender;
79 u8 height;
80 u8 build;
81 u8 type;
82 u8 region_move;
83 FacelineType faceline_type;
84 FacelineColor faceline_color;
85 FacelineWrinkle faceline_wrinkle;
86 FacelineMake faceline_make;
87 HairType hair_type;
88 CommonColor hair_color;
89 HairFlip hair_flip;
90 EyeType eye_type;
91 CommonColor eye_color;
92 u8 eye_scale;
93 u8 eye_aspect;
94 u8 eye_rotate;
95 u8 eye_x;
96 u8 eye_y;
97 EyebrowType eyebrow_type;
98 CommonColor eyebrow_color;
99 u8 eyebrow_scale;
100 u8 eyebrow_aspect;
101 u8 eyebrow_rotate;
102 u8 eyebrow_x;
103 u8 eyebrow_y;
104 NoseType nose_type;
105 u8 nose_scale;
106 u8 nose_y;
107 MouthType mouth_type;
108 CommonColor mouth_color;
109 u8 mouth_scale;
110 u8 mouth_aspect;
111 u8 mouth_y;
112 CommonColor beard_color;
113 BeardType beard_type;
114 MustacheType mustache_type;
115 u8 mustache_scale;
116 u8 mustache_y;
117 GlassType glass_type;
118 CommonColor glass_color;
119 u8 glass_scale;
120 u8 glass_y;
121 MoleType mole_type;
122 u8 mole_scale;
123 u8 mole_x;
124 u8 mole_y;
125 u8 padding;
126};
127static_assert(sizeof(CharInfo) == 0x58, "CharInfo has incorrect size.");
128static_assert(std::has_unique_object_representations_v<CharInfo>,
129 "All bits of CharInfo must contribute to its value.");
130
131struct CharInfoElement {
132 CharInfo char_info{};
133 Source source{};
134};
135static_assert(sizeof(CharInfoElement) == 0x5c, "CharInfoElement has incorrect size.");
136
137}; // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/assert.h"
5#include "core/hle/service/mii/mii_util.h"
6#include "core/hle/service/mii/types/core_data.h"
7#include "core/hle/service/mii/types/raw_data.h"
8
9namespace Service::Mii {
10
11void CoreData::SetDefault() {
12 data = {};
13 name = GetDefaultNickname();
14}
15
16void CoreData::BuildRandom(Age age, Gender gender, Race race) {
17 if (gender == Gender::All) {
18 gender = MiiUtil::GetRandomValue(Gender::Max);
19 }
20
21 if (age == Age::All) {
22 const auto random{MiiUtil::GetRandomValue<int>(10)};
23 if (random >= 8) {
24 age = Age::Old;
25 } else if (random >= 4) {
26 age = Age::Normal;
27 } else {
28 age = Age::Young;
29 }
30 }
31
32 if (race == Race::All) {
33 const auto random{MiiUtil::GetRandomValue<int>(10)};
34 if (random >= 8) {
35 race = Race::Black;
36 } else if (random >= 4) {
37 race = Race::White;
38 } else {
39 race = Race::Asian;
40 }
41 }
42
43 SetGender(gender);
44 SetFavoriteColor(MiiUtil::GetRandomValue(FavoriteColor::Max));
45 SetRegionMove(0);
46 SetFontRegion(FontRegion::Standard);
47 SetType(0);
48 SetHeight(64);
49 SetBuild(64);
50
51 u32 axis_y{};
52 if (gender == Gender::Female && age == Age::Young) {
53 axis_y = MiiUtil::GetRandomValue<u32>(3);
54 }
55
56 const std::size_t index{3 * static_cast<std::size_t>(age) +
57 9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
58
59 const auto& faceline_type_info{RawData::RandomMiiFaceline.at(index)};
60 const auto& faceline_color_info{RawData::RandomMiiFacelineColor.at(
61 3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
62 const auto& faceline_wrinkle_info{RawData::RandomMiiFacelineWrinkle.at(index)};
63 const auto& faceline_makeup_info{RawData::RandomMiiFacelineMakeup.at(index)};
64 const auto& hair_type_info{RawData::RandomMiiHairType.at(index)};
65 const auto& hair_color_info{RawData::RandomMiiHairColor.at(3 * static_cast<std::size_t>(race) +
66 static_cast<std::size_t>(age))};
67 const auto& eye_type_info{RawData::RandomMiiEyeType.at(index)};
68 const auto& eye_color_info{RawData::RandomMiiEyeColor.at(static_cast<std::size_t>(race))};
69 const auto& eyebrow_type_info{RawData::RandomMiiEyebrowType.at(index)};
70 const auto& nose_type_info{RawData::RandomMiiNoseType.at(index)};
71 const auto& mouth_type_info{RawData::RandomMiiMouthType.at(index)};
72 const auto& glasses_type_info{RawData::RandomMiiGlassType.at(static_cast<std::size_t>(age))};
73
74 data.faceline_type.Assign(
75 faceline_type_info
76 .values[MiiUtil::GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
77 data.faceline_color.Assign(
78 faceline_color_info
79 .values[MiiUtil::GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
80 data.faceline_wrinkle.Assign(
81 faceline_wrinkle_info
82 .values[MiiUtil::GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
83 data.faceline_makeup.Assign(
84 faceline_makeup_info
85 .values[MiiUtil::GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
86
87 data.hair_type.Assign(
88 hair_type_info.values[MiiUtil::GetRandomValue<std::size_t>(hair_type_info.values_count)]);
89 SetHairColor(RawData::GetHairColorFromVer3(
90 hair_color_info
91 .values[MiiUtil::GetRandomValue<std::size_t>(hair_color_info.values_count)]));
92 SetHairFlip(MiiUtil::GetRandomValue(HairFlip::Max));
93
94 data.eye_type.Assign(
95 eye_type_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_type_info.values_count)]);
96
97 const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
98 const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
99 const auto eye_rotate_offset{32 - RawData::EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
100 const auto eye_rotate{32 - RawData::EyeRotateLookup[data.eye_type]};
101
102 SetEyeColor(RawData::GetEyeColorFromVer3(
103 eye_color_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_color_info.values_count)]));
104 SetEyeScale(4);
105 SetEyeAspect(3);
106 SetEyeRotate(static_cast<u8>(eye_rotate_offset - eye_rotate));
107 SetEyeX(2);
108 SetEyeY(static_cast<u8>(axis_y + 12));
109
110 data.eyebrow_type.Assign(
111 eyebrow_type_info
112 .values[MiiUtil::GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
113
114 const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
115 const auto eyebrow_y{race == Race::Asian ? 9 : 10};
116 const auto eyebrow_rotate_offset{32 - RawData::EyebrowRotateLookup[eyebrow_rotate_1] + 6};
117 const auto eyebrow_rotate{
118 32 - RawData::EyebrowRotateLookup[static_cast<std::size_t>(data.eyebrow_type.Value())]};
119
120 SetEyebrowColor(GetHairColor());
121 SetEyebrowScale(4);
122 SetEyebrowAspect(3);
123 SetEyebrowRotate(static_cast<u8>(eyebrow_rotate_offset - eyebrow_rotate));
124 SetEyebrowX(2);
125 SetEyebrowY(static_cast<u8>(axis_y + eyebrow_y));
126
127 data.nose_type.Assign(
128 nose_type_info.values[MiiUtil::GetRandomValue<std::size_t>(nose_type_info.values_count)]);
129 SetNoseScale(gender == Gender::Female ? 3 : 4);
130 SetNoseY(static_cast<u8>(axis_y + 9));
131
132 const auto mouth_color{gender == Gender::Female ? MiiUtil::GetRandomValue<int>(4) : 0};
133
134 data.mouth_type.Assign(
135 mouth_type_info.values[MiiUtil::GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
136 SetMouthColor(RawData::GetMouthColorFromVer3(mouth_color));
137 SetMouthScale(4);
138 SetMouthAspect(3);
139 SetMouthY(static_cast<u8>(axis_y + 13));
140
141 SetBeardColor(GetHairColor());
142 SetMustacheScale(4);
143
144 if (gender == Gender::Male && age != Age::Young && MiiUtil::GetRandomValue<int>(10) < 2) {
145 const auto mustache_and_beard_flag{MiiUtil::GetRandomValue(BeardAndMustacheFlag::All)};
146
147 auto beard_type{BeardType::None};
148 auto mustache_type{MustacheType::None};
149
150 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
151 BeardAndMustacheFlag::Beard) {
152 beard_type = MiiUtil::GetRandomValue(BeardType::Min, BeardType::Max);
153 }
154
155 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
156 BeardAndMustacheFlag::Mustache) {
157 mustache_type = MiiUtil::GetRandomValue(MustacheType::Min, MustacheType::Max);
158 }
159
160 SetMustacheType(mustache_type);
161 SetBeardType(beard_type);
162 SetMustacheY(10);
163 } else {
164 SetMustacheType(MustacheType::None);
165 SetBeardType(BeardType::None);
166 SetMustacheY(static_cast<u8>(axis_y + 10));
167 }
168
169 const auto glasses_type_start{MiiUtil::GetRandomValue<std::size_t>(100)};
170 u8 glasses_type{};
171 while (glasses_type_start < glasses_type_info.values[glasses_type]) {
172 if (++glasses_type >= glasses_type_info.values_count) {
173 ASSERT(false);
174 break;
175 }
176 }
177
178 SetGlassType(static_cast<GlassType>(glasses_type));
179 SetGlassColor(RawData::GetGlassColorFromVer3(0));
180 SetGlassScale(4);
181
182 SetMoleType(MoleType::None);
183 SetMoleScale(4);
184 SetMoleX(2);
185 SetMoleY(20);
186}
187
188u32 CoreData::IsValid() const {
189 // TODO: Complete this
190 return 0;
191}
192
193void CoreData::SetFontRegion(FontRegion value) {
194 data.font_region.Assign(static_cast<u32>(value));
195}
196
197void CoreData::SetFavoriteColor(FavoriteColor value) {
198 data.favorite_color.Assign(static_cast<u32>(value));
199}
200
201void CoreData::SetGender(Gender value) {
202 data.gender.Assign(static_cast<u32>(value));
203}
204
205void CoreData::SetHeight(u8 value) {
206 data.height.Assign(value);
207}
208
209void CoreData::SetBuild(u8 value) {
210 data.build.Assign(value);
211}
212
213void CoreData::SetType(u8 value) {
214 data.type.Assign(value);
215}
216
217void CoreData::SetRegionMove(u8 value) {
218 data.region_move.Assign(value);
219}
220
221void CoreData::SetFacelineType(FacelineType value) {
222 data.faceline_type.Assign(static_cast<u32>(value));
223}
224
225void CoreData::SetFacelineColor(FacelineColor value) {
226 data.faceline_color.Assign(static_cast<u32>(value));
227}
228
229void CoreData::SetFacelineWrinkle(FacelineWrinkle value) {
230 data.faceline_wrinkle.Assign(static_cast<u32>(value));
231}
232
233void CoreData::SetFacelineMake(FacelineMake value) {
234 data.faceline_makeup.Assign(static_cast<u32>(value));
235}
236
237void CoreData::SetHairType(HairType value) {
238 data.hair_type.Assign(static_cast<u32>(value));
239}
240
241void CoreData::SetHairColor(CommonColor value) {
242 data.hair_color.Assign(static_cast<u32>(value));
243}
244
245void CoreData::SetHairFlip(HairFlip value) {
246 data.hair_flip.Assign(static_cast<u32>(value));
247}
248
249void CoreData::SetEyeType(EyeType value) {
250 data.eye_type.Assign(static_cast<u32>(value));
251}
252
253void CoreData::SetEyeColor(CommonColor value) {
254 data.eye_color.Assign(static_cast<u32>(value));
255}
256
257void CoreData::SetEyeScale(u8 value) {
258 data.eye_scale.Assign(value);
259}
260
261void CoreData::SetEyeAspect(u8 value) {
262 data.eye_aspect.Assign(value);
263}
264
265void CoreData::SetEyeRotate(u8 value) {
266 data.eye_rotate.Assign(value);
267}
268
269void CoreData::SetEyeX(u8 value) {
270 data.eye_x.Assign(value);
271}
272
273void CoreData::SetEyeY(u8 value) {
274 data.eye_y.Assign(value);
275}
276
277void CoreData::SetEyebrowType(EyebrowType value) {
278 data.eyebrow_type.Assign(static_cast<u32>(value));
279}
280
281void CoreData::SetEyebrowColor(CommonColor value) {
282 data.eyebrow_color.Assign(static_cast<u32>(value));
283}
284
285void CoreData::SetEyebrowScale(u8 value) {
286 data.eyebrow_scale.Assign(value);
287}
288
289void CoreData::SetEyebrowAspect(u8 value) {
290 data.eyebrow_aspect.Assign(value);
291}
292
293void CoreData::SetEyebrowRotate(u8 value) {
294 data.eyebrow_rotate.Assign(value);
295}
296
297void CoreData::SetEyebrowX(u8 value) {
298 data.eyebrow_x.Assign(value);
299}
300
301void CoreData::SetEyebrowY(u8 value) {
302 data.eyebrow_y.Assign(value);
303}
304
305void CoreData::SetNoseType(NoseType value) {
306 data.nose_type.Assign(static_cast<u32>(value));
307}
308
309void CoreData::SetNoseScale(u8 value) {
310 data.nose_scale.Assign(value);
311}
312
313void CoreData::SetNoseY(u8 value) {
314 data.nose_y.Assign(value);
315}
316
317void CoreData::SetMouthType(u8 value) {
318 data.mouth_type.Assign(value);
319}
320
321void CoreData::SetMouthColor(CommonColor value) {
322 data.mouth_color.Assign(static_cast<u32>(value));
323}
324
325void CoreData::SetMouthScale(u8 value) {
326 data.mouth_scale.Assign(value);
327}
328
329void CoreData::SetMouthAspect(u8 value) {
330 data.mouth_aspect.Assign(value);
331}
332
333void CoreData::SetMouthY(u8 value) {
334 data.mouth_y.Assign(value);
335}
336
337void CoreData::SetBeardColor(CommonColor value) {
338 data.beard_color.Assign(static_cast<u32>(value));
339}
340
341void CoreData::SetBeardType(BeardType value) {
342 data.beard_type.Assign(static_cast<u32>(value));
343}
344
345void CoreData::SetMustacheType(MustacheType value) {
346 data.mustache_type.Assign(static_cast<u32>(value));
347}
348
349void CoreData::SetMustacheScale(u8 value) {
350 data.mustache_scale.Assign(value);
351}
352
353void CoreData::SetMustacheY(u8 value) {
354 data.mustache_y.Assign(value);
355}
356
357void CoreData::SetGlassType(GlassType value) {
358 data.glasses_type.Assign(static_cast<u32>(value));
359}
360
361void CoreData::SetGlassColor(CommonColor value) {
362 data.glasses_color.Assign(static_cast<u32>(value));
363}
364
365void CoreData::SetGlassScale(u8 value) {
366 data.glasses_scale.Assign(value);
367}
368
369void CoreData::SetGlassY(u8 value) {
370 data.glasses_y.Assign(value);
371}
372
373void CoreData::SetMoleType(MoleType value) {
374 data.mole_type.Assign(static_cast<u32>(value));
375}
376
377void CoreData::SetMoleScale(u8 value) {
378 data.mole_scale.Assign(value);
379}
380
381void CoreData::SetMoleX(u8 value) {
382 data.mole_x.Assign(value);
383}
384
385void CoreData::SetMoleY(u8 value) {
386 data.mole_y.Assign(value);
387}
388
389void CoreData::SetNickname(Nickname nickname) {
390 name = nickname;
391}
392
393FontRegion CoreData::GetFontRegion() const {
394 return static_cast<FontRegion>(data.font_region.Value());
395}
396
397FavoriteColor CoreData::GetFavoriteColor() const {
398 return static_cast<FavoriteColor>(data.favorite_color.Value());
399}
400
401Gender CoreData::GetGender() const {
402 return static_cast<Gender>(data.gender.Value());
403}
404
405u8 CoreData::GetHeight() const {
406 return static_cast<u8>(data.height.Value());
407}
408
409u8 CoreData::GetBuild() const {
410 return static_cast<u8>(data.build.Value());
411}
412
413u8 CoreData::GetType() const {
414 return static_cast<u8>(data.type.Value());
415}
416
417u8 CoreData::GetRegionMove() const {
418 return static_cast<u8>(data.region_move.Value());
419}
420
421FacelineType CoreData::GetFacelineType() const {
422 return static_cast<FacelineType>(data.faceline_type.Value());
423}
424
425FacelineColor CoreData::GetFacelineColor() const {
426 return static_cast<FacelineColor>(data.faceline_color.Value());
427}
428
429FacelineWrinkle CoreData::GetFacelineWrinkle() const {
430 return static_cast<FacelineWrinkle>(data.faceline_wrinkle.Value());
431}
432
433FacelineMake CoreData::GetFacelineMake() const {
434 return static_cast<FacelineMake>(data.faceline_makeup.Value());
435}
436
437HairType CoreData::GetHairType() const {
438 return static_cast<HairType>(data.hair_type.Value());
439}
440
441CommonColor CoreData::GetHairColor() const {
442 return static_cast<CommonColor>(data.hair_color.Value());
443}
444
445HairFlip CoreData::GetHairFlip() const {
446 return static_cast<HairFlip>(data.hair_flip.Value());
447}
448
449EyeType CoreData::GetEyeType() const {
450 return static_cast<EyeType>(data.eye_type.Value());
451}
452
453CommonColor CoreData::GetEyeColor() const {
454 return static_cast<CommonColor>(data.eye_color.Value());
455}
456
457u8 CoreData::GetEyeScale() const {
458 return static_cast<u8>(data.eye_scale.Value());
459}
460
461u8 CoreData::GetEyeAspect() const {
462 return static_cast<u8>(data.eye_aspect.Value());
463}
464
465u8 CoreData::GetEyeRotate() const {
466 return static_cast<u8>(data.eye_rotate.Value());
467}
468
469u8 CoreData::GetEyeX() const {
470 return static_cast<u8>(data.eye_x.Value());
471}
472
473u8 CoreData::GetEyeY() const {
474 return static_cast<u8>(data.eye_y.Value());
475}
476
477EyebrowType CoreData::GetEyebrowType() const {
478 return static_cast<EyebrowType>(data.eyebrow_type.Value());
479}
480
481CommonColor CoreData::GetEyebrowColor() const {
482 return static_cast<CommonColor>(data.eyebrow_color.Value());
483}
484
485u8 CoreData::GetEyebrowScale() const {
486 return static_cast<u8>(data.eyebrow_scale.Value());
487}
488
489u8 CoreData::GetEyebrowAspect() const {
490 return static_cast<u8>(data.eyebrow_aspect.Value());
491}
492
493u8 CoreData::GetEyebrowRotate() const {
494 return static_cast<u8>(data.eyebrow_rotate.Value());
495}
496
497u8 CoreData::GetEyebrowX() const {
498 return static_cast<u8>(data.eyebrow_x.Value());
499}
500
501u8 CoreData::GetEyebrowY() const {
502 return static_cast<u8>(data.eyebrow_y.Value());
503}
504
505NoseType CoreData::GetNoseType() const {
506 return static_cast<NoseType>(data.nose_type.Value());
507}
508
509u8 CoreData::GetNoseScale() const {
510 return static_cast<u8>(data.nose_scale.Value());
511}
512
513u8 CoreData::GetNoseY() const {
514 return static_cast<u8>(data.nose_y.Value());
515}
516
517MouthType CoreData::GetMouthType() const {
518 return static_cast<MouthType>(data.mouth_type.Value());
519}
520
521CommonColor CoreData::GetMouthColor() const {
522 return static_cast<CommonColor>(data.mouth_color.Value());
523}
524
525u8 CoreData::GetMouthScale() const {
526 return static_cast<u8>(data.mouth_scale.Value());
527}
528
529u8 CoreData::GetMouthAspect() const {
530 return static_cast<u8>(data.mouth_aspect.Value());
531}
532
533u8 CoreData::GetMouthY() const {
534 return static_cast<u8>(data.mouth_y.Value());
535}
536
537CommonColor CoreData::GetBeardColor() const {
538 return static_cast<CommonColor>(data.beard_color.Value());
539}
540
541BeardType CoreData::GetBeardType() const {
542 return static_cast<BeardType>(data.beard_type.Value());
543}
544
545MustacheType CoreData::GetMustacheType() const {
546 return static_cast<MustacheType>(data.mustache_type.Value());
547}
548
549u8 CoreData::GetMustacheScale() const {
550 return static_cast<u8>(data.mustache_scale.Value());
551}
552
553u8 CoreData::GetMustacheY() const {
554 return static_cast<u8>(data.mustache_y.Value());
555}
556
557GlassType CoreData::GetGlassType() const {
558 return static_cast<GlassType>(data.glasses_type.Value());
559}
560
561CommonColor CoreData::GetGlassColor() const {
562 return static_cast<CommonColor>(data.glasses_color.Value());
563}
564
565u8 CoreData::GetGlassScale() const {
566 return static_cast<u8>(data.glasses_scale.Value());
567}
568
569u8 CoreData::GetGlassY() const {
570 return static_cast<u8>(data.glasses_y.Value());
571}
572
573MoleType CoreData::GetMoleType() const {
574 return static_cast<MoleType>(data.mole_type.Value());
575}
576
577u8 CoreData::GetMoleScale() const {
578 return static_cast<u8>(data.mole_scale.Value());
579}
580
581u8 CoreData::GetMoleX() const {
582 return static_cast<u8>(data.mole_x.Value());
583}
584
585u8 CoreData::GetMoleY() const {
586 return static_cast<u8>(data.mole_y.Value());
587}
588
589Nickname CoreData::GetNickname() const {
590 return name;
591}
592
593Nickname CoreData::GetDefaultNickname() const {
594 return {u'n', u'o', u' ', u'n', u'a', u'm', u'e'};
595}
596
597Nickname CoreData::GetInvalidNickname() const {
598 return {u'?', u'?', u'?'};
599}
600
601} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/mii/mii_types.h"
7
8namespace Service::Mii {
9
10struct StoreDataBitFields {
11 union {
12 u32 word_0{};
13
14 BitField<0, 8, u32> hair_type;
15 BitField<8, 7, u32> height;
16 BitField<15, 1, u32> mole_type;
17 BitField<16, 7, u32> build;
18 BitField<23, 1, u32> hair_flip;
19 BitField<24, 7, u32> hair_color;
20 BitField<31, 1, u32> type;
21 };
22
23 union {
24 u32 word_1{};
25
26 BitField<0, 7, u32> eye_color;
27 BitField<7, 1, u32> gender;
28 BitField<8, 7, u32> eyebrow_color;
29 BitField<16, 7, u32> mouth_color;
30 BitField<24, 7, u32> beard_color;
31 };
32
33 union {
34 u32 word_2{};
35
36 BitField<0, 7, u32> glasses_color;
37 BitField<8, 6, u32> eye_type;
38 BitField<14, 2, u32> region_move;
39 BitField<16, 6, u32> mouth_type;
40 BitField<22, 2, u32> font_region;
41 BitField<24, 5, u32> eye_y;
42 BitField<29, 3, u32> glasses_scale;
43 };
44
45 union {
46 u32 word_3{};
47
48 BitField<0, 5, u32> eyebrow_type;
49 BitField<5, 3, u32> mustache_type;
50 BitField<8, 5, u32> nose_type;
51 BitField<13, 3, u32> beard_type;
52 BitField<16, 5, u32> nose_y;
53 BitField<21, 3, u32> mouth_aspect;
54 BitField<24, 5, u32> mouth_y;
55 BitField<29, 3, u32> eyebrow_aspect;
56 };
57
58 union {
59 u32 word_4{};
60
61 BitField<0, 5, u32> mustache_y;
62 BitField<5, 3, u32> eye_rotate;
63 BitField<8, 5, u32> glasses_y;
64 BitField<13, 3, u32> eye_aspect;
65 BitField<16, 5, u32> mole_x;
66 BitField<21, 3, u32> eye_scale;
67 BitField<24, 5, u32> mole_y;
68 };
69
70 union {
71 u32 word_5{};
72
73 BitField<0, 5, u32> glasses_type;
74 BitField<8, 4, u32> favorite_color;
75 BitField<12, 4, u32> faceline_type;
76 BitField<16, 4, u32> faceline_color;
77 BitField<20, 4, u32> faceline_wrinkle;
78 BitField<24, 4, u32> faceline_makeup;
79 BitField<28, 4, u32> eye_x;
80 };
81
82 union {
83 u32 word_6{};
84
85 BitField<0, 4, u32> eyebrow_scale;
86 BitField<4, 4, u32> eyebrow_rotate;
87 BitField<8, 4, u32> eyebrow_x;
88 BitField<12, 4, u32> eyebrow_y;
89 BitField<16, 4, u32> nose_scale;
90 BitField<20, 4, u32> mouth_scale;
91 BitField<24, 4, u32> mustache_scale;
92 BitField<28, 4, u32> mole_scale;
93 };
94};
95static_assert(sizeof(StoreDataBitFields) == 0x1c, "StoreDataBitFields has incorrect size.");
96static_assert(std::is_trivially_copyable_v<StoreDataBitFields>,
97 "StoreDataBitFields is not trivially copyable.");
98
99class CoreData {
100public:
101 void SetDefault();
102 void BuildRandom(Age age, Gender gender, Race race);
103
104 u32 IsValid() const;
105
106 void SetFontRegion(FontRegion value);
107 void SetFavoriteColor(FavoriteColor value);
108 void SetGender(Gender value);
109 void SetHeight(u8 value);
110 void SetBuild(u8 value);
111 void SetType(u8 value);
112 void SetRegionMove(u8 value);
113 void SetFacelineType(FacelineType value);
114 void SetFacelineColor(FacelineColor value);
115 void SetFacelineWrinkle(FacelineWrinkle value);
116 void SetFacelineMake(FacelineMake value);
117 void SetHairType(HairType value);
118 void SetHairColor(CommonColor value);
119 void SetHairFlip(HairFlip value);
120 void SetEyeType(EyeType value);
121 void SetEyeColor(CommonColor value);
122 void SetEyeScale(u8 value);
123 void SetEyeAspect(u8 value);
124 void SetEyeRotate(u8 value);
125 void SetEyeX(u8 value);
126 void SetEyeY(u8 value);
127 void SetEyebrowType(EyebrowType value);
128 void SetEyebrowColor(CommonColor value);
129 void SetEyebrowScale(u8 value);
130 void SetEyebrowAspect(u8 value);
131 void SetEyebrowRotate(u8 value);
132 void SetEyebrowX(u8 value);
133 void SetEyebrowY(u8 value);
134 void SetNoseType(NoseType value);
135 void SetNoseScale(u8 value);
136 void SetNoseY(u8 value);
137 void SetMouthType(u8 value);
138 void SetMouthColor(CommonColor value);
139 void SetMouthScale(u8 value);
140 void SetMouthAspect(u8 value);
141 void SetMouthY(u8 value);
142 void SetBeardColor(CommonColor value);
143 void SetBeardType(BeardType value);
144 void SetMustacheType(MustacheType value);
145 void SetMustacheScale(u8 value);
146 void SetMustacheY(u8 value);
147 void SetGlassType(GlassType value);
148 void SetGlassColor(CommonColor value);
149 void SetGlassScale(u8 value);
150 void SetGlassY(u8 value);
151 void SetMoleType(MoleType value);
152 void SetMoleScale(u8 value);
153 void SetMoleX(u8 value);
154 void SetMoleY(u8 value);
155 void SetNickname(Nickname nickname);
156
157 FontRegion GetFontRegion() const;
158 FavoriteColor GetFavoriteColor() const;
159 Gender GetGender() const;
160 u8 GetHeight() const;
161 u8 GetBuild() const;
162 u8 GetType() const;
163 u8 GetRegionMove() const;
164 FacelineType GetFacelineType() const;
165 FacelineColor GetFacelineColor() const;
166 FacelineWrinkle GetFacelineWrinkle() const;
167 FacelineMake GetFacelineMake() const;
168 HairType GetHairType() const;
169 CommonColor GetHairColor() const;
170 HairFlip GetHairFlip() const;
171 EyeType GetEyeType() const;
172 CommonColor GetEyeColor() const;
173 u8 GetEyeScale() const;
174 u8 GetEyeAspect() const;
175 u8 GetEyeRotate() const;
176 u8 GetEyeX() const;
177 u8 GetEyeY() const;
178 EyebrowType GetEyebrowType() const;
179 CommonColor GetEyebrowColor() const;
180 u8 GetEyebrowScale() const;
181 u8 GetEyebrowAspect() const;
182 u8 GetEyebrowRotate() const;
183 u8 GetEyebrowX() const;
184 u8 GetEyebrowY() const;
185 NoseType GetNoseType() const;
186 u8 GetNoseScale() const;
187 u8 GetNoseY() const;
188 MouthType GetMouthType() const;
189 CommonColor GetMouthColor() const;
190 u8 GetMouthScale() const;
191 u8 GetMouthAspect() const;
192 u8 GetMouthY() const;
193 CommonColor GetBeardColor() const;
194 BeardType GetBeardType() const;
195 MustacheType GetMustacheType() const;
196 u8 GetMustacheScale() const;
197 u8 GetMustacheY() const;
198 GlassType GetGlassType() const;
199 CommonColor GetGlassColor() const;
200 u8 GetGlassScale() const;
201 u8 GetGlassY() const;
202 MoleType GetMoleType() const;
203 u8 GetMoleScale() const;
204 u8 GetMoleX() const;
205 u8 GetMoleY() const;
206 Nickname GetNickname() const;
207 Nickname GetDefaultNickname() const;
208 Nickname GetInvalidNickname() const;
209
210private:
211 StoreDataBitFields data{};
212 Nickname name{};
213};
214static_assert(sizeof(CoreData) == 0x30, "CoreData has incorrect size.");
215
216}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/raw_data.cpp b/src/core/hle/service/mii/types/raw_data.cpp
index e5245b791..5143abcc8 100644
--- a/src/core/hle/service/mii/raw_data.cpp
+++ b/src/core/hle/service/mii/types/raw_data.cpp
@@ -1,10 +1,87 @@
1// SPDX-FileCopyrightText: Ryujinx Team and Contributors 1// SPDX-FileCopyrightText: Ryujinx Team and Contributors
2// SPDX-License-Identifier: MIT 2// SPDX-License-Identifier: MIT
3 3
4#include "core/hle/service/mii/raw_data.h" 4#include "core/hle/service/mii/types/raw_data.h"
5 5
6namespace Service::Mii::RawData { 6namespace Service::Mii::RawData {
7 7
8constexpr std::array<u8, static_cast<u8>(FacelineColor::Count)> FromVer3FacelineColorTable{
9 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5,
10};
11
12constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3HairColorTable{
13 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0,
14 0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
15 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4,
16 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5,
17 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7,
18 0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4,
19};
20
21constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3EyeColorTable{
22 0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4,
23 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
24 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4,
25 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
26 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2,
27 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
28};
29
30constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3MouthlineColorTable{
31 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
32 0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
33 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
34 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
35 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
36 0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3,
37};
38
39constexpr std::array<u8, static_cast<u8>(CommonColor::Count)> FromVer3GlassColorTable{
40 0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3,
41 0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
42 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
43 0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5,
44 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4,
45 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
46};
47
48constexpr std::array<u8, static_cast<u8>(GlassType::Count)> FromVer3GlassTypeTable{
49 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1,
50 0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7,
51};
52
53constexpr std::array<u8, 8> Ver3FacelineColorTable{
54 0x0, 0x1, 0x2, 0x3, 0x4, 0x5,
55};
56
57constexpr std::array<u8, 8> Ver3HairColorTable{
58 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
59};
60
61constexpr std::array<u8, 6> Ver3EyeColorTable{
62 0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
63};
64
65constexpr std::array<u8, 5> Ver3MouthColorTable{
66 0x13, 0x14, 0x15, 0x16, 0x17,
67};
68
69constexpr std::array<u8, 7> Ver3GlassColorTable{
70 0x8, 0xe, 0xf, 0x10, 0x11, 0x12, 0x0,
71};
72
73const std::array<u8, 62> EyeRotateLookup{
74 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
75 0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
76 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
77 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
78};
79
80const std::array<u8, 24> EyebrowRotateLookup{
81 0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07, 0x04, 0x07, 0x06, 0x08,
82 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05,
83};
84
8const std::array<Service::Mii::DefaultMii, 2> BaseMii{ 85const std::array<Service::Mii::DefaultMii, 2> BaseMii{
9 Service::Mii::DefaultMii{ 86 Service::Mii::DefaultMii{
10 .face_type = 0, 87 .face_type = 0,
@@ -51,11 +128,12 @@ const std::array<Service::Mii::DefaultMii, 2> BaseMii{
51 .mole_y = 20, 128 .mole_y = 20,
52 .height = 64, 129 .height = 64,
53 .weight = 64, 130 .weight = 64,
54 .gender = Gender::Male, 131 .gender = 0,
55 .favorite_color = 0, 132 .favorite_color = 0,
56 .region = 0, 133 .region_move = 0,
57 .font_region = FontRegion::Standard, 134 .font_region = 0,
58 .type = 0, 135 .type = 0,
136 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
59 }, 137 },
60 Service::Mii::DefaultMii{ 138 Service::Mii::DefaultMii{
61 .face_type = 0, 139 .face_type = 0,
@@ -102,11 +180,12 @@ const std::array<Service::Mii::DefaultMii, 2> BaseMii{
102 .mole_y = 20, 180 .mole_y = 20,
103 .height = 64, 181 .height = 64,
104 .weight = 64, 182 .weight = 64,
105 .gender = Gender::Female, 183 .gender = 1,
106 .favorite_color = 0, 184 .favorite_color = 0,
107 .region = 0, 185 .region_move = 0,
108 .font_region = FontRegion::Standard, 186 .font_region = 0,
109 .type = 0, 187 .type = 0,
188 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
110 }, 189 },
111}; 190};
112 191
@@ -156,11 +235,12 @@ const std::array<Service::Mii::DefaultMii, 6> DefaultMii{
156 .mole_y = 20, 235 .mole_y = 20,
157 .height = 64, 236 .height = 64,
158 .weight = 64, 237 .weight = 64,
159 .gender = Gender::Male, 238 .gender = 0,
160 .favorite_color = 4, 239 .favorite_color = 4,
161 .region = 0, 240 .region_move = 0,
162 .font_region = FontRegion::Standard, 241 .font_region = 0,
163 .type = 0, 242 .type = 0,
243 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
164 }, 244 },
165 Service::Mii::DefaultMii{ 245 Service::Mii::DefaultMii{
166 .face_type = 0, 246 .face_type = 0,
@@ -207,11 +287,12 @@ const std::array<Service::Mii::DefaultMii, 6> DefaultMii{
207 .mole_y = 20, 287 .mole_y = 20,
208 .height = 64, 288 .height = 64,
209 .weight = 64, 289 .weight = 64,
210 .gender = Gender::Male, 290 .gender = 0,
211 .favorite_color = 5, 291 .favorite_color = 5,
212 .region = 0, 292 .region_move = 0,
213 .font_region = FontRegion::Standard, 293 .font_region = 0,
214 .type = 0, 294 .type = 0,
295 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
215 }, 296 },
216 Service::Mii::DefaultMii{ 297 Service::Mii::DefaultMii{
217 .face_type = 0, 298 .face_type = 0,
@@ -258,11 +339,12 @@ const std::array<Service::Mii::DefaultMii, 6> DefaultMii{
258 .mole_y = 20, 339 .mole_y = 20,
259 .height = 64, 340 .height = 64,
260 .weight = 64, 341 .weight = 64,
261 .gender = Gender::Male, 342 .gender = 0,
262 .favorite_color = 0, 343 .favorite_color = 0,
263 .region = 0, 344 .region_move = 0,
264 .font_region = FontRegion::Standard, 345 .font_region = 0,
265 .type = 0, 346 .type = 0,
347 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
266 }, 348 },
267 Service::Mii::DefaultMii{ 349 Service::Mii::DefaultMii{
268 .face_type = 0, 350 .face_type = 0,
@@ -309,11 +391,12 @@ const std::array<Service::Mii::DefaultMii, 6> DefaultMii{
309 .mole_y = 20, 391 .mole_y = 20,
310 .height = 64, 392 .height = 64,
311 .weight = 64, 393 .weight = 64,
312 .gender = Gender::Female, 394 .gender = 1,
313 .favorite_color = 2, 395 .favorite_color = 2,
314 .region = 0, 396 .region_move = 0,
315 .font_region = FontRegion::Standard, 397 .font_region = 0,
316 .type = 0, 398 .type = 0,
399 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
317 }, 400 },
318 Service::Mii::DefaultMii{ 401 Service::Mii::DefaultMii{
319 .face_type = 0, 402 .face_type = 0,
@@ -360,11 +443,12 @@ const std::array<Service::Mii::DefaultMii, 6> DefaultMii{
360 .mole_y = 20, 443 .mole_y = 20,
361 .height = 64, 444 .height = 64,
362 .weight = 64, 445 .weight = 64,
363 .gender = Gender::Female, 446 .gender = 1,
364 .favorite_color = 6, 447 .favorite_color = 6,
365 .region = 0, 448 .region_move = 0,
366 .font_region = FontRegion::Standard, 449 .font_region = 0,
367 .type = 0, 450 .type = 0,
451 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
368 }, 452 },
369 Service::Mii::DefaultMii{ 453 Service::Mii::DefaultMii{
370 .face_type = 0, 454 .face_type = 0,
@@ -411,176 +495,177 @@ const std::array<Service::Mii::DefaultMii, 6> DefaultMii{
411 .mole_y = 20, 495 .mole_y = 20,
412 .height = 64, 496 .height = 64,
413 .weight = 64, 497 .weight = 64,
414 .gender = Gender::Female, 498 .gender = 1,
415 .favorite_color = 7, 499 .favorite_color = 7,
416 .region = 0, 500 .region_move = 0,
417 .font_region = FontRegion::Standard, 501 .font_region = 0,
418 .type = 0, 502 .type = 0,
503 .nickname = {u'n', u'o', u' ', u'n', u'a', u'm', u'e'},
419 }, 504 },
420 505
421}; 506};
422 507
423const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFaceline{ 508const std::array<RandomMiiData4, 18> RandomMiiFaceline{
424 Service::Mii::RandomMiiData4{ 509 RandomMiiData4{
425 .gender = Gender::Male, 510 .gender = static_cast<u32>(Gender::Male),
426 .age = Age::Young, 511 .age = static_cast<u32>(Age::Young),
427 .race = Race::Black, 512 .race = static_cast<u32>(Race::Black),
428 .values_count = 10, 513 .values_count = 10,
429 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, 514 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
430 }, 515 },
431 Service::Mii::RandomMiiData4{ 516 RandomMiiData4{
432 .gender = Gender::Male, 517 .gender = static_cast<u32>(Gender::Male),
433 .age = Age::Normal, 518 .age = static_cast<u32>(Age::Normal),
434 .race = Race::Black, 519 .race = static_cast<u32>(Race::Black),
435 .values_count = 10, 520 .values_count = 10,
436 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, 521 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
437 }, 522 },
438 Service::Mii::RandomMiiData4{ 523 RandomMiiData4{
439 .gender = Gender::Male, 524 .gender = static_cast<u32>(Gender::Male),
440 .age = Age::Old, 525 .age = static_cast<u32>(Age::Old),
441 .race = Race::Black, 526 .race = static_cast<u32>(Race::Black),
442 .values_count = 10, 527 .values_count = 10,
443 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, 528 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
444 }, 529 },
445 Service::Mii::RandomMiiData4{ 530 RandomMiiData4{
446 .gender = Gender::Male, 531 .gender = static_cast<u32>(Gender::Male),
447 .age = Age::Young, 532 .age = static_cast<u32>(Age::Young),
448 .race = Race::White, 533 .race = static_cast<u32>(Race::White),
449 .values_count = 12, 534 .values_count = 12,
450 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, 535 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
451 }, 536 },
452 Service::Mii::RandomMiiData4{ 537 RandomMiiData4{
453 .gender = Gender::Male, 538 .gender = static_cast<u32>(Gender::Male),
454 .age = Age::Normal, 539 .age = static_cast<u32>(Age::Normal),
455 .race = Race::White, 540 .race = static_cast<u32>(Race::White),
456 .values_count = 13, 541 .values_count = 13,
457 .values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11}, 542 .values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11},
458 }, 543 },
459 Service::Mii::RandomMiiData4{ 544 RandomMiiData4{
460 .gender = Gender::Male, 545 .gender = static_cast<u32>(Gender::Male),
461 .age = Age::Old, 546 .age = static_cast<u32>(Age::Old),
462 .race = Race::White, 547 .race = static_cast<u32>(Race::White),
463 .values_count = 12, 548 .values_count = 12,
464 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, 549 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
465 }, 550 },
466 Service::Mii::RandomMiiData4{ 551 RandomMiiData4{
467 .gender = Gender::Male, 552 .gender = static_cast<u32>(Gender::Male),
468 .age = Age::Young, 553 .age = static_cast<u32>(Age::Young),
469 .race = Race::Asian, 554 .race = static_cast<u32>(Race::Asian),
470 .values_count = 12, 555 .values_count = 12,
471 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, 556 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
472 }, 557 },
473 Service::Mii::RandomMiiData4{ 558 RandomMiiData4{
474 .gender = Gender::Male, 559 .gender = static_cast<u32>(Gender::Male),
475 .age = Age::Normal, 560 .age = static_cast<u32>(Age::Normal),
476 .race = Race::Asian, 561 .race = static_cast<u32>(Race::Asian),
477 .values_count = 13, 562 .values_count = 13,
478 .values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11}, 563 .values = {0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 10, 11},
479 }, 564 },
480 Service::Mii::RandomMiiData4{ 565 RandomMiiData4{
481 .gender = Gender::Male, 566 .gender = static_cast<u32>(Gender::Male),
482 .age = Age::Old, 567 .age = static_cast<u32>(Age::Old),
483 .race = Race::Asian, 568 .race = static_cast<u32>(Race::Asian),
484 .values_count = 12, 569 .values_count = 12,
485 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11}, 570 .values = {0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 10, 11},
486 }, 571 },
487 Service::Mii::RandomMiiData4{ 572 RandomMiiData4{
488 .gender = Gender::Female, 573 .gender = static_cast<u32>(Gender::Female),
489 .age = Age::Young, 574 .age = static_cast<u32>(Age::Young),
490 .race = Race::Black, 575 .race = static_cast<u32>(Race::Black),
491 .values_count = 10, 576 .values_count = 10,
492 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, 577 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
493 }, 578 },
494 Service::Mii::RandomMiiData4{ 579 RandomMiiData4{
495 .gender = Gender::Female, 580 .gender = static_cast<u32>(Gender::Female),
496 .age = Age::Normal, 581 .age = static_cast<u32>(Age::Normal),
497 .race = Race::Black, 582 .race = static_cast<u32>(Race::Black),
498 .values_count = 10, 583 .values_count = 10,
499 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, 584 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
500 }, 585 },
501 Service::Mii::RandomMiiData4{ 586 RandomMiiData4{
502 .gender = Gender::Female, 587 .gender = static_cast<u32>(Gender::Female),
503 .age = Age::Old, 588 .age = static_cast<u32>(Age::Old),
504 .race = Race::Black, 589 .race = static_cast<u32>(Race::Black),
505 .values_count = 10, 590 .values_count = 10,
506 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9}, 591 .values = {0, 0, 1, 1, 2, 3, 4, 5, 9, 9},
507 }, 592 },
508 Service::Mii::RandomMiiData4{ 593 RandomMiiData4{
509 .gender = Gender::Female, 594 .gender = static_cast<u32>(Gender::Female),
510 .age = Age::Young, 595 .age = static_cast<u32>(Age::Young),
511 .race = Race::White, 596 .race = static_cast<u32>(Race::White),
512 .values_count = 12, 597 .values_count = 12,
513 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, 598 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
514 }, 599 },
515 Service::Mii::RandomMiiData4{ 600 RandomMiiData4{
516 .gender = Gender::Female, 601 .gender = static_cast<u32>(Gender::Female),
517 .age = Age::Normal, 602 .age = static_cast<u32>(Age::Normal),
518 .race = Race::White, 603 .race = static_cast<u32>(Race::White),
519 .values_count = 12, 604 .values_count = 12,
520 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, 605 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
521 }, 606 },
522 Service::Mii::RandomMiiData4{ 607 RandomMiiData4{
523 .gender = Gender::Female, 608 .gender = static_cast<u32>(Gender::Female),
524 .age = Age::Old, 609 .age = static_cast<u32>(Age::Old),
525 .race = Race::White, 610 .race = static_cast<u32>(Race::White),
526 .values_count = 12, 611 .values_count = 12,
527 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, 612 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
528 }, 613 },
529 Service::Mii::RandomMiiData4{ 614 RandomMiiData4{
530 .gender = Gender::Female, 615 .gender = static_cast<u32>(Gender::Female),
531 .age = Age::Young, 616 .age = static_cast<u32>(Age::Young),
532 .race = Race::Asian, 617 .race = static_cast<u32>(Race::Asian),
533 .values_count = 12, 618 .values_count = 12,
534 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, 619 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
535 }, 620 },
536 Service::Mii::RandomMiiData4{ 621 RandomMiiData4{
537 .gender = Gender::Female, 622 .gender = static_cast<u32>(Gender::Female),
538 .age = Age::Normal, 623 .age = static_cast<u32>(Age::Normal),
539 .race = Race::Asian, 624 .race = static_cast<u32>(Race::Asian),
540 .values_count = 12, 625 .values_count = 12,
541 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, 626 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
542 }, 627 },
543 Service::Mii::RandomMiiData4{ 628 RandomMiiData4{
544 .gender = Gender::Female, 629 .gender = static_cast<u32>(Gender::Female),
545 .age = Age::Old, 630 .age = static_cast<u32>(Age::Old),
546 .race = Race::Asian, 631 .race = static_cast<u32>(Race::Asian),
547 .values_count = 12, 632 .values_count = 12,
548 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10}, 633 .values = {0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 8, 10},
549 }, 634 },
550}; 635};
551 636
552const std::array<Service::Mii::RandomMiiData3, 6> RandomMiiFacelineColor{ 637const std::array<RandomMiiData3, 6> RandomMiiFacelineColor{
553 Service::Mii::RandomMiiData3{ 638 RandomMiiData3{
554 .arg_1 = 0, 639 .arg_1 = 0,
555 .arg_2 = 0, 640 .arg_2 = 0,
556 .values_count = 10, 641 .values_count = 10,
557 .values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5}, 642 .values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5},
558 }, 643 },
559 Service::Mii::RandomMiiData3{ 644 RandomMiiData3{
560 .arg_1 = 0, 645 .arg_1 = 0,
561 .arg_2 = 1, 646 .arg_2 = 1,
562 .values_count = 10, 647 .values_count = 10,
563 .values = {0, 0, 0, 0, 1, 1, 2, 3, 3, 3}, 648 .values = {0, 0, 0, 0, 1, 1, 2, 3, 3, 3},
564 }, 649 },
565 Service::Mii::RandomMiiData3{ 650 RandomMiiData3{
566 .arg_1 = 0, 651 .arg_1 = 0,
567 .arg_2 = 2, 652 .arg_2 = 2,
568 .values_count = 10, 653 .values_count = 10,
569 .values = {0, 0, 1, 1, 1, 1, 1, 1, 1, 2}, 654 .values = {0, 0, 1, 1, 1, 1, 1, 1, 1, 2},
570 }, 655 },
571 Service::Mii::RandomMiiData3{ 656 RandomMiiData3{
572 .arg_1 = 1, 657 .arg_1 = 1,
573 .arg_2 = 0, 658 .arg_2 = 0,
574 .values_count = 10, 659 .values_count = 10,
575 .values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5}, 660 .values = {2, 2, 4, 4, 4, 4, 5, 5, 5, 5},
576 }, 661 },
577 Service::Mii::RandomMiiData3{ 662 RandomMiiData3{
578 .arg_1 = 1, 663 .arg_1 = 1,
579 .arg_2 = 1, 664 .arg_2 = 1,
580 .values_count = 10, 665 .values_count = 10,
581 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 3}, 666 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 3},
582 }, 667 },
583 Service::Mii::RandomMiiData3{ 668 RandomMiiData3{
584 .arg_1 = 1, 669 .arg_1 = 1,
585 .arg_2 = 2, 670 .arg_2 = 2,
586 .values_count = 10, 671 .values_count = 10,
@@ -588,407 +673,407 @@ const std::array<Service::Mii::RandomMiiData3, 6> RandomMiiFacelineColor{
588 }, 673 },
589}; 674};
590 675
591const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineWrinkle{ 676const std::array<RandomMiiData4, 18> RandomMiiFacelineWrinkle{
592 Service::Mii::RandomMiiData4{ 677 RandomMiiData4{
593 .gender = Gender::Male, 678 .gender = static_cast<u32>(Gender::Male),
594 .age = Age::Young, 679 .age = static_cast<u32>(Age::Young),
595 .race = Race::Black, 680 .race = static_cast<u32>(Race::Black),
596 .values_count = 20, 681 .values_count = 20,
597 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 682 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
598 }, 683 },
599 Service::Mii::RandomMiiData4{ 684 RandomMiiData4{
600 .gender = Gender::Male, 685 .gender = static_cast<u32>(Gender::Male),
601 .age = Age::Normal, 686 .age = static_cast<u32>(Age::Normal),
602 .race = Race::Black, 687 .race = static_cast<u32>(Race::Black),
603 .values_count = 20, 688 .values_count = 20,
604 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 689 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
605 }, 690 },
606 Service::Mii::RandomMiiData4{ 691 RandomMiiData4{
607 .gender = Gender::Male, 692 .gender = static_cast<u32>(Gender::Male),
608 .age = Age::Old, 693 .age = static_cast<u32>(Age::Old),
609 .race = Race::Black, 694 .race = static_cast<u32>(Race::Black),
610 .values_count = 20, 695 .values_count = 20,
611 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8}, 696 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8},
612 }, 697 },
613 Service::Mii::RandomMiiData4{ 698 RandomMiiData4{
614 .gender = Gender::Male, 699 .gender = static_cast<u32>(Gender::Male),
615 .age = Age::Young, 700 .age = static_cast<u32>(Age::Young),
616 .race = Race::White, 701 .race = static_cast<u32>(Race::White),
617 .values_count = 20, 702 .values_count = 20,
618 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9}, 703 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9},
619 }, 704 },
620 Service::Mii::RandomMiiData4{ 705 RandomMiiData4{
621 .gender = Gender::Male, 706 .gender = static_cast<u32>(Gender::Male),
622 .age = Age::Normal, 707 .age = static_cast<u32>(Age::Normal),
623 .race = Race::White, 708 .race = static_cast<u32>(Race::White),
624 .values_count = 20, 709 .values_count = 20,
625 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9}, 710 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9},
626 }, 711 },
627 Service::Mii::RandomMiiData4{ 712 RandomMiiData4{
628 .gender = Gender::Male, 713 .gender = static_cast<u32>(Gender::Male),
629 .age = Age::Old, 714 .age = static_cast<u32>(Age::Old),
630 .race = Race::White, 715 .race = static_cast<u32>(Race::White),
631 .values_count = 20, 716 .values_count = 20,
632 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 717 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
633 }, 718 },
634 Service::Mii::RandomMiiData4{ 719 RandomMiiData4{
635 .gender = Gender::Male, 720 .gender = static_cast<u32>(Gender::Male),
636 .age = Age::Young, 721 .age = static_cast<u32>(Age::Young),
637 .race = Race::Asian, 722 .race = static_cast<u32>(Race::Asian),
638 .values_count = 20, 723 .values_count = 20,
639 .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11}, 724 .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11},
640 }, 725 },
641 Service::Mii::RandomMiiData4{ 726 RandomMiiData4{
642 .gender = Gender::Male, 727 .gender = static_cast<u32>(Gender::Male),
643 .age = Age::Normal, 728 .age = static_cast<u32>(Age::Normal),
644 .race = Race::Asian, 729 .race = static_cast<u32>(Race::Asian),
645 .values_count = 20, 730 .values_count = 20,
646 .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11}, 731 .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11},
647 }, 732 },
648 Service::Mii::RandomMiiData4{ 733 RandomMiiData4{
649 .gender = Gender::Male, 734 .gender = static_cast<u32>(Gender::Male),
650 .age = Age::Old, 735 .age = static_cast<u32>(Age::Old),
651 .race = Race::Asian, 736 .race = static_cast<u32>(Race::Asian),
652 .values_count = 20, 737 .values_count = 20,
653 .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11}, 738 .values = {9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11},
654 }, 739 },
655 Service::Mii::RandomMiiData4{ 740 RandomMiiData4{
656 .gender = Gender::Female, 741 .gender = static_cast<u32>(Gender::Female),
657 .age = Age::Young, 742 .age = static_cast<u32>(Age::Young),
658 .race = Race::Black, 743 .race = static_cast<u32>(Race::Black),
659 .values_count = 20, 744 .values_count = 20,
660 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 745 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
661 }, 746 },
662 Service::Mii::RandomMiiData4{ 747 RandomMiiData4{
663 .gender = Gender::Female, 748 .gender = static_cast<u32>(Gender::Female),
664 .age = Age::Normal, 749 .age = static_cast<u32>(Age::Normal),
665 .race = Race::Black, 750 .race = static_cast<u32>(Race::Black),
666 .values_count = 20, 751 .values_count = 20,
667 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 752 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
668 }, 753 },
669 Service::Mii::RandomMiiData4{ 754 RandomMiiData4{
670 .gender = Gender::Female, 755 .gender = static_cast<u32>(Gender::Female),
671 .age = Age::Old, 756 .age = static_cast<u32>(Age::Old),
672 .race = Race::Black, 757 .race = static_cast<u32>(Race::Black),
673 .values_count = 20, 758 .values_count = 20,
674 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 759 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
675 }, 760 },
676 Service::Mii::RandomMiiData4{ 761 RandomMiiData4{
677 .gender = Gender::Female, 762 .gender = static_cast<u32>(Gender::Female),
678 .age = Age::Young, 763 .age = static_cast<u32>(Age::Young),
679 .race = Race::White, 764 .race = static_cast<u32>(Race::White),
680 .values_count = 20, 765 .values_count = 20,
681 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8}, 766 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8},
682 }, 767 },
683 Service::Mii::RandomMiiData4{ 768 RandomMiiData4{
684 .gender = Gender::Female, 769 .gender = static_cast<u32>(Gender::Female),
685 .age = Age::Normal, 770 .age = static_cast<u32>(Age::Normal),
686 .race = Race::White, 771 .race = static_cast<u32>(Race::White),
687 .values_count = 20, 772 .values_count = 20,
688 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8}, 773 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 8, 8},
689 }, 774 },
690 Service::Mii::RandomMiiData4{ 775 RandomMiiData4{
691 .gender = Gender::Female, 776 .gender = static_cast<u32>(Gender::Female),
692 .age = Age::Old, 777 .age = static_cast<u32>(Age::Old),
693 .race = Race::White, 778 .race = static_cast<u32>(Race::White),
694 .values_count = 20, 779 .values_count = 20,
695 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4}, 780 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 4},
696 }, 781 },
697 Service::Mii::RandomMiiData4{ 782 RandomMiiData4{
698 .gender = Gender::Female, 783 .gender = static_cast<u32>(Gender::Female),
699 .age = Age::Young, 784 .age = static_cast<u32>(Age::Young),
700 .race = Race::Asian, 785 .race = static_cast<u32>(Race::Asian),
701 .values_count = 20, 786 .values_count = 20,
702 .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11}, 787 .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11},
703 }, 788 },
704 Service::Mii::RandomMiiData4{ 789 RandomMiiData4{
705 .gender = Gender::Female, 790 .gender = static_cast<u32>(Gender::Female),
706 .age = Age::Normal, 791 .age = static_cast<u32>(Age::Normal),
707 .race = Race::Asian, 792 .race = static_cast<u32>(Race::Asian),
708 .values_count = 20, 793 .values_count = 20,
709 .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11}, 794 .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11},
710 }, 795 },
711 Service::Mii::RandomMiiData4{ 796 RandomMiiData4{
712 .gender = Gender::Female, 797 .gender = static_cast<u32>(Gender::Female),
713 .age = Age::Old, 798 .age = static_cast<u32>(Age::Old),
714 .race = Race::Asian, 799 .race = static_cast<u32>(Race::Asian),
715 .values_count = 20, 800 .values_count = 20,
716 .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11}, 801 .values = {9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11},
717 }, 802 },
718}; 803};
719 804
720const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineMakeup{ 805const std::array<RandomMiiData4, 18> RandomMiiFacelineMakeup{
721 Service::Mii::RandomMiiData4{ 806 RandomMiiData4{
722 .gender = Gender::Male, 807 .gender = static_cast<u32>(Gender::Male),
723 .age = Age::Young, 808 .age = static_cast<u32>(Age::Young),
724 .race = Race::Black, 809 .race = static_cast<u32>(Race::Black),
725 .values_count = 20, 810 .values_count = 20,
726 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 811 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
727 }, 812 },
728 Service::Mii::RandomMiiData4{ 813 RandomMiiData4{
729 .gender = Gender::Male, 814 .gender = static_cast<u32>(Gender::Male),
730 .age = Age::Normal, 815 .age = static_cast<u32>(Age::Normal),
731 .race = Race::Black, 816 .race = static_cast<u32>(Race::Black),
732 .values_count = 20, 817 .values_count = 20,
733 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9}, 818 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9},
734 }, 819 },
735 Service::Mii::RandomMiiData4{ 820 RandomMiiData4{
736 .gender = Gender::Male, 821 .gender = static_cast<u32>(Gender::Male),
737 .age = Age::Old, 822 .age = static_cast<u32>(Age::Old),
738 .race = Race::Black, 823 .race = static_cast<u32>(Race::Black),
739 .values_count = 20, 824 .values_count = 20,
740 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9}, 825 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9},
741 }, 826 },
742 Service::Mii::RandomMiiData4{ 827 RandomMiiData4{
743 .gender = Gender::Male, 828 .gender = static_cast<u32>(Gender::Male),
744 .age = Age::Young, 829 .age = static_cast<u32>(Age::Young),
745 .race = Race::White, 830 .race = static_cast<u32>(Race::White),
746 .values_count = 20, 831 .values_count = 20,
747 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, 832 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
748 }, 833 },
749 Service::Mii::RandomMiiData4{ 834 RandomMiiData4{
750 .gender = Gender::Male, 835 .gender = static_cast<u32>(Gender::Male),
751 .age = Age::Normal, 836 .age = static_cast<u32>(Age::Normal),
752 .race = Race::White, 837 .race = static_cast<u32>(Race::White),
753 .values_count = 20, 838 .values_count = 20,
754 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, 839 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
755 }, 840 },
756 Service::Mii::RandomMiiData4{ 841 RandomMiiData4{
757 .gender = Gender::Male, 842 .gender = static_cast<u32>(Gender::Male),
758 .age = Age::Old, 843 .age = static_cast<u32>(Age::Old),
759 .race = Race::White, 844 .race = static_cast<u32>(Race::White),
760 .values_count = 20, 845 .values_count = 20,
761 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, 846 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
762 }, 847 },
763 Service::Mii::RandomMiiData4{ 848 RandomMiiData4{
764 .gender = Gender::Male, 849 .gender = static_cast<u32>(Gender::Male),
765 .age = Age::Young, 850 .age = static_cast<u32>(Age::Young),
766 .race = Race::Asian, 851 .race = static_cast<u32>(Race::Asian),
767 .values_count = 20, 852 .values_count = 20,
768 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, 853 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
769 }, 854 },
770 Service::Mii::RandomMiiData4{ 855 RandomMiiData4{
771 .gender = Gender::Male, 856 .gender = static_cast<u32>(Gender::Male),
772 .age = Age::Normal, 857 .age = static_cast<u32>(Age::Normal),
773 .race = Race::Asian, 858 .race = static_cast<u32>(Race::Asian),
774 .values_count = 20, 859 .values_count = 20,
775 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, 860 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
776 }, 861 },
777 Service::Mii::RandomMiiData4{ 862 RandomMiiData4{
778 .gender = Gender::Male, 863 .gender = static_cast<u32>(Gender::Male),
779 .age = Age::Old, 864 .age = static_cast<u32>(Age::Old),
780 .race = Race::Asian, 865 .race = static_cast<u32>(Race::Asian),
781 .values_count = 20, 866 .values_count = 20,
782 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}, 867 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9},
783 }, 868 },
784 Service::Mii::RandomMiiData4{ 869 RandomMiiData4{
785 .gender = Gender::Female, 870 .gender = static_cast<u32>(Gender::Female),
786 .age = Age::Young, 871 .age = static_cast<u32>(Age::Young),
787 .race = Race::Black, 872 .race = static_cast<u32>(Race::Black),
788 .values_count = 20, 873 .values_count = 20,
789 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2}, 874 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2},
790 }, 875 },
791 Service::Mii::RandomMiiData4{ 876 RandomMiiData4{
792 .gender = Gender::Female, 877 .gender = static_cast<u32>(Gender::Female),
793 .age = Age::Normal, 878 .age = static_cast<u32>(Age::Normal),
794 .race = Race::Black, 879 .race = static_cast<u32>(Race::Black),
795 .values_count = 20, 880 .values_count = 20,
796 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9}, 881 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9},
797 }, 882 },
798 Service::Mii::RandomMiiData4{ 883 RandomMiiData4{
799 .gender = Gender::Female, 884 .gender = static_cast<u32>(Gender::Female),
800 .age = Age::Old, 885 .age = static_cast<u32>(Age::Old),
801 .race = Race::Black, 886 .race = static_cast<u32>(Race::Black),
802 .values_count = 20, 887 .values_count = 20,
803 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9}, 888 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 9, 9},
804 }, 889 },
805 Service::Mii::RandomMiiData4{ 890 RandomMiiData4{
806 .gender = Gender::Female, 891 .gender = static_cast<u32>(Gender::Female),
807 .age = Age::Young, 892 .age = static_cast<u32>(Age::Young),
808 .race = Race::White, 893 .race = static_cast<u32>(Race::White),
809 .values_count = 20, 894 .values_count = 20,
810 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9}, 895 .values = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9},
811 }, 896 },
812 Service::Mii::RandomMiiData4{ 897 RandomMiiData4{
813 .gender = Gender::Female, 898 .gender = static_cast<u32>(Gender::Female),
814 .age = Age::Normal, 899 .age = static_cast<u32>(Age::Normal),
815 .race = Race::White, 900 .race = static_cast<u32>(Race::White),
816 .values_count = 20, 901 .values_count = 20,
817 .values = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}, 902 .values = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9},
818 }, 903 },
819 Service::Mii::RandomMiiData4{ 904 RandomMiiData4{
820 .gender = Gender::Female, 905 .gender = static_cast<u32>(Gender::Female),
821 .age = Age::Old, 906 .age = static_cast<u32>(Age::Old),
822 .race = Race::White, 907 .race = static_cast<u32>(Race::White),
823 .values_count = 20, 908 .values_count = 20,
824 .values = {0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 9}, 909 .values = {0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 9},
825 }, 910 },
826 Service::Mii::RandomMiiData4{ 911 RandomMiiData4{
827 .gender = Gender::Female, 912 .gender = static_cast<u32>(Gender::Female),
828 .age = Age::Young, 913 .age = static_cast<u32>(Age::Young),
829 .race = Race::Asian, 914 .race = static_cast<u32>(Race::Asian),
830 .values_count = 20, 915 .values_count = 20,
831 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 916 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
832 }, 917 },
833 Service::Mii::RandomMiiData4{ 918 RandomMiiData4{
834 .gender = Gender::Female, 919 .gender = static_cast<u32>(Gender::Female),
835 .age = Age::Normal, 920 .age = static_cast<u32>(Age::Normal),
836 .race = Race::Asian, 921 .race = static_cast<u32>(Race::Asian),
837 .values_count = 20, 922 .values_count = 20,
838 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 923 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
839 }, 924 },
840 Service::Mii::RandomMiiData4{ 925 RandomMiiData4{
841 .gender = Gender::Female, 926 .gender = static_cast<u32>(Gender::Female),
842 .age = Age::Old, 927 .age = static_cast<u32>(Age::Old),
843 .race = Race::Asian, 928 .race = static_cast<u32>(Race::Asian),
844 .values_count = 20, 929 .values_count = 20,
845 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 930 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
846 }, 931 },
847}; 932};
848 933
849const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiHairType{ 934const std::array<RandomMiiData4, 18> RandomMiiHairType{
850 Service::Mii::RandomMiiData4{ 935 RandomMiiData4{
851 .gender = Gender::Male, 936 .gender = static_cast<u32>(Gender::Male),
852 .age = Age::Young, 937 .age = static_cast<u32>(Age::Young),
853 .race = Race::Black, 938 .race = static_cast<u32>(Race::Black),
854 .values_count = 30, 939 .values_count = 30,
855 .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 940 .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45,
856 47, 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 75, 76, 86, 89}, 941 47, 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 75, 76, 86, 89},
857 }, 942 },
858 Service::Mii::RandomMiiData4{ 943 RandomMiiData4{
859 .gender = Gender::Male, 944 .gender = static_cast<u32>(Gender::Male),
860 .age = Age::Normal, 945 .age = static_cast<u32>(Age::Normal),
861 .race = Race::Black, 946 .race = static_cast<u32>(Race::Black),
862 .values_count = 31, 947 .values_count = 31,
863 .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47, 948 .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47,
864 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87}, 949 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87},
865 }, 950 },
866 Service::Mii::RandomMiiData4{ 951 RandomMiiData4{
867 .gender = Gender::Male, 952 .gender = static_cast<u32>(Gender::Male),
868 .age = Age::Old, 953 .age = static_cast<u32>(Age::Old),
869 .race = Race::Black, 954 .race = static_cast<u32>(Race::Black),
870 .values_count = 31, 955 .values_count = 31,
871 .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47, 956 .values = {13, 23, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 47,
872 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87}, 957 48, 49, 50, 51, 52, 54, 56, 57, 64, 66, 73, 75, 81, 86, 87},
873 }, 958 },
874 Service::Mii::RandomMiiData4{ 959 RandomMiiData4{
875 .gender = Gender::Male, 960 .gender = static_cast<u32>(Gender::Male),
876 .age = Age::Young, 961 .age = static_cast<u32>(Age::Young),
877 .race = Race::White, 962 .race = static_cast<u32>(Race::White),
878 .values_count = 38, 963 .values_count = 38,
879 .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 40, 42, 43, 44, 45, 47, 48, 49, 50, 964 .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 40, 42, 43, 44, 45, 47, 48, 49, 50,
880 51, 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 75, 76, 86, 89}, 965 51, 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 75, 76, 86, 89},
881 }, 966 },
882 Service::Mii::RandomMiiData4{ 967 RandomMiiData4{
883 .gender = Gender::Male, 968 .gender = static_cast<u32>(Gender::Male),
884 .age = Age::Normal, 969 .age = static_cast<u32>(Age::Normal),
885 .race = Race::White, 970 .race = static_cast<u32>(Race::White),
886 .values_count = 39, 971 .values_count = 39,
887 .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51, 972 .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51,
888 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87}, 973 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87},
889 }, 974 },
890 Service::Mii::RandomMiiData4{ 975 RandomMiiData4{
891 .gender = Gender::Male, 976 .gender = static_cast<u32>(Gender::Male),
892 .age = Age::Old, 977 .age = static_cast<u32>(Age::Old),
893 .race = Race::White, 978 .race = static_cast<u32>(Race::White),
894 .values_count = 39, 979 .values_count = 39,
895 .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51, 980 .values = {13, 23, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 43, 44, 45, 47, 48, 49, 50, 51,
896 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87}, 981 52, 53, 54, 55, 56, 58, 59, 60, 64, 65, 66, 67, 68, 70, 73, 75, 81, 86, 87},
897 }, 982 },
898 Service::Mii::RandomMiiData4{ 983 RandomMiiData4{
899 .gender = Gender::Male, 984 .gender = static_cast<u32>(Gender::Male),
900 .age = Age::Young, 985 .age = static_cast<u32>(Age::Young),
901 .race = Race::Asian, 986 .race = static_cast<u32>(Race::Asian),
902 .values_count = 18, 987 .values_count = 18,
903 .values = {13, 23, 30, 36, 37, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88}, 988 .values = {13, 23, 30, 36, 37, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88},
904 }, 989 },
905 Service::Mii::RandomMiiData4{ 990 RandomMiiData4{
906 .gender = Gender::Male, 991 .gender = static_cast<u32>(Gender::Male),
907 .age = Age::Normal, 992 .age = static_cast<u32>(Age::Normal),
908 .race = Race::Asian, 993 .race = static_cast<u32>(Race::Asian),
909 .values_count = 19, 994 .values_count = 19,
910 .values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88}, 995 .values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88},
911 }, 996 },
912 Service::Mii::RandomMiiData4{ 997 RandomMiiData4{
913 .gender = Gender::Male, 998 .gender = static_cast<u32>(Gender::Male),
914 .age = Age::Old, 999 .age = static_cast<u32>(Age::Old),
915 .race = Race::Asian, 1000 .race = static_cast<u32>(Race::Asian),
916 .values_count = 19, 1001 .values_count = 19,
917 .values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88}, 1002 .values = {13, 23, 30, 36, 37, 39, 41, 45, 47, 51, 53, 54, 55, 58, 59, 65, 67, 86, 88},
918 }, 1003 },
919 Service::Mii::RandomMiiData4{ 1004 RandomMiiData4{
920 .gender = Gender::Female, 1005 .gender = static_cast<u32>(Gender::Female),
921 .age = Age::Young, 1006 .age = static_cast<u32>(Age::Young),
922 .race = Race::Black, 1007 .race = static_cast<u32>(Race::Black),
923 .values_count = 39, 1008 .values_count = 39,
924 .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1009 .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
925 21, 22, 24, 25, 26, 28, 46, 50, 61, 62, 63, 64, 69, 76, 77, 79, 80, 83, 85}, 1010 21, 22, 24, 25, 26, 28, 46, 50, 61, 62, 63, 64, 69, 76, 77, 79, 80, 83, 85},
926 }, 1011 },
927 Service::Mii::RandomMiiData4{ 1012 RandomMiiData4{
928 .gender = Gender::Female, 1013 .gender = static_cast<u32>(Gender::Female),
929 .age = Age::Normal, 1014 .age = static_cast<u32>(Age::Normal),
930 .race = Race::Black, 1015 .race = static_cast<u32>(Race::Black),
931 .values_count = 42, 1016 .values_count = 42,
932 .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 1017 .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14,
933 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50, 1018 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50,
934 61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87}, 1019 61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87},
935 }, 1020 },
936 Service::Mii::RandomMiiData4{ 1021 RandomMiiData4{
937 .gender = Gender::Female, 1022 .gender = static_cast<u32>(Gender::Female),
938 .age = Age::Old, 1023 .age = static_cast<u32>(Age::Old),
939 .race = Race::Black, 1024 .race = static_cast<u32>(Race::Black),
940 .values_count = 42, 1025 .values_count = 42,
941 .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 1026 .values = {0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14,
942 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50, 1027 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 46, 50,
943 61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87}, 1028 61, 62, 63, 64, 69, 72, 74, 77, 78, 82, 83, 84, 85, 87},
944 }, 1029 },
945 Service::Mii::RandomMiiData4{ 1030 RandomMiiData4{
946 .gender = Gender::Female, 1031 .gender = static_cast<u32>(Gender::Female),
947 .age = Age::Young, 1032 .age = static_cast<u32>(Age::Young),
948 .race = Race::White, 1033 .race = static_cast<u32>(Race::White),
949 .values_count = 44, 1034 .values_count = 44,
950 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1035 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
951 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 42, 50, 1036 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 42, 50,
952 58, 60, 62, 63, 64, 69, 71, 76, 79, 80, 81, 82, 83, 86}, 1037 58, 60, 62, 63, 64, 69, 71, 76, 79, 80, 81, 82, 83, 86},
953 }, 1038 },
954 Service::Mii::RandomMiiData4{ 1039 RandomMiiData4{
955 .gender = Gender::Female, 1040 .gender = static_cast<u32>(Gender::Female),
956 .age = Age::Normal, 1041 .age = static_cast<u32>(Age::Normal),
957 .race = Race::White, 1042 .race = static_cast<u32>(Race::White),
958 .values_count = 44, 1043 .values_count = 44,
959 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1044 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
960 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58, 1045 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58,
961 60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85}, 1046 60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85},
962 }, 1047 },
963 Service::Mii::RandomMiiData4{ 1048 RandomMiiData4{
964 .gender = Gender::Female, 1049 .gender = static_cast<u32>(Gender::Female),
965 .age = Age::Old, 1050 .age = static_cast<u32>(Age::Old),
966 .race = Race::White, 1051 .race = static_cast<u32>(Race::White),
967 .values_count = 44, 1052 .values_count = 44,
968 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1053 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
969 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58, 1054 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 29, 50, 58,
970 60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85}, 1055 60, 62, 63, 64, 69, 71, 72, 74, 79, 81, 82, 83, 84, 85},
971 }, 1056 },
972 Service::Mii::RandomMiiData4{ 1057 RandomMiiData4{
973 .gender = Gender::Female, 1058 .gender = static_cast<u32>(Gender::Female),
974 .age = Age::Young, 1059 .age = static_cast<u32>(Age::Young),
975 .race = Race::Asian, 1060 .race = static_cast<u32>(Race::Asian),
976 .values_count = 24, 1061 .values_count = 24,
977 .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 1062 .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14,
978 16, 17, 18, 20, 21, 24, 25, 58, 62, 69, 76, 83}, 1063 16, 17, 18, 20, 21, 24, 25, 58, 62, 69, 76, 83},
979 }, 1064 },
980 Service::Mii::RandomMiiData4{ 1065 RandomMiiData4{
981 .gender = Gender::Female, 1066 .gender = static_cast<u32>(Gender::Female),
982 .age = Age::Normal, 1067 .age = static_cast<u32>(Age::Normal),
983 .race = Race::Asian, 1068 .race = static_cast<u32>(Race::Asian),
984 .values_count = 27, 1069 .values_count = 27,
985 .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17, 1070 .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17,
986 18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85}, 1071 18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85},
987 }, 1072 },
988 Service::Mii::RandomMiiData4{ 1073 RandomMiiData4{
989 .gender = Gender::Female, 1074 .gender = static_cast<u32>(Gender::Female),
990 .age = Age::Old, 1075 .age = static_cast<u32>(Age::Old),
991 .race = Race::Asian, 1076 .race = static_cast<u32>(Race::Asian),
992 .values_count = 27, 1077 .values_count = 27,
993 .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17, 1078 .values = {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 16, 17,
994 18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85}, 1079 18, 20, 21, 24, 25, 58, 62, 69, 74, 76, 81, 83, 85},
@@ -996,55 +1081,55 @@ const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiHairType{
996}; 1081};
997 1082
998const std::array<RandomMiiData3, 9> RandomMiiHairColor{ 1083const std::array<RandomMiiData3, 9> RandomMiiHairColor{
999 Service::Mii::RandomMiiData3{ 1084 RandomMiiData3{
1000 .arg_1 = 0, 1085 .arg_1 = 0,
1001 .arg_2 = 0, 1086 .arg_2 = 0,
1002 .values_count = 20, 1087 .values_count = 20,
1003 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1088 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1004 }, 1089 },
1005 Service::Mii::RandomMiiData3{ 1090 RandomMiiData3{
1006 .arg_1 = 0, 1091 .arg_1 = 0,
1007 .arg_2 = 1, 1092 .arg_2 = 1,
1008 .values_count = 20, 1093 .values_count = 20,
1009 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1094 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1010 }, 1095 },
1011 Service::Mii::RandomMiiData3{ 1096 RandomMiiData3{
1012 .arg_1 = 0, 1097 .arg_1 = 0,
1013 .arg_2 = 2, 1098 .arg_2 = 2,
1014 .values_count = 20, 1099 .values_count = 20,
1015 .values = {0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, 1100 .values = {0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
1016 }, 1101 },
1017 Service::Mii::RandomMiiData3{ 1102 RandomMiiData3{
1018 .arg_1 = 1, 1103 .arg_1 = 1,
1019 .arg_2 = 0, 1104 .arg_2 = 0,
1020 .values_count = 20, 1105 .values_count = 20,
1021 .values = {2, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7}, 1106 .values = {2, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7},
1022 }, 1107 },
1023 Service::Mii::RandomMiiData3{ 1108 RandomMiiData3{
1024 .arg_1 = 1, 1109 .arg_1 = 1,
1025 .arg_2 = 1, 1110 .arg_2 = 1,
1026 .values_count = 20, 1111 .values_count = 20,
1027 .values = {2, 3, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7}, 1112 .values = {2, 3, 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7},
1028 }, 1113 },
1029 Service::Mii::RandomMiiData3{ 1114 RandomMiiData3{
1030 .arg_1 = 1, 1115 .arg_1 = 1,
1031 .arg_2 = 2, 1116 .arg_2 = 2,
1032 .values_count = 20, 1117 .values_count = 20,
1033 .values = {2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7}, 1118 .values = {2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7},
1034 }, 1119 },
1035 Service::Mii::RandomMiiData3{ 1120 RandomMiiData3{
1036 .arg_1 = 2, 1121 .arg_1 = 2,
1037 .arg_2 = 0, 1122 .arg_2 = 0,
1038 .values_count = 20, 1123 .values_count = 20,
1039 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, 1124 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
1040 }, 1125 },
1041 Service::Mii::RandomMiiData3{ 1126 RandomMiiData3{
1042 .arg_1 = 2, 1127 .arg_1 = 2,
1043 .arg_2 = 1, 1128 .arg_2 = 1,
1044 .values_count = 20, 1129 .values_count = 20,
1045 .values = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3}, 1130 .values = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3},
1046 }, 1131 },
1047 Service::Mii::RandomMiiData3{ 1132 RandomMiiData3{
1048 .arg_1 = 2, 1133 .arg_1 = 2,
1049 .arg_2 = 2, 1134 .arg_2 = 2,
1050 .values_count = 20, 1135 .values_count = 20,
@@ -1052,598 +1137,642 @@ const std::array<RandomMiiData3, 9> RandomMiiHairColor{
1052 }, 1137 },
1053}; 1138};
1054 1139
1055const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyeType{ 1140const std::array<RandomMiiData4, 18> RandomMiiEyeType{
1056 Service::Mii::RandomMiiData4{ 1141 RandomMiiData4{
1057 .gender = Gender::Male, 1142 .gender = static_cast<u32>(Gender::Male),
1058 .age = Age::Young, 1143 .age = static_cast<u32>(Age::Young),
1059 .race = Race::Black, 1144 .race = static_cast<u32>(Race::Black),
1060 .values_count = 26, 1145 .values_count = 26,
1061 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27, 1146 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27,
1062 29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57}, 1147 29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57},
1063 }, 1148 },
1064 Service::Mii::RandomMiiData4{ 1149 RandomMiiData4{
1065 .gender = Gender::Male, 1150 .gender = static_cast<u32>(Gender::Male),
1066 .age = Age::Normal, 1151 .age = static_cast<u32>(Age::Normal),
1067 .race = Race::Black, 1152 .race = static_cast<u32>(Race::Black),
1068 .values_count = 26, 1153 .values_count = 26,
1069 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27, 1154 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 27,
1070 29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57}, 1155 29, 32, 34, 36, 38, 39, 41, 43, 47, 49, 51, 53, 57},
1071 }, 1156 },
1072 Service::Mii::RandomMiiData4{ 1157 RandomMiiData4{
1073 .gender = Gender::Male, 1158 .gender = static_cast<u32>(Gender::Male),
1074 .age = Age::Old, 1159 .age = static_cast<u32>(Age::Old),
1075 .race = Race::Black, 1160 .race = static_cast<u32>(Race::Black),
1076 .values_count = 27, 1161 .values_count = 27,
1077 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 26, 27, 1162 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 26, 27,
1078 29, 32, 34, 36, 38, 39, 41, 43, 47, 48, 49, 53, 57}, 1163 29, 32, 34, 36, 38, 39, 41, 43, 47, 48, 49, 53, 57},
1079 }, 1164 },
1080 Service::Mii::RandomMiiData4{ 1165 RandomMiiData4{
1081 .gender = Gender::Male, 1166 .gender = static_cast<u32>(Gender::Male),
1082 .age = Age::Young, 1167 .age = static_cast<u32>(Age::Young),
1083 .race = Race::White, 1168 .race = static_cast<u32>(Race::White),
1084 .values_count = 35, 1169 .values_count = 35,
1085 .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29, 1170 .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29,
1086 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57}, 1171 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57},
1087 }, 1172 },
1088 Service::Mii::RandomMiiData4{ 1173 RandomMiiData4{
1089 .gender = Gender::Male, 1174 .gender = static_cast<u32>(Gender::Male),
1090 .age = Age::Normal, 1175 .age = static_cast<u32>(Age::Normal),
1091 .race = Race::White, 1176 .race = static_cast<u32>(Race::White),
1092 .values_count = 35, 1177 .values_count = 35,
1093 .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29, 1178 .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 21, 22, 27, 29,
1094 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57}, 1179 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 49, 51, 53, 55, 56, 57},
1095 }, 1180 },
1096 Service::Mii::RandomMiiData4{ 1181 RandomMiiData4{
1097 .gender = Gender::Male, 1182 .gender = static_cast<u32>(Gender::Male),
1098 .age = Age::Old, 1183 .age = static_cast<u32>(Age::Old),
1099 .race = Race::White, 1184 .race = static_cast<u32>(Race::White),
1100 .values_count = 35, 1185 .values_count = 35,
1101 .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 21, 22, 26, 27, 29, 1186 .values = {2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 21, 22, 26, 27, 29,
1102 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 48, 49, 50, 53, 56, 57}, 1187 31, 32, 34, 36, 37, 38, 39, 41, 43, 44, 47, 48, 49, 50, 53, 56, 57},
1103 }, 1188 },
1104 Service::Mii::RandomMiiData4{ 1189 RandomMiiData4{
1105 .gender = Gender::Male, 1190 .gender = static_cast<u32>(Gender::Male),
1106 .age = Age::Young, 1191 .age = static_cast<u32>(Age::Young),
1107 .race = Race::Asian, 1192 .race = static_cast<u32>(Race::Asian),
1108 .values_count = 30, 1193 .values_count = 30,
1109 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21, 1194 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21,
1110 22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57}, 1195 22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57},
1111 }, 1196 },
1112 Service::Mii::RandomMiiData4{ 1197 RandomMiiData4{
1113 .gender = Gender::Male, 1198 .gender = static_cast<u32>(Gender::Male),
1114 .age = Age::Normal, 1199 .age = static_cast<u32>(Age::Normal),
1115 .race = Race::Asian, 1200 .race = static_cast<u32>(Race::Asian),
1116 .values_count = 30, 1201 .values_count = 30,
1117 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21, 1202 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21,
1118 22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57}, 1203 22, 31, 32, 34, 36, 37, 39, 41, 44, 49, 51, 53, 55, 56, 57},
1119 }, 1204 },
1120 Service::Mii::RandomMiiData4{ 1205 RandomMiiData4{
1121 .gender = Gender::Male, 1206 .gender = static_cast<u32>(Gender::Male),
1122 .age = Age::Old, 1207 .age = static_cast<u32>(Age::Old),
1123 .race = Race::Asian, 1208 .race = static_cast<u32>(Race::Asian),
1124 .values_count = 30, 1209 .values_count = 30,
1125 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 21, 22, 1210 .values = {2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 21, 22,
1126 26, 31, 32, 34, 36, 37, 39, 41, 44, 48, 49, 50, 51, 53, 57}, 1211 26, 31, 32, 34, 36, 37, 39, 41, 44, 48, 49, 50, 51, 53, 57},
1127 }, 1212 },
1128 Service::Mii::RandomMiiData4{ 1213 RandomMiiData4{
1129 .gender = Gender::Female, 1214 .gender = static_cast<u32>(Gender::Female),
1130 .age = Age::Young, 1215 .age = static_cast<u32>(Age::Young),
1131 .race = Race::Black, 1216 .race = static_cast<u32>(Race::Black),
1132 .values_count = 39, 1217 .values_count = 39,
1133 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27, 1218 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27,
1134 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59}, 1219 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59},
1135 }, 1220 },
1136 Service::Mii::RandomMiiData4{ 1221 RandomMiiData4{
1137 .gender = Gender::Female, 1222 .gender = static_cast<u32>(Gender::Female),
1138 .age = Age::Normal, 1223 .age = static_cast<u32>(Age::Normal),
1139 .race = Race::Black, 1224 .race = static_cast<u32>(Race::Black),
1140 .values_count = 39, 1225 .values_count = 39,
1141 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27, 1226 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 27,
1142 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59}, 1227 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59},
1143 }, 1228 },
1144 Service::Mii::RandomMiiData4{ 1229 RandomMiiData4{
1145 .gender = Gender::Female, 1230 .gender = static_cast<u32>(Gender::Female),
1146 .age = Age::Old, 1231 .age = static_cast<u32>(Age::Old),
1147 .race = Race::Black, 1232 .race = static_cast<u32>(Race::Black),
1148 .values_count = 40, 1233 .values_count = 40,
1149 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 26, 1234 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 25, 26,
1150 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59}, 1235 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 59},
1151 }, 1236 },
1152 Service::Mii::RandomMiiData4{ 1237 RandomMiiData4{
1153 .gender = Gender::Female, 1238 .gender = static_cast<u32>(Gender::Female),
1154 .age = Age::Young, 1239 .age = static_cast<u32>(Age::Young),
1155 .race = Race::White, 1240 .race = static_cast<u32>(Race::White),
1156 .values_count = 46, 1241 .values_count = 46,
1157 .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 1242 .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17,
1158 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37, 1243 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37,
1159 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59}, 1244 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59},
1160 }, 1245 },
1161 Service::Mii::RandomMiiData4{ 1246 RandomMiiData4{
1162 .gender = Gender::Female, 1247 .gender = static_cast<u32>(Gender::Female),
1163 .age = Age::Normal, 1248 .age = static_cast<u32>(Age::Normal),
1164 .race = Race::White, 1249 .race = static_cast<u32>(Race::White),
1165 .values_count = 46, 1250 .values_count = 46,
1166 .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 1251 .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17,
1167 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37, 1252 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 30, 32, 33, 34, 35, 37,
1168 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59}, 1253 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59},
1169 }, 1254 },
1170 Service::Mii::RandomMiiData4{ 1255 RandomMiiData4{
1171 .gender = Gender::Female, 1256 .gender = static_cast<u32>(Gender::Female),
1172 .age = Age::Old, 1257 .age = static_cast<u32>(Age::Old),
1173 .race = Race::White, 1258 .race = static_cast<u32>(Race::White),
1174 .values_count = 46, 1259 .values_count = 46,
1175 .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 1260 .values = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18,
1176 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 37, 1261 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 37,
1177 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59}, 1262 38, 39, 40, 41, 42, 45, 46, 47, 48, 53, 54, 57, 58, 59},
1178 }, 1263 },
1179 Service::Mii::RandomMiiData4{ 1264 RandomMiiData4{
1180 .gender = Gender::Female, 1265 .gender = static_cast<u32>(Gender::Female),
1181 .age = Age::Young, 1266 .age = static_cast<u32>(Age::Young),
1182 .race = Race::Asian, 1267 .race = static_cast<u32>(Race::Asian),
1183 .values_count = 34, 1268 .values_count = 34,
1184 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 1269 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23,
1185 24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47}, 1270 24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47},
1186 }, 1271 },
1187 Service::Mii::RandomMiiData4{ 1272 RandomMiiData4{
1188 .gender = Gender::Female, 1273 .gender = static_cast<u32>(Gender::Female),
1189 .age = Age::Normal, 1274 .age = static_cast<u32>(Age::Normal),
1190 .race = Race::Asian, 1275 .race = static_cast<u32>(Race::Asian),
1191 .values_count = 34, 1276 .values_count = 34,
1192 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 1277 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23,
1193 24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47}, 1278 24, 25, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47},
1194 }, 1279 },
1195 Service::Mii::RandomMiiData4{ 1280 RandomMiiData4{
1196 .gender = Gender::Female, 1281 .gender = static_cast<u32>(Gender::Female),
1197 .age = Age::Old, 1282 .age = static_cast<u32>(Age::Old),
1198 .race = Race::Asian, 1283 .race = static_cast<u32>(Race::Asian),
1199 .values_count = 35, 1284 .values_count = 35,
1200 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24, 1285 .values = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 23, 24,
1201 25, 26, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47}, 1286 25, 26, 27, 28, 29, 32, 33, 34, 35, 38, 39, 40, 41, 42, 45, 46, 47},
1202 }, 1287 },
1203}; 1288};
1204 1289
1205const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiEyeColor{ 1290const std::array<RandomMiiData2, 3> RandomMiiEyeColor{
1206 Service::Mii::RandomMiiData2{ 1291 RandomMiiData2{
1207 .arg_1 = 0, 1292 .arg_1 = 0,
1208 .values_count = 10, 1293 .values_count = 10,
1209 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 1294 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
1210 }, 1295 },
1211 Service::Mii::RandomMiiData2{ 1296 RandomMiiData2{
1212 .arg_1 = 1, 1297 .arg_1 = 1,
1213 .values_count = 10, 1298 .values_count = 10,
1214 .values = {0, 1, 1, 2, 3, 3, 4, 4, 4, 5}, 1299 .values = {0, 1, 1, 2, 3, 3, 4, 4, 4, 5},
1215 }, 1300 },
1216 Service::Mii::RandomMiiData2{ 1301 RandomMiiData2{
1217 .arg_1 = 2, 1302 .arg_1 = 2,
1218 .values_count = 10, 1303 .values_count = 10,
1219 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 1304 .values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
1220 }, 1305 },
1221}; 1306};
1222 1307
1223const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyebrowType{ 1308const std::array<RandomMiiData4, 18> RandomMiiEyebrowType{
1224 Service::Mii::RandomMiiData4{ 1309 RandomMiiData4{
1225 .gender = Gender::Male, 1310 .gender = static_cast<u32>(Gender::Male),
1226 .age = Age::Young, 1311 .age = static_cast<u32>(Age::Young),
1227 .race = Race::Black, 1312 .race = static_cast<u32>(Race::Black),
1228 .values_count = 18, 1313 .values_count = 18,
1229 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20}, 1314 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20},
1230 }, 1315 },
1231 Service::Mii::RandomMiiData4{ 1316 RandomMiiData4{
1232 .gender = Gender::Male, 1317 .gender = static_cast<u32>(Gender::Male),
1233 .age = Age::Normal, 1318 .age = static_cast<u32>(Age::Normal),
1234 .race = Race::Black, 1319 .race = static_cast<u32>(Race::Black),
1235 .values_count = 18, 1320 .values_count = 18,
1236 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20}, 1321 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20},
1237 }, 1322 },
1238 Service::Mii::RandomMiiData4{ 1323 RandomMiiData4{
1239 .gender = Gender::Male, 1324 .gender = static_cast<u32>(Gender::Male),
1240 .age = Age::Old, 1325 .age = static_cast<u32>(Age::Old),
1241 .race = Race::Black, 1326 .race = static_cast<u32>(Race::Black),
1242 .values_count = 18, 1327 .values_count = 18,
1243 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20}, 1328 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 20},
1244 }, 1329 },
1245 Service::Mii::RandomMiiData4{ 1330 RandomMiiData4{
1246 .gender = Gender::Male, 1331 .gender = static_cast<u32>(Gender::Male),
1247 .age = Age::Young, 1332 .age = static_cast<u32>(Age::Young),
1248 .race = Race::White, 1333 .race = static_cast<u32>(Race::White),
1249 .values_count = 23, 1334 .values_count = 23,
1250 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1335 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
1251 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, 1336 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22},
1252 }, 1337 },
1253 Service::Mii::RandomMiiData4{ 1338 RandomMiiData4{
1254 .gender = Gender::Male, 1339 .gender = static_cast<u32>(Gender::Male),
1255 .age = Age::Normal, 1340 .age = static_cast<u32>(Age::Normal),
1256 .race = Race::White, 1341 .race = static_cast<u32>(Race::White),
1257 .values_count = 23, 1342 .values_count = 23,
1258 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1343 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
1259 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, 1344 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22},
1260 }, 1345 },
1261 Service::Mii::RandomMiiData4{ 1346 RandomMiiData4{
1262 .gender = Gender::Male, 1347 .gender = static_cast<u32>(Gender::Male),
1263 .age = Age::Old, 1348 .age = static_cast<u32>(Age::Old),
1264 .race = Race::White, 1349 .race = static_cast<u32>(Race::White),
1265 .values_count = 23, 1350 .values_count = 23,
1266 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1351 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
1267 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, 1352 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22},
1268 }, 1353 },
1269 Service::Mii::RandomMiiData4{ 1354 RandomMiiData4{
1270 .gender = Gender::Male, 1355 .gender = static_cast<u32>(Gender::Male),
1271 .age = Age::Young, 1356 .age = static_cast<u32>(Age::Young),
1272 .race = Race::Asian, 1357 .race = static_cast<u32>(Race::Asian),
1273 .values_count = 21, 1358 .values_count = 21,
1274 .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22}, 1359 .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22},
1275 }, 1360 },
1276 Service::Mii::RandomMiiData4{ 1361 RandomMiiData4{
1277 .gender = Gender::Male, 1362 .gender = static_cast<u32>(Gender::Male),
1278 .age = Age::Normal, 1363 .age = static_cast<u32>(Age::Normal),
1279 .race = Race::Asian, 1364 .race = static_cast<u32>(Race::Asian),
1280 .values_count = 21, 1365 .values_count = 21,
1281 .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22}, 1366 .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22},
1282 }, 1367 },
1283 Service::Mii::RandomMiiData4{ 1368 RandomMiiData4{
1284 .gender = Gender::Male, 1369 .gender = static_cast<u32>(Gender::Male),
1285 .age = Age::Old, 1370 .age = static_cast<u32>(Age::Old),
1286 .race = Race::Asian, 1371 .race = static_cast<u32>(Race::Asian),
1287 .values_count = 21, 1372 .values_count = 21,
1288 .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22}, 1373 .values = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22},
1289 }, 1374 },
1290 Service::Mii::RandomMiiData4{ 1375 RandomMiiData4{
1291 .gender = Gender::Female, 1376 .gender = static_cast<u32>(Gender::Female),
1292 .age = Age::Young, 1377 .age = static_cast<u32>(Age::Young),
1293 .race = Race::Black, 1378 .race = static_cast<u32>(Race::Black),
1294 .values_count = 9, 1379 .values_count = 9,
1295 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13}, 1380 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13},
1296 }, 1381 },
1297 Service::Mii::RandomMiiData4{ 1382 RandomMiiData4{
1298 .gender = Gender::Female, 1383 .gender = static_cast<u32>(Gender::Female),
1299 .age = Age::Normal, 1384 .age = static_cast<u32>(Age::Normal),
1300 .race = Race::Black, 1385 .race = static_cast<u32>(Race::Black),
1301 .values_count = 9, 1386 .values_count = 9,
1302 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13}, 1387 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13},
1303 }, 1388 },
1304 Service::Mii::RandomMiiData4{ 1389 RandomMiiData4{
1305 .gender = Gender::Female, 1390 .gender = static_cast<u32>(Gender::Female),
1306 .age = Age::Old, 1391 .age = static_cast<u32>(Age::Old),
1307 .race = Race::Black, 1392 .race = static_cast<u32>(Race::Black),
1308 .values_count = 9, 1393 .values_count = 9,
1309 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13}, 1394 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13},
1310 }, 1395 },
1311 Service::Mii::RandomMiiData4{ 1396 RandomMiiData4{
1312 .gender = Gender::Female, 1397 .gender = static_cast<u32>(Gender::Female),
1313 .age = Age::Young, 1398 .age = static_cast<u32>(Age::Young),
1314 .race = Race::White, 1399 .race = static_cast<u32>(Race::White),
1315 .values_count = 11, 1400 .values_count = 11,
1316 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19}, 1401 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19},
1317 }, 1402 },
1318 Service::Mii::RandomMiiData4{ 1403 RandomMiiData4{
1319 .gender = Gender::Female, 1404 .gender = static_cast<u32>(Gender::Female),
1320 .age = Age::Normal, 1405 .age = static_cast<u32>(Age::Normal),
1321 .race = Race::White, 1406 .race = static_cast<u32>(Race::White),
1322 .values_count = 11, 1407 .values_count = 11,
1323 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19}, 1408 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19},
1324 }, 1409 },
1325 Service::Mii::RandomMiiData4{ 1410 RandomMiiData4{
1326 .gender = Gender::Female, 1411 .gender = static_cast<u32>(Gender::Female),
1327 .age = Age::Old, 1412 .age = static_cast<u32>(Age::Old),
1328 .race = Race::White, 1413 .race = static_cast<u32>(Race::White),
1329 .values_count = 11, 1414 .values_count = 11,
1330 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19}, 1415 .values = {0, 1, 3, 7, 8, 9, 10, 11, 13, 15, 19},
1331 }, 1416 },
1332 Service::Mii::RandomMiiData4{ 1417 RandomMiiData4{
1333 .gender = Gender::Female, 1418 .gender = static_cast<u32>(Gender::Female),
1334 .age = Age::Young, 1419 .age = static_cast<u32>(Age::Young),
1335 .race = Race::Asian, 1420 .race = static_cast<u32>(Race::Asian),
1336 .values_count = 9, 1421 .values_count = 9,
1337 .values = {0, 3, 7, 8, 9, 10, 11, 13, 15}, 1422 .values = {0, 3, 7, 8, 9, 10, 11, 13, 15},
1338 }, 1423 },
1339 Service::Mii::RandomMiiData4{ 1424 RandomMiiData4{
1340 .gender = Gender::Female, 1425 .gender = static_cast<u32>(Gender::Female),
1341 .age = Age::Normal, 1426 .age = static_cast<u32>(Age::Normal),
1342 .race = Race::Asian, 1427 .race = static_cast<u32>(Race::Asian),
1343 .values_count = 9, 1428 .values_count = 9,
1344 .values = {0, 3, 7, 8, 9, 10, 11, 13, 15}, 1429 .values = {0, 3, 7, 8, 9, 10, 11, 13, 15},
1345 }, 1430 },
1346 Service::Mii::RandomMiiData4{ 1431 RandomMiiData4{
1347 .gender = Gender::Female, 1432 .gender = static_cast<u32>(Gender::Female),
1348 .age = Age::Old, 1433 .age = static_cast<u32>(Age::Old),
1349 .race = Race::Asian, 1434 .race = static_cast<u32>(Race::Asian),
1350 .values_count = 9, 1435 .values_count = 9,
1351 .values = {0, 3, 7, 8, 9, 10, 11, 13, 15}, 1436 .values = {0, 3, 7, 8, 9, 10, 11, 13, 15},
1352 }, 1437 },
1353}; 1438};
1354 1439
1355const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiNoseType{ 1440const std::array<RandomMiiData4, 18> RandomMiiNoseType{
1356 Service::Mii::RandomMiiData4{ 1441 RandomMiiData4{
1357 .gender = Gender::Male, 1442 .gender = static_cast<u32>(Gender::Male),
1358 .age = Age::Young, 1443 .age = static_cast<u32>(Age::Young),
1359 .race = Race::Black, 1444 .race = static_cast<u32>(Race::Black),
1360 .values_count = 11, 1445 .values_count = 11,
1361 .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14}, 1446 .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14},
1362 }, 1447 },
1363 Service::Mii::RandomMiiData4{ 1448 RandomMiiData4{
1364 .gender = Gender::Male, 1449 .gender = static_cast<u32>(Gender::Male),
1365 .age = Age::Normal, 1450 .age = static_cast<u32>(Age::Normal),
1366 .race = Race::Black, 1451 .race = static_cast<u32>(Race::Black),
1367 .values_count = 11, 1452 .values_count = 11,
1368 .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14}, 1453 .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14},
1369 }, 1454 },
1370 Service::Mii::RandomMiiData4{ 1455 RandomMiiData4{
1371 .gender = Gender::Male, 1456 .gender = static_cast<u32>(Gender::Male),
1372 .age = Age::Old, 1457 .age = static_cast<u32>(Age::Old),
1373 .race = Race::Black, 1458 .race = static_cast<u32>(Race::Black),
1374 .values_count = 11, 1459 .values_count = 11,
1375 .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14}, 1460 .values = {0, 1, 2, 3, 4, 5, 7, 8, 10, 13, 14},
1376 }, 1461 },
1377 Service::Mii::RandomMiiData4{ 1462 RandomMiiData4{
1378 .gender = Gender::Male, 1463 .gender = static_cast<u32>(Gender::Male),
1379 .age = Age::Young, 1464 .age = static_cast<u32>(Age::Young),
1380 .race = Race::White, 1465 .race = static_cast<u32>(Race::White),
1381 .values_count = 18, 1466 .values_count = 18,
1382 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 1467 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
1383 }, 1468 },
1384 Service::Mii::RandomMiiData4{ 1469 RandomMiiData4{
1385 .gender = Gender::Male, 1470 .gender = static_cast<u32>(Gender::Male),
1386 .age = Age::Normal, 1471 .age = static_cast<u32>(Age::Normal),
1387 .race = Race::White, 1472 .race = static_cast<u32>(Race::White),
1388 .values_count = 18, 1473 .values_count = 18,
1389 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 1474 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
1390 }, 1475 },
1391 Service::Mii::RandomMiiData4{ 1476 RandomMiiData4{
1392 .gender = Gender::Male, 1477 .gender = static_cast<u32>(Gender::Male),
1393 .age = Age::Old, 1478 .age = static_cast<u32>(Age::Old),
1394 .race = Race::White, 1479 .race = static_cast<u32>(Race::White),
1395 .values_count = 15, 1480 .values_count = 15,
1396 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16}, 1481 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16},
1397 }, 1482 },
1398 Service::Mii::RandomMiiData4{ 1483 RandomMiiData4{
1399 .gender = Gender::Male, 1484 .gender = static_cast<u32>(Gender::Male),
1400 .age = Age::Young, 1485 .age = static_cast<u32>(Age::Young),
1401 .race = Race::Asian, 1486 .race = static_cast<u32>(Race::Asian),
1402 .values_count = 18, 1487 .values_count = 18,
1403 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 1488 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
1404 }, 1489 },
1405 Service::Mii::RandomMiiData4{ 1490 RandomMiiData4{
1406 .gender = Gender::Male, 1491 .gender = static_cast<u32>(Gender::Male),
1407 .age = Age::Normal, 1492 .age = static_cast<u32>(Age::Normal),
1408 .race = Race::Asian, 1493 .race = static_cast<u32>(Race::Asian),
1409 .values_count = 18, 1494 .values_count = 18,
1410 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 1495 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
1411 }, 1496 },
1412 Service::Mii::RandomMiiData4{ 1497 RandomMiiData4{
1413 .gender = Gender::Male, 1498 .gender = static_cast<u32>(Gender::Male),
1414 .age = Age::Old, 1499 .age = static_cast<u32>(Age::Old),
1415 .race = Race::Asian, 1500 .race = static_cast<u32>(Race::Asian),
1416 .values_count = 15, 1501 .values_count = 15,
1417 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16}, 1502 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16},
1418 }, 1503 },
1419 Service::Mii::RandomMiiData4{ 1504 RandomMiiData4{
1420 .gender = Gender::Female, 1505 .gender = static_cast<u32>(Gender::Female),
1421 .age = Age::Young, 1506 .age = static_cast<u32>(Age::Young),
1422 .race = Race::Black, 1507 .race = static_cast<u32>(Race::Black),
1423 .values_count = 8, 1508 .values_count = 8,
1424 .values = {0, 1, 3, 4, 8, 10, 13, 14}, 1509 .values = {0, 1, 3, 4, 8, 10, 13, 14},
1425 }, 1510 },
1426 Service::Mii::RandomMiiData4{ 1511 RandomMiiData4{
1427 .gender = Gender::Female, 1512 .gender = static_cast<u32>(Gender::Female),
1428 .age = Age::Normal, 1513 .age = static_cast<u32>(Age::Normal),
1429 .race = Race::Black, 1514 .race = static_cast<u32>(Race::Black),
1430 .values_count = 8, 1515 .values_count = 8,
1431 .values = {0, 1, 3, 4, 8, 10, 13, 14}, 1516 .values = {0, 1, 3, 4, 8, 10, 13, 14},
1432 }, 1517 },
1433 Service::Mii::RandomMiiData4{ 1518 RandomMiiData4{
1434 .gender = Gender::Female, 1519 .gender = static_cast<u32>(Gender::Female),
1435 .age = Age::Old, 1520 .age = static_cast<u32>(Age::Old),
1436 .race = Race::Black, 1521 .race = static_cast<u32>(Race::Black),
1437 .values_count = 8, 1522 .values_count = 8,
1438 .values = {0, 1, 3, 4, 8, 10, 13, 14}, 1523 .values = {0, 1, 3, 4, 8, 10, 13, 14},
1439 }, 1524 },
1440 Service::Mii::RandomMiiData4{ 1525 RandomMiiData4{
1441 .gender = Gender::Female, 1526 .gender = static_cast<u32>(Gender::Female),
1442 .age = Age::Young, 1527 .age = static_cast<u32>(Age::Young),
1443 .race = Race::White, 1528 .race = static_cast<u32>(Race::White),
1444 .values_count = 12, 1529 .values_count = 12,
1445 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15}, 1530 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15},
1446 }, 1531 },
1447 Service::Mii::RandomMiiData4{ 1532 RandomMiiData4{
1448 .gender = Gender::Female, 1533 .gender = static_cast<u32>(Gender::Female),
1449 .age = Age::Normal, 1534 .age = static_cast<u32>(Age::Normal),
1450 .race = Race::White, 1535 .race = static_cast<u32>(Race::White),
1451 .values_count = 11, 1536 .values_count = 11,
1452 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15}, 1537 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15},
1453 }, 1538 },
1454 Service::Mii::RandomMiiData4{ 1539 RandomMiiData4{
1455 .gender = Gender::Female, 1540 .gender = static_cast<u32>(Gender::Female),
1456 .age = Age::Old, 1541 .age = static_cast<u32>(Age::Old),
1457 .race = Race::White, 1542 .race = static_cast<u32>(Race::White),
1458 .values_count = 10, 1543 .values_count = 10,
1459 .values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14}, 1544 .values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14},
1460 }, 1545 },
1461 Service::Mii::RandomMiiData4{ 1546 RandomMiiData4{
1462 .gender = Gender::Female, 1547 .gender = static_cast<u32>(Gender::Female),
1463 .age = Age::Young, 1548 .age = static_cast<u32>(Age::Young),
1464 .race = Race::Asian, 1549 .race = static_cast<u32>(Race::Asian),
1465 .values_count = 12, 1550 .values_count = 12,
1466 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15}, 1551 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15},
1467 }, 1552 },
1468 Service::Mii::RandomMiiData4{ 1553 RandomMiiData4{
1469 .gender = Gender::Female, 1554 .gender = static_cast<u32>(Gender::Female),
1470 .age = Age::Normal, 1555 .age = static_cast<u32>(Age::Normal),
1471 .race = Race::Asian, 1556 .race = static_cast<u32>(Race::Asian),
1472 .values_count = 11, 1557 .values_count = 11,
1473 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15}, 1558 .values = {0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 15},
1474 }, 1559 },
1475 Service::Mii::RandomMiiData4{ 1560 RandomMiiData4{
1476 .gender = Gender::Female, 1561 .gender = static_cast<u32>(Gender::Female),
1477 .age = Age::Old, 1562 .age = static_cast<u32>(Age::Old),
1478 .race = Race::Asian, 1563 .race = static_cast<u32>(Race::Asian),
1479 .values_count = 10, 1564 .values_count = 10,
1480 .values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14}, 1565 .values = {0, 1, 3, 4, 6, 8, 10, 11, 13, 14},
1481 }, 1566 },
1482}; 1567};
1483 1568
1484const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiMouthType{ 1569const std::array<RandomMiiData4, 18> RandomMiiMouthType{
1485 Service::Mii::RandomMiiData4{ 1570 RandomMiiData4{
1486 .gender = Gender::Male, 1571 .gender = static_cast<u32>(Gender::Male),
1487 .age = Age::Young, 1572 .age = static_cast<u32>(Age::Young),
1488 .race = Race::Black, 1573 .race = static_cast<u32>(Race::Black),
1489 .values_count = 25, 1574 .values_count = 25,
1490 .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 17, 18, 1575 .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 17, 18,
1491 19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35}, 1576 19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35},
1492 }, 1577 },
1493 Service::Mii::RandomMiiData4{ 1578 RandomMiiData4{
1494 .gender = Gender::Male, 1579 .gender = static_cast<u32>(Gender::Male),
1495 .age = Age::Normal, 1580 .age = static_cast<u32>(Age::Normal),
1496 .race = Race::Black, 1581 .race = static_cast<u32>(Race::Black),
1497 .values_count = 27, 1582 .values_count = 27,
1498 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 1583 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17,
1499 18, 19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35}, 1584 18, 19, 21, 22, 23, 25, 26, 28, 30, 32, 33, 34, 35},
1500 }, 1585 },
1501 Service::Mii::RandomMiiData4{ 1586 RandomMiiData4{
1502 .gender = Gender::Male, 1587 .gender = static_cast<u32>(Gender::Male),
1503 .age = Age::Old, 1588 .age = static_cast<u32>(Age::Old),
1504 .race = Race::Black, 1589 .race = static_cast<u32>(Race::Black),
1505 .values_count = 28, 1590 .values_count = 28,
1506 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 1591 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17,
1507 18, 19, 21, 22, 23, 25, 26, 28, 30, 31, 32, 33, 34, 35}, 1592 18, 19, 21, 22, 23, 25, 26, 28, 30, 31, 32, 33, 34, 35},
1508 }, 1593 },
1509 Service::Mii::RandomMiiData4{ 1594 RandomMiiData4{
1510 .gender = Gender::Male, 1595 .gender = static_cast<u32>(Gender::Male),
1511 .age = Age::Young, 1596 .age = static_cast<u32>(Age::Young),
1512 .race = Race::White, 1597 .race = static_cast<u32>(Race::White),
1513 .values_count = 24, 1598 .values_count = 24,
1514 .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16, 1599 .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16,
1515 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, 1600 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
1516 }, 1601 },
1517 Service::Mii::RandomMiiData4{ 1602 RandomMiiData4{
1518 .gender = Gender::Male, 1603 .gender = static_cast<u32>(Gender::Male),
1519 .age = Age::Normal, 1604 .age = static_cast<u32>(Age::Normal),
1520 .race = Race::White, 1605 .race = static_cast<u32>(Race::White),
1521 .values_count = 26, 1606 .values_count = 26,
1522 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1607 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1523 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, 1608 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
1524 }, 1609 },
1525 Service::Mii::RandomMiiData4{ 1610 RandomMiiData4{
1526 .gender = Gender::Male, 1611 .gender = static_cast<u32>(Gender::Male),
1527 .age = Age::Old, 1612 .age = static_cast<u32>(Age::Old),
1528 .race = Race::White, 1613 .race = static_cast<u32>(Race::White),
1529 .values_count = 26, 1614 .values_count = 26,
1530 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1615 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1531 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, 1616 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
1532 }, 1617 },
1533 Service::Mii::RandomMiiData4{ 1618 RandomMiiData4{
1534 .gender = Gender::Male, 1619 .gender = static_cast<u32>(Gender::Male),
1535 .age = Age::Young, 1620 .age = static_cast<u32>(Age::Young),
1536 .race = Race::Asian, 1621 .race = static_cast<u32>(Race::Asian),
1537 .values_count = 24, 1622 .values_count = 24,
1538 .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16, 1623 .values = {0, 2, 3, 6, 7, 8, 9, 10, 12, 14, 15, 16,
1539 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, 1624 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
1540 }, 1625 },
1541 Service::Mii::RandomMiiData4{ 1626 RandomMiiData4{
1542 .gender = Gender::Male, 1627 .gender = static_cast<u32>(Gender::Male),
1543 .age = Age::Normal, 1628 .age = static_cast<u32>(Age::Normal),
1544 .race = Race::Asian, 1629 .race = static_cast<u32>(Race::Asian),
1545 .values_count = 26, 1630 .values_count = 26,
1546 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1631 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1547 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, 1632 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
1548 }, 1633 },
1549 Service::Mii::RandomMiiData4{ 1634 RandomMiiData4{
1550 .gender = Gender::Male, 1635 .gender = static_cast<u32>(Gender::Male),
1551 .age = Age::Old, 1636 .age = static_cast<u32>(Age::Old),
1552 .race = Race::Asian, 1637 .race = static_cast<u32>(Race::Asian),
1553 .values_count = 26, 1638 .values_count = 26,
1554 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1639 .values = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1555 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35}, 1640 16, 17, 18, 19, 20, 21, 22, 23, 30, 31, 33, 34, 35},
1556 }, 1641 },
1557 Service::Mii::RandomMiiData4{ 1642 RandomMiiData4{
1558 .gender = Gender::Female, 1643 .gender = static_cast<u32>(Gender::Female),
1559 .age = Age::Young, 1644 .age = static_cast<u32>(Age::Young),
1560 .race = Race::Black, 1645 .race = static_cast<u32>(Race::Black),
1561 .values_count = 25, 1646 .values_count = 25,
1562 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15, 1647 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15,
1563 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35}, 1648 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35},
1564 }, 1649 },
1565 Service::Mii::RandomMiiData4{ 1650 RandomMiiData4{
1566 .gender = Gender::Female, 1651 .gender = static_cast<u32>(Gender::Female),
1567 .age = Age::Normal, 1652 .age = static_cast<u32>(Age::Normal),
1568 .race = Race::Black, 1653 .race = static_cast<u32>(Race::Black),
1569 .values_count = 26, 1654 .values_count = 26,
1570 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 1655 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
1571 15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35}, 1656 15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35},
1572 }, 1657 },
1573 Service::Mii::RandomMiiData4{ 1658 RandomMiiData4{
1574 .gender = Gender::Female, 1659 .gender = static_cast<u32>(Gender::Female),
1575 .age = Age::Old, 1660 .age = static_cast<u32>(Age::Old),
1576 .race = Race::Black, 1661 .race = static_cast<u32>(Race::Black),
1577 .values_count = 26, 1662 .values_count = 26,
1578 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 1663 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
1579 15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35}, 1664 15, 17, 18, 19, 21, 22, 23, 25, 26, 30, 33, 34, 35},
1580 }, 1665 },
1581 Service::Mii::RandomMiiData4{ 1666 RandomMiiData4{
1582 .gender = Gender::Female, 1667 .gender = static_cast<u32>(Gender::Female),
1583 .age = Age::Young, 1668 .age = static_cast<u32>(Age::Young),
1584 .race = Race::White, 1669 .race = static_cast<u32>(Race::White),
1585 .values_count = 25, 1670 .values_count = 25,
1586 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15, 1671 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 15,
1587 17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35}, 1672 17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35},
1588 }, 1673 },
1589 Service::Mii::RandomMiiData4{ 1674 RandomMiiData4{
1590 .gender = Gender::Female, 1675 .gender = static_cast<u32>(Gender::Female),
1591 .age = Age::Normal, 1676 .age = static_cast<u32>(Age::Normal),
1592 .race = Race::White, 1677 .race = static_cast<u32>(Race::White),
1593 .values_count = 26, 1678 .values_count = 26,
1594 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 1679 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
1595 15, 17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35}, 1680 15, 17, 18, 19, 21, 22, 23, 24, 26, 27, 29, 33, 35},
1596 }, 1681 },
1597 Service::Mii::RandomMiiData4{ 1682 RandomMiiData4{
1598 .gender = Gender::Female, 1683 .gender = static_cast<u32>(Gender::Female),
1599 .age = Age::Old, 1684 .age = static_cast<u32>(Age::Old),
1600 .race = Race::White, 1685 .race = static_cast<u32>(Race::White),
1601 .values_count = 25, 1686 .values_count = 25,
1602 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 1687 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
1603 15, 17, 18, 19, 21, 22, 23, 24, 25, 29, 33, 35}, 1688 15, 17, 18, 19, 21, 22, 23, 24, 25, 29, 33, 35},
1604 }, 1689 },
1605 Service::Mii::RandomMiiData4{ 1690 RandomMiiData4{
1606 .gender = Gender::Female, 1691 .gender = static_cast<u32>(Gender::Female),
1607 .age = Age::Young, 1692 .age = static_cast<u32>(Age::Young),
1608 .race = Race::Asian, 1693 .race = static_cast<u32>(Race::Asian),
1609 .values_count = 24, 1694 .values_count = 24,
1610 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 1695 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14,
1611 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33}, 1696 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33},
1612 }, 1697 },
1613 Service::Mii::RandomMiiData4{ 1698 RandomMiiData4{
1614 .gender = Gender::Female, 1699 .gender = static_cast<u32>(Gender::Female),
1615 .age = Age::Normal, 1700 .age = static_cast<u32>(Age::Normal),
1616 .race = Race::Asian, 1701 .race = static_cast<u32>(Race::Asian),
1617 .values_count = 25, 1702 .values_count = 25,
1618 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 1703 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
1619 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33}, 1704 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33},
1620 }, 1705 },
1621 Service::Mii::RandomMiiData4{ 1706 RandomMiiData4{
1622 .gender = Gender::Female, 1707 .gender = static_cast<u32>(Gender::Female),
1623 .age = Age::Old, 1708 .age = static_cast<u32>(Age::Old),
1624 .race = Race::Asian, 1709 .race = static_cast<u32>(Race::Asian),
1625 .values_count = 25, 1710 .values_count = 25,
1626 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 1711 .values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14,
1627 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33}, 1712 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 33},
1628 }, 1713 },
1629}; 1714};
1630 1715
1631const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiGlassType{ 1716const std::array<RandomMiiData2, 3> RandomMiiGlassType{
1632 Service::Mii::RandomMiiData2{ 1717 RandomMiiData2{
1633 .arg_1 = 0, 1718 .arg_1 = 0,
1634 .values_count = 9, 1719 .values_count = 9,
1635 .values = {90, 94, 96, 100, 0, 0, 0, 0, 0}, 1720 .values = {90, 94, 96, 100, 0, 0, 0, 0, 0},
1636 }, 1721 },
1637 Service::Mii::RandomMiiData2{ 1722 RandomMiiData2{
1638 .arg_1 = 1, 1723 .arg_1 = 1,
1639 .values_count = 9, 1724 .values_count = 9,
1640 .values = {83, 86, 90, 93, 94, 96, 98, 100, 0}, 1725 .values = {83, 86, 90, 93, 94, 96, 98, 100, 0},
1641 }, 1726 },
1642 Service::Mii::RandomMiiData2{ 1727 RandomMiiData2{
1643 .arg_1 = 2, 1728 .arg_1 = 2,
1644 .values_count = 9, 1729 .values_count = 9,
1645 .values = {78, 83, 0, 93, 0, 0, 98, 100, 0}, 1730 .values = {78, 83, 0, 93, 0, 0, 98, 100, 0},
1646 }, 1731 },
1647}; 1732};
1648 1733
1734u8 FromVer3GetFacelineColor(u8 color) {
1735 return FromVer3FacelineColorTable[color];
1736}
1737
1738u8 FromVer3GetHairColor(u8 color) {
1739 return FromVer3HairColorTable[color];
1740}
1741
1742u8 FromVer3GetEyeColor(u8 color) {
1743 return FromVer3EyeColorTable[color];
1744}
1745
1746u8 FromVer3GetMouthlineColor(u8 color) {
1747 return FromVer3MouthlineColorTable[color];
1748}
1749
1750u8 FromVer3GetGlassColor(u8 color) {
1751 return FromVer3GlassColorTable[color];
1752}
1753
1754u8 FromVer3GetGlassType(u8 type) {
1755 return FromVer3GlassTypeTable[type];
1756}
1757
1758FacelineColor GetFacelineColorFromVer3(u32 color) {
1759 return static_cast<FacelineColor>(Ver3FacelineColorTable[color]);
1760}
1761
1762CommonColor GetHairColorFromVer3(u32 color) {
1763 return static_cast<CommonColor>(Ver3HairColorTable[color]);
1764}
1765
1766CommonColor GetEyeColorFromVer3(u32 color) {
1767 return static_cast<CommonColor>(Ver3EyeColorTable[color]);
1768}
1769
1770CommonColor GetMouthColorFromVer3(u32 color) {
1771 return static_cast<CommonColor>(Ver3MouthColorTable[color]);
1772}
1773
1774CommonColor GetGlassColorFromVer3(u32 color) {
1775 return static_cast<CommonColor>(Ver3GlassColorTable[color]);
1776}
1777
1649} // namespace Service::Mii::RawData 1778} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7
8#include "core/hle/service/mii/mii_types.h"
9
10namespace Service::Mii::RawData {
11
12struct RandomMiiValues {
13 std::array<u8, 188> values{};
14};
15static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
16
17struct RandomMiiData4 {
18 u32 gender{};
19 u32 age{};
20 u32 race{};
21 u32 values_count{};
22 std::array<u32, 47> values{};
23};
24static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
25
26struct RandomMiiData3 {
27 u32 arg_1;
28 u32 arg_2;
29 u32 values_count;
30 std::array<u32, 47> values{};
31};
32static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
33
34struct RandomMiiData2 {
35 u32 arg_1;
36 u32 values_count;
37 std::array<u32, 47> values{};
38};
39static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
40
41extern const std::array<Service::Mii::DefaultMii, 2> BaseMii;
42extern const std::array<Service::Mii::DefaultMii, 6> DefaultMii;
43
44extern const std::array<u8, 62> EyeRotateLookup;
45extern const std::array<u8, 24> EyebrowRotateLookup;
46
47extern const std::array<RandomMiiData4, 18> RandomMiiFaceline;
48extern const std::array<RandomMiiData3, 6> RandomMiiFacelineColor;
49extern const std::array<RandomMiiData4, 18> RandomMiiFacelineWrinkle;
50extern const std::array<RandomMiiData4, 18> RandomMiiFacelineMakeup;
51extern const std::array<RandomMiiData4, 18> RandomMiiHairType;
52extern const std::array<RandomMiiData3, 9> RandomMiiHairColor;
53extern const std::array<RandomMiiData4, 18> RandomMiiEyeType;
54extern const std::array<RandomMiiData2, 3> RandomMiiEyeColor;
55extern const std::array<RandomMiiData4, 18> RandomMiiEyebrowType;
56extern const std::array<RandomMiiData4, 18> RandomMiiNoseType;
57extern const std::array<RandomMiiData4, 18> RandomMiiMouthType;
58extern const std::array<RandomMiiData2, 3> RandomMiiGlassType;
59
60u8 FromVer3GetFacelineColor(u8 color);
61u8 FromVer3GetHairColor(u8 color);
62u8 FromVer3GetEyeColor(u8 color);
63u8 FromVer3GetMouthlineColor(u8 color);
64u8 FromVer3GetGlassColor(u8 color);
65u8 FromVer3GetGlassType(u8 type);
66
67FacelineColor GetFacelineColorFromVer3(u32 color);
68CommonColor GetHairColorFromVer3(u32 color);
69CommonColor GetEyeColorFromVer3(u32 color);
70CommonColor GetMouthColorFromVer3(u32 color);
71CommonColor GetGlassColorFromVer3(u32 color);
72
73} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/mii/mii_util.h"
5#include "core/hle/service/mii/types/raw_data.h"
6#include "core/hle/service/mii/types/store_data.h"
7
8namespace Service::Mii {
9
10void StoreData::BuildDefault(u32 mii_index) {
11 const auto& default_mii = RawData::DefaultMii[mii_index];
12 core_data.SetDefault();
13
14 core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type));
15 core_data.SetFacelineColor(
16 RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color)));
17 core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle));
18 core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup));
19
20 core_data.SetHairType(static_cast<HairType>(default_mii.hair_type));
21 core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color)));
22 core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip));
23 core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type));
24 core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color)));
25 core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale));
26 core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect));
27 core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate));
28 core_data.SetEyeX(static_cast<u8>(default_mii.eye_x));
29 core_data.SetEyeY(static_cast<u8>(default_mii.eye_y));
30
31 core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type));
32 core_data.SetEyebrowColor(
33 RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color)));
34 core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale));
35 core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect));
36 core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate));
37 core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x));
38 core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y));
39
40 core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type));
41 core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale));
42 core_data.SetNoseY(static_cast<u8>(default_mii.nose_y));
43
44 core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type));
45 core_data.SetMouthColor(
46 RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color)));
47 core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale));
48 core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect));
49 core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y));
50
51 core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type));
52 core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type));
53 core_data.SetBeardColor(
54 RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color)));
55 core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale));
56 core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y));
57
58 core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type));
59 core_data.SetGlassColor(
60 RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color)));
61 core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale));
62 core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y));
63
64 core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type));
65 core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale));
66 core_data.SetMoleX(static_cast<u8>(default_mii.mole_x));
67 core_data.SetMoleY(static_cast<u8>(default_mii.mole_y));
68
69 core_data.SetHeight(static_cast<u8>(default_mii.height));
70 core_data.SetBuild(static_cast<u8>(default_mii.weight));
71 core_data.SetGender(static_cast<Gender>(default_mii.gender));
72 core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color));
73 core_data.SetRegionMove(static_cast<u8>(default_mii.region_move));
74 core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region));
75 core_data.SetType(static_cast<u8>(default_mii.type));
76 core_data.SetNickname(default_mii.nickname);
77
78 const auto device_id = MiiUtil::GetDeviceId();
79 create_id = MiiUtil::MakeCreateId();
80 device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
81 data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
82}
83
84void StoreData::BuildBase(Gender gender) {
85 const auto& default_mii = RawData::BaseMii[gender == Gender::Female ? 1 : 0];
86 core_data.SetDefault();
87
88 core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type));
89 core_data.SetFacelineColor(
90 RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color)));
91 core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle));
92 core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup));
93
94 core_data.SetHairType(static_cast<HairType>(default_mii.hair_type));
95 core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color)));
96 core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip));
97 core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type));
98 core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color)));
99 core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale));
100 core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect));
101 core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate));
102 core_data.SetEyeX(static_cast<u8>(default_mii.eye_x));
103 core_data.SetEyeY(static_cast<u8>(default_mii.eye_y));
104
105 core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type));
106 core_data.SetEyebrowColor(
107 RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color)));
108 core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale));
109 core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect));
110 core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate));
111 core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x));
112 core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y));
113
114 core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type));
115 core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale));
116 core_data.SetNoseY(static_cast<u8>(default_mii.nose_y));
117
118 core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type));
119 core_data.SetMouthColor(
120 RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color)));
121 core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale));
122 core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect));
123 core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y));
124
125 core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type));
126 core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type));
127 core_data.SetBeardColor(
128 RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color)));
129 core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale));
130 core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y));
131
132 core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type));
133 core_data.SetGlassColor(
134 RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color)));
135 core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale));
136 core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y));
137
138 core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type));
139 core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale));
140 core_data.SetMoleX(static_cast<u8>(default_mii.mole_x));
141 core_data.SetMoleY(static_cast<u8>(default_mii.mole_y));
142
143 core_data.SetHeight(static_cast<u8>(default_mii.height));
144 core_data.SetBuild(static_cast<u8>(default_mii.weight));
145 core_data.SetGender(static_cast<Gender>(default_mii.gender));
146 core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color));
147 core_data.SetRegionMove(static_cast<u8>(default_mii.region_move));
148 core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region));
149 core_data.SetType(static_cast<u8>(default_mii.type));
150 core_data.SetNickname(default_mii.nickname);
151
152 const auto device_id = MiiUtil::GetDeviceId();
153 create_id = MiiUtil::MakeCreateId();
154 device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
155 data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
156}
157
158void StoreData::BuildRandom(Age age, Gender gender, Race race) {
159 core_data.BuildRandom(age, gender, race);
160 const auto device_id = MiiUtil::GetDeviceId();
161 create_id = MiiUtil::MakeCreateId();
162 device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
163 data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
164}
165
166void StoreData::SetInvalidName() {
167 const auto& invalid_name = core_data.GetInvalidNickname();
168 const auto device_id = MiiUtil::GetDeviceId();
169 core_data.SetNickname(invalid_name);
170 device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
171 data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
172}
173
174bool StoreData::IsSpecial() const {
175 return GetType() == 1;
176}
177
178u32 StoreData::IsValid() const {
179 // TODO: complete this
180 return 0;
181}
182
183void StoreData::SetFontRegion(FontRegion value) {
184 core_data.SetFontRegion(value);
185}
186
187void StoreData::SetFavoriteColor(FavoriteColor value) {
188 core_data.SetFavoriteColor(value);
189}
190
191void StoreData::SetGender(Gender value) {
192 core_data.SetGender(value);
193}
194
195void StoreData::SetHeight(u8 value) {
196 core_data.SetHeight(value);
197}
198
199void StoreData::SetBuild(u8 value) {
200 core_data.SetBuild(value);
201}
202
203void StoreData::SetType(u8 value) {
204 core_data.SetType(value);
205}
206
207void StoreData::SetRegionMove(u8 value) {
208 core_data.SetRegionMove(value);
209}
210
211void StoreData::SetFacelineType(FacelineType value) {
212 core_data.SetFacelineType(value);
213}
214
215void StoreData::SetFacelineColor(FacelineColor value) {
216 core_data.SetFacelineColor(value);
217}
218
219void StoreData::SetFacelineWrinkle(FacelineWrinkle value) {
220 core_data.SetFacelineWrinkle(value);
221}
222
223void StoreData::SetFacelineMake(FacelineMake value) {
224 core_data.SetFacelineMake(value);
225}
226
227void StoreData::SetHairType(HairType value) {
228 core_data.SetHairType(value);
229}
230
231void StoreData::SetHairColor(CommonColor value) {
232 core_data.SetHairColor(value);
233}
234
235void StoreData::SetHairFlip(HairFlip value) {
236 core_data.SetHairFlip(value);
237}
238
239void StoreData::SetEyeType(EyeType value) {
240 core_data.SetEyeType(value);
241}
242
243void StoreData::SetEyeColor(CommonColor value) {
244 core_data.SetEyeColor(value);
245}
246
247void StoreData::SetEyeScale(u8 value) {
248 core_data.SetEyeScale(value);
249}
250
251void StoreData::SetEyeAspect(u8 value) {
252 core_data.SetEyeAspect(value);
253}
254
255void StoreData::SetEyeRotate(u8 value) {
256 core_data.SetEyeRotate(value);
257}
258
259void StoreData::SetEyeX(u8 value) {
260 core_data.SetEyeX(value);
261}
262
263void StoreData::SetEyeY(u8 value) {
264 core_data.SetEyeY(value);
265}
266
267void StoreData::SetEyebrowType(EyebrowType value) {
268 core_data.SetEyebrowType(value);
269}
270
271void StoreData::SetEyebrowColor(CommonColor value) {
272 core_data.SetEyebrowColor(value);
273}
274
275void StoreData::SetEyebrowScale(u8 value) {
276 core_data.SetEyebrowScale(value);
277}
278
279void StoreData::SetEyebrowAspect(u8 value) {
280 core_data.SetEyebrowAspect(value);
281}
282
283void StoreData::SetEyebrowRotate(u8 value) {
284 core_data.SetEyebrowRotate(value);
285}
286
287void StoreData::SetEyebrowX(u8 value) {
288 core_data.SetEyebrowX(value);
289}
290
291void StoreData::SetEyebrowY(u8 value) {
292 core_data.SetEyebrowY(value);
293}
294
295void StoreData::SetNoseType(NoseType value) {
296 core_data.SetNoseType(value);
297}
298
299void StoreData::SetNoseScale(u8 value) {
300 core_data.SetNoseScale(value);
301}
302
303void StoreData::SetNoseY(u8 value) {
304 core_data.SetNoseY(value);
305}
306
307void StoreData::SetMouthType(u8 value) {
308 core_data.SetMouthType(value);
309}
310
311void StoreData::SetMouthColor(CommonColor value) {
312 core_data.SetMouthColor(value);
313}
314
315void StoreData::SetMouthScale(u8 value) {
316 core_data.SetMouthScale(value);
317}
318
319void StoreData::SetMouthAspect(u8 value) {
320 core_data.SetMouthAspect(value);
321}
322
323void StoreData::SetMouthY(u8 value) {
324 core_data.SetMouthY(value);
325}
326
327void StoreData::SetBeardColor(CommonColor value) {
328 core_data.SetBeardColor(value);
329}
330
331void StoreData::SetBeardType(BeardType value) {
332 core_data.SetBeardType(value);
333}
334
335void StoreData::SetMustacheType(MustacheType value) {
336 core_data.SetMustacheType(value);
337}
338
339void StoreData::SetMustacheScale(u8 value) {
340 core_data.SetMustacheScale(value);
341}
342
343void StoreData::SetMustacheY(u8 value) {
344 core_data.SetMustacheY(value);
345}
346
347void StoreData::SetGlassType(GlassType value) {
348 core_data.SetGlassType(value);
349}
350
351void StoreData::SetGlassColor(CommonColor value) {
352 core_data.SetGlassColor(value);
353}
354
355void StoreData::SetGlassScale(u8 value) {
356 core_data.SetGlassScale(value);
357}
358
359void StoreData::SetGlassY(u8 value) {
360 core_data.SetGlassY(value);
361}
362
363void StoreData::SetMoleType(MoleType value) {
364 core_data.SetMoleType(value);
365}
366
367void StoreData::SetMoleScale(u8 value) {
368 core_data.SetMoleScale(value);
369}
370
371void StoreData::SetMoleX(u8 value) {
372 core_data.SetMoleX(value);
373}
374
375void StoreData::SetMoleY(u8 value) {
376 core_data.SetMoleY(value);
377}
378
379void StoreData::SetNickname(Nickname value) {
380 core_data.SetNickname(value);
381}
382
383Common::UUID StoreData::GetCreateId() const {
384 return create_id;
385}
386
387FontRegion StoreData::GetFontRegion() const {
388 return static_cast<FontRegion>(core_data.GetFontRegion());
389}
390
391FavoriteColor StoreData::GetFavoriteColor() const {
392 return core_data.GetFavoriteColor();
393}
394
395Gender StoreData::GetGender() const {
396 return core_data.GetGender();
397}
398
399u8 StoreData::GetHeight() const {
400 return core_data.GetHeight();
401}
402
403u8 StoreData::GetBuild() const {
404 return core_data.GetBuild();
405}
406
407u8 StoreData::GetType() const {
408 return core_data.GetType();
409}
410
411u8 StoreData::GetRegionMove() const {
412 return core_data.GetRegionMove();
413}
414
415FacelineType StoreData::GetFacelineType() const {
416 return core_data.GetFacelineType();
417}
418
419FacelineColor StoreData::GetFacelineColor() const {
420 return core_data.GetFacelineColor();
421}
422
423FacelineWrinkle StoreData::GetFacelineWrinkle() const {
424 return core_data.GetFacelineWrinkle();
425}
426
427FacelineMake StoreData::GetFacelineMake() const {
428 return core_data.GetFacelineMake();
429}
430
431HairType StoreData::GetHairType() const {
432 return core_data.GetHairType();
433}
434
435CommonColor StoreData::GetHairColor() const {
436 return core_data.GetHairColor();
437}
438
439HairFlip StoreData::GetHairFlip() const {
440 return core_data.GetHairFlip();
441}
442
443EyeType StoreData::GetEyeType() const {
444 return core_data.GetEyeType();
445}
446
447CommonColor StoreData::GetEyeColor() const {
448 return core_data.GetEyeColor();
449}
450
451u8 StoreData::GetEyeScale() const {
452 return core_data.GetEyeScale();
453}
454
455u8 StoreData::GetEyeAspect() const {
456 return core_data.GetEyeAspect();
457}
458
459u8 StoreData::GetEyeRotate() const {
460 return core_data.GetEyeRotate();
461}
462
463u8 StoreData::GetEyeX() const {
464 return core_data.GetEyeX();
465}
466
467u8 StoreData::GetEyeY() const {
468 return core_data.GetEyeY();
469}
470
471EyebrowType StoreData::GetEyebrowType() const {
472 return core_data.GetEyebrowType();
473}
474
475CommonColor StoreData::GetEyebrowColor() const {
476 return core_data.GetEyebrowColor();
477}
478
479u8 StoreData::GetEyebrowScale() const {
480 return core_data.GetEyebrowScale();
481}
482
483u8 StoreData::GetEyebrowAspect() const {
484 return core_data.GetEyebrowAspect();
485}
486
487u8 StoreData::GetEyebrowRotate() const {
488 return core_data.GetEyebrowRotate();
489}
490
491u8 StoreData::GetEyebrowX() const {
492 return core_data.GetEyebrowX();
493}
494
495u8 StoreData::GetEyebrowY() const {
496 return core_data.GetEyebrowY();
497}
498
499NoseType StoreData::GetNoseType() const {
500 return core_data.GetNoseType();
501}
502
503u8 StoreData::GetNoseScale() const {
504 return core_data.GetNoseScale();
505}
506
507u8 StoreData::GetNoseY() const {
508 return core_data.GetNoseY();
509}
510
511MouthType StoreData::GetMouthType() const {
512 return core_data.GetMouthType();
513}
514
515CommonColor StoreData::GetMouthColor() const {
516 return core_data.GetMouthColor();
517}
518
519u8 StoreData::GetMouthScale() const {
520 return core_data.GetMouthScale();
521}
522
523u8 StoreData::GetMouthAspect() const {
524 return core_data.GetMouthAspect();
525}
526
527u8 StoreData::GetMouthY() const {
528 return core_data.GetMouthY();
529}
530
531CommonColor StoreData::GetBeardColor() const {
532 return core_data.GetBeardColor();
533}
534
535BeardType StoreData::GetBeardType() const {
536 return core_data.GetBeardType();
537}
538
539MustacheType StoreData::GetMustacheType() const {
540 return core_data.GetMustacheType();
541}
542
543u8 StoreData::GetMustacheScale() const {
544 return core_data.GetMustacheScale();
545}
546
547u8 StoreData::GetMustacheY() const {
548 return core_data.GetMustacheY();
549}
550
551GlassType StoreData::GetGlassType() const {
552 return core_data.GetGlassType();
553}
554
555CommonColor StoreData::GetGlassColor() const {
556 return core_data.GetGlassColor();
557}
558
559u8 StoreData::GetGlassScale() const {
560 return core_data.GetGlassScale();
561}
562
563u8 StoreData::GetGlassY() const {
564 return core_data.GetGlassY();
565}
566
567MoleType StoreData::GetMoleType() const {
568 return core_data.GetMoleType();
569}
570
571u8 StoreData::GetMoleScale() const {
572 return core_data.GetMoleScale();
573}
574
575u8 StoreData::GetMoleX() const {
576 return core_data.GetMoleX();
577}
578
579u8 StoreData::GetMoleY() const {
580 return core_data.GetMoleY();
581}
582
583Nickname StoreData::GetNickname() const {
584 return core_data.GetNickname();
585}
586
587bool StoreData::operator==(const StoreData& data) {
588 bool is_identical = data.core_data.IsValid() == 0;
589 is_identical &= core_data.GetNickname().data == data.core_data.GetNickname().data;
590 is_identical &= GetCreateId() == data.GetCreateId();
591 is_identical &= GetFontRegion() == data.GetFontRegion();
592 is_identical &= GetFavoriteColor() == data.GetFavoriteColor();
593 is_identical &= GetGender() == data.GetGender();
594 is_identical &= GetHeight() == data.GetHeight();
595 is_identical &= GetBuild() == data.GetBuild();
596 is_identical &= GetType() == data.GetType();
597 is_identical &= GetRegionMove() == data.GetRegionMove();
598 is_identical &= GetFacelineType() == data.GetFacelineType();
599 is_identical &= GetFacelineColor() == data.GetFacelineColor();
600 is_identical &= GetFacelineWrinkle() == data.GetFacelineWrinkle();
601 is_identical &= GetFacelineMake() == data.GetFacelineMake();
602 is_identical &= GetHairType() == data.GetHairType();
603 is_identical &= GetHairColor() == data.GetHairColor();
604 is_identical &= GetHairFlip() == data.GetHairFlip();
605 is_identical &= GetEyeType() == data.GetEyeType();
606 is_identical &= GetEyeColor() == data.GetEyeColor();
607 is_identical &= GetEyeScale() == data.GetEyeScale();
608 is_identical &= GetEyeAspect() == data.GetEyeAspect();
609 is_identical &= GetEyeRotate() == data.GetEyeRotate();
610 is_identical &= GetEyeX() == data.GetEyeX();
611 is_identical &= GetEyeY() == data.GetEyeY();
612 is_identical &= GetEyebrowType() == data.GetEyebrowType();
613 is_identical &= GetEyebrowColor() == data.GetEyebrowColor();
614 is_identical &= GetEyebrowScale() == data.GetEyebrowScale();
615 is_identical &= GetEyebrowAspect() == data.GetEyebrowAspect();
616 is_identical &= GetEyebrowRotate() == data.GetEyebrowRotate();
617 is_identical &= GetEyebrowX() == data.GetEyebrowX();
618 is_identical &= GetEyebrowY() == data.GetEyebrowY();
619 is_identical &= GetNoseType() == data.GetNoseType();
620 is_identical &= GetNoseScale() == data.GetNoseScale();
621 is_identical &= GetNoseY() == data.GetNoseY();
622 is_identical &= GetMouthType() == data.GetMouthType();
623 is_identical &= GetMouthColor() == data.GetMouthColor();
624 is_identical &= GetMouthScale() == data.GetMouthScale();
625 is_identical &= GetMouthAspect() == data.GetMouthAspect();
626 is_identical &= GetMouthY() == data.GetMouthY();
627 is_identical &= GetBeardColor() == data.GetBeardColor();
628 is_identical &= GetBeardType() == data.GetBeardType();
629 is_identical &= GetMustacheType() == data.GetMustacheType();
630 is_identical &= GetMustacheScale() == data.GetMustacheScale();
631 is_identical &= GetMustacheY() == data.GetMustacheY();
632 is_identical &= GetGlassType() == data.GetGlassType();
633 is_identical &= GetGlassColor() == data.GetGlassColor();
634 is_identical &= GetGlassScale() == data.GetGlassScale();
635 is_identical &= GetGlassY() == data.GetGlassY();
636 is_identical &= GetMoleType() == data.GetMoleType();
637 is_identical &= GetMoleScale() == data.GetMoleScale();
638 is_identical &= GetMoleX() == data.GetMoleX();
639 is_identical &= data.GetMoleY() == data.GetMoleY();
640 return is_identical;
641}
642
643} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/mii/mii_types.h"
7#include "core/hle/service/mii/types/core_data.h"
8
9namespace Service::Mii {
10
11class StoreData {
12public:
13 // nn::mii::detail::StoreDataRaw::BuildDefault
14 void BuildDefault(u32 mii_index);
15 // nn::mii::detail::StoreDataRaw::BuildDefault
16
17 void BuildBase(Gender gender);
18 // nn::mii::detail::StoreDataRaw::BuildRandom
19 void BuildRandom(Age age, Gender gender, Race race);
20
21 bool IsSpecial() const;
22
23 u32 IsValid() const;
24
25 void SetFontRegion(FontRegion value);
26 void SetFavoriteColor(FavoriteColor value);
27 void SetGender(Gender value);
28 void SetHeight(u8 value);
29 void SetBuild(u8 value);
30 void SetType(u8 value);
31 void SetRegionMove(u8 value);
32 void SetFacelineType(FacelineType value);
33 void SetFacelineColor(FacelineColor value);
34 void SetFacelineWrinkle(FacelineWrinkle value);
35 void SetFacelineMake(FacelineMake value);
36 void SetHairType(HairType value);
37 void SetHairColor(CommonColor value);
38 void SetHairFlip(HairFlip value);
39 void SetEyeType(EyeType value);
40 void SetEyeColor(CommonColor value);
41 void SetEyeScale(u8 value);
42 void SetEyeAspect(u8 value);
43 void SetEyeRotate(u8 value);
44 void SetEyeX(u8 value);
45 void SetEyeY(u8 value);
46 void SetEyebrowType(EyebrowType value);
47 void SetEyebrowColor(CommonColor value);
48 void SetEyebrowScale(u8 value);
49 void SetEyebrowAspect(u8 value);
50 void SetEyebrowRotate(u8 value);
51 void SetEyebrowX(u8 value);
52 void SetEyebrowY(u8 value);
53 void SetNoseType(NoseType value);
54 void SetNoseScale(u8 value);
55 void SetNoseY(u8 value);
56 void SetMouthType(u8 value);
57 void SetMouthColor(CommonColor value);
58 void SetMouthScale(u8 value);
59 void SetMouthAspect(u8 value);
60 void SetMouthY(u8 value);
61 void SetBeardColor(CommonColor value);
62 void SetBeardType(BeardType value);
63 void SetMustacheType(MustacheType value);
64 void SetMustacheScale(u8 value);
65 void SetMustacheY(u8 value);
66 void SetGlassType(GlassType value);
67 void SetGlassColor(CommonColor value);
68 void SetGlassScale(u8 value);
69 void SetGlassY(u8 value);
70 void SetMoleType(MoleType value);
71 void SetMoleScale(u8 value);
72 void SetMoleX(u8 value);
73 void SetMoleY(u8 value);
74 void SetNickname(Nickname nickname);
75 void SetInvalidName();
76
77 Common::UUID GetCreateId() const;
78 FontRegion GetFontRegion() const;
79 FavoriteColor GetFavoriteColor() const;
80 Gender GetGender() const;
81 u8 GetHeight() const;
82 u8 GetBuild() const;
83 u8 GetType() const;
84 u8 GetRegionMove() const;
85 FacelineType GetFacelineType() const;
86 FacelineColor GetFacelineColor() const;
87 FacelineWrinkle GetFacelineWrinkle() const;
88 FacelineMake GetFacelineMake() const;
89 HairType GetHairType() const;
90 CommonColor GetHairColor() const;
91 HairFlip GetHairFlip() const;
92 EyeType GetEyeType() const;
93 CommonColor GetEyeColor() const;
94 u8 GetEyeScale() const;
95 u8 GetEyeAspect() const;
96 u8 GetEyeRotate() const;
97 u8 GetEyeX() const;
98 u8 GetEyeY() const;
99 EyebrowType GetEyebrowType() const;
100 CommonColor GetEyebrowColor() const;
101 u8 GetEyebrowScale() const;
102 u8 GetEyebrowAspect() const;
103 u8 GetEyebrowRotate() const;
104 u8 GetEyebrowX() const;
105 u8 GetEyebrowY() const;
106 NoseType GetNoseType() const;
107 u8 GetNoseScale() const;
108 u8 GetNoseY() const;
109 MouthType GetMouthType() const;
110 CommonColor GetMouthColor() const;
111 u8 GetMouthScale() const;
112 u8 GetMouthAspect() const;
113 u8 GetMouthY() const;
114 CommonColor GetBeardColor() const;
115 BeardType GetBeardType() const;
116 MustacheType GetMustacheType() const;
117 u8 GetMustacheScale() const;
118 u8 GetMustacheY() const;
119 GlassType GetGlassType() const;
120 CommonColor GetGlassColor() const;
121 u8 GetGlassScale() const;
122 u8 GetGlassY() const;
123 MoleType GetMoleType() const;
124 u8 GetMoleScale() const;
125 u8 GetMoleX() const;
126 u8 GetMoleY() const;
127 Nickname GetNickname() const;
128
129 bool operator==(const StoreData& data);
130
131private:
132 CoreData core_data{};
133 Common::UUID create_id{};
134 u16 data_crc{};
135 u16 device_crc{};
136};
137static_assert(sizeof(StoreData) == 0x44, "StoreData has incorrect size.");
138
139struct StoreDataElement {
140 StoreData store_data{};
141 Source source{};
142};
143static_assert(sizeof(StoreDataElement) == 0x48, "StoreDataElement has incorrect size.");
144
145}; // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/mii/mii_util.h"
5#include "core/hle/service/mii/types/raw_data.h"
6#include "core/hle/service/mii/types/store_data.h"
7#include "core/hle/service/mii/types/ver3_store_data.h"
8
9namespace Service::Mii {
10
11void NfpStoreDataExtension::SetFromStoreData(const StoreData& store_data) {
12 faceline_color = static_cast<u8>(store_data.GetFacelineColor()) & 0xf;
13 hair_color = static_cast<u8>(store_data.GetHairColor()) & 0x7f;
14 eye_color = static_cast<u8>(store_data.GetEyeColor()) & 0x7f;
15 eyebrow_color = static_cast<u8>(store_data.GetEyebrowColor()) & 0x7f;
16 mouth_color = static_cast<u8>(store_data.GetMouthColor()) & 0x7f;
17 beard_color = static_cast<u8>(store_data.GetBeardColor()) & 0x7f;
18 glass_color = static_cast<u8>(store_data.GetGlassColor()) & 0x7f;
19 glass_type = static_cast<u8>(store_data.GetGlassType()) & 0x1f;
20}
21
22void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const {
23 out_store_data.BuildBase(Gender::Male);
24
25 if (!IsValid()) {
26 return;
27 }
28
29 // TODO: We are ignoring a bunch of data from the mii_v3
30
31 out_store_data.SetGender(static_cast<Gender>(mii_information.gender.Value()));
32 out_store_data.SetFavoriteColor(
33 static_cast<FavoriteColor>(mii_information.favorite_color.Value()));
34 out_store_data.SetHeight(height);
35 out_store_data.SetBuild(build);
36
37 out_store_data.SetNickname(mii_name);
38 out_store_data.SetFontRegion(
39 static_cast<FontRegion>(static_cast<u8>(region_information.font_region)));
40
41 out_store_data.SetFacelineType(
42 static_cast<FacelineType>(appearance_bits1.faceline_type.Value()));
43 out_store_data.SetFacelineColor(
44 static_cast<FacelineColor>(appearance_bits1.faceline_color.Value()));
45 out_store_data.SetFacelineWrinkle(
46 static_cast<FacelineWrinkle>(appearance_bits2.faceline_wrinkle.Value()));
47 out_store_data.SetFacelineMake(
48 static_cast<FacelineMake>(appearance_bits2.faceline_make.Value()));
49
50 out_store_data.SetHairType(static_cast<HairType>(hair_type));
51 out_store_data.SetHairColor(static_cast<CommonColor>(appearance_bits3.hair_color.Value()));
52 out_store_data.SetHairFlip(static_cast<HairFlip>(appearance_bits3.hair_flip.Value()));
53
54 out_store_data.SetEyeType(static_cast<EyeType>(appearance_bits4.eye_type.Value()));
55 out_store_data.SetEyeColor(static_cast<CommonColor>(appearance_bits4.eye_color.Value()));
56 out_store_data.SetEyeScale(static_cast<u8>(appearance_bits4.eye_scale));
57 out_store_data.SetEyeAspect(static_cast<u8>(appearance_bits4.eye_aspect));
58 out_store_data.SetEyeRotate(static_cast<u8>(appearance_bits4.eye_rotate));
59 out_store_data.SetEyeX(static_cast<u8>(appearance_bits4.eye_x));
60 out_store_data.SetEyeY(static_cast<u8>(appearance_bits4.eye_y));
61
62 out_store_data.SetEyebrowType(static_cast<EyebrowType>(appearance_bits5.eyebrow_type.Value()));
63 out_store_data.SetEyebrowColor(
64 static_cast<CommonColor>(appearance_bits5.eyebrow_color.Value()));
65 out_store_data.SetEyebrowScale(static_cast<u8>(appearance_bits5.eyebrow_scale));
66 out_store_data.SetEyebrowAspect(static_cast<u8>(appearance_bits5.eyebrow_aspect));
67 out_store_data.SetEyebrowRotate(static_cast<u8>(appearance_bits5.eyebrow_rotate));
68 out_store_data.SetEyebrowX(static_cast<u8>(appearance_bits5.eyebrow_x));
69 out_store_data.SetEyebrowY(static_cast<u8>(appearance_bits5.eyebrow_y));
70
71 out_store_data.SetNoseType(static_cast<NoseType>(appearance_bits6.nose_type.Value()));
72 out_store_data.SetNoseScale(static_cast<u8>(appearance_bits6.nose_scale));
73 out_store_data.SetNoseY(static_cast<u8>(appearance_bits6.nose_y));
74
75 out_store_data.SetMouthType(static_cast<u8>(appearance_bits7.mouth_type));
76 out_store_data.SetMouthColor(static_cast<CommonColor>(appearance_bits7.mouth_color.Value()));
77 out_store_data.SetMouthScale(static_cast<u8>(appearance_bits7.mouth_scale));
78 out_store_data.SetMouthAspect(static_cast<u8>(appearance_bits7.mouth_aspect));
79 out_store_data.SetMouthY(static_cast<u8>(appearance_bits8.mouth_y));
80
81 out_store_data.SetMustacheType(
82 static_cast<MustacheType>(appearance_bits8.mustache_type.Value()));
83 out_store_data.SetMustacheScale(static_cast<u8>(appearance_bits9.mustache_scale));
84 out_store_data.SetMustacheY(static_cast<u8>(appearance_bits9.mustache_y));
85
86 out_store_data.SetBeardType(static_cast<BeardType>(appearance_bits9.beard_type.Value()));
87 out_store_data.SetBeardColor(static_cast<CommonColor>(appearance_bits9.beard_color.Value()));
88
89 out_store_data.SetGlassType(static_cast<GlassType>(appearance_bits10.glass_type.Value()));
90 out_store_data.SetGlassColor(static_cast<CommonColor>(appearance_bits10.glass_color.Value()));
91 out_store_data.SetGlassScale(static_cast<u8>(appearance_bits10.glass_scale));
92 out_store_data.SetGlassY(static_cast<u8>(appearance_bits10.glass_y));
93
94 out_store_data.SetMoleType(static_cast<MoleType>(appearance_bits11.mole_type.Value()));
95 out_store_data.SetMoleScale(static_cast<u8>(appearance_bits11.mole_scale));
96 out_store_data.SetMoleX(static_cast<u8>(appearance_bits11.mole_x));
97 out_store_data.SetMoleY(static_cast<u8>(appearance_bits11.mole_y));
98}
99
100void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) {
101 version = 1;
102 mii_information.gender.Assign(static_cast<u8>(store_data.GetGender()));
103 mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor()));
104 height = store_data.GetHeight();
105 build = store_data.GetBuild();
106
107 mii_name = store_data.GetNickname();
108 region_information.font_region.Assign(static_cast<u8>(store_data.GetFontRegion()));
109
110 appearance_bits1.faceline_type.Assign(static_cast<u8>(store_data.GetFacelineType()));
111 appearance_bits2.faceline_wrinkle.Assign(static_cast<u8>(store_data.GetFacelineWrinkle()));
112 appearance_bits2.faceline_make.Assign(static_cast<u8>(store_data.GetFacelineMake()));
113
114 hair_type = static_cast<u8>(store_data.GetHairType());
115 appearance_bits3.hair_flip.Assign(static_cast<u8>(store_data.GetHairFlip()));
116
117 appearance_bits4.eye_type.Assign(static_cast<u8>(store_data.GetEyeType()));
118 appearance_bits4.eye_scale.Assign(store_data.GetEyeScale());
119 appearance_bits4.eye_aspect.Assign(store_data.GetEyebrowAspect());
120 appearance_bits4.eye_rotate.Assign(store_data.GetEyeRotate());
121 appearance_bits4.eye_x.Assign(store_data.GetEyeX());
122 appearance_bits4.eye_y.Assign(store_data.GetEyeY());
123
124 appearance_bits5.eyebrow_type.Assign(static_cast<u8>(store_data.GetEyebrowType()));
125 appearance_bits5.eyebrow_scale.Assign(store_data.GetEyebrowScale());
126 appearance_bits5.eyebrow_aspect.Assign(store_data.GetEyebrowAspect());
127 appearance_bits5.eyebrow_rotate.Assign(store_data.GetEyebrowRotate());
128 appearance_bits5.eyebrow_x.Assign(store_data.GetEyebrowX());
129 appearance_bits5.eyebrow_y.Assign(store_data.GetEyebrowY());
130
131 appearance_bits6.nose_type.Assign(static_cast<u8>(store_data.GetNoseType()));
132 appearance_bits6.nose_scale.Assign(store_data.GetNoseScale());
133 appearance_bits6.nose_y.Assign(store_data.GetNoseY());
134
135 appearance_bits7.mouth_type.Assign(static_cast<u8>(store_data.GetMouthType()));
136 appearance_bits7.mouth_scale.Assign(store_data.GetMouthScale());
137 appearance_bits7.mouth_aspect.Assign(store_data.GetMouthAspect());
138 appearance_bits8.mouth_y.Assign(store_data.GetMouthY());
139
140 appearance_bits8.mustache_type.Assign(static_cast<u8>(store_data.GetMustacheType()));
141 appearance_bits9.mustache_scale.Assign(store_data.GetMustacheScale());
142 appearance_bits9.mustache_y.Assign(store_data.GetMustacheY());
143
144 appearance_bits9.beard_type.Assign(static_cast<u8>(store_data.GetBeardType()));
145
146 appearance_bits10.glass_scale.Assign(store_data.GetGlassScale());
147 appearance_bits10.glass_y.Assign(store_data.GetGlassY());
148
149 appearance_bits11.mole_type.Assign(static_cast<u8>(store_data.GetMoleType()));
150 appearance_bits11.mole_scale.Assign(store_data.GetMoleScale());
151 appearance_bits11.mole_x.Assign(store_data.GetMoleX());
152 appearance_bits11.mole_y.Assign(store_data.GetMoleY());
153
154 // These types are converted to V3 from a table
155 appearance_bits1.faceline_color.Assign(
156 RawData::FromVer3GetFacelineColor(static_cast<u8>(store_data.GetFacelineColor())));
157 appearance_bits3.hair_color.Assign(
158 RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetHairColor())));
159 appearance_bits4.eye_color.Assign(
160 RawData::FromVer3GetEyeColor(static_cast<u8>(store_data.GetEyeColor())));
161 appearance_bits5.eyebrow_color.Assign(
162 RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetEyebrowColor())));
163 appearance_bits7.mouth_color.Assign(
164 RawData::FromVer3GetMouthlineColor(static_cast<u8>(store_data.GetMouthColor())));
165 appearance_bits9.beard_color.Assign(
166 RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetBeardColor())));
167 appearance_bits10.glass_color.Assign(
168 RawData::FromVer3GetGlassColor(static_cast<u8>(store_data.GetGlassColor())));
169 appearance_bits10.glass_type.Assign(
170 RawData::FromVer3GetGlassType(static_cast<u8>(store_data.GetGlassType())));
171
172 crc = MiiUtil::CalculateCrc16(&version, sizeof(Ver3StoreData) - sizeof(u16));
173}
174
175u32 Ver3StoreData::IsValid() const {
176 bool is_valid = version == 0 || version == 3;
177
178 is_valid = is_valid && (mii_name.data[0] != '\0');
179
180 is_valid = is_valid && (mii_information.birth_month < 13);
181 is_valid = is_valid && (mii_information.birth_day < 32);
182 is_valid = is_valid && (mii_information.favorite_color <= static_cast<u8>(FavoriteColor::Max));
183 is_valid = is_valid && (height <= MaxHeight);
184 is_valid = is_valid && (build <= MaxBuild);
185
186 is_valid = is_valid && (appearance_bits1.faceline_type <= static_cast<u8>(FacelineType::Max));
187 is_valid = is_valid && (appearance_bits1.faceline_color <= MaxVer3CommonColor - 2);
188 is_valid =
189 is_valid && (appearance_bits2.faceline_wrinkle <= static_cast<u8>(FacelineWrinkle::Max));
190 is_valid = is_valid && (appearance_bits2.faceline_make <= static_cast<u8>(FacelineMake::Max));
191
192 is_valid = is_valid && (hair_type <= static_cast<u8>(HairType::Max));
193 is_valid = is_valid && (appearance_bits3.hair_color <= MaxVer3CommonColor);
194
195 is_valid = is_valid && (appearance_bits4.eye_type <= static_cast<u8>(EyeType::Max));
196 is_valid = is_valid && (appearance_bits4.eye_color <= MaxVer3CommonColor - 2);
197 is_valid = is_valid && (appearance_bits4.eye_scale <= MaxEyeScale);
198 is_valid = is_valid && (appearance_bits4.eye_aspect <= MaxEyeAspect);
199 is_valid = is_valid && (appearance_bits4.eye_rotate <= MaxEyeRotate);
200 is_valid = is_valid && (appearance_bits4.eye_x <= MaxEyeX);
201 is_valid = is_valid && (appearance_bits4.eye_y <= MaxEyeY);
202
203 is_valid = is_valid && (appearance_bits5.eyebrow_type <= static_cast<u8>(EyebrowType::Max));
204 is_valid = is_valid && (appearance_bits5.eyebrow_color <= MaxVer3CommonColor);
205 is_valid = is_valid && (appearance_bits5.eyebrow_scale <= MaxEyebrowScale);
206 is_valid = is_valid && (appearance_bits5.eyebrow_aspect <= MaxEyebrowAspect);
207 is_valid = is_valid && (appearance_bits5.eyebrow_rotate <= MaxEyebrowRotate);
208 is_valid = is_valid && (appearance_bits5.eyebrow_x <= MaxEyebrowX);
209 is_valid = is_valid && (appearance_bits5.eyebrow_y <= MaxEyebrowY);
210
211 is_valid = is_valid && (appearance_bits6.nose_type <= static_cast<u8>(NoseType::Max));
212 is_valid = is_valid && (appearance_bits6.nose_scale <= MaxNoseScale);
213 is_valid = is_valid && (appearance_bits6.nose_y <= MaxNoseY);
214
215 is_valid = is_valid && (appearance_bits7.mouth_type <= static_cast<u8>(MouthType::Max));
216 is_valid = is_valid && (appearance_bits7.mouth_color <= MaxVer3CommonColor - 3);
217 is_valid = is_valid && (appearance_bits7.mouth_scale <= MaxMouthScale);
218 is_valid = is_valid && (appearance_bits7.mouth_aspect <= MaxMoutAspect);
219 is_valid = is_valid && (appearance_bits8.mouth_y <= MaxMouthY);
220
221 is_valid = is_valid && (appearance_bits8.mustache_type <= static_cast<u8>(MustacheType::Max));
222 is_valid = is_valid && (appearance_bits9.mustache_scale < MaxMustacheScale);
223 is_valid = is_valid && (appearance_bits9.mustache_y <= MasMustacheY);
224
225 is_valid = is_valid && (appearance_bits9.beard_type <= static_cast<u8>(BeardType::Max));
226 is_valid = is_valid && (appearance_bits9.beard_color <= MaxVer3CommonColor);
227
228 is_valid = is_valid && (appearance_bits10.glass_type <= MaxVer3GlassType);
229 is_valid = is_valid && (appearance_bits10.glass_color <= MaxVer3CommonColor - 2);
230 is_valid = is_valid && (appearance_bits10.glass_scale <= MaxGlassScale);
231 is_valid = is_valid && (appearance_bits10.glass_y <= MaxGlassScale);
232
233 is_valid = is_valid && (appearance_bits11.mole_type <= static_cast<u8>(MoleType::Max));
234 is_valid = is_valid && (appearance_bits11.mole_scale <= MaxMoleScale);
235 is_valid = is_valid && (appearance_bits11.mole_x <= MaxMoleX);
236 is_valid = is_valid && (appearance_bits11.mole_y <= MaxMoleY);
237
238 return is_valid;
239}
240
241} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/mii/mii_types.h"
7
8namespace Service::Mii {
9class StoreData;
10
11// This is nn::mii::Ver3StoreData
12// Based on citra HLE::Applets::MiiData and PretendoNetwork.
13// https://github.com/citra-emu/citra/blob/master/src/core/hle/applets/mii_selector.h#L48
14// https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299
15
16struct NfpStoreDataExtension {
17 void SetFromStoreData(const StoreData& store_data);
18
19 u8 faceline_color;
20 u8 hair_color;
21 u8 eye_color;
22 u8 eyebrow_color;
23 u8 mouth_color;
24 u8 beard_color;
25 u8 glass_color;
26 u8 glass_type;
27};
28static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size");
29
30#pragma pack(push, 4)
31class Ver3StoreData {
32public:
33 void BuildToStoreData(StoreData& out_store_data) const;
34 void BuildFromStoreData(const StoreData& store_data);
35
36 u32 IsValid() const;
37
38 u8 version;
39 union {
40 u8 raw;
41
42 BitField<0, 1, u8> allow_copying;
43 BitField<1, 1, u8> profanity_flag;
44 BitField<2, 2, u8> region_lock;
45 BitField<4, 2, u8> font_region;
46 } region_information;
47 u16_be mii_id;
48 u64_be system_id;
49 u32_be specialness_and_creation_date;
50 std::array<u8, 6> creator_mac;
51 u16_be padding;
52 union {
53 u16 raw;
54
55 BitField<0, 1, u16> gender;
56 BitField<1, 4, u16> birth_month;
57 BitField<5, 5, u16> birth_day;
58 BitField<10, 4, u16> favorite_color;
59 BitField<14, 1, u16> favorite;
60 } mii_information;
61 Nickname mii_name;
62 u8 height;
63 u8 build;
64 union {
65 u8 raw;
66
67 BitField<0, 1, u8> disable_sharing;
68 BitField<1, 4, u8> faceline_type;
69 BitField<5, 3, u8> faceline_color;
70 } appearance_bits1;
71 union {
72 u8 raw;
73
74 BitField<0, 4, u8> faceline_wrinkle;
75 BitField<4, 4, u8> faceline_make;
76 } appearance_bits2;
77 u8 hair_type;
78 union {
79 u8 raw;
80
81 BitField<0, 3, u8> hair_color;
82 BitField<3, 1, u8> hair_flip;
83 } appearance_bits3;
84 union {
85 u32 raw;
86
87 BitField<0, 6, u32> eye_type;
88 BitField<6, 3, u32> eye_color;
89 BitField<9, 4, u32> eye_scale;
90 BitField<13, 3, u32> eye_aspect;
91 BitField<16, 5, u32> eye_rotate;
92 BitField<21, 4, u32> eye_x;
93 BitField<25, 5, u32> eye_y;
94 } appearance_bits4;
95 union {
96 u32 raw;
97
98 BitField<0, 5, u32> eyebrow_type;
99 BitField<5, 3, u32> eyebrow_color;
100 BitField<8, 4, u32> eyebrow_scale;
101 BitField<12, 3, u32> eyebrow_aspect;
102 BitField<16, 4, u32> eyebrow_rotate;
103 BitField<21, 4, u32> eyebrow_x;
104 BitField<25, 5, u32> eyebrow_y;
105 } appearance_bits5;
106 union {
107 u16 raw;
108
109 BitField<0, 5, u16> nose_type;
110 BitField<5, 4, u16> nose_scale;
111 BitField<9, 5, u16> nose_y;
112 } appearance_bits6;
113 union {
114 u16 raw;
115
116 BitField<0, 6, u16> mouth_type;
117 BitField<6, 3, u16> mouth_color;
118 BitField<9, 4, u16> mouth_scale;
119 BitField<13, 3, u16> mouth_aspect;
120 } appearance_bits7;
121 union {
122 u8 raw;
123
124 BitField<0, 5, u8> mouth_y;
125 BitField<5, 3, u8> mustache_type;
126 } appearance_bits8;
127 u8 allow_copying;
128 union {
129 u16 raw;
130
131 BitField<0, 3, u16> beard_type;
132 BitField<3, 3, u16> beard_color;
133 BitField<6, 4, u16> mustache_scale;
134 BitField<10, 5, u16> mustache_y;
135 } appearance_bits9;
136 union {
137 u16 raw;
138
139 BitField<0, 4, u16> glass_type;
140 BitField<4, 3, u16> glass_color;
141 BitField<7, 4, u16> glass_scale;
142 BitField<11, 5, u16> glass_y;
143 } appearance_bits10;
144 union {
145 u16 raw;
146
147 BitField<0, 1, u16> mole_type;
148 BitField<1, 4, u16> mole_scale;
149 BitField<5, 5, u16> mole_x;
150 BitField<10, 5, u16> mole_y;
151 } appearance_bits11;
152
153 Nickname author_name;
154 INSERT_PADDING_BYTES(0x2);
155 u16_be crc;
156};
157static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size");
158#pragma pack(pop)
159
160}; // namespace Service::Mii
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 5df40f9a0..5dda12343 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -28,7 +28,6 @@
28#include "core/hle/kernel/k_event.h" 28#include "core/hle/kernel/k_event.h"
29#include "core/hle/service/ipc_helpers.h" 29#include "core/hle/service/ipc_helpers.h"
30#include "core/hle/service/mii/mii_manager.h" 30#include "core/hle/service/mii/mii_manager.h"
31#include "core/hle/service/mii/types.h"
32#include "core/hle/service/nfc/common/amiibo_crypto.h" 31#include "core/hle/service/nfc/common/amiibo_crypto.h"
33#include "core/hle/service/nfc/common/device.h" 32#include "core/hle/service/nfc/common/device.h"
34#include "core/hle/service/nfc/mifare_result.h" 33#include "core/hle/service/nfc/mifare_result.h"
@@ -681,12 +680,16 @@ Result NfcDevice::GetRegisterInfo(NFP::RegisterInfo& register_info) const {
681 return ResultRegistrationIsNotInitialized; 680 return ResultRegistrationIsNotInitialized;
682 } 681 }
683 682
684 Service::Mii::MiiManager manager; 683 Mii::CharInfo char_info{};
684 Mii::StoreData store_data{};
685 tag_data.owner_mii.BuildToStoreData(store_data);
686 char_info.SetFromStoreData(store_data);
687
685 const auto& settings = tag_data.settings; 688 const auto& settings = tag_data.settings;
686 689
687 // TODO: Validate this data 690 // TODO: Validate this data
688 register_info = { 691 register_info = {
689 .mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii), 692 .mii_char_info = char_info,
690 .creation_date = settings.init_date.GetWriteDate(), 693 .creation_date = settings.init_date.GetWriteDate(),
691 .amiibo_name = GetAmiiboName(settings), 694 .amiibo_name = GetAmiiboName(settings),
692 .font_region = settings.settings.font_region, 695 .font_region = settings.settings.font_region,
@@ -825,8 +828,11 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
825 return ResultWrongDeviceState; 828 return ResultWrongDeviceState;
826 } 829 }
827 830
828 Service::Mii::MiiManager manager; 831 Service::Mii::StoreData store_data{};
829 const auto mii = manager.BuildBase(Mii::Gender::Male); 832 Service::Mii::NfpStoreDataExtension extension{};
833 store_data.BuildBase(Mii::Gender::Male);
834 extension.SetFromStoreData(store_data);
835
830 auto& settings = tag_data.settings; 836 auto& settings = tag_data.settings;
831 837
832 if (tag_data.settings.settings.amiibo_initialized == 0) { 838 if (tag_data.settings.settings.amiibo_initialized == 0) {
@@ -835,8 +841,8 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
835 } 841 }
836 842
837 SetAmiiboName(settings, register_info.amiibo_name); 843 SetAmiiboName(settings, register_info.amiibo_name);
838 tag_data.owner_mii = manager.BuildFromStoreData(mii); 844 tag_data.owner_mii.BuildFromStoreData(store_data);
839 tag_data.mii_extension = manager.SetFromStoreData(mii); 845 tag_data.mii_extension = extension;
840 tag_data.unknown = 0; 846 tag_data.unknown = 0;
841 tag_data.unknown2 = {}; 847 tag_data.unknown2 = {};
842 settings.country_code_id = 0; 848 settings.country_code_id = 0;
@@ -1453,7 +1459,7 @@ void NfcDevice::UpdateRegisterInfoCrc() {
1453 1459
1454void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, 1460void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data,
1455 const NFP::EncryptedNTAG215File& encrypted_file) const { 1461 const NFP::EncryptedNTAG215File& encrypted_file) const {
1456 Service::Mii::MiiManager manager; 1462 Service::Mii::StoreData store_data{};
1457 auto& settings = stubbed_tag_data.settings; 1463 auto& settings = stubbed_tag_data.settings;
1458 1464
1459 stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file); 1465 stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file);
@@ -1467,7 +1473,8 @@ void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data,
1467 SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'}); 1473 SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'});
1468 settings.settings.font_region.Assign(0); 1474 settings.settings.font_region.Assign(0);
1469 settings.init_date = GetAmiiboDate(GetCurrentPosixTime()); 1475 settings.init_date = GetAmiiboDate(GetCurrentPosixTime());
1470 stubbed_tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildBase(Mii::Gender::Male)); 1476 store_data.BuildBase(Mii::Gender::Male);
1477 stubbed_tag_data.owner_mii.BuildFromStoreData(store_data);
1471 1478
1472 // Admin info 1479 // Admin info
1473 settings.settings.amiibo_initialized.Assign(1); 1480 settings.settings.amiibo_initialized.Assign(1);
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index aed12a7f8..f96d21220 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -6,7 +6,9 @@
6#include <array> 6#include <array>
7 7
8#include "common/swap.h" 8#include "common/swap.h"
9#include "core/hle/service/mii/types.h" 9#include "core/hle/service/mii/types/char_info.h"
10#include "core/hle/service/mii/types/store_data.h"
11#include "core/hle/service/mii/types/ver3_store_data.h"
10#include "core/hle/service/nfc/nfc_types.h" 12#include "core/hle/service/nfc/nfc_types.h"
11 13
12namespace Service::NFP { 14namespace Service::NFP {
@@ -322,7 +324,7 @@ static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
322 324
323// This is nn::nfp::RegisterInfoPrivate 325// This is nn::nfp::RegisterInfoPrivate
324struct RegisterInfoPrivate { 326struct RegisterInfoPrivate {
325 Service::Mii::MiiStoreData mii_store_data; 327 Service::Mii::StoreData mii_store_data;
326 WriteDate creation_date; 328 WriteDate creation_date;
327 AmiiboName amiibo_name; 329 AmiiboName amiibo_name;
328 u8 font_region; 330 u8 font_region;
diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp
index 4988fcc83..b457a736a 100644
--- a/src/yuzu/applets/qt_amiibo_settings.cpp
+++ b/src/yuzu/applets/qt_amiibo_settings.cpp
@@ -160,7 +160,8 @@ void QtAmiiboSettingsDialog::LoadAmiiboData() {
160 } 160 }
161 161
162 const auto amiibo_name = std::string(register_info.amiibo_name.data()); 162 const auto amiibo_name = std::string(register_info.amiibo_name.data());
163 const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data()); 163 const auto owner_name =
164 Common::UTF16ToUTF8(register_info.mii_char_info.GetNickname().data.data());
164 const auto creation_date = 165 const auto creation_date =
165 QDate(register_info.creation_date.year, register_info.creation_date.month, 166 QDate(register_info.creation_date.year, register_info.creation_date.month,
166 register_info.creation_date.day); 167 register_info.creation_date.day);