Compare commits
1 Commits
android-70
...
android-69
Author | SHA1 | Date | |
---|---|---|---|
2e06210846 |
@ -270,7 +270,6 @@ public:
|
|||||||
m_vulkan_library);
|
m_vulkan_library);
|
||||||
|
|
||||||
m_system.SetFilesystem(m_vfs);
|
m_system.SetFilesystem(m_vfs);
|
||||||
m_system.GetUserChannel().clear();
|
|
||||||
|
|
||||||
// Initialize system.
|
// Initialize system.
|
||||||
jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
|
jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
|
||||||
|
@ -584,23 +584,13 @@ add_library(core STATIC
|
|||||||
hle/service/lm/lm.h
|
hle/service/lm/lm.h
|
||||||
hle/service/mig/mig.cpp
|
hle/service/mig/mig.cpp
|
||||||
hle/service/mig/mig.h
|
hle/service/mig/mig.h
|
||||||
hle/service/mii/types/char_info.cpp
|
|
||||||
hle/service/mii/types/char_info.h
|
|
||||||
hle/service/mii/types/core_data.cpp
|
|
||||||
hle/service/mii/types/core_data.h
|
|
||||||
hle/service/mii/types/raw_data.cpp
|
|
||||||
hle/service/mii/types/raw_data.h
|
|
||||||
hle/service/mii/types/store_data.cpp
|
|
||||||
hle/service/mii/types/store_data.h
|
|
||||||
hle/service/mii/types/ver3_store_data.cpp
|
|
||||||
hle/service/mii/types/ver3_store_data.h
|
|
||||||
hle/service/mii/mii.cpp
|
hle/service/mii/mii.cpp
|
||||||
hle/service/mii/mii.h
|
hle/service/mii/mii.h
|
||||||
hle/service/mii/mii_manager.cpp
|
hle/service/mii/mii_manager.cpp
|
||||||
hle/service/mii/mii_manager.h
|
hle/service/mii/mii_manager.h
|
||||||
hle/service/mii/mii_result.h
|
hle/service/mii/raw_data.cpp
|
||||||
hle/service/mii/mii_types.h
|
hle/service/mii/raw_data.h
|
||||||
hle/service/mii/mii_util.h
|
hle/service/mii/types.h
|
||||||
hle/service/mm/mm_u.cpp
|
hle/service/mm/mm_u.cpp
|
||||||
hle/service/mm/mm_u.h
|
hle/service/mm/mm_u.h
|
||||||
hle/service/mnpp/mnpp_app.cpp
|
hle/service/mnpp/mnpp_app.cpp
|
||||||
|
@ -406,7 +406,6 @@ struct System::Impl {
|
|||||||
gpu_core->NotifyShutdown();
|
gpu_core->NotifyShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
Network::CancelPendingSocketOperations();
|
|
||||||
kernel.SuspendApplication(true);
|
kernel.SuspendApplication(true);
|
||||||
if (services) {
|
if (services) {
|
||||||
services->KillNVNFlinger();
|
services->KillNVNFlinger();
|
||||||
@ -428,7 +427,6 @@ struct System::Impl {
|
|||||||
debugger.reset();
|
debugger.reset();
|
||||||
kernel.Shutdown();
|
kernel.Shutdown();
|
||||||
memory.Reset();
|
memory.Reset();
|
||||||
Network::RestartSocketOperations();
|
|
||||||
|
|
||||||
if (auto room_member = room_network.GetRoomMember().lock()) {
|
if (auto room_member = room_network.GetRoomMember().lock()) {
|
||||||
Network::GameInfo game_info{};
|
Network::GameInfo game_info{};
|
||||||
@ -564,8 +562,6 @@ struct System::Impl {
|
|||||||
|
|
||||||
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
|
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
|
||||||
gpu_dirty_memory_write_manager{};
|
gpu_dirty_memory_write_manager{};
|
||||||
|
|
||||||
std::deque<std::vector<u8>> user_channel;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
||||||
@ -1040,10 +1036,6 @@ void System::ExecuteProgram(std::size_t program_index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::deque<std::vector<u8>>& System::GetUserChannel() {
|
|
||||||
return impl->user_channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void System::RegisterExitCallback(ExitCallback&& callback) {
|
void System::RegisterExitCallback(ExitCallback&& callback) {
|
||||||
impl->exit_callback = std::move(callback);
|
impl->exit_callback = std::move(callback);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <deque>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -460,12 +459,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void ExecuteProgram(std::size_t program_index);
|
void ExecuteProgram(std::size_t program_index);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a reference to the user channel stack.
|
|
||||||
* It is used to transfer data between programs.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] std::deque<std::vector<u8>>& GetUserChannel();
|
|
||||||
|
|
||||||
/// Type used for the frontend to designate a callback for System to exit the application.
|
/// Type used for the frontend to designate a callback for System to exit the application.
|
||||||
using ExitCallback = std::function<void()>;
|
using ExitCallback = std::function<void()>;
|
||||||
|
|
||||||
|
@ -45,10 +45,6 @@ CNMT::CNMT(CNMTHeader header_, OptionalHeader opt_header_,
|
|||||||
|
|
||||||
CNMT::~CNMT() = default;
|
CNMT::~CNMT() = default;
|
||||||
|
|
||||||
const CNMTHeader& CNMT::GetHeader() const {
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 CNMT::GetTitleID() const {
|
u64 CNMT::GetTitleID() const {
|
||||||
return header.title_id;
|
return header.title_id;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,6 @@ public:
|
|||||||
std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_);
|
std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_);
|
||||||
~CNMT();
|
~CNMT();
|
||||||
|
|
||||||
const CNMTHeader& GetHeader() const;
|
|
||||||
u64 GetTitleID() const;
|
u64 GetTitleID() const;
|
||||||
u32 GetTitleVersion() const;
|
u32 GetTitleVersion() const;
|
||||||
TitleType GetType() const;
|
TitleType GetType() const;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/scope_exit.h"
|
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
#include "core/file_sys/card_image.h"
|
#include "core/file_sys/card_image.h"
|
||||||
#include "core/file_sys/common_funcs.h"
|
#include "core/file_sys/common_funcs.h"
|
||||||
@ -626,7 +625,7 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
|
|||||||
nca->GetTitleId() != title_id) {
|
nca->GetTitleId() != title_id) {
|
||||||
// Create fake cnmt for patch to multiprogram application
|
// Create fake cnmt for patch to multiprogram application
|
||||||
const auto sub_nca_result =
|
const auto sub_nca_result =
|
||||||
InstallEntry(*nca, cnmt.GetHeader(), record, overwrite_if_exists, copy);
|
InstallEntry(*nca, TitleType::Update, overwrite_if_exists, copy);
|
||||||
if (sub_nca_result != InstallResult::Success) {
|
if (sub_nca_result != InstallResult::Success) {
|
||||||
return sub_nca_result;
|
return sub_nca_result;
|
||||||
}
|
}
|
||||||
@ -673,31 +672,6 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
|
|||||||
return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
|
return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallResult RegisteredCache::InstallEntry(const NCA& nca, const CNMTHeader& base_header,
|
|
||||||
const ContentRecord& base_record,
|
|
||||||
bool overwrite_if_exists, const VfsCopyFunction& copy) {
|
|
||||||
const CNMTHeader header{
|
|
||||||
.title_id = nca.GetTitleId(),
|
|
||||||
.title_version = base_header.title_version,
|
|
||||||
.type = base_header.type,
|
|
||||||
.reserved = {},
|
|
||||||
.table_offset = 0x10,
|
|
||||||
.number_content_entries = 1,
|
|
||||||
.number_meta_entries = 0,
|
|
||||||
.attributes = 0,
|
|
||||||
.reserved2 = {},
|
|
||||||
.is_committed = 0,
|
|
||||||
.required_download_system_version = 0,
|
|
||||||
.reserved3 = {},
|
|
||||||
};
|
|
||||||
const OptionalHeader opt_header{0, 0};
|
|
||||||
const CNMT new_cnmt(header, opt_header, {base_record}, {});
|
|
||||||
if (!RawInstallYuzuMeta(new_cnmt)) {
|
|
||||||
return InstallResult::ErrorMetaFailed;
|
|
||||||
}
|
|
||||||
return RawInstallNCA(nca, copy, overwrite_if_exists, base_record.nca_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
|
bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
|
||||||
bool removed_data = false;
|
bool removed_data = false;
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ enum class NCAContentType : u8;
|
|||||||
enum class TitleType : u8;
|
enum class TitleType : u8;
|
||||||
|
|
||||||
struct ContentRecord;
|
struct ContentRecord;
|
||||||
struct CNMTHeader;
|
|
||||||
struct MetaRecord;
|
struct MetaRecord;
|
||||||
class RegisteredCache;
|
class RegisteredCache;
|
||||||
|
|
||||||
@ -170,10 +169,6 @@ public:
|
|||||||
InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
|
InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
|
||||||
const VfsCopyFunction& copy = &VfsRawCopy);
|
const VfsCopyFunction& copy = &VfsRawCopy);
|
||||||
|
|
||||||
InstallResult InstallEntry(const NCA& nca, const CNMTHeader& base_header,
|
|
||||||
const ContentRecord& base_record, bool overwrite_if_exists = false,
|
|
||||||
const VfsCopyFunction& copy = &VfsRawCopy);
|
|
||||||
|
|
||||||
// Removes an existing entry based on title id
|
// Removes an existing entry based on title id
|
||||||
bool RemoveExistingEntry(u64 title_id) const;
|
bool RemoveExistingEntry(u64 title_id) const;
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
|||||||
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
||||||
|
|
||||||
enum class LaunchParameterKind : u32 {
|
enum class LaunchParameterKind : u32 {
|
||||||
UserChannel = 1,
|
ApplicationSpecific = 1,
|
||||||
AccountPreselectedUser = 2,
|
AccountPreselectedUser = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1518,26 +1518,27 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto kind = rp.PopEnum<LaunchParameterKind>();
|
const auto kind = rp.PopEnum<LaunchParameterKind>();
|
||||||
|
|
||||||
LOG_INFO(Service_AM, "called, kind={:08X}", kind);
|
LOG_DEBUG(Service_AM, "called, kind={:08X}", kind);
|
||||||
|
|
||||||
if (kind == LaunchParameterKind::UserChannel) {
|
if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) {
|
||||||
auto channel = system.GetUserChannel();
|
const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) {
|
||||||
if (channel.empty()) {
|
return system.GetFileSystemController().GetBCATDirectory(tid);
|
||||||
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
|
});
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
const auto build_id_full = system.GetApplicationProcessBuildID();
|
||||||
rb.Push(AM::ResultNoDataInChannel);
|
u64 build_id{};
|
||||||
|
std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
|
||||||
|
|
||||||
|
auto data =
|
||||||
|
backend->GetLaunchParameter({system.GetApplicationProcessProgramID(), build_id});
|
||||||
|
if (data.has_value()) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IStorage>(system, std::move(*data));
|
||||||
|
launch_popped_application_specific = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = channel.back();
|
|
||||||
channel.pop_back();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IStorage>(system, std::move(data));
|
|
||||||
} else if (kind == LaunchParameterKind::AccountPreselectedUser &&
|
} else if (kind == LaunchParameterKind::AccountPreselectedUser &&
|
||||||
!launch_popped_account_preselect) {
|
!launch_popped_account_preselect) {
|
||||||
// TODO: Verify this is hw-accurate
|
|
||||||
LaunchParameterAccountPreselectedUser params{};
|
LaunchParameterAccountPreselectedUser params{};
|
||||||
|
|
||||||
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
|
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
|
||||||
@ -1549,6 +1550,7 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
|||||||
params.current_user = *uuid;
|
params.current_user = *uuid;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
|
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
|
||||||
@ -1556,11 +1558,12 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
rb.PushIpcInterface<IStorage>(system, std::move(buffer));
|
rb.PushIpcInterface<IStorage>(system, std::move(buffer));
|
||||||
launch_popped_account_preselect = true;
|
launch_popped_account_preselect = true;
|
||||||
} else {
|
return;
|
||||||
LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(AM::ResultNoDataInChannel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(AM::ResultNoDataInChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
|
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
|
||||||
@ -1852,22 +1855,14 @@ void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
|
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
system.GetUserChannel().clear();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
|
void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto storage = rp.PopIpcInterface<IStorage>().lock();
|
|
||||||
if (storage) {
|
|
||||||
system.GetUserChannel().push_back(storage->GetData());
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -339,6 +339,7 @@ private:
|
|||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
|
||||||
|
bool launch_popped_application_specific = false;
|
||||||
bool launch_popped_account_preselect = false;
|
bool launch_popped_account_preselect = false;
|
||||||
s32 previous_program_index{-1};
|
s32 previous_program_index{-1};
|
||||||
Kernel::KEvent* gpu_error_detected_event;
|
Kernel::KEvent* gpu_error_detected_event;
|
||||||
|
@ -85,18 +85,15 @@ void MiiEdit::Execute() {
|
|||||||
break;
|
break;
|
||||||
case MiiEditAppletMode::CreateMii:
|
case MiiEditAppletMode::CreateMii:
|
||||||
case MiiEditAppletMode::EditMii: {
|
case MiiEditAppletMode::EditMii: {
|
||||||
Mii::CharInfo char_info{};
|
Service::Mii::MiiManager mii_manager;
|
||||||
Mii::StoreData store_data{};
|
|
||||||
store_data.BuildBase(Mii::Gender::Male);
|
|
||||||
char_info.SetFromStoreData(store_data);
|
|
||||||
|
|
||||||
const MiiEditCharInfo edit_char_info{
|
const MiiEditCharInfo char_info{
|
||||||
.mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
|
.mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
|
||||||
? applet_input_v4.char_info.mii_info
|
? applet_input_v4.char_info.mii_info
|
||||||
: char_info},
|
: mii_manager.BuildBase(Mii::Gender::Male)},
|
||||||
};
|
};
|
||||||
|
|
||||||
MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info);
|
MiiEditOutputForCharInfoEditing(MiiEditResult::Success, char_info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/uuid.h"
|
#include "core/hle/service/mii/types.h"
|
||||||
#include "core/hle/service/mii/types/char_info.h"
|
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Applets {
|
||||||
|
|
||||||
|
@ -7,16 +7,17 @@
|
|||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/mii/mii.h"
|
#include "core/hle/service/mii/mii.h"
|
||||||
#include "core/hle/service/mii/mii_manager.h"
|
#include "core/hle/service/mii/mii_manager.h"
|
||||||
#include "core/hle/service/mii/mii_result.h"
|
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::Mii {
|
namespace Service::Mii {
|
||||||
|
|
||||||
|
constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1};
|
||||||
|
|
||||||
class IDatabaseService final : public ServiceFramework<IDatabaseService> {
|
class IDatabaseService final : public ServiceFramework<IDatabaseService> {
|
||||||
public:
|
public:
|
||||||
explicit IDatabaseService(Core::System& system_, bool is_system_)
|
explicit IDatabaseService(Core::System& system_)
|
||||||
: ServiceFramework{system_, "IDatabaseService"}, is_system{is_system_} {
|
: ServiceFramework{system_, "IDatabaseService"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IDatabaseService::IsUpdated, "IsUpdated"},
|
{0, &IDatabaseService::IsUpdated, "IsUpdated"},
|
||||||
@ -53,27 +54,34 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename T>
|
||||||
|
std::vector<u8> SerializeArray(const std::vector<T>& values) {
|
||||||
|
std::vector<u8> out(values.size() * sizeof(T));
|
||||||
|
std::size_t offset{};
|
||||||
|
for (const auto& value : values) {
|
||||||
|
std::memcpy(out.data() + offset, &value, sizeof(T));
|
||||||
|
offset += sizeof(T);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
void IsUpdated(HLERequestContext& ctx) {
|
void IsUpdated(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
|
|
||||||
const bool is_updated = manager.IsUpdated(metadata, source_flag);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u8>(is_updated);
|
rb.Push(manager.CheckAndResetUpdateCounter(source_flag, current_update_counter));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IsFullDatabase(HLERequestContext& ctx) {
|
void IsFullDatabase(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Mii, "called");
|
LOG_DEBUG(Service_Mii, "called");
|
||||||
|
|
||||||
const bool is_full_database = manager.IsFullDatabase();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u8>(is_full_database);
|
rb.Push(manager.IsFullDatabase());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCount(HLERequestContext& ctx) {
|
void GetCount(HLERequestContext& ctx) {
|
||||||
@ -82,63 +90,57 @@ private:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
|
|
||||||
const u32 mii_count = manager.GetCount(metadata, source_flag);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(mii_count);
|
rb.Push<u32>(manager.GetCount(source_flag));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get(HLERequestContext& ctx) {
|
void Get(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
||||||
const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
|
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
|
|
||||||
u32 mii_count{};
|
const auto default_miis{manager.GetDefault(source_flag)};
|
||||||
std::vector<CharInfoElement> char_info_elements(output_size);
|
if (default_miis.size() > 0) {
|
||||||
Result result = manager.Get(metadata, char_info_elements, mii_count, source_flag);
|
ctx.WriteBuffer(SerializeArray(default_miis));
|
||||||
|
|
||||||
if (mii_count != 0) {
|
|
||||||
ctx.WriteBuffer(char_info_elements);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(result);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(mii_count);
|
rb.Push<u32>(static_cast<u32>(default_miis.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get1(HLERequestContext& ctx) {
|
void Get1(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
||||||
const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
|
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
|
|
||||||
u32 mii_count{};
|
const auto default_miis{manager.GetDefault(source_flag)};
|
||||||
std::vector<CharInfo> char_info(output_size);
|
|
||||||
Result result = manager.Get(metadata, char_info, mii_count, source_flag);
|
|
||||||
|
|
||||||
if (mii_count != 0) {
|
std::vector<CharInfo> values;
|
||||||
ctx.WriteBuffer(char_info);
|
for (const auto& element : default_miis) {
|
||||||
|
values.emplace_back(element.info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.WriteBuffer(SerializeArray(values));
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(result);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(mii_count);
|
rb.Push<u32>(static_cast<u32>(default_miis.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateLatest(HLERequestContext& ctx) {
|
void UpdateLatest(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto char_info{rp.PopRaw<CharInfo>()};
|
const auto info{rp.PopRaw<CharInfo>()};
|
||||||
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
|
|
||||||
CharInfo new_char_info{};
|
CharInfo new_char_info{};
|
||||||
const auto result = manager.UpdateLatest(metadata, new_char_info, char_info, source_flag);
|
const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)};
|
||||||
if (result.IsFailure()) {
|
if (result != ResultSuccess) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(result);
|
rb.Push(result);
|
||||||
return;
|
return;
|
||||||
@ -151,6 +153,7 @@ private:
|
|||||||
|
|
||||||
void BuildRandom(HLERequestContext& ctx) {
|
void BuildRandom(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
const auto age{rp.PopRaw<Age>()};
|
const auto age{rp.PopRaw<Age>()};
|
||||||
const auto gender{rp.PopRaw<Gender>()};
|
const auto gender{rp.PopRaw<Gender>()};
|
||||||
const auto race{rp.PopRaw<Race>()};
|
const auto race{rp.PopRaw<Race>()};
|
||||||
@ -159,48 +162,47 @@ private:
|
|||||||
|
|
||||||
if (age > Age::All) {
|
if (age > Age::All) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultInvalidArgument);
|
rb.Push(ERROR_INVALID_ARGUMENT);
|
||||||
|
LOG_ERROR(Service_Mii, "invalid age={}", age);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gender > Gender::All) {
|
if (gender > Gender::All) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultInvalidArgument);
|
rb.Push(ERROR_INVALID_ARGUMENT);
|
||||||
|
LOG_ERROR(Service_Mii, "invalid gender={}", gender);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (race > Race::All) {
|
if (race > Race::All) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultInvalidArgument);
|
rb.Push(ERROR_INVALID_ARGUMENT);
|
||||||
|
LOG_ERROR(Service_Mii, "invalid race={}", race);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharInfo char_info{};
|
|
||||||
manager.BuildRandom(char_info, age, gender, race);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw<CharInfo>(char_info);
|
rb.PushRaw<CharInfo>(manager.BuildRandom(age, gender, race));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildDefault(HLERequestContext& ctx) {
|
void BuildDefault(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto index{rp.Pop<u32>()};
|
const auto index{rp.Pop<u32>()};
|
||||||
|
|
||||||
LOG_INFO(Service_Mii, "called with index={}", index);
|
LOG_DEBUG(Service_Mii, "called with index={}", index);
|
||||||
|
|
||||||
if (index > 5) {
|
if (index > 5) {
|
||||||
|
LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}",
|
||||||
|
index);
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultInvalidArgument);
|
rb.Push(ERROR_INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharInfo char_info{};
|
|
||||||
manager.BuildDefault(char_info, index);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw<CharInfo>(char_info);
|
rb.PushRaw<CharInfo>(manager.BuildDefault(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetIndex(HLERequestContext& ctx) {
|
void GetIndex(HLERequestContext& ctx) {
|
||||||
@ -209,21 +211,19 @@ private:
|
|||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called");
|
LOG_DEBUG(Service_Mii, "called");
|
||||||
|
|
||||||
s32 index{};
|
u32 index{};
|
||||||
const auto result = manager.GetIndex(metadata, info, index);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(result);
|
rb.Push(manager.GetIndex(info, index));
|
||||||
rb.Push(index);
|
rb.Push(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetInterfaceVersion(HLERequestContext& ctx) {
|
void SetInterfaceVersion(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto interface_version{rp.PopRaw<u32>()};
|
current_interface_version = rp.PopRaw<u32>();
|
||||||
|
|
||||||
LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
|
LOG_DEBUG(Service_Mii, "called, interface_version={:08X}", current_interface_version);
|
||||||
|
|
||||||
manager.SetInterfaceVersion(metadata, interface_version);
|
UNIMPLEMENTED_IF(current_interface_version != 1);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
@ -231,27 +231,30 @@ private:
|
|||||||
|
|
||||||
void Convert(HLERequestContext& ctx) {
|
void Convert(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
|
const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
|
||||||
|
|
||||||
LOG_INFO(Service_Mii, "called");
|
LOG_INFO(Service_Mii, "called");
|
||||||
|
|
||||||
CharInfo char_info{};
|
|
||||||
manager.ConvertV3ToCharInfo(char_info, mii_v3);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw<CharInfo>(char_info);
|
rb.PushRaw<CharInfo>(manager.ConvertV3ToCharInfo(mii_v3));
|
||||||
}
|
}
|
||||||
|
|
||||||
MiiManager manager{};
|
constexpr bool IsInterfaceVersionSupported(u32 interface_version) const {
|
||||||
DatabaseSessionMetadata metadata{};
|
return current_interface_version >= interface_version;
|
||||||
bool is_system{};
|
}
|
||||||
|
|
||||||
|
MiiManager manager;
|
||||||
|
|
||||||
|
u32 current_interface_version{};
|
||||||
|
u64 current_update_counter{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class MiiDBModule final : public ServiceFramework<MiiDBModule> {
|
class MiiDBModule final : public ServiceFramework<MiiDBModule> {
|
||||||
public:
|
public:
|
||||||
explicit MiiDBModule(Core::System& system_, const char* name_, bool is_system_)
|
explicit MiiDBModule(Core::System& system_, const char* name_)
|
||||||
: ServiceFramework{system_, name_}, is_system{is_system_} {
|
: ServiceFramework{system_, name_} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
|
{0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
|
||||||
@ -265,12 +268,10 @@ private:
|
|||||||
void GetDatabaseService(HLERequestContext& ctx) {
|
void GetDatabaseService(HLERequestContext& ctx) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IDatabaseService>(system, is_system);
|
rb.PushIpcInterface<IDatabaseService>(system);
|
||||||
|
|
||||||
LOG_DEBUG(Service_Mii, "called");
|
LOG_DEBUG(Service_Mii, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_system{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MiiImg final : public ServiceFramework<MiiImg> {
|
class MiiImg final : public ServiceFramework<MiiImg> {
|
||||||
@ -302,10 +303,8 @@ public:
|
|||||||
void LoopProcess(Core::System& system) {
|
void LoopProcess(Core::System& system) {
|
||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
|
|
||||||
server_manager->RegisterNamedService("mii:e",
|
server_manager->RegisterNamedService("mii:e", std::make_shared<MiiDBModule>(system, "mii:e"));
|
||||||
std::make_shared<MiiDBModule>(system, "mii:e", true));
|
server_manager->RegisterNamedService("mii:u", std::make_shared<MiiDBModule>(system, "mii:u"));
|
||||||
server_manager->RegisterNamedService("mii:u",
|
|
||||||
std::make_shared<MiiDBModule>(system, "mii:u", false));
|
|
||||||
server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
|
server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
}
|
}
|
||||||
|
@ -10,24 +10,385 @@
|
|||||||
|
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/hle/service/mii/mii_manager.h"
|
#include "core/hle/service/mii/mii_manager.h"
|
||||||
#include "core/hle/service/mii/mii_result.h"
|
#include "core/hle/service/mii/raw_data.h"
|
||||||
#include "core/hle/service/mii/mii_util.h"
|
|
||||||
#include "core/hle/service/mii/types/core_data.h"
|
|
||||||
#include "core/hle/service/mii/types/raw_data.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
namespace Service::Mii {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr Result ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
|
||||||
|
|
||||||
constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
|
constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
|
||||||
|
|
||||||
MiiManager::MiiManager() {}
|
constexpr MiiStoreData::Name DefaultMiiName{u'n', u'o', u' ', u'n', u'a', u'm', u'e'};
|
||||||
|
constexpr std::array<u8, 8> HairColorLookup{8, 1, 2, 3, 4, 5, 6, 7};
|
||||||
|
constexpr std::array<u8, 6> EyeColorLookup{8, 9, 10, 11, 12, 13};
|
||||||
|
constexpr std::array<u8, 5> MouthColorLookup{19, 20, 21, 22, 23};
|
||||||
|
constexpr std::array<u8, 7> GlassesColorLookup{8, 14, 15, 16, 17, 18, 0};
|
||||||
|
constexpr std::array<u8, 62> EyeRotateLookup{
|
||||||
|
{0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
|
||||||
|
0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
|
||||||
|
0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04}};
|
||||||
|
constexpr std::array<u8, 24> EyebrowRotateLookup{{0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07,
|
||||||
|
0x04, 0x07, 0x06, 0x08, 0x05, 0x05, 0x06, 0x06,
|
||||||
|
0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05}};
|
||||||
|
|
||||||
bool MiiManager::IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
|
template <typename T, std::size_t SourceArraySize, std::size_t DestArraySize>
|
||||||
|
std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& in) {
|
||||||
|
std::array<T, DestArraySize> out{};
|
||||||
|
std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
CharInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
|
||||||
|
MiiStoreBitFields bf;
|
||||||
|
std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields));
|
||||||
|
|
||||||
|
return {
|
||||||
|
.uuid = data.data.uuid,
|
||||||
|
.name = ResizeArray<char16_t, 10, 11>(data.data.name),
|
||||||
|
.font_region = static_cast<u8>(bf.font_region.Value()),
|
||||||
|
.favorite_color = static_cast<u8>(bf.favorite_color.Value()),
|
||||||
|
.gender = static_cast<u8>(bf.gender.Value()),
|
||||||
|
.height = static_cast<u8>(bf.height.Value()),
|
||||||
|
.build = static_cast<u8>(bf.build.Value()),
|
||||||
|
.type = static_cast<u8>(bf.type.Value()),
|
||||||
|
.region_move = static_cast<u8>(bf.region_move.Value()),
|
||||||
|
.faceline_type = static_cast<u8>(bf.faceline_type.Value()),
|
||||||
|
.faceline_color = static_cast<u8>(bf.faceline_color.Value()),
|
||||||
|
.faceline_wrinkle = static_cast<u8>(bf.faceline_wrinkle.Value()),
|
||||||
|
.faceline_make = static_cast<u8>(bf.faceline_makeup.Value()),
|
||||||
|
.hair_type = static_cast<u8>(bf.hair_type.Value()),
|
||||||
|
.hair_color = static_cast<u8>(bf.hair_color.Value()),
|
||||||
|
.hair_flip = static_cast<u8>(bf.hair_flip.Value()),
|
||||||
|
.eye_type = static_cast<u8>(bf.eye_type.Value()),
|
||||||
|
.eye_color = static_cast<u8>(bf.eye_color.Value()),
|
||||||
|
.eye_scale = static_cast<u8>(bf.eye_scale.Value()),
|
||||||
|
.eye_aspect = static_cast<u8>(bf.eye_aspect.Value()),
|
||||||
|
.eye_rotate = static_cast<u8>(bf.eye_rotate.Value()),
|
||||||
|
.eye_x = static_cast<u8>(bf.eye_x.Value()),
|
||||||
|
.eye_y = static_cast<u8>(bf.eye_y.Value()),
|
||||||
|
.eyebrow_type = static_cast<u8>(bf.eyebrow_type.Value()),
|
||||||
|
.eyebrow_color = static_cast<u8>(bf.eyebrow_color.Value()),
|
||||||
|
.eyebrow_scale = static_cast<u8>(bf.eyebrow_scale.Value()),
|
||||||
|
.eyebrow_aspect = static_cast<u8>(bf.eyebrow_aspect.Value()),
|
||||||
|
.eyebrow_rotate = static_cast<u8>(bf.eyebrow_rotate.Value()),
|
||||||
|
.eyebrow_x = static_cast<u8>(bf.eyebrow_x.Value()),
|
||||||
|
.eyebrow_y = static_cast<u8>(bf.eyebrow_y.Value() + 3),
|
||||||
|
.nose_type = static_cast<u8>(bf.nose_type.Value()),
|
||||||
|
.nose_scale = static_cast<u8>(bf.nose_scale.Value()),
|
||||||
|
.nose_y = static_cast<u8>(bf.nose_y.Value()),
|
||||||
|
.mouth_type = static_cast<u8>(bf.mouth_type.Value()),
|
||||||
|
.mouth_color = static_cast<u8>(bf.mouth_color.Value()),
|
||||||
|
.mouth_scale = static_cast<u8>(bf.mouth_scale.Value()),
|
||||||
|
.mouth_aspect = static_cast<u8>(bf.mouth_aspect.Value()),
|
||||||
|
.mouth_y = static_cast<u8>(bf.mouth_y.Value()),
|
||||||
|
.beard_color = static_cast<u8>(bf.beard_color.Value()),
|
||||||
|
.beard_type = static_cast<u8>(bf.beard_type.Value()),
|
||||||
|
.mustache_type = static_cast<u8>(bf.mustache_type.Value()),
|
||||||
|
.mustache_scale = static_cast<u8>(bf.mustache_scale.Value()),
|
||||||
|
.mustache_y = static_cast<u8>(bf.mustache_y.Value()),
|
||||||
|
.glasses_type = static_cast<u8>(bf.glasses_type.Value()),
|
||||||
|
.glasses_color = static_cast<u8>(bf.glasses_color.Value()),
|
||||||
|
.glasses_scale = static_cast<u8>(bf.glasses_scale.Value()),
|
||||||
|
.glasses_y = static_cast<u8>(bf.glasses_y.Value()),
|
||||||
|
.mole_type = static_cast<u8>(bf.mole_type.Value()),
|
||||||
|
.mole_scale = static_cast<u8>(bf.mole_scale.Value()),
|
||||||
|
.mole_x = static_cast<u8>(bf.mole_x.Value()),
|
||||||
|
.mole_y = static_cast<u8>(bf.mole_y.Value()),
|
||||||
|
.padding = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 GenerateCrc16(const void* data, std::size_t size) {
|
||||||
|
s32 crc{};
|
||||||
|
for (std::size_t i = 0; i < size; i++) {
|
||||||
|
crc ^= static_cast<const u8*>(data)[i] << 8;
|
||||||
|
for (std::size_t j = 0; j < 8; j++) {
|
||||||
|
crc <<= 1;
|
||||||
|
if ((crc & 0x10000) != 0) {
|
||||||
|
crc = (crc ^ 0x1021) & 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Common::swap16(static_cast<u16>(crc));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T GetRandomValue(T min, T max) {
|
||||||
|
std::random_device device;
|
||||||
|
std::mt19937 gen(device());
|
||||||
|
std::uniform_int_distribution<u64> distribution(static_cast<u64>(min), static_cast<u64>(max));
|
||||||
|
return static_cast<T>(distribution(gen));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T GetRandomValue(T max) {
|
||||||
|
return GetRandomValue<T>({}, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
MiiStoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Common::UUID& user_id) {
|
||||||
|
MiiStoreBitFields bf{};
|
||||||
|
|
||||||
|
if (gender == Gender::All) {
|
||||||
|
gender = GetRandomValue<Gender>(Gender::Maximum);
|
||||||
|
}
|
||||||
|
|
||||||
|
bf.gender.Assign(gender);
|
||||||
|
bf.favorite_color.Assign(GetRandomValue<u8>(11));
|
||||||
|
bf.region_move.Assign(0);
|
||||||
|
bf.font_region.Assign(FontRegion::Standard);
|
||||||
|
bf.type.Assign(0);
|
||||||
|
bf.height.Assign(64);
|
||||||
|
bf.build.Assign(64);
|
||||||
|
|
||||||
|
if (age == Age::All) {
|
||||||
|
const auto temp{GetRandomValue<int>(10)};
|
||||||
|
if (temp >= 8) {
|
||||||
|
age = Age::Old;
|
||||||
|
} else if (temp >= 4) {
|
||||||
|
age = Age::Normal;
|
||||||
|
} else {
|
||||||
|
age = Age::Young;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (race == Race::All) {
|
||||||
|
const auto temp{GetRandomValue<int>(10)};
|
||||||
|
if (temp >= 8) {
|
||||||
|
race = Race::Black;
|
||||||
|
} else if (temp >= 4) {
|
||||||
|
race = Race::White;
|
||||||
|
} else {
|
||||||
|
race = Race::Asian;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 axis_y{};
|
||||||
|
if (gender == Gender::Female && age == Age::Young) {
|
||||||
|
axis_y = GetRandomValue<u32>(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t index{3 * static_cast<std::size_t>(age) +
|
||||||
|
9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
|
||||||
|
|
||||||
|
const auto faceline_type_info{RawData::RandomMiiFaceline.at(index)};
|
||||||
|
const auto faceline_color_info{RawData::RandomMiiFacelineColor.at(
|
||||||
|
3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
|
||||||
|
const auto faceline_wrinkle_info{RawData::RandomMiiFacelineWrinkle.at(index)};
|
||||||
|
const auto faceline_makeup_info{RawData::RandomMiiFacelineMakeup.at(index)};
|
||||||
|
const auto hair_type_info{RawData::RandomMiiHairType.at(index)};
|
||||||
|
const auto hair_color_info{RawData::RandomMiiHairColor.at(3 * static_cast<std::size_t>(race) +
|
||||||
|
static_cast<std::size_t>(age))};
|
||||||
|
const auto eye_type_info{RawData::RandomMiiEyeType.at(index)};
|
||||||
|
const auto eye_color_info{RawData::RandomMiiEyeColor.at(static_cast<std::size_t>(race))};
|
||||||
|
const auto eyebrow_type_info{RawData::RandomMiiEyebrowType.at(index)};
|
||||||
|
const auto nose_type_info{RawData::RandomMiiNoseType.at(index)};
|
||||||
|
const auto mouth_type_info{RawData::RandomMiiMouthType.at(index)};
|
||||||
|
const auto glasses_type_info{RawData::RandomMiiGlassType.at(static_cast<std::size_t>(age))};
|
||||||
|
|
||||||
|
bf.faceline_type.Assign(
|
||||||
|
faceline_type_info.values[GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
|
||||||
|
bf.faceline_color.Assign(
|
||||||
|
faceline_color_info.values[GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
|
||||||
|
bf.faceline_wrinkle.Assign(
|
||||||
|
faceline_wrinkle_info
|
||||||
|
.values[GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
|
||||||
|
bf.faceline_makeup.Assign(
|
||||||
|
faceline_makeup_info
|
||||||
|
.values[GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
|
||||||
|
|
||||||
|
bf.hair_type.Assign(
|
||||||
|
hair_type_info.values[GetRandomValue<std::size_t>(hair_type_info.values_count)]);
|
||||||
|
bf.hair_color.Assign(
|
||||||
|
HairColorLookup[hair_color_info
|
||||||
|
.values[GetRandomValue<std::size_t>(hair_color_info.values_count)]]);
|
||||||
|
bf.hair_flip.Assign(GetRandomValue<HairFlip>(HairFlip::Maximum));
|
||||||
|
|
||||||
|
bf.eye_type.Assign(
|
||||||
|
eye_type_info.values[GetRandomValue<std::size_t>(eye_type_info.values_count)]);
|
||||||
|
|
||||||
|
const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
|
||||||
|
const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
|
||||||
|
const auto eye_rotate_offset{32 - EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
|
||||||
|
const auto eye_rotate{32 - EyeRotateLookup[bf.eye_type]};
|
||||||
|
|
||||||
|
bf.eye_color.Assign(
|
||||||
|
EyeColorLookup[eye_color_info
|
||||||
|
.values[GetRandomValue<std::size_t>(eye_color_info.values_count)]]);
|
||||||
|
bf.eye_scale.Assign(4);
|
||||||
|
bf.eye_aspect.Assign(3);
|
||||||
|
bf.eye_rotate.Assign(eye_rotate_offset - eye_rotate);
|
||||||
|
bf.eye_x.Assign(2);
|
||||||
|
bf.eye_y.Assign(axis_y + 12);
|
||||||
|
|
||||||
|
bf.eyebrow_type.Assign(
|
||||||
|
eyebrow_type_info.values[GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
|
||||||
|
|
||||||
|
const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
|
||||||
|
const auto eyebrow_y{race == Race::Asian ? 9 : 10};
|
||||||
|
const auto eyebrow_rotate_offset{32 - EyebrowRotateLookup[eyebrow_rotate_1] + 6};
|
||||||
|
const auto eyebrow_rotate{
|
||||||
|
32 - EyebrowRotateLookup[static_cast<std::size_t>(bf.eyebrow_type.Value())]};
|
||||||
|
|
||||||
|
bf.eyebrow_color.Assign(bf.hair_color);
|
||||||
|
bf.eyebrow_scale.Assign(4);
|
||||||
|
bf.eyebrow_aspect.Assign(3);
|
||||||
|
bf.eyebrow_rotate.Assign(eyebrow_rotate_offset - eyebrow_rotate);
|
||||||
|
bf.eyebrow_x.Assign(2);
|
||||||
|
bf.eyebrow_y.Assign(axis_y + eyebrow_y);
|
||||||
|
|
||||||
|
const auto nose_scale{gender == Gender::Female ? 3 : 4};
|
||||||
|
|
||||||
|
bf.nose_type.Assign(
|
||||||
|
nose_type_info.values[GetRandomValue<std::size_t>(nose_type_info.values_count)]);
|
||||||
|
bf.nose_scale.Assign(nose_scale);
|
||||||
|
bf.nose_y.Assign(axis_y + 9);
|
||||||
|
|
||||||
|
const auto mouth_color{gender == Gender::Female ? GetRandomValue<int>(4) : 0};
|
||||||
|
|
||||||
|
bf.mouth_type.Assign(
|
||||||
|
mouth_type_info.values[GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
|
||||||
|
bf.mouth_color.Assign(MouthColorLookup[mouth_color]);
|
||||||
|
bf.mouth_scale.Assign(4);
|
||||||
|
bf.mouth_aspect.Assign(3);
|
||||||
|
bf.mouth_y.Assign(axis_y + 13);
|
||||||
|
|
||||||
|
bf.beard_color.Assign(bf.hair_color);
|
||||||
|
bf.mustache_scale.Assign(4);
|
||||||
|
|
||||||
|
if (gender == Gender::Male && age != Age::Young && GetRandomValue<int>(10) < 2) {
|
||||||
|
const auto mustache_and_beard_flag{
|
||||||
|
GetRandomValue<BeardAndMustacheFlag>(BeardAndMustacheFlag::All)};
|
||||||
|
|
||||||
|
auto beard_type{BeardType::None};
|
||||||
|
auto mustache_type{MustacheType::None};
|
||||||
|
|
||||||
|
if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
|
||||||
|
BeardAndMustacheFlag::Beard) {
|
||||||
|
beard_type = GetRandomValue<BeardType>(BeardType::Beard1, BeardType::Beard5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
|
||||||
|
BeardAndMustacheFlag::Mustache) {
|
||||||
|
mustache_type =
|
||||||
|
GetRandomValue<MustacheType>(MustacheType::Mustache1, MustacheType::Mustache5);
|
||||||
|
}
|
||||||
|
|
||||||
|
bf.mustache_type.Assign(mustache_type);
|
||||||
|
bf.beard_type.Assign(beard_type);
|
||||||
|
bf.mustache_y.Assign(10);
|
||||||
|
} else {
|
||||||
|
bf.mustache_type.Assign(MustacheType::None);
|
||||||
|
bf.beard_type.Assign(BeardType::None);
|
||||||
|
bf.mustache_y.Assign(axis_y + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto glasses_type_start{GetRandomValue<std::size_t>(100)};
|
||||||
|
u8 glasses_type{};
|
||||||
|
while (glasses_type_start < glasses_type_info.values[glasses_type]) {
|
||||||
|
if (++glasses_type >= glasses_type_info.values_count) {
|
||||||
|
ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bf.glasses_type.Assign(glasses_type);
|
||||||
|
bf.glasses_color.Assign(GlassesColorLookup[0]);
|
||||||
|
bf.glasses_scale.Assign(4);
|
||||||
|
bf.glasses_y.Assign(axis_y + 10);
|
||||||
|
|
||||||
|
bf.mole_type.Assign(0);
|
||||||
|
bf.mole_scale.Assign(4);
|
||||||
|
bf.mole_x.Assign(2);
|
||||||
|
bf.mole_y.Assign(20);
|
||||||
|
|
||||||
|
return {DefaultMiiName, bf, user_id};
|
||||||
|
}
|
||||||
|
|
||||||
|
MiiStoreData BuildDefaultStoreData(const DefaultMii& info, const Common::UUID& user_id) {
|
||||||
|
MiiStoreBitFields bf{};
|
||||||
|
|
||||||
|
bf.font_region.Assign(info.font_region);
|
||||||
|
bf.favorite_color.Assign(info.favorite_color);
|
||||||
|
bf.gender.Assign(info.gender);
|
||||||
|
bf.height.Assign(info.height);
|
||||||
|
bf.build.Assign(info.weight);
|
||||||
|
bf.type.Assign(info.type);
|
||||||
|
bf.region_move.Assign(info.region);
|
||||||
|
bf.faceline_type.Assign(info.face_type);
|
||||||
|
bf.faceline_color.Assign(info.face_color);
|
||||||
|
bf.faceline_wrinkle.Assign(info.face_wrinkle);
|
||||||
|
bf.faceline_makeup.Assign(info.face_makeup);
|
||||||
|
bf.hair_type.Assign(info.hair_type);
|
||||||
|
bf.hair_color.Assign(HairColorLookup[info.hair_color]);
|
||||||
|
bf.hair_flip.Assign(static_cast<HairFlip>(info.hair_flip));
|
||||||
|
bf.eye_type.Assign(info.eye_type);
|
||||||
|
bf.eye_color.Assign(EyeColorLookup[info.eye_color]);
|
||||||
|
bf.eye_scale.Assign(info.eye_scale);
|
||||||
|
bf.eye_aspect.Assign(info.eye_aspect);
|
||||||
|
bf.eye_rotate.Assign(info.eye_rotate);
|
||||||
|
bf.eye_x.Assign(info.eye_x);
|
||||||
|
bf.eye_y.Assign(info.eye_y);
|
||||||
|
bf.eyebrow_type.Assign(info.eyebrow_type);
|
||||||
|
bf.eyebrow_color.Assign(HairColorLookup[info.eyebrow_color]);
|
||||||
|
bf.eyebrow_scale.Assign(info.eyebrow_scale);
|
||||||
|
bf.eyebrow_aspect.Assign(info.eyebrow_aspect);
|
||||||
|
bf.eyebrow_rotate.Assign(info.eyebrow_rotate);
|
||||||
|
bf.eyebrow_x.Assign(info.eyebrow_x);
|
||||||
|
bf.eyebrow_y.Assign(info.eyebrow_y - 3);
|
||||||
|
bf.nose_type.Assign(info.nose_type);
|
||||||
|
bf.nose_scale.Assign(info.nose_scale);
|
||||||
|
bf.nose_y.Assign(info.nose_y);
|
||||||
|
bf.mouth_type.Assign(info.mouth_type);
|
||||||
|
bf.mouth_color.Assign(MouthColorLookup[info.mouth_color]);
|
||||||
|
bf.mouth_scale.Assign(info.mouth_scale);
|
||||||
|
bf.mouth_aspect.Assign(info.mouth_aspect);
|
||||||
|
bf.mouth_y.Assign(info.mouth_y);
|
||||||
|
bf.beard_color.Assign(HairColorLookup[info.beard_color]);
|
||||||
|
bf.beard_type.Assign(static_cast<BeardType>(info.beard_type));
|
||||||
|
bf.mustache_type.Assign(static_cast<MustacheType>(info.mustache_type));
|
||||||
|
bf.mustache_scale.Assign(info.mustache_scale);
|
||||||
|
bf.mustache_y.Assign(info.mustache_y);
|
||||||
|
bf.glasses_type.Assign(info.glasses_type);
|
||||||
|
bf.glasses_color.Assign(GlassesColorLookup[info.glasses_color]);
|
||||||
|
bf.glasses_scale.Assign(info.glasses_scale);
|
||||||
|
bf.glasses_y.Assign(info.glasses_y);
|
||||||
|
bf.mole_type.Assign(info.mole_type);
|
||||||
|
bf.mole_scale.Assign(info.mole_scale);
|
||||||
|
bf.mole_x.Assign(info.mole_x);
|
||||||
|
bf.mole_y.Assign(info.mole_y);
|
||||||
|
|
||||||
|
return {DefaultMiiName, bf, user_id};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
MiiStoreData::MiiStoreData() = default;
|
||||||
|
|
||||||
|
MiiStoreData::MiiStoreData(const MiiStoreData::Name& name, const MiiStoreBitFields& bit_fields,
|
||||||
|
const Common::UUID& user_id) {
|
||||||
|
data.name = name;
|
||||||
|
data.uuid = Common::UUID::MakeRandomRFC4122V4();
|
||||||
|
|
||||||
|
std::memcpy(data.data.data(), &bit_fields, sizeof(MiiStoreBitFields));
|
||||||
|
data_crc = GenerateCrc16(data.data.data(), sizeof(data));
|
||||||
|
device_crc = GenerateCrc16(&user_id, sizeof(Common::UUID));
|
||||||
|
}
|
||||||
|
|
||||||
|
MiiManager::MiiManager() : user_id{Service::Account::ProfileManager().GetLastOpenedUser()} {}
|
||||||
|
|
||||||
|
bool MiiManager::CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter) {
|
||||||
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto metadata_update_counter = metadata.update_counter;
|
const bool result{current_update_counter != update_counter};
|
||||||
metadata.update_counter = update_counter;
|
|
||||||
return metadata_update_counter != update_counter;
|
current_update_counter = update_counter;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MiiManager::IsFullDatabase() const {
|
bool MiiManager::IsFullDatabase() const {
|
||||||
@ -35,138 +396,306 @@ bool MiiManager::IsFullDatabase() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
|
u32 MiiManager::GetCount(SourceFlag source_flag) const {
|
||||||
u32 mii_count{};
|
std::size_t count{};
|
||||||
if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
|
|
||||||
mii_count += DefaultMiiCount;
|
|
||||||
}
|
|
||||||
if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
|
if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
|
||||||
// TODO(bunnei): We don't implement the Mii database, but when we do, update this
|
// TODO(bunnei): We don't implement the Mii database, but when we do, update this
|
||||||
|
count += 0;
|
||||||
}
|
}
|
||||||
return mii_count;
|
if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
|
||||||
|
count += DefaultMiiCount;
|
||||||
|
}
|
||||||
|
return static_cast<u32>(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MiiManager::UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
|
Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) {
|
||||||
const CharInfo& char_info, SourceFlag source_flag) {
|
|
||||||
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
||||||
return ResultNotFound;
|
return ERROR_CANNOT_FIND_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bunnei): We don't implement the Mii database, so we can't have an entry
|
// TODO(bunnei): We don't implement the Mii database, so we can't have an entry
|
||||||
return ResultNotFound;
|
return ERROR_CANNOT_FIND_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiiManager::BuildDefault(CharInfo& out_char_info, u32 index) const {
|
CharInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) {
|
||||||
StoreData store_data{};
|
return ConvertStoreDataToInfo(BuildRandomStoreData(age, gender, race, user_id));
|
||||||
store_data.BuildDefault(index);
|
|
||||||
out_char_info.SetFromStoreData(store_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiiManager::BuildBase(CharInfo& out_char_info, Gender gender) const {
|
CharInfo MiiManager::BuildBase(Gender gender) {
|
||||||
StoreData store_data{};
|
const std::size_t index = gender == Gender::Female ? 1 : 0;
|
||||||
store_data.BuildBase(gender);
|
return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::BaseMii.at(index), user_id));
|
||||||
out_char_info.SetFromStoreData(store_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiiManager::BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const {
|
CharInfo MiiManager::BuildDefault(std::size_t index) {
|
||||||
StoreData store_data{};
|
return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::DefaultMii.at(index), user_id));
|
||||||
store_data.BuildRandom(age, gender, race);
|
|
||||||
out_char_info.SetFromStoreData(store_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiiManager::ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const {
|
CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const {
|
||||||
StoreData store_data{};
|
Service::Mii::MiiManager manager;
|
||||||
mii_v3.BuildToStoreData(store_data);
|
auto mii = manager.BuildBase(Mii::Gender::Male);
|
||||||
out_char_info.SetFromStoreData(store_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MiiManager::Get(const DatabaseSessionMetadata& metadata,
|
if (!ValidateV3Info(mii_v3)) {
|
||||||
std::span<CharInfoElement> out_elements, u32& out_count,
|
return mii;
|
||||||
SourceFlag source_flag) {
|
|
||||||
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
|
||||||
return BuildDefault(out_elements, out_count, source_flag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bunnei): We don't implement the Mii database, so we can't have an entry
|
// TODO: We are ignoring a bunch of data from the mii_v3
|
||||||
|
|
||||||
// Include default Mii at the end of the list
|
mii.gender = static_cast<u8>(mii_v3.mii_information.gender);
|
||||||
return BuildDefault(out_elements, out_count, source_flag);
|
mii.favorite_color = static_cast<u8>(mii_v3.mii_information.favorite_color);
|
||||||
}
|
mii.height = mii_v3.height;
|
||||||
|
mii.build = mii_v3.build;
|
||||||
|
|
||||||
Result MiiManager::Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
|
// Copy name until string terminator
|
||||||
u32& out_count, SourceFlag source_flag) {
|
mii.name = {};
|
||||||
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
|
for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
|
||||||
return BuildDefault(out_char_info, out_count, source_flag);
|
mii.name[index] = mii_v3.mii_name[index];
|
||||||
}
|
if (mii.name[index] == 0) {
|
||||||
|
break;
|
||||||
// TODO(bunnei): We don't implement the Mii database, so we can't have an entry
|
|
||||||
|
|
||||||
// Include default Mii at the end of the list
|
|
||||||
return BuildDefault(out_char_info, out_count, source_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MiiManager::BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
|
|
||||||
SourceFlag source_flag) {
|
|
||||||
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
StoreData store_data{};
|
|
||||||
|
|
||||||
for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
|
|
||||||
if (out_elements.size() <= static_cast<std::size_t>(out_count)) {
|
|
||||||
return ResultInvalidArgumentSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store_data.BuildDefault(static_cast<u32>(index));
|
|
||||||
|
|
||||||
out_elements[out_count].source = Source::Default;
|
|
||||||
out_elements[out_count].char_info.SetFromStoreData(store_data);
|
|
||||||
out_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess;
|
mii.font_region = mii_v3.region_information.character_set;
|
||||||
|
|
||||||
|
mii.faceline_type = mii_v3.appearance_bits1.face_shape;
|
||||||
|
mii.faceline_color = mii_v3.appearance_bits1.skin_color;
|
||||||
|
mii.faceline_wrinkle = mii_v3.appearance_bits2.wrinkles;
|
||||||
|
mii.faceline_make = mii_v3.appearance_bits2.makeup;
|
||||||
|
|
||||||
|
mii.hair_type = mii_v3.hair_style;
|
||||||
|
mii.hair_color = mii_v3.appearance_bits3.hair_color;
|
||||||
|
mii.hair_flip = mii_v3.appearance_bits3.flip_hair;
|
||||||
|
|
||||||
|
mii.eye_type = static_cast<u8>(mii_v3.appearance_bits4.eye_type);
|
||||||
|
mii.eye_color = static_cast<u8>(mii_v3.appearance_bits4.eye_color);
|
||||||
|
mii.eye_scale = static_cast<u8>(mii_v3.appearance_bits4.eye_scale);
|
||||||
|
mii.eye_aspect = static_cast<u8>(mii_v3.appearance_bits4.eye_vertical_stretch);
|
||||||
|
mii.eye_rotate = static_cast<u8>(mii_v3.appearance_bits4.eye_rotation);
|
||||||
|
mii.eye_x = static_cast<u8>(mii_v3.appearance_bits4.eye_spacing);
|
||||||
|
mii.eye_y = static_cast<u8>(mii_v3.appearance_bits4.eye_y_position);
|
||||||
|
|
||||||
|
mii.eyebrow_type = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_style);
|
||||||
|
mii.eyebrow_color = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_color);
|
||||||
|
mii.eyebrow_scale = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_scale);
|
||||||
|
mii.eyebrow_aspect = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_yscale);
|
||||||
|
mii.eyebrow_rotate = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_rotation);
|
||||||
|
mii.eyebrow_x = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_spacing);
|
||||||
|
mii.eyebrow_y = static_cast<u8>(mii_v3.appearance_bits5.eyebrow_y_position);
|
||||||
|
|
||||||
|
mii.nose_type = static_cast<u8>(mii_v3.appearance_bits6.nose_type);
|
||||||
|
mii.nose_scale = static_cast<u8>(mii_v3.appearance_bits6.nose_scale);
|
||||||
|
mii.nose_y = static_cast<u8>(mii_v3.appearance_bits6.nose_y_position);
|
||||||
|
|
||||||
|
mii.mouth_type = static_cast<u8>(mii_v3.appearance_bits7.mouth_type);
|
||||||
|
mii.mouth_color = static_cast<u8>(mii_v3.appearance_bits7.mouth_color);
|
||||||
|
mii.mouth_scale = static_cast<u8>(mii_v3.appearance_bits7.mouth_scale);
|
||||||
|
mii.mouth_aspect = static_cast<u8>(mii_v3.appearance_bits7.mouth_horizontal_stretch);
|
||||||
|
mii.mouth_y = static_cast<u8>(mii_v3.appearance_bits8.mouth_y_position);
|
||||||
|
|
||||||
|
mii.mustache_type = static_cast<u8>(mii_v3.appearance_bits8.mustache_type);
|
||||||
|
mii.mustache_scale = static_cast<u8>(mii_v3.appearance_bits9.mustache_scale);
|
||||||
|
mii.mustache_y = static_cast<u8>(mii_v3.appearance_bits9.mustache_y_position);
|
||||||
|
|
||||||
|
mii.beard_type = static_cast<u8>(mii_v3.appearance_bits9.bear_type);
|
||||||
|
mii.beard_color = static_cast<u8>(mii_v3.appearance_bits9.facial_hair_color);
|
||||||
|
|
||||||
|
mii.glasses_type = static_cast<u8>(mii_v3.appearance_bits10.glasses_type);
|
||||||
|
mii.glasses_color = static_cast<u8>(mii_v3.appearance_bits10.glasses_color);
|
||||||
|
mii.glasses_scale = static_cast<u8>(mii_v3.appearance_bits10.glasses_scale);
|
||||||
|
mii.glasses_y = static_cast<u8>(mii_v3.appearance_bits10.glasses_y_position);
|
||||||
|
|
||||||
|
mii.mole_type = static_cast<u8>(mii_v3.appearance_bits11.mole_enabled);
|
||||||
|
mii.mole_scale = static_cast<u8>(mii_v3.appearance_bits11.mole_scale);
|
||||||
|
mii.mole_x = static_cast<u8>(mii_v3.appearance_bits11.mole_x_position);
|
||||||
|
mii.mole_y = static_cast<u8>(mii_v3.appearance_bits11.mole_y_position);
|
||||||
|
|
||||||
|
// TODO: Validate mii data
|
||||||
|
|
||||||
|
return mii;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MiiManager::BuildDefault(std::span<CharInfo> out_char_info, u32& out_count,
|
Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const {
|
||||||
SourceFlag source_flag) {
|
Service::Mii::MiiManager manager;
|
||||||
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
|
Ver3StoreData mii_v3{};
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
StoreData store_data{};
|
// TODO: We are ignoring a bunch of data from the mii_v3
|
||||||
|
|
||||||
for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
|
mii_v3.version = 1;
|
||||||
if (out_char_info.size() <= static_cast<std::size_t>(out_count)) {
|
mii_v3.mii_information.gender.Assign(mii.gender);
|
||||||
return ResultInvalidArgumentSize;
|
mii_v3.mii_information.favorite_color.Assign(mii.favorite_color);
|
||||||
|
mii_v3.height = mii.height;
|
||||||
|
mii_v3.build = mii.build;
|
||||||
|
|
||||||
|
// Copy name until string terminator
|
||||||
|
mii_v3.mii_name = {};
|
||||||
|
for (std::size_t index = 0; index < mii.name.size() - 1; index++) {
|
||||||
|
mii_v3.mii_name[index] = mii.name[index];
|
||||||
|
if (mii_v3.mii_name[index] == 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
store_data.BuildDefault(static_cast<u32>(index));
|
|
||||||
|
|
||||||
out_char_info[out_count].SetFromStoreData(store_data);
|
|
||||||
out_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess;
|
mii_v3.region_information.character_set.Assign(mii.font_region);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type);
|
||||||
|
mii_v3.appearance_bits2.wrinkles.Assign(mii.faceline_wrinkle);
|
||||||
|
mii_v3.appearance_bits2.makeup.Assign(mii.faceline_make);
|
||||||
|
|
||||||
|
mii_v3.hair_style = mii.hair_type;
|
||||||
|
mii_v3.appearance_bits3.flip_hair.Assign(mii.hair_flip);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits4.eye_type.Assign(mii.eye_type);
|
||||||
|
mii_v3.appearance_bits4.eye_scale.Assign(mii.eye_scale);
|
||||||
|
mii_v3.appearance_bits4.eye_vertical_stretch.Assign(mii.eye_aspect);
|
||||||
|
mii_v3.appearance_bits4.eye_rotation.Assign(mii.eye_rotate);
|
||||||
|
mii_v3.appearance_bits4.eye_spacing.Assign(mii.eye_x);
|
||||||
|
mii_v3.appearance_bits4.eye_y_position.Assign(mii.eye_y);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits5.eyebrow_style.Assign(mii.eyebrow_type);
|
||||||
|
mii_v3.appearance_bits5.eyebrow_scale.Assign(mii.eyebrow_scale);
|
||||||
|
mii_v3.appearance_bits5.eyebrow_yscale.Assign(mii.eyebrow_aspect);
|
||||||
|
mii_v3.appearance_bits5.eyebrow_rotation.Assign(mii.eyebrow_rotate);
|
||||||
|
mii_v3.appearance_bits5.eyebrow_spacing.Assign(mii.eyebrow_x);
|
||||||
|
mii_v3.appearance_bits5.eyebrow_y_position.Assign(mii.eyebrow_y);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits6.nose_type.Assign(mii.nose_type);
|
||||||
|
mii_v3.appearance_bits6.nose_scale.Assign(mii.nose_scale);
|
||||||
|
mii_v3.appearance_bits6.nose_y_position.Assign(mii.nose_y);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits7.mouth_type.Assign(mii.mouth_type);
|
||||||
|
mii_v3.appearance_bits7.mouth_scale.Assign(mii.mouth_scale);
|
||||||
|
mii_v3.appearance_bits7.mouth_horizontal_stretch.Assign(mii.mouth_aspect);
|
||||||
|
mii_v3.appearance_bits8.mouth_y_position.Assign(mii.mouth_y);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits8.mustache_type.Assign(mii.mustache_type);
|
||||||
|
mii_v3.appearance_bits9.mustache_scale.Assign(mii.mustache_scale);
|
||||||
|
mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale);
|
||||||
|
mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y);
|
||||||
|
|
||||||
|
mii_v3.appearance_bits11.mole_enabled.Assign(mii.mole_type);
|
||||||
|
mii_v3.appearance_bits11.mole_scale.Assign(mii.mole_scale);
|
||||||
|
mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x);
|
||||||
|
mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y);
|
||||||
|
|
||||||
|
// These types are converted to V3 from a table
|
||||||
|
mii_v3.appearance_bits1.skin_color.Assign(Ver3FacelineColorTable[mii.faceline_color]);
|
||||||
|
mii_v3.appearance_bits3.hair_color.Assign(Ver3HairColorTable[mii.hair_color]);
|
||||||
|
mii_v3.appearance_bits4.eye_color.Assign(Ver3EyeColorTable[mii.eye_color]);
|
||||||
|
mii_v3.appearance_bits5.eyebrow_color.Assign(Ver3HairColorTable[mii.eyebrow_color]);
|
||||||
|
mii_v3.appearance_bits7.mouth_color.Assign(Ver3MouthlineColorTable[mii.mouth_color]);
|
||||||
|
mii_v3.appearance_bits9.facial_hair_color.Assign(Ver3HairColorTable[mii.beard_color]);
|
||||||
|
mii_v3.appearance_bits10.glasses_color.Assign(Ver3GlassColorTable[mii.glasses_color]);
|
||||||
|
mii_v3.appearance_bits10.glasses_type.Assign(Ver3GlassTypeTable[mii.glasses_type]);
|
||||||
|
|
||||||
|
mii_v3.crc = GenerateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16));
|
||||||
|
|
||||||
|
// TODO: Validate mii_v3 data
|
||||||
|
|
||||||
|
return mii_v3;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
|
NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const {
|
||||||
s32& out_index) {
|
return {
|
||||||
|
.faceline_color = static_cast<u8>(mii.faceline_color & 0xf),
|
||||||
|
.hair_color = static_cast<u8>(mii.hair_color & 0x7f),
|
||||||
|
.eye_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
|
||||||
|
.eyebrow_color = static_cast<u8>(mii.eyebrow_color & 0x7f),
|
||||||
|
.mouth_color = static_cast<u8>(mii.mouth_color & 0x7f),
|
||||||
|
.beard_color = static_cast<u8>(mii.beard_color & 0x7f),
|
||||||
|
.glass_color = static_cast<u8>(mii.glasses_color & 0x7f),
|
||||||
|
.glass_type = static_cast<u8>(mii.glasses_type & 0x1f),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (char_info.Verify() != ValidationResult::NoErrors) {
|
bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
|
||||||
return ResultInvalidCharInfo;
|
bool is_valid = mii_v3.version == 0 || mii_v3.version == 3;
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.mii_name[0] != 0);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.mii_information.birth_month < 13);
|
||||||
|
is_valid = is_valid && (mii_v3.mii_information.birth_day < 32);
|
||||||
|
is_valid = is_valid && (mii_v3.mii_information.favorite_color < 12);
|
||||||
|
is_valid = is_valid && (mii_v3.height < 128);
|
||||||
|
is_valid = is_valid && (mii_v3.build < 128);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits1.face_shape < 12);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits1.skin_color < 7);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits2.wrinkles < 12);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits2.makeup < 12);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.hair_style < 132);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits3.hair_color < 8);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits4.eye_type < 60);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits4.eye_color < 6);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits4.eye_scale < 8);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits4.eye_vertical_stretch < 7);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits4.eye_rotation < 8);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits4.eye_spacing < 13);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits4.eye_y_position < 19);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_style < 25);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_color < 8);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_scale < 9);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_yscale < 7);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_rotation < 12);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_spacing < 12);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits5.eyebrow_y_position < 19);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits6.nose_type < 18);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits6.nose_scale < 9);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits6.nose_y_position < 19);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits7.mouth_type < 36);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits7.mouth_color < 5);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits7.mouth_scale < 9);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits7.mouth_horizontal_stretch < 7);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits8.mouth_y_position < 19);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits8.mustache_type < 6);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits9.mustache_scale < 7);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits9.mustache_y_position < 17);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits9.bear_type < 6);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits9.facial_hair_color < 8);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits10.glasses_type < 9);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits10.glasses_color < 6);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits10.glasses_scale < 8);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits10.glasses_y_position < 21);
|
||||||
|
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits11.mole_enabled < 2);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits11.mole_scale < 9);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits11.mole_x_position < 17);
|
||||||
|
is_valid = is_valid && (mii_v3.appearance_bits11.mole_y_position < 31);
|
||||||
|
|
||||||
|
return is_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) {
|
||||||
|
std::vector<MiiInfoElement> result;
|
||||||
|
|
||||||
|
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (std::size_t index = 0; index < DefaultMiiCount; index++) {
|
||||||
|
result.emplace_back(BuildDefault(index), Source::Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result MiiManager::GetIndex([[maybe_unused]] const CharInfo& info, u32& index) {
|
||||||
constexpr u32 INVALID_INDEX{0xFFFFFFFF};
|
constexpr u32 INVALID_INDEX{0xFFFFFFFF};
|
||||||
|
|
||||||
out_index = INVALID_INDEX;
|
index = INVALID_INDEX;
|
||||||
|
|
||||||
// TODO(bunnei): We don't implement the Mii database, so we can't have an index
|
// TODO(bunnei): We don't implement the Mii database, so we can't have an index
|
||||||
return ResultNotFound;
|
return ERROR_CANNOT_FIND_ENTRY;
|
||||||
}
|
|
||||||
|
|
||||||
void MiiManager::SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version) {
|
|
||||||
metadata.interface_version = version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::Mii
|
} // namespace Service::Mii
|
||||||
|
@ -6,10 +6,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/mii/mii_types.h"
|
#include "core/hle/service/mii/types.h"
|
||||||
#include "core/hle/service/mii/types/char_info.h"
|
|
||||||
#include "core/hle/service/mii/types/store_data.h"
|
|
||||||
#include "core/hle/service/mii/types/ver3_store_data.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
namespace Service::Mii {
|
||||||
|
|
||||||
@ -19,30 +16,26 @@ class MiiManager {
|
|||||||
public:
|
public:
|
||||||
MiiManager();
|
MiiManager();
|
||||||
|
|
||||||
bool IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
|
bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
|
||||||
|
|
||||||
bool IsFullDatabase() const;
|
bool IsFullDatabase() const;
|
||||||
u32 GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
|
u32 GetCount(SourceFlag source_flag) const;
|
||||||
Result UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
|
Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag);
|
||||||
const CharInfo& char_info, SourceFlag source_flag);
|
CharInfo BuildRandom(Age age, Gender gender, Race race);
|
||||||
Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfoElement> out_elements,
|
CharInfo BuildBase(Gender gender);
|
||||||
u32& out_count, SourceFlag source_flag);
|
CharInfo BuildDefault(std::size_t index);
|
||||||
Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
|
CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
|
||||||
u32& out_count, SourceFlag source_flag);
|
bool ValidateV3Info(const Ver3StoreData& mii_v3) const;
|
||||||
void BuildDefault(CharInfo& out_char_info, u32 index) const;
|
std::vector<MiiInfoElement> GetDefault(SourceFlag source_flag);
|
||||||
void BuildBase(CharInfo& out_char_info, Gender gender) const;
|
Result GetIndex(const CharInfo& info, u32& index);
|
||||||
void BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const;
|
|
||||||
void ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const;
|
// This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData
|
||||||
std::vector<CharInfoElement> GetDefault(SourceFlag source_flag);
|
Ver3StoreData BuildFromStoreData(const CharInfo& mii) const;
|
||||||
Result GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
|
|
||||||
s32& out_index);
|
// This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData
|
||||||
void SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version);
|
NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
|
const Common::UUID user_id{};
|
||||||
SourceFlag source_flag);
|
|
||||||
Result BuildDefault(std::span<CharInfo> out_char_info, u32& out_count, SourceFlag source_flag);
|
|
||||||
|
|
||||||
u64 update_counter{};
|
u64 update_counter{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/result.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
constexpr Result ResultInvalidArgument{ErrorModule::Mii, 1};
|
|
||||||
constexpr Result ResultInvalidArgumentSize{ErrorModule::Mii, 2};
|
|
||||||
constexpr Result ResultNotUpdated{ErrorModule::Mii, 3};
|
|
||||||
constexpr Result ResultNotFound{ErrorModule::Mii, 4};
|
|
||||||
constexpr Result ResultDatabaseFull{ErrorModule::Mii, 5};
|
|
||||||
constexpr Result ResultInvalidCharInfo{ErrorModule::Mii, 100};
|
|
||||||
constexpr Result ResultInvalidStoreData{ErrorModule::Mii, 109};
|
|
||||||
constexpr Result ResultInvalidOperation{ErrorModule::Mii, 202};
|
|
||||||
constexpr Result ResultPermissionDenied{ErrorModule::Mii, 203};
|
|
||||||
|
|
||||||
}; // namespace Service::Mii
|
|
@ -1,694 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "common/bit_field.h"
|
|
||||||
#include "common/common_funcs.h"
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "common/uuid.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
constexpr u8 MaxHeight = 127;
|
|
||||||
constexpr u8 MaxBuild = 127;
|
|
||||||
constexpr u8 MaxType = 1;
|
|
||||||
constexpr u8 MaxRegionMove = 3;
|
|
||||||
constexpr u8 MaxEyeScale = 7;
|
|
||||||
constexpr u8 MaxEyeAspect = 6;
|
|
||||||
constexpr u8 MaxEyeRotate = 7;
|
|
||||||
constexpr u8 MaxEyeX = 12;
|
|
||||||
constexpr u8 MaxEyeY = 18;
|
|
||||||
constexpr u8 MaxEyebrowScale = 8;
|
|
||||||
constexpr u8 MaxEyebrowAspect = 6;
|
|
||||||
constexpr u8 MaxEyebrowRotate = 11;
|
|
||||||
constexpr u8 MaxEyebrowX = 12;
|
|
||||||
constexpr u8 MaxEyebrowY = 18;
|
|
||||||
constexpr u8 MaxNoseScale = 8;
|
|
||||||
constexpr u8 MaxNoseY = 18;
|
|
||||||
constexpr u8 MaxMouthScale = 8;
|
|
||||||
constexpr u8 MaxMoutAspect = 6;
|
|
||||||
constexpr u8 MaxMouthY = 18;
|
|
||||||
constexpr u8 MaxMustacheScale = 8;
|
|
||||||
constexpr u8 MasMustacheY = 16;
|
|
||||||
constexpr u8 MaxGlassScale = 7;
|
|
||||||
constexpr u8 MaxGlassY = 20;
|
|
||||||
constexpr u8 MaxMoleScale = 8;
|
|
||||||
constexpr u8 MaxMoleX = 16;
|
|
||||||
constexpr u8 MaxMoleY = 30;
|
|
||||||
constexpr u8 MaxVer3CommonColor = 7;
|
|
||||||
constexpr u8 MaxVer3GlassType = 8;
|
|
||||||
|
|
||||||
enum class Age : u8 {
|
|
||||||
Young,
|
|
||||||
Normal,
|
|
||||||
Old,
|
|
||||||
All, // Default
|
|
||||||
|
|
||||||
Max = All,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Gender : u8 {
|
|
||||||
Male,
|
|
||||||
Female,
|
|
||||||
All, // Default
|
|
||||||
|
|
||||||
Max = Female,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Race : u8 {
|
|
||||||
Black,
|
|
||||||
White,
|
|
||||||
Asian,
|
|
||||||
All, // Default
|
|
||||||
|
|
||||||
Max = All,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class HairType : u8 {
|
|
||||||
NormalLong, // Default
|
|
||||||
NormalShort,
|
|
||||||
NormalMedium,
|
|
||||||
NormalExtraLong,
|
|
||||||
NormalLongBottom,
|
|
||||||
NormalTwoPeaks,
|
|
||||||
PartingLong,
|
|
||||||
FrontLock,
|
|
||||||
PartingShort,
|
|
||||||
PartingExtraLongCurved,
|
|
||||||
PartingExtraLong,
|
|
||||||
PartingMiddleLong,
|
|
||||||
PartingSquared,
|
|
||||||
PartingLongBottom,
|
|
||||||
PeaksTop,
|
|
||||||
PeaksSquared,
|
|
||||||
PartingPeaks,
|
|
||||||
PeaksLongBottom,
|
|
||||||
Peaks,
|
|
||||||
PeaksRounded,
|
|
||||||
PeaksSide,
|
|
||||||
PeaksMedium,
|
|
||||||
PeaksLong,
|
|
||||||
PeaksRoundedLong,
|
|
||||||
PartingFrontPeaks,
|
|
||||||
PartingLongFront,
|
|
||||||
PartingLongRounded,
|
|
||||||
PartingFrontPeaksLong,
|
|
||||||
PartingExtraLongRounded,
|
|
||||||
LongRounded,
|
|
||||||
NormalUnknown1,
|
|
||||||
NormalUnknown2,
|
|
||||||
NormalUnknown3,
|
|
||||||
NormalUnknown4,
|
|
||||||
NormalUnknown5,
|
|
||||||
NormalUnknown6,
|
|
||||||
DreadLocks,
|
|
||||||
PlatedMats,
|
|
||||||
Caps,
|
|
||||||
Afro,
|
|
||||||
PlatedMatsLong,
|
|
||||||
Beanie,
|
|
||||||
Short,
|
|
||||||
ShortTopLongSide,
|
|
||||||
ShortUnknown1,
|
|
||||||
ShortUnknown2,
|
|
||||||
MilitaryParting,
|
|
||||||
Military,
|
|
||||||
ShortUnknown3,
|
|
||||||
ShortUnknown4,
|
|
||||||
ShortUnknown5,
|
|
||||||
ShortUnknown6,
|
|
||||||
NoneTop,
|
|
||||||
None,
|
|
||||||
LongUnknown1,
|
|
||||||
LongUnknown2,
|
|
||||||
LongUnknown3,
|
|
||||||
LongUnknown4,
|
|
||||||
LongUnknown5,
|
|
||||||
LongUnknown6,
|
|
||||||
LongUnknown7,
|
|
||||||
LongUnknown8,
|
|
||||||
LongUnknown9,
|
|
||||||
LongUnknown10,
|
|
||||||
LongUnknown11,
|
|
||||||
LongUnknown12,
|
|
||||||
LongUnknown13,
|
|
||||||
LongUnknown14,
|
|
||||||
LongUnknown15,
|
|
||||||
LongUnknown16,
|
|
||||||
LongUnknown17,
|
|
||||||
LongUnknown18,
|
|
||||||
LongUnknown19,
|
|
||||||
LongUnknown20,
|
|
||||||
LongUnknown21,
|
|
||||||
LongUnknown22,
|
|
||||||
LongUnknown23,
|
|
||||||
LongUnknown24,
|
|
||||||
LongUnknown25,
|
|
||||||
LongUnknown26,
|
|
||||||
LongUnknown27,
|
|
||||||
LongUnknown28,
|
|
||||||
LongUnknown29,
|
|
||||||
LongUnknown30,
|
|
||||||
LongUnknown31,
|
|
||||||
LongUnknown32,
|
|
||||||
LongUnknown33,
|
|
||||||
LongUnknown34,
|
|
||||||
LongUnknown35,
|
|
||||||
LongUnknown36,
|
|
||||||
LongUnknown37,
|
|
||||||
LongUnknown38,
|
|
||||||
LongUnknown39,
|
|
||||||
LongUnknown40,
|
|
||||||
LongUnknown41,
|
|
||||||
LongUnknown42,
|
|
||||||
LongUnknown43,
|
|
||||||
LongUnknown44,
|
|
||||||
LongUnknown45,
|
|
||||||
LongUnknown46,
|
|
||||||
LongUnknown47,
|
|
||||||
LongUnknown48,
|
|
||||||
LongUnknown49,
|
|
||||||
LongUnknown50,
|
|
||||||
LongUnknown51,
|
|
||||||
LongUnknown52,
|
|
||||||
LongUnknown53,
|
|
||||||
LongUnknown54,
|
|
||||||
LongUnknown55,
|
|
||||||
LongUnknown56,
|
|
||||||
LongUnknown57,
|
|
||||||
LongUnknown58,
|
|
||||||
LongUnknown59,
|
|
||||||
LongUnknown60,
|
|
||||||
LongUnknown61,
|
|
||||||
LongUnknown62,
|
|
||||||
LongUnknown63,
|
|
||||||
LongUnknown64,
|
|
||||||
LongUnknown65,
|
|
||||||
LongUnknown66,
|
|
||||||
TwoMediumFrontStrandsOneLongBackPonyTail,
|
|
||||||
TwoFrontStrandsLongBackPonyTail,
|
|
||||||
PartingFrontTwoLongBackPonyTails,
|
|
||||||
TwoFrontStrandsOneLongBackPonyTail,
|
|
||||||
LongBackPonyTail,
|
|
||||||
LongFrontTwoLongBackPonyTails,
|
|
||||||
StrandsTwoShortSidedPonyTails,
|
|
||||||
TwoMediumSidedPonyTails,
|
|
||||||
ShortFrontTwoBackPonyTails,
|
|
||||||
TwoShortSidedPonyTails,
|
|
||||||
TwoLongSidedPonyTails,
|
|
||||||
LongFrontTwoBackPonyTails,
|
|
||||||
|
|
||||||
Max = LongFrontTwoBackPonyTails,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MoleType : u8 {
|
|
||||||
None, // Default
|
|
||||||
OneDot,
|
|
||||||
|
|
||||||
Max = OneDot,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class HairFlip : u8 {
|
|
||||||
Left, // Default
|
|
||||||
Right,
|
|
||||||
|
|
||||||
Max = Right,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CommonColor : u8 {
|
|
||||||
// For simplicity common colors aren't listed
|
|
||||||
Max = 99,
|
|
||||||
Count = 100,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FavoriteColor : u8 {
|
|
||||||
Red, // Default
|
|
||||||
Orange,
|
|
||||||
Yellow,
|
|
||||||
LimeGreen,
|
|
||||||
Green,
|
|
||||||
Blue,
|
|
||||||
LightBlue,
|
|
||||||
Pink,
|
|
||||||
Purple,
|
|
||||||
Brown,
|
|
||||||
White,
|
|
||||||
Black,
|
|
||||||
|
|
||||||
Max = Black,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class EyeType : u8 {
|
|
||||||
Normal, // Default
|
|
||||||
NormalLash,
|
|
||||||
WhiteLash,
|
|
||||||
WhiteNoBottom,
|
|
||||||
OvalAngledWhite,
|
|
||||||
AngryWhite,
|
|
||||||
DotLashType1,
|
|
||||||
Line,
|
|
||||||
DotLine,
|
|
||||||
OvalWhite,
|
|
||||||
RoundedWhite,
|
|
||||||
NormalShadow,
|
|
||||||
CircleWhite,
|
|
||||||
Circle,
|
|
||||||
CircleWhiteStroke,
|
|
||||||
NormalOvalNoBottom,
|
|
||||||
NormalOvalLarge,
|
|
||||||
NormalRoundedNoBottom,
|
|
||||||
SmallLash,
|
|
||||||
Small,
|
|
||||||
TwoSmall,
|
|
||||||
NormalLongLash,
|
|
||||||
WhiteTwoLashes,
|
|
||||||
WhiteThreeLashes,
|
|
||||||
DotAngry,
|
|
||||||
DotAngled,
|
|
||||||
Oval,
|
|
||||||
SmallWhite,
|
|
||||||
WhiteAngledNoBottom,
|
|
||||||
WhiteAngledNoLeft,
|
|
||||||
SmallWhiteTwoLashes,
|
|
||||||
LeafWhiteLash,
|
|
||||||
WhiteLargeNoBottom,
|
|
||||||
Dot,
|
|
||||||
DotLashType2,
|
|
||||||
DotThreeLashes,
|
|
||||||
WhiteOvalTop,
|
|
||||||
WhiteOvalBottom,
|
|
||||||
WhiteOvalBottomFlat,
|
|
||||||
WhiteOvalTwoLashes,
|
|
||||||
WhiteOvalThreeLashes,
|
|
||||||
WhiteOvalNoBottomTwoLashes,
|
|
||||||
DotWhite,
|
|
||||||
WhiteOvalTopFlat,
|
|
||||||
WhiteThinLeaf,
|
|
||||||
StarThreeLashes,
|
|
||||||
LineTwoLashes,
|
|
||||||
CrowsFeet,
|
|
||||||
WhiteNoBottomFlat,
|
|
||||||
WhiteNoBottomRounded,
|
|
||||||
WhiteSmallBottomLine,
|
|
||||||
WhiteNoBottomLash,
|
|
||||||
WhiteNoPartialBottomLash,
|
|
||||||
WhiteOvalBottomLine,
|
|
||||||
WhiteNoBottomLashTopLine,
|
|
||||||
WhiteNoPartialBottomTwoLashes,
|
|
||||||
NormalTopLine,
|
|
||||||
WhiteOvalLash,
|
|
||||||
RoundTired,
|
|
||||||
WhiteLarge,
|
|
||||||
|
|
||||||
Max = WhiteLarge,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MouthType : u8 {
|
|
||||||
Neutral, // Default
|
|
||||||
NeutralLips,
|
|
||||||
Smile,
|
|
||||||
SmileStroke,
|
|
||||||
SmileTeeth,
|
|
||||||
LipsSmall,
|
|
||||||
LipsLarge,
|
|
||||||
Wave,
|
|
||||||
WaveAngrySmall,
|
|
||||||
NeutralStrokeLarge,
|
|
||||||
TeethSurprised,
|
|
||||||
LipsExtraLarge,
|
|
||||||
LipsUp,
|
|
||||||
NeutralDown,
|
|
||||||
Surprised,
|
|
||||||
TeethMiddle,
|
|
||||||
NeutralStroke,
|
|
||||||
LipsExtraSmall,
|
|
||||||
Malicious,
|
|
||||||
LipsDual,
|
|
||||||
NeutralComma,
|
|
||||||
NeutralUp,
|
|
||||||
TeethLarge,
|
|
||||||
WaveAngry,
|
|
||||||
LipsSexy,
|
|
||||||
SmileInverted,
|
|
||||||
LipsSexyOutline,
|
|
||||||
SmileRounded,
|
|
||||||
LipsTeeth,
|
|
||||||
NeutralOpen,
|
|
||||||
TeethRounded,
|
|
||||||
WaveAngrySmallInverted,
|
|
||||||
NeutralCommaInverted,
|
|
||||||
TeethFull,
|
|
||||||
SmileDownLine,
|
|
||||||
Kiss,
|
|
||||||
|
|
||||||
Max = Kiss,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FontRegion : u8 {
|
|
||||||
Standard, // Default
|
|
||||||
China,
|
|
||||||
Korea,
|
|
||||||
Taiwan,
|
|
||||||
|
|
||||||
Max = Taiwan,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FacelineType : u8 {
|
|
||||||
Sharp, // Default
|
|
||||||
Rounded,
|
|
||||||
SharpRounded,
|
|
||||||
SharpRoundedSmall,
|
|
||||||
Large,
|
|
||||||
LargeRounded,
|
|
||||||
SharpSmall,
|
|
||||||
Flat,
|
|
||||||
Bump,
|
|
||||||
Angular,
|
|
||||||
FlatRounded,
|
|
||||||
AngularSmall,
|
|
||||||
|
|
||||||
Max = AngularSmall,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FacelineColor : u8 {
|
|
||||||
Beige, // Default
|
|
||||||
WarmBeige,
|
|
||||||
Natural,
|
|
||||||
Honey,
|
|
||||||
Chestnut,
|
|
||||||
Porcelain,
|
|
||||||
Ivory,
|
|
||||||
WarmIvory,
|
|
||||||
Almond,
|
|
||||||
Espresso,
|
|
||||||
|
|
||||||
Max = Espresso,
|
|
||||||
Count = Max + 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FacelineWrinkle : u8 {
|
|
||||||
None, // Default
|
|
||||||
TearTroughs,
|
|
||||||
FacialPain,
|
|
||||||
Cheeks,
|
|
||||||
Folds,
|
|
||||||
UnderTheEyes,
|
|
||||||
SplitChin,
|
|
||||||
Chin,
|
|
||||||
BrowDroop,
|
|
||||||
MouthFrown,
|
|
||||||
CrowsFeet,
|
|
||||||
FoldsCrowsFrown,
|
|
||||||
|
|
||||||
Max = FoldsCrowsFrown,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FacelineMake : u8 {
|
|
||||||
None, // Default
|
|
||||||
CheekPorcelain,
|
|
||||||
CheekNatural,
|
|
||||||
EyeShadowBlue,
|
|
||||||
CheekBlushPorcelain,
|
|
||||||
CheekBlushNatural,
|
|
||||||
CheekPorcelainEyeShadowBlue,
|
|
||||||
CheekPorcelainEyeShadowNatural,
|
|
||||||
CheekBlushPorcelainEyeShadowEspresso,
|
|
||||||
Freckles,
|
|
||||||
LionsManeBeard,
|
|
||||||
StubbleBeard,
|
|
||||||
|
|
||||||
Max = StubbleBeard,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class EyebrowType : u8 {
|
|
||||||
FlatAngledLarge, // Default
|
|
||||||
LowArchRoundedThin,
|
|
||||||
SoftAngledLarge,
|
|
||||||
MediumArchRoundedThin,
|
|
||||||
RoundedMedium,
|
|
||||||
LowArchMedium,
|
|
||||||
RoundedThin,
|
|
||||||
UpThin,
|
|
||||||
MediumArchRoundedMedium,
|
|
||||||
RoundedLarge,
|
|
||||||
UpLarge,
|
|
||||||
FlatAngledLargeInverted,
|
|
||||||
MediumArchFlat,
|
|
||||||
AngledThin,
|
|
||||||
HorizontalLarge,
|
|
||||||
HighArchFlat,
|
|
||||||
Flat,
|
|
||||||
MediumArchLarge,
|
|
||||||
LowArchThin,
|
|
||||||
RoundedThinInverted,
|
|
||||||
HighArchLarge,
|
|
||||||
Hairy,
|
|
||||||
Dotted,
|
|
||||||
None,
|
|
||||||
|
|
||||||
Max = None,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class NoseType : u8 {
|
|
||||||
Normal, // Default
|
|
||||||
Rounded,
|
|
||||||
Dot,
|
|
||||||
Arrow,
|
|
||||||
Roman,
|
|
||||||
Triangle,
|
|
||||||
Button,
|
|
||||||
RoundedInverted,
|
|
||||||
Potato,
|
|
||||||
Grecian,
|
|
||||||
Snub,
|
|
||||||
Aquiline,
|
|
||||||
ArrowLeft,
|
|
||||||
RoundedLarge,
|
|
||||||
Hooked,
|
|
||||||
Fat,
|
|
||||||
Droopy,
|
|
||||||
ArrowLarge,
|
|
||||||
|
|
||||||
Max = ArrowLarge,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BeardType : u8 {
|
|
||||||
None,
|
|
||||||
Goatee,
|
|
||||||
GoateeLong,
|
|
||||||
LionsManeLong,
|
|
||||||
LionsMane,
|
|
||||||
Full,
|
|
||||||
|
|
||||||
Min = Goatee,
|
|
||||||
Max = Full,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MustacheType : u8 {
|
|
||||||
None,
|
|
||||||
Walrus,
|
|
||||||
Pencil,
|
|
||||||
Horseshoe,
|
|
||||||
Normal,
|
|
||||||
Toothbrush,
|
|
||||||
|
|
||||||
Min = Walrus,
|
|
||||||
Max = Toothbrush,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class GlassType : u8 {
|
|
||||||
None,
|
|
||||||
Oval,
|
|
||||||
Wayfarer,
|
|
||||||
Rectangle,
|
|
||||||
TopRimless,
|
|
||||||
Rounded,
|
|
||||||
Oversized,
|
|
||||||
CatEye,
|
|
||||||
Square,
|
|
||||||
BottomRimless,
|
|
||||||
SemiOpaqueRounded,
|
|
||||||
SemiOpaqueCatEye,
|
|
||||||
SemiOpaqueOval,
|
|
||||||
SemiOpaqueRectangle,
|
|
||||||
SemiOpaqueAviator,
|
|
||||||
OpaqueRounded,
|
|
||||||
OpaqueCatEye,
|
|
||||||
OpaqueOval,
|
|
||||||
OpaqueRectangle,
|
|
||||||
OpaqueAviator,
|
|
||||||
|
|
||||||
Max = OpaqueAviator,
|
|
||||||
Count = Max + 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BeardAndMustacheFlag : u32 {
|
|
||||||
Beard = 1,
|
|
||||||
Mustache,
|
|
||||||
All = Beard | Mustache,
|
|
||||||
};
|
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
|
|
||||||
|
|
||||||
enum class Source : u32 {
|
|
||||||
Database = 0,
|
|
||||||
Default = 1,
|
|
||||||
Account = 2,
|
|
||||||
Friend = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SourceFlag : u32 {
|
|
||||||
None = 0,
|
|
||||||
Database = 1 << 0,
|
|
||||||
Default = 1 << 1,
|
|
||||||
};
|
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
|
|
||||||
|
|
||||||
enum class ValidationResult : u32 {
|
|
||||||
NoErrors = 0x0,
|
|
||||||
InvalidBeardColor = 0x1,
|
|
||||||
InvalidBeardType = 0x2,
|
|
||||||
InvalidBuild = 0x3,
|
|
||||||
InvalidEyeAspect = 0x4,
|
|
||||||
InvalidEyeColor = 0x5,
|
|
||||||
InvalidEyeRotate = 0x6,
|
|
||||||
InvalidEyeScale = 0x7,
|
|
||||||
InvalidEyeType = 0x8,
|
|
||||||
InvalidEyeX = 0x9,
|
|
||||||
InvalidEyeY = 0xa,
|
|
||||||
InvalidEyebrowAspect = 0xb,
|
|
||||||
InvalidEyebrowColor = 0xc,
|
|
||||||
InvalidEyebrowRotate = 0xd,
|
|
||||||
InvalidEyebrowScale = 0xe,
|
|
||||||
InvalidEyebrowType = 0xf,
|
|
||||||
InvalidEyebrowX = 0x10,
|
|
||||||
InvalidEyebrowY = 0x11,
|
|
||||||
InvalidFacelineColor = 0x12,
|
|
||||||
InvalidFacelineMake = 0x13,
|
|
||||||
InvalidFacelineWrinkle = 0x14,
|
|
||||||
InvalidFacelineType = 0x15,
|
|
||||||
InvalidColor = 0x16,
|
|
||||||
InvalidFont = 0x17,
|
|
||||||
InvalidGender = 0x18,
|
|
||||||
InvalidGlassColor = 0x19,
|
|
||||||
InvalidGlassScale = 0x1a,
|
|
||||||
InvalidGlassType = 0x1b,
|
|
||||||
InvalidGlassY = 0x1c,
|
|
||||||
InvalidHairColor = 0x1d,
|
|
||||||
InvalidHairFlip = 0x1e,
|
|
||||||
InvalidHairType = 0x1f,
|
|
||||||
InvalidHeight = 0x20,
|
|
||||||
InvalidMoleScale = 0x21,
|
|
||||||
InvalidMoleType = 0x22,
|
|
||||||
InvalidMoleX = 0x23,
|
|
||||||
InvalidMoleY = 0x24,
|
|
||||||
InvalidMouthAspect = 0x25,
|
|
||||||
InvalidMouthColor = 0x26,
|
|
||||||
InvalidMouthScale = 0x27,
|
|
||||||
InvalidMouthType = 0x28,
|
|
||||||
InvalidMouthY = 0x29,
|
|
||||||
InvalidMustacheScale = 0x2a,
|
|
||||||
InvalidMustacheType = 0x2b,
|
|
||||||
InvalidMustacheY = 0x2c,
|
|
||||||
InvalidNoseScale = 0x2e,
|
|
||||||
InvalidNoseType = 0x2f,
|
|
||||||
InvalidNoseY = 0x30,
|
|
||||||
InvalidRegionMove = 0x31,
|
|
||||||
InvalidCreateId = 0x32,
|
|
||||||
InvalidName = 0x33,
|
|
||||||
InvalidType = 0x35,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Nickname {
|
|
||||||
static constexpr std::size_t MaxNameSize = 10;
|
|
||||||
std::array<char16_t, MaxNameSize> data;
|
|
||||||
|
|
||||||
// Checks for null, non-zero terminated or dirty strings
|
|
||||||
bool IsValid() const {
|
|
||||||
if (data[0] == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[MaxNameSize] != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::size_t index = 1;
|
|
||||||
while (data[index] != 0) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
while (index < MaxNameSize && data[index] == 0) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
return index == MaxNameSize;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static_assert(sizeof(Nickname) == 0x14, "Nickname is an invalid size");
|
|
||||||
|
|
||||||
struct DefaultMii {
|
|
||||||
u32 face_type{};
|
|
||||||
u32 face_color{};
|
|
||||||
u32 face_wrinkle{};
|
|
||||||
u32 face_makeup{};
|
|
||||||
u32 hair_type{};
|
|
||||||
u32 hair_color{};
|
|
||||||
u32 hair_flip{};
|
|
||||||
u32 eye_type{};
|
|
||||||
u32 eye_color{};
|
|
||||||
u32 eye_scale{};
|
|
||||||
u32 eye_aspect{};
|
|
||||||
u32 eye_rotate{};
|
|
||||||
u32 eye_x{};
|
|
||||||
u32 eye_y{};
|
|
||||||
u32 eyebrow_type{};
|
|
||||||
u32 eyebrow_color{};
|
|
||||||
u32 eyebrow_scale{};
|
|
||||||
u32 eyebrow_aspect{};
|
|
||||||
u32 eyebrow_rotate{};
|
|
||||||
u32 eyebrow_x{};
|
|
||||||
u32 eyebrow_y{};
|
|
||||||
u32 nose_type{};
|
|
||||||
u32 nose_scale{};
|
|
||||||
u32 nose_y{};
|
|
||||||
u32 mouth_type{};
|
|
||||||
u32 mouth_color{};
|
|
||||||
u32 mouth_scale{};
|
|
||||||
u32 mouth_aspect{};
|
|
||||||
u32 mouth_y{};
|
|
||||||
u32 mustache_type{};
|
|
||||||
u32 beard_type{};
|
|
||||||
u32 beard_color{};
|
|
||||||
u32 mustache_scale{};
|
|
||||||
u32 mustache_y{};
|
|
||||||
u32 glasses_type{};
|
|
||||||
u32 glasses_color{};
|
|
||||||
u32 glasses_scale{};
|
|
||||||
u32 glasses_y{};
|
|
||||||
u32 mole_type{};
|
|
||||||
u32 mole_scale{};
|
|
||||||
u32 mole_x{};
|
|
||||||
u32 mole_y{};
|
|
||||||
u32 height{};
|
|
||||||
u32 weight{};
|
|
||||||
u32 gender{};
|
|
||||||
u32 favorite_color{};
|
|
||||||
u32 region_move{};
|
|
||||||
u32 font_region{};
|
|
||||||
u32 type{};
|
|
||||||
Nickname nickname;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(DefaultMii) == 0xd8, "DefaultMii has incorrect size.");
|
|
||||||
|
|
||||||
struct DatabaseSessionMetadata {
|
|
||||||
u32 interface_version;
|
|
||||||
u32 magic;
|
|
||||||
u64 update_counter;
|
|
||||||
|
|
||||||
bool IsInterfaceVersionSupported(u32 version) const {
|
|
||||||
return version <= interface_version;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Mii
|
|
@ -1,59 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <random>
|
|
||||||
#include <span>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "common/swap.h"
|
|
||||||
#include "common/uuid.h"
|
|
||||||
#include "core/hle/service/mii/mii_types.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
class MiiUtil {
|
|
||||||
public:
|
|
||||||
static u16 CalculateCrc16(const void* data, std::size_t size) {
|
|
||||||
s32 crc{};
|
|
||||||
for (std::size_t i = 0; i < size; i++) {
|
|
||||||
crc ^= static_cast<const u8*>(data)[i] << 8;
|
|
||||||
for (std::size_t j = 0; j < 8; j++) {
|
|
||||||
crc <<= 1;
|
|
||||||
if ((crc & 0x10000) != 0) {
|
|
||||||
crc = (crc ^ 0x1021) & 0xFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Common::swap16(static_cast<u16>(crc));
|
|
||||||
}
|
|
||||||
|
|
||||||
static Common::UUID MakeCreateId() {
|
|
||||||
return Common::UUID::MakeRandomRFC4122V4();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Common::UUID GetDeviceId() {
|
|
||||||
// This should be nn::settings::detail::GetMiiAuthorId()
|
|
||||||
return Common::UUID::MakeDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static T GetRandomValue(T min, T max) {
|
|
||||||
std::random_device device;
|
|
||||||
std::mt19937 gen(device());
|
|
||||||
std::uniform_int_distribution<u64> distribution(static_cast<u64>(min),
|
|
||||||
static_cast<u64>(max));
|
|
||||||
return static_cast<T>(distribution(gen));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static T GetRandomValue(T max) {
|
|
||||||
return GetRandomValue<T>({}, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsFontRegionValid(FontRegion font, std::span<const char16_t> text) {
|
|
||||||
// TODO: This function needs to check against the font tables
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace Service::Mii
|
|
File diff suppressed because it is too large
Load Diff
27
src/core/hle/service/mii/raw_data.h
Normal file
27
src/core/hle/service/mii/raw_data.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "core/hle/service/mii/types.h"
|
||||||
|
|
||||||
|
namespace Service::Mii::RawData {
|
||||||
|
|
||||||
|
extern const std::array<Service::Mii::DefaultMii, 2> BaseMii;
|
||||||
|
extern const std::array<Service::Mii::DefaultMii, 6> DefaultMii;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFaceline;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData3, 6> RandomMiiFacelineColor;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineWrinkle;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiFacelineMakeup;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiHairType;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData3, 9> RandomMiiHairColor;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyeType;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiEyeColor;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiEyebrowType;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiNoseType;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData4, 18> RandomMiiMouthType;
|
||||||
|
extern const std::array<Service::Mii::RandomMiiData2, 3> RandomMiiGlassType;
|
||||||
|
|
||||||
|
} // namespace Service::Mii::RawData
|
553
src/core/hle/service/mii/types.h
Normal file
553
src/core/hle/service/mii/types.h
Normal file
@ -0,0 +1,553 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/uuid.h"
|
||||||
|
|
||||||
|
namespace Service::Mii {
|
||||||
|
|
||||||
|
enum class Age : u32 {
|
||||||
|
Young,
|
||||||
|
Normal,
|
||||||
|
Old,
|
||||||
|
All,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BeardType : u32 {
|
||||||
|
None,
|
||||||
|
Beard1,
|
||||||
|
Beard2,
|
||||||
|
Beard3,
|
||||||
|
Beard4,
|
||||||
|
Beard5,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BeardAndMustacheFlag : u32 {
|
||||||
|
Beard = 1,
|
||||||
|
Mustache,
|
||||||
|
All = Beard | Mustache,
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
|
||||||
|
|
||||||
|
enum class FontRegion : u32 {
|
||||||
|
Standard,
|
||||||
|
China,
|
||||||
|
Korea,
|
||||||
|
Taiwan,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Gender : u32 {
|
||||||
|
Male,
|
||||||
|
Female,
|
||||||
|
All,
|
||||||
|
Maximum = Female,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class HairFlip : u32 {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Maximum = Right,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MustacheType : u32 {
|
||||||
|
None,
|
||||||
|
Mustache1,
|
||||||
|
Mustache2,
|
||||||
|
Mustache3,
|
||||||
|
Mustache4,
|
||||||
|
Mustache5,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Race : u32 {
|
||||||
|
Black,
|
||||||
|
White,
|
||||||
|
Asian,
|
||||||
|
All,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Source : u32 {
|
||||||
|
Database = 0,
|
||||||
|
Default = 1,
|
||||||
|
Account = 2,
|
||||||
|
Friend = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SourceFlag : u32 {
|
||||||
|
None = 0,
|
||||||
|
Database = 1 << 0,
|
||||||
|
Default = 1 << 1,
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
|
||||||
|
|
||||||
|
// nn::mii::CharInfo
|
||||||
|
struct CharInfo {
|
||||||
|
Common::UUID uuid;
|
||||||
|
std::array<char16_t, 11> name;
|
||||||
|
u8 font_region;
|
||||||
|
u8 favorite_color;
|
||||||
|
u8 gender;
|
||||||
|
u8 height;
|
||||||
|
u8 build;
|
||||||
|
u8 type;
|
||||||
|
u8 region_move;
|
||||||
|
u8 faceline_type;
|
||||||
|
u8 faceline_color;
|
||||||
|
u8 faceline_wrinkle;
|
||||||
|
u8 faceline_make;
|
||||||
|
u8 hair_type;
|
||||||
|
u8 hair_color;
|
||||||
|
u8 hair_flip;
|
||||||
|
u8 eye_type;
|
||||||
|
u8 eye_color;
|
||||||
|
u8 eye_scale;
|
||||||
|
u8 eye_aspect;
|
||||||
|
u8 eye_rotate;
|
||||||
|
u8 eye_x;
|
||||||
|
u8 eye_y;
|
||||||
|
u8 eyebrow_type;
|
||||||
|
u8 eyebrow_color;
|
||||||
|
u8 eyebrow_scale;
|
||||||
|
u8 eyebrow_aspect;
|
||||||
|
u8 eyebrow_rotate;
|
||||||
|
u8 eyebrow_x;
|
||||||
|
u8 eyebrow_y;
|
||||||
|
u8 nose_type;
|
||||||
|
u8 nose_scale;
|
||||||
|
u8 nose_y;
|
||||||
|
u8 mouth_type;
|
||||||
|
u8 mouth_color;
|
||||||
|
u8 mouth_scale;
|
||||||
|
u8 mouth_aspect;
|
||||||
|
u8 mouth_y;
|
||||||
|
u8 beard_color;
|
||||||
|
u8 beard_type;
|
||||||
|
u8 mustache_type;
|
||||||
|
u8 mustache_scale;
|
||||||
|
u8 mustache_y;
|
||||||
|
u8 glasses_type;
|
||||||
|
u8 glasses_color;
|
||||||
|
u8 glasses_scale;
|
||||||
|
u8 glasses_y;
|
||||||
|
u8 mole_type;
|
||||||
|
u8 mole_scale;
|
||||||
|
u8 mole_x;
|
||||||
|
u8 mole_y;
|
||||||
|
u8 padding;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CharInfo) == 0x58, "CharInfo has incorrect size.");
|
||||||
|
static_assert(std::has_unique_object_representations_v<CharInfo>,
|
||||||
|
"All bits of CharInfo must contribute to its value.");
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
|
||||||
|
struct MiiInfoElement {
|
||||||
|
MiiInfoElement(const CharInfo& info_, Source source_) : info{info_}, source{source_} {}
|
||||||
|
|
||||||
|
CharInfo info{};
|
||||||
|
Source source{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
|
||||||
|
|
||||||
|
struct MiiStoreBitFields {
|
||||||
|
union {
|
||||||
|
u32 word_0{};
|
||||||
|
|
||||||
|
BitField<0, 8, u32> hair_type;
|
||||||
|
BitField<8, 7, u32> height;
|
||||||
|
BitField<15, 1, u32> mole_type;
|
||||||
|
BitField<16, 7, u32> build;
|
||||||
|
BitField<23, 1, HairFlip> hair_flip;
|
||||||
|
BitField<24, 7, u32> hair_color;
|
||||||
|
BitField<31, 1, u32> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 word_1{};
|
||||||
|
|
||||||
|
BitField<0, 7, u32> eye_color;
|
||||||
|
BitField<7, 1, Gender> gender;
|
||||||
|
BitField<8, 7, u32> eyebrow_color;
|
||||||
|
BitField<16, 7, u32> mouth_color;
|
||||||
|
BitField<24, 7, u32> beard_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 word_2{};
|
||||||
|
|
||||||
|
BitField<0, 7, u32> glasses_color;
|
||||||
|
BitField<8, 6, u32> eye_type;
|
||||||
|
BitField<14, 2, u32> region_move;
|
||||||
|
BitField<16, 6, u32> mouth_type;
|
||||||
|
BitField<22, 2, FontRegion> font_region;
|
||||||
|
BitField<24, 5, u32> eye_y;
|
||||||
|
BitField<29, 3, u32> glasses_scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 word_3{};
|
||||||
|
|
||||||
|
BitField<0, 5, u32> eyebrow_type;
|
||||||
|
BitField<5, 3, MustacheType> mustache_type;
|
||||||
|
BitField<8, 5, u32> nose_type;
|
||||||
|
BitField<13, 3, BeardType> beard_type;
|
||||||
|
BitField<16, 5, u32> nose_y;
|
||||||
|
BitField<21, 3, u32> mouth_aspect;
|
||||||
|
BitField<24, 5, u32> mouth_y;
|
||||||
|
BitField<29, 3, u32> eyebrow_aspect;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 word_4{};
|
||||||
|
|
||||||
|
BitField<0, 5, u32> mustache_y;
|
||||||
|
BitField<5, 3, u32> eye_rotate;
|
||||||
|
BitField<8, 5, u32> glasses_y;
|
||||||
|
BitField<13, 3, u32> eye_aspect;
|
||||||
|
BitField<16, 5, u32> mole_x;
|
||||||
|
BitField<21, 3, u32> eye_scale;
|
||||||
|
BitField<24, 5, u32> mole_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 word_5{};
|
||||||
|
|
||||||
|
BitField<0, 5, u32> glasses_type;
|
||||||
|
BitField<8, 4, u32> favorite_color;
|
||||||
|
BitField<12, 4, u32> faceline_type;
|
||||||
|
BitField<16, 4, u32> faceline_color;
|
||||||
|
BitField<20, 4, u32> faceline_wrinkle;
|
||||||
|
BitField<24, 4, u32> faceline_makeup;
|
||||||
|
BitField<28, 4, u32> eye_x;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 word_6{};
|
||||||
|
|
||||||
|
BitField<0, 4, u32> eyebrow_scale;
|
||||||
|
BitField<4, 4, u32> eyebrow_rotate;
|
||||||
|
BitField<8, 4, u32> eyebrow_x;
|
||||||
|
BitField<12, 4, u32> eyebrow_y;
|
||||||
|
BitField<16, 4, u32> nose_scale;
|
||||||
|
BitField<20, 4, u32> mouth_scale;
|
||||||
|
BitField<24, 4, u32> mustache_scale;
|
||||||
|
BitField<28, 4, u32> mole_scale;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
|
||||||
|
static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
|
||||||
|
"MiiStoreBitFields is not trivially copyable.");
|
||||||
|
|
||||||
|
// This is nn::mii::Ver3StoreData
|
||||||
|
// Based on citra HLE::Applets::MiiData and PretendoNetwork.
|
||||||
|
// https://github.com/citra-emu/citra/blob/master/src/core/hle/applets/mii_selector.h#L48
|
||||||
|
// https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299
|
||||||
|
struct Ver3StoreData {
|
||||||
|
u8 version;
|
||||||
|
union {
|
||||||
|
u8 raw;
|
||||||
|
|
||||||
|
BitField<0, 1, u8> allow_copying;
|
||||||
|
BitField<1, 1, u8> profanity_flag;
|
||||||
|
BitField<2, 2, u8> region_lock;
|
||||||
|
BitField<4, 2, u8> character_set;
|
||||||
|
} region_information;
|
||||||
|
u16_be mii_id;
|
||||||
|
u64_be system_id;
|
||||||
|
u32_be specialness_and_creation_date;
|
||||||
|
std::array<u8, 0x6> creator_mac;
|
||||||
|
u16_be padding;
|
||||||
|
union {
|
||||||
|
u16 raw;
|
||||||
|
|
||||||
|
BitField<0, 1, u16> gender;
|
||||||
|
BitField<1, 4, u16> birth_month;
|
||||||
|
BitField<5, 5, u16> birth_day;
|
||||||
|
BitField<10, 4, u16> favorite_color;
|
||||||
|
BitField<14, 1, u16> favorite;
|
||||||
|
} mii_information;
|
||||||
|
std::array<char16_t, 0xA> mii_name;
|
||||||
|
u8 height;
|
||||||
|
u8 build;
|
||||||
|
union {
|
||||||
|
u8 raw;
|
||||||
|
|
||||||
|
BitField<0, 1, u8> disable_sharing;
|
||||||
|
BitField<1, 4, u8> face_shape;
|
||||||
|
BitField<5, 3, u8> skin_color;
|
||||||
|
} appearance_bits1;
|
||||||
|
union {
|
||||||
|
u8 raw;
|
||||||
|
|
||||||
|
BitField<0, 4, u8> wrinkles;
|
||||||
|
BitField<4, 4, u8> makeup;
|
||||||
|
} appearance_bits2;
|
||||||
|
u8 hair_style;
|
||||||
|
union {
|
||||||
|
u8 raw;
|
||||||
|
|
||||||
|
BitField<0, 3, u8> hair_color;
|
||||||
|
BitField<3, 1, u8> flip_hair;
|
||||||
|
} appearance_bits3;
|
||||||
|
union {
|
||||||
|
u32 raw;
|
||||||
|
|
||||||
|
BitField<0, 6, u32> eye_type;
|
||||||
|
BitField<6, 3, u32> eye_color;
|
||||||
|
BitField<9, 4, u32> eye_scale;
|
||||||
|
BitField<13, 3, u32> eye_vertical_stretch;
|
||||||
|
BitField<16, 5, u32> eye_rotation;
|
||||||
|
BitField<21, 4, u32> eye_spacing;
|
||||||
|
BitField<25, 5, u32> eye_y_position;
|
||||||
|
} appearance_bits4;
|
||||||
|
union {
|
||||||
|
u32 raw;
|
||||||
|
|
||||||
|
BitField<0, 5, u32> eyebrow_style;
|
||||||
|
BitField<5, 3, u32> eyebrow_color;
|
||||||
|
BitField<8, 4, u32> eyebrow_scale;
|
||||||
|
BitField<12, 3, u32> eyebrow_yscale;
|
||||||
|
BitField<16, 4, u32> eyebrow_rotation;
|
||||||
|
BitField<21, 4, u32> eyebrow_spacing;
|
||||||
|
BitField<25, 5, u32> eyebrow_y_position;
|
||||||
|
} appearance_bits5;
|
||||||
|
union {
|
||||||
|
u16 raw;
|
||||||
|
|
||||||
|
BitField<0, 5, u16> nose_type;
|
||||||
|
BitField<5, 4, u16> nose_scale;
|
||||||
|
BitField<9, 5, u16> nose_y_position;
|
||||||
|
} appearance_bits6;
|
||||||
|
union {
|
||||||
|
u16 raw;
|
||||||
|
|
||||||
|
BitField<0, 6, u16> mouth_type;
|
||||||
|
BitField<6, 3, u16> mouth_color;
|
||||||
|
BitField<9, 4, u16> mouth_scale;
|
||||||
|
BitField<13, 3, u16> mouth_horizontal_stretch;
|
||||||
|
} appearance_bits7;
|
||||||
|
union {
|
||||||
|
u8 raw;
|
||||||
|
|
||||||
|
BitField<0, 5, u8> mouth_y_position;
|
||||||
|
BitField<5, 3, u8> mustache_type;
|
||||||
|
} appearance_bits8;
|
||||||
|
u8 allow_copying;
|
||||||
|
union {
|
||||||
|
u16 raw;
|
||||||
|
|
||||||
|
BitField<0, 3, u16> bear_type;
|
||||||
|
BitField<3, 3, u16> facial_hair_color;
|
||||||
|
BitField<6, 4, u16> mustache_scale;
|
||||||
|
BitField<10, 5, u16> mustache_y_position;
|
||||||
|
} appearance_bits9;
|
||||||
|
union {
|
||||||
|
u16 raw;
|
||||||
|
|
||||||
|
BitField<0, 4, u16> glasses_type;
|
||||||
|
BitField<4, 3, u16> glasses_color;
|
||||||
|
BitField<7, 4, u16> glasses_scale;
|
||||||
|
BitField<11, 5, u16> glasses_y_position;
|
||||||
|
} appearance_bits10;
|
||||||
|
union {
|
||||||
|
u16 raw;
|
||||||
|
|
||||||
|
BitField<0, 1, u16> mole_enabled;
|
||||||
|
BitField<1, 4, u16> mole_scale;
|
||||||
|
BitField<5, 5, u16> mole_x_position;
|
||||||
|
BitField<10, 5, u16> mole_y_position;
|
||||||
|
} appearance_bits11;
|
||||||
|
|
||||||
|
std::array<u16_le, 0xA> author_name;
|
||||||
|
INSERT_PADDING_BYTES(0x2);
|
||||||
|
u16_be crc;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size");
|
||||||
|
|
||||||
|
struct NfpStoreDataExtension {
|
||||||
|
u8 faceline_color;
|
||||||
|
u8 hair_color;
|
||||||
|
u8 eye_color;
|
||||||
|
u8 eyebrow_color;
|
||||||
|
u8 mouth_color;
|
||||||
|
u8 beard_color;
|
||||||
|
u8 glass_color;
|
||||||
|
u8 glass_type;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size");
|
||||||
|
|
||||||
|
constexpr std::array<u8, 0x10> Ver3FacelineColorTable{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<u8, 100> Ver3HairColorTable{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x4, 0x3, 0x5, 0x4, 0x4, 0x6, 0x2, 0x0,
|
||||||
|
0x6, 0x4, 0x3, 0x2, 0x2, 0x7, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
|
||||||
|
0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x4,
|
||||||
|
0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5,
|
||||||
|
0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x7, 0x5, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x7,
|
||||||
|
0x7, 0x7, 0x7, 0x7, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0, 0x4, 0x4, 0x4, 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<u8, 100> Ver3EyeColorTable{
|
||||||
|
0x0, 0x2, 0x2, 0x2, 0x1, 0x3, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x2, 0x2, 0x4,
|
||||||
|
0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
|
||||||
|
0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x0, 0x4, 0x4,
|
||||||
|
0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
|
||||||
|
0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2,
|
||||||
|
0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<u8, 100> Ver3MouthlineColorTable{
|
||||||
|
0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
|
||||||
|
0x4, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x1, 0x4,
|
||||||
|
0x4, 0x2, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
|
||||||
|
0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4,
|
||||||
|
0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
|
||||||
|
0x3, 0x3, 0x3, 0x3, 0x4, 0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x3, 0x3,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<u8, 100> Ver3GlassColorTable{
|
||||||
|
0x0, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x4, 0x0, 0x5, 0x1, 0x1, 0x3, 0x5, 0x1, 0x2, 0x3,
|
||||||
|
0x4, 0x5, 0x4, 0x2, 0x2, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
|
||||||
|
0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
|
||||||
|
0x3, 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x0, 0x5, 0x5,
|
||||||
|
0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x1, 0x4,
|
||||||
|
0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<u8, 20> Ver3GlassTypeTable{
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1,
|
||||||
|
0x2, 0x1, 0x3, 0x7, 0x7, 0x6, 0x7, 0x8, 0x7, 0x7,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MiiStoreData {
|
||||||
|
using Name = std::array<char16_t, 10>;
|
||||||
|
|
||||||
|
MiiStoreData();
|
||||||
|
MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
|
||||||
|
const Common::UUID& user_id);
|
||||||
|
|
||||||
|
// This corresponds to the above structure MiiStoreBitFields. I did it like this because the
|
||||||
|
// BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
|
||||||
|
// not suitable for our uses.
|
||||||
|
struct {
|
||||||
|
std::array<u8, 0x1C> data{};
|
||||||
|
static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
|
||||||
|
|
||||||
|
Name name{};
|
||||||
|
Common::UUID uuid{};
|
||||||
|
} data;
|
||||||
|
|
||||||
|
u16 data_crc{};
|
||||||
|
u16 device_crc{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
|
||||||
|
|
||||||
|
struct MiiStoreDataElement {
|
||||||
|
MiiStoreData data{};
|
||||||
|
Source source{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
|
||||||
|
|
||||||
|
struct MiiDatabase {
|
||||||
|
u32 magic{}; // 'NFDB'
|
||||||
|
std::array<MiiStoreData, 0x64> miis{};
|
||||||
|
INSERT_PADDING_BYTES(1);
|
||||||
|
u8 count{};
|
||||||
|
u16 crc{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
|
||||||
|
|
||||||
|
struct RandomMiiValues {
|
||||||
|
std::array<u8, 0xbc> values{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
|
||||||
|
|
||||||
|
struct RandomMiiData4 {
|
||||||
|
Gender gender{};
|
||||||
|
Age age{};
|
||||||
|
Race race{};
|
||||||
|
u32 values_count{};
|
||||||
|
std::array<u32, 47> values{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
|
||||||
|
|
||||||
|
struct RandomMiiData3 {
|
||||||
|
u32 arg_1;
|
||||||
|
u32 arg_2;
|
||||||
|
u32 values_count;
|
||||||
|
std::array<u32, 47> values{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
|
||||||
|
|
||||||
|
struct RandomMiiData2 {
|
||||||
|
u32 arg_1;
|
||||||
|
u32 values_count;
|
||||||
|
std::array<u32, 47> values{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
|
||||||
|
|
||||||
|
struct DefaultMii {
|
||||||
|
u32 face_type{};
|
||||||
|
u32 face_color{};
|
||||||
|
u32 face_wrinkle{};
|
||||||
|
u32 face_makeup{};
|
||||||
|
u32 hair_type{};
|
||||||
|
u32 hair_color{};
|
||||||
|
u32 hair_flip{};
|
||||||
|
u32 eye_type{};
|
||||||
|
u32 eye_color{};
|
||||||
|
u32 eye_scale{};
|
||||||
|
u32 eye_aspect{};
|
||||||
|
u32 eye_rotate{};
|
||||||
|
u32 eye_x{};
|
||||||
|
u32 eye_y{};
|
||||||
|
u32 eyebrow_type{};
|
||||||
|
u32 eyebrow_color{};
|
||||||
|
u32 eyebrow_scale{};
|
||||||
|
u32 eyebrow_aspect{};
|
||||||
|
u32 eyebrow_rotate{};
|
||||||
|
u32 eyebrow_x{};
|
||||||
|
u32 eyebrow_y{};
|
||||||
|
u32 nose_type{};
|
||||||
|
u32 nose_scale{};
|
||||||
|
u32 nose_y{};
|
||||||
|
u32 mouth_type{};
|
||||||
|
u32 mouth_color{};
|
||||||
|
u32 mouth_scale{};
|
||||||
|
u32 mouth_aspect{};
|
||||||
|
u32 mouth_y{};
|
||||||
|
u32 mustache_type{};
|
||||||
|
u32 beard_type{};
|
||||||
|
u32 beard_color{};
|
||||||
|
u32 mustache_scale{};
|
||||||
|
u32 mustache_y{};
|
||||||
|
u32 glasses_type{};
|
||||||
|
u32 glasses_color{};
|
||||||
|
u32 glasses_scale{};
|
||||||
|
u32 glasses_y{};
|
||||||
|
u32 mole_type{};
|
||||||
|
u32 mole_scale{};
|
||||||
|
u32 mole_x{};
|
||||||
|
u32 mole_y{};
|
||||||
|
u32 height{};
|
||||||
|
u32 weight{};
|
||||||
|
Gender gender{};
|
||||||
|
u32 favorite_color{};
|
||||||
|
u32 region{};
|
||||||
|
FontRegion font_region{};
|
||||||
|
u32 type{};
|
||||||
|
INSERT_PADDING_WORDS(5);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
} // namespace Service::Mii
|
@ -1,482 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/types/char_info.h"
|
|
||||||
#include "core/hle/service/mii/types/store_data.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
void CharInfo::SetFromStoreData(const StoreData& store_data) {
|
|
||||||
name = store_data.GetNickname();
|
|
||||||
null_terminator = '\0';
|
|
||||||
create_id = store_data.GetCreateId();
|
|
||||||
font_region = store_data.GetFontRegion();
|
|
||||||
favorite_color = store_data.GetFavoriteColor();
|
|
||||||
gender = store_data.GetGender();
|
|
||||||
height = store_data.GetHeight();
|
|
||||||
build = store_data.GetBuild();
|
|
||||||
type = store_data.GetType();
|
|
||||||
region_move = store_data.GetRegionMove();
|
|
||||||
faceline_type = store_data.GetFacelineType();
|
|
||||||
faceline_color = store_data.GetFacelineColor();
|
|
||||||
faceline_wrinkle = store_data.GetFacelineWrinkle();
|
|
||||||
faceline_make = store_data.GetFacelineMake();
|
|
||||||
hair_type = store_data.GetHairType();
|
|
||||||
hair_color = store_data.GetHairColor();
|
|
||||||
hair_flip = store_data.GetHairFlip();
|
|
||||||
eye_type = store_data.GetEyeType();
|
|
||||||
eye_color = store_data.GetEyeColor();
|
|
||||||
eye_scale = store_data.GetEyeScale();
|
|
||||||
eye_aspect = store_data.GetEyeAspect();
|
|
||||||
eye_rotate = store_data.GetEyeRotate();
|
|
||||||
eye_x = store_data.GetEyeX();
|
|
||||||
eye_y = store_data.GetEyeY();
|
|
||||||
eyebrow_type = store_data.GetEyebrowType();
|
|
||||||
eyebrow_color = store_data.GetEyebrowColor();
|
|
||||||
eyebrow_scale = store_data.GetEyebrowScale();
|
|
||||||
eyebrow_aspect = store_data.GetEyebrowAspect();
|
|
||||||
eyebrow_rotate = store_data.GetEyebrowRotate();
|
|
||||||
eyebrow_x = store_data.GetEyebrowX();
|
|
||||||
eyebrow_y = store_data.GetEyebrowY();
|
|
||||||
nose_type = store_data.GetNoseType();
|
|
||||||
nose_scale = store_data.GetNoseScale();
|
|
||||||
nose_y = store_data.GetNoseY();
|
|
||||||
mouth_type = store_data.GetMouthType();
|
|
||||||
mouth_color = store_data.GetMouthColor();
|
|
||||||
mouth_scale = store_data.GetMouthScale();
|
|
||||||
mouth_aspect = store_data.GetMouthAspect();
|
|
||||||
mouth_y = store_data.GetMouthY();
|
|
||||||
beard_color = store_data.GetBeardColor();
|
|
||||||
beard_type = store_data.GetBeardType();
|
|
||||||
mustache_type = store_data.GetMustacheType();
|
|
||||||
mustache_scale = store_data.GetMustacheScale();
|
|
||||||
mustache_y = store_data.GetMustacheY();
|
|
||||||
glass_type = store_data.GetGlassType();
|
|
||||||
glass_color = store_data.GetGlassColor();
|
|
||||||
glass_scale = store_data.GetGlassScale();
|
|
||||||
glass_y = store_data.GetGlassY();
|
|
||||||
mole_type = store_data.GetMoleType();
|
|
||||||
mole_scale = store_data.GetMoleScale();
|
|
||||||
mole_x = store_data.GetMoleX();
|
|
||||||
mole_y = store_data.GetMoleY();
|
|
||||||
padding = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
ValidationResult CharInfo::Verify() const {
|
|
||||||
if (!create_id.IsValid()) {
|
|
||||||
return ValidationResult::InvalidCreateId;
|
|
||||||
}
|
|
||||||
if (!name.IsValid()) {
|
|
||||||
return ValidationResult::InvalidName;
|
|
||||||
}
|
|
||||||
if (font_region > FontRegion::Max) {
|
|
||||||
return ValidationResult::InvalidFont;
|
|
||||||
}
|
|
||||||
if (favorite_color > FavoriteColor::Max) {
|
|
||||||
return ValidationResult::InvalidColor;
|
|
||||||
}
|
|
||||||
if (gender > Gender::Max) {
|
|
||||||
return ValidationResult::InvalidGender;
|
|
||||||
}
|
|
||||||
if (height > MaxHeight) {
|
|
||||||
return ValidationResult::InvalidHeight;
|
|
||||||
}
|
|
||||||
if (build > MaxBuild) {
|
|
||||||
return ValidationResult::InvalidBuild;
|
|
||||||
}
|
|
||||||
if (type > MaxType) {
|
|
||||||
return ValidationResult::InvalidType;
|
|
||||||
}
|
|
||||||
if (region_move > MaxRegionMove) {
|
|
||||||
return ValidationResult::InvalidRegionMove;
|
|
||||||
}
|
|
||||||
if (faceline_type > FacelineType::Max) {
|
|
||||||
return ValidationResult::InvalidFacelineType;
|
|
||||||
}
|
|
||||||
if (faceline_color > FacelineColor::Max) {
|
|
||||||
return ValidationResult::InvalidFacelineColor;
|
|
||||||
}
|
|
||||||
if (faceline_wrinkle > FacelineWrinkle::Max) {
|
|
||||||
return ValidationResult::InvalidFacelineWrinkle;
|
|
||||||
}
|
|
||||||
if (faceline_make > FacelineMake::Max) {
|
|
||||||
return ValidationResult::InvalidFacelineMake;
|
|
||||||
}
|
|
||||||
if (hair_type > HairType::Max) {
|
|
||||||
return ValidationResult::InvalidHairType;
|
|
||||||
}
|
|
||||||
if (hair_color > CommonColor::Max) {
|
|
||||||
return ValidationResult::InvalidHairColor;
|
|
||||||
}
|
|
||||||
if (hair_flip > HairFlip::Max) {
|
|
||||||
return ValidationResult::InvalidHairFlip;
|
|
||||||
}
|
|
||||||
if (eye_type > EyeType::Max) {
|
|
||||||
return ValidationResult::InvalidEyeType;
|
|
||||||
}
|
|
||||||
if (eye_color > CommonColor::Max) {
|
|
||||||
return ValidationResult::InvalidEyeColor;
|
|
||||||
}
|
|
||||||
if (eye_scale > MaxEyeScale) {
|
|
||||||
return ValidationResult::InvalidEyeScale;
|
|
||||||
}
|
|
||||||
if (eye_aspect > MaxEyeAspect) {
|
|
||||||
return ValidationResult::InvalidEyeAspect;
|
|
||||||
}
|
|
||||||
if (eye_rotate > MaxEyeX) {
|
|
||||||
return ValidationResult::InvalidEyeRotate;
|
|
||||||
}
|
|
||||||
if (eye_x > MaxEyeX) {
|
|
||||||
return ValidationResult::InvalidEyeX;
|
|
||||||
}
|
|
||||||
if (eye_y > MaxEyeY) {
|
|
||||||
return ValidationResult::InvalidEyeY;
|
|
||||||
}
|
|
||||||
if (eyebrow_type > EyebrowType::Max) {
|
|
||||||
return ValidationResult::InvalidEyebrowType;
|
|
||||||
}
|
|
||||||
if (eyebrow_color > CommonColor::Max) {
|
|
||||||
return ValidationResult::InvalidEyebrowColor;
|
|
||||||
}
|
|
||||||
if (eyebrow_scale > MaxEyebrowScale) {
|
|
||||||
return ValidationResult::InvalidEyebrowScale;
|
|
||||||
}
|
|
||||||
if (eyebrow_aspect > MaxEyebrowAspect) {
|
|
||||||
return ValidationResult::InvalidEyebrowAspect;
|
|
||||||
}
|
|
||||||
if (eyebrow_rotate > MaxEyebrowRotate) {
|
|
||||||
return ValidationResult::InvalidEyebrowRotate;
|
|
||||||
}
|
|
||||||
if (eyebrow_x > MaxEyebrowX) {
|
|
||||||
return ValidationResult::InvalidEyebrowX;
|
|
||||||
}
|
|
||||||
if (eyebrow_y > MaxEyebrowY) {
|
|
||||||
return ValidationResult::InvalidEyebrowY;
|
|
||||||
}
|
|
||||||
if (nose_type > NoseType::Max) {
|
|
||||||
return ValidationResult::InvalidNoseType;
|
|
||||||
}
|
|
||||||
if (nose_scale > MaxNoseScale) {
|
|
||||||
return ValidationResult::InvalidNoseScale;
|
|
||||||
}
|
|
||||||
if (nose_y > MaxNoseY) {
|
|
||||||
return ValidationResult::InvalidNoseY;
|
|
||||||
}
|
|
||||||
if (mouth_type > MouthType::Max) {
|
|
||||||
return ValidationResult::InvalidMouthType;
|
|
||||||
}
|
|
||||||
if (mouth_color > CommonColor::Max) {
|
|
||||||
return ValidationResult::InvalidMouthColor;
|
|
||||||
}
|
|
||||||
if (mouth_scale > MaxMouthScale) {
|
|
||||||
return ValidationResult::InvalidMouthScale;
|
|
||||||
}
|
|
||||||
if (mouth_aspect > MaxMoutAspect) {
|
|
||||||
return ValidationResult::InvalidMouthAspect;
|
|
||||||
}
|
|
||||||
if (mouth_y > MaxMouthY) {
|
|
||||||
return ValidationResult::InvalidMoleY;
|
|
||||||
}
|
|
||||||
if (beard_color > CommonColor::Max) {
|
|
||||||
return ValidationResult::InvalidBeardColor;
|
|
||||||
}
|
|
||||||
if (beard_type > BeardType::Max) {
|
|
||||||
return ValidationResult::InvalidBeardType;
|
|
||||||
}
|
|
||||||
if (mustache_type > MustacheType::Max) {
|
|
||||||
return ValidationResult::InvalidMustacheType;
|
|
||||||
}
|
|
||||||
if (mustache_scale > MaxMustacheScale) {
|
|
||||||
return ValidationResult::InvalidMustacheScale;
|
|
||||||
}
|
|
||||||
if (mustache_y > MasMustacheY) {
|
|
||||||
return ValidationResult::InvalidMustacheY;
|
|
||||||
}
|
|
||||||
if (glass_type > GlassType::Max) {
|
|
||||||
return ValidationResult::InvalidGlassType;
|
|
||||||
}
|
|
||||||
if (glass_color > CommonColor::Max) {
|
|
||||||
return ValidationResult::InvalidGlassColor;
|
|
||||||
}
|
|
||||||
if (glass_scale > MaxGlassScale) {
|
|
||||||
return ValidationResult::InvalidGlassScale;
|
|
||||||
}
|
|
||||||
if (glass_y > MaxGlassY) {
|
|
||||||
return ValidationResult::InvalidGlassY;
|
|
||||||
}
|
|
||||||
if (mole_type > MoleType::Max) {
|
|
||||||
return ValidationResult::InvalidMoleType;
|
|
||||||
}
|
|
||||||
if (mole_scale > MaxMoleScale) {
|
|
||||||
return ValidationResult::InvalidMoleScale;
|
|
||||||
}
|
|
||||||
if (mole_x > MaxMoleX) {
|
|
||||||
return ValidationResult::InvalidMoleX;
|
|
||||||
}
|
|
||||||
if (mole_y > MaxMoleY) {
|
|
||||||
return ValidationResult::InvalidMoleY;
|
|
||||||
}
|
|
||||||
return ValidationResult::NoErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::UUID CharInfo::GetCreateId() const {
|
|
||||||
return create_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nickname CharInfo::GetNickname() const {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontRegion CharInfo::GetFontRegion() const {
|
|
||||||
return font_region;
|
|
||||||
}
|
|
||||||
|
|
||||||
FavoriteColor CharInfo::GetFavoriteColor() const {
|
|
||||||
return favorite_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gender CharInfo::GetGender() const {
|
|
||||||
return gender;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetHeight() const {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetBuild() const {
|
|
||||||
return build;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetType() const {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetRegionMove() const {
|
|
||||||
return region_move;
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineType CharInfo::GetFacelineType() const {
|
|
||||||
return faceline_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineColor CharInfo::GetFacelineColor() const {
|
|
||||||
return faceline_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineWrinkle CharInfo::GetFacelineWrinkle() const {
|
|
||||||
return faceline_wrinkle;
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineMake CharInfo::GetFacelineMake() const {
|
|
||||||
return faceline_make;
|
|
||||||
}
|
|
||||||
|
|
||||||
HairType CharInfo::GetHairType() const {
|
|
||||||
return hair_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CharInfo::GetHairColor() const {
|
|
||||||
return hair_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
HairFlip CharInfo::GetHairFlip() const {
|
|
||||||
return hair_flip;
|
|
||||||
}
|
|
||||||
|
|
||||||
EyeType CharInfo::GetEyeType() const {
|
|
||||||
return eye_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CharInfo::GetEyeColor() const {
|
|
||||||
return eye_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyeScale() const {
|
|
||||||
return eye_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyeAspect() const {
|
|
||||||
return eye_aspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyeRotate() const {
|
|
||||||
return eye_rotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyeX() const {
|
|
||||||
return eye_x;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyeY() const {
|
|
||||||
return eye_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
EyebrowType CharInfo::GetEyebrowType() const {
|
|
||||||
return eyebrow_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CharInfo::GetEyebrowColor() const {
|
|
||||||
return eyebrow_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyebrowScale() const {
|
|
||||||
return eyebrow_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyebrowAspect() const {
|
|
||||||
return eyebrow_aspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyebrowRotate() const {
|
|
||||||
return eyebrow_rotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyebrowX() const {
|
|
||||||
return eyebrow_x;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetEyebrowY() const {
|
|
||||||
return eyebrow_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
NoseType CharInfo::GetNoseType() const {
|
|
||||||
return nose_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetNoseScale() const {
|
|
||||||
return nose_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetNoseY() const {
|
|
||||||
return nose_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
MouthType CharInfo::GetMouthType() const {
|
|
||||||
return mouth_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CharInfo::GetMouthColor() const {
|
|
||||||
return mouth_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMouthScale() const {
|
|
||||||
return mouth_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMouthAspect() const {
|
|
||||||
return mouth_aspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMouthY() const {
|
|
||||||
return mouth_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CharInfo::GetBeardColor() const {
|
|
||||||
return beard_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
BeardType CharInfo::GetBeardType() const {
|
|
||||||
return beard_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
MustacheType CharInfo::GetMustacheType() const {
|
|
||||||
return mustache_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMustacheScale() const {
|
|
||||||
return mustache_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMustacheY() const {
|
|
||||||
return mustache_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
GlassType CharInfo::GetGlassType() const {
|
|
||||||
return glass_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CharInfo::GetGlassColor() const {
|
|
||||||
return glass_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetGlassScale() const {
|
|
||||||
return glass_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetGlassY() const {
|
|
||||||
return glass_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
MoleType CharInfo::GetMoleType() const {
|
|
||||||
return mole_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMoleScale() const {
|
|
||||||
return mole_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMoleX() const {
|
|
||||||
return mole_x;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CharInfo::GetMoleY() const {
|
|
||||||
return mole_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CharInfo::operator==(const CharInfo& info) {
|
|
||||||
bool is_identical = info.Verify() == ValidationResult::NoErrors;
|
|
||||||
is_identical &= name.data == info.GetNickname().data;
|
|
||||||
is_identical &= create_id == info.GetCreateId();
|
|
||||||
is_identical &= font_region == info.GetFontRegion();
|
|
||||||
is_identical &= favorite_color == info.GetFavoriteColor();
|
|
||||||
is_identical &= gender == info.GetGender();
|
|
||||||
is_identical &= height == info.GetHeight();
|
|
||||||
is_identical &= build == info.GetBuild();
|
|
||||||
is_identical &= type == info.GetType();
|
|
||||||
is_identical &= region_move == info.GetRegionMove();
|
|
||||||
is_identical &= faceline_type == info.GetFacelineType();
|
|
||||||
is_identical &= faceline_color == info.GetFacelineColor();
|
|
||||||
is_identical &= faceline_wrinkle == info.GetFacelineWrinkle();
|
|
||||||
is_identical &= faceline_make == info.GetFacelineMake();
|
|
||||||
is_identical &= hair_type == info.GetHairType();
|
|
||||||
is_identical &= hair_color == info.GetHairColor();
|
|
||||||
is_identical &= hair_flip == info.GetHairFlip();
|
|
||||||
is_identical &= eye_type == info.GetEyeType();
|
|
||||||
is_identical &= eye_color == info.GetEyeColor();
|
|
||||||
is_identical &= eye_scale == info.GetEyeScale();
|
|
||||||
is_identical &= eye_aspect == info.GetEyeAspect();
|
|
||||||
is_identical &= eye_rotate == info.GetEyeRotate();
|
|
||||||
is_identical &= eye_x == info.GetEyeX();
|
|
||||||
is_identical &= eye_y == info.GetEyeY();
|
|
||||||
is_identical &= eyebrow_type == info.GetEyebrowType();
|
|
||||||
is_identical &= eyebrow_color == info.GetEyebrowColor();
|
|
||||||
is_identical &= eyebrow_scale == info.GetEyebrowScale();
|
|
||||||
is_identical &= eyebrow_aspect == info.GetEyebrowAspect();
|
|
||||||
is_identical &= eyebrow_rotate == info.GetEyebrowRotate();
|
|
||||||
is_identical &= eyebrow_x == info.GetEyebrowX();
|
|
||||||
is_identical &= eyebrow_y == info.GetEyebrowY();
|
|
||||||
is_identical &= nose_type == info.GetNoseType();
|
|
||||||
is_identical &= nose_scale == info.GetNoseScale();
|
|
||||||
is_identical &= nose_y == info.GetNoseY();
|
|
||||||
is_identical &= mouth_type == info.GetMouthType();
|
|
||||||
is_identical &= mouth_color == info.GetMouthColor();
|
|
||||||
is_identical &= mouth_scale == info.GetMouthScale();
|
|
||||||
is_identical &= mouth_aspect == info.GetMouthAspect();
|
|
||||||
is_identical &= mouth_y == info.GetMouthY();
|
|
||||||
is_identical &= beard_color == info.GetBeardColor();
|
|
||||||
is_identical &= beard_type == info.GetBeardType();
|
|
||||||
is_identical &= mustache_type == info.GetMustacheType();
|
|
||||||
is_identical &= mustache_scale == info.GetMustacheScale();
|
|
||||||
is_identical &= mustache_y == info.GetMustacheY();
|
|
||||||
is_identical &= glass_type == info.GetGlassType();
|
|
||||||
is_identical &= glass_color == info.GetGlassColor();
|
|
||||||
is_identical &= glass_scale == info.GetGlassScale();
|
|
||||||
is_identical &= glass_y == info.GetGlassY();
|
|
||||||
is_identical &= mole_type == info.GetMoleType();
|
|
||||||
is_identical &= mole_scale == info.GetMoleScale();
|
|
||||||
is_identical &= mole_x == info.GetMoleX();
|
|
||||||
is_identical &= mole_y == info.GetMoleY();
|
|
||||||
return is_identical;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Mii
|
|
@ -1,137 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/mii_types.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
class StoreData;
|
|
||||||
|
|
||||||
// This is nn::mii::detail::CharInfoRaw
|
|
||||||
class CharInfo {
|
|
||||||
public:
|
|
||||||
void SetFromStoreData(const StoreData& store_data_raw);
|
|
||||||
|
|
||||||
ValidationResult Verify() const;
|
|
||||||
|
|
||||||
Common::UUID GetCreateId() const;
|
|
||||||
Nickname GetNickname() const;
|
|
||||||
FontRegion GetFontRegion() const;
|
|
||||||
FavoriteColor GetFavoriteColor() const;
|
|
||||||
Gender GetGender() const;
|
|
||||||
u8 GetHeight() const;
|
|
||||||
u8 GetBuild() const;
|
|
||||||
u8 GetType() const;
|
|
||||||
u8 GetRegionMove() const;
|
|
||||||
FacelineType GetFacelineType() const;
|
|
||||||
FacelineColor GetFacelineColor() const;
|
|
||||||
FacelineWrinkle GetFacelineWrinkle() const;
|
|
||||||
FacelineMake GetFacelineMake() const;
|
|
||||||
HairType GetHairType() const;
|
|
||||||
CommonColor GetHairColor() const;
|
|
||||||
HairFlip GetHairFlip() const;
|
|
||||||
EyeType GetEyeType() const;
|
|
||||||
CommonColor GetEyeColor() const;
|
|
||||||
u8 GetEyeScale() const;
|
|
||||||
u8 GetEyeAspect() const;
|
|
||||||
u8 GetEyeRotate() const;
|
|
||||||
u8 GetEyeX() const;
|
|
||||||
u8 GetEyeY() const;
|
|
||||||
EyebrowType GetEyebrowType() const;
|
|
||||||
CommonColor GetEyebrowColor() const;
|
|
||||||
u8 GetEyebrowScale() const;
|
|
||||||
u8 GetEyebrowAspect() const;
|
|
||||||
u8 GetEyebrowRotate() const;
|
|
||||||
u8 GetEyebrowX() const;
|
|
||||||
u8 GetEyebrowY() const;
|
|
||||||
NoseType GetNoseType() const;
|
|
||||||
u8 GetNoseScale() const;
|
|
||||||
u8 GetNoseY() const;
|
|
||||||
MouthType GetMouthType() const;
|
|
||||||
CommonColor GetMouthColor() const;
|
|
||||||
u8 GetMouthScale() const;
|
|
||||||
u8 GetMouthAspect() const;
|
|
||||||
u8 GetMouthY() const;
|
|
||||||
CommonColor GetBeardColor() const;
|
|
||||||
BeardType GetBeardType() const;
|
|
||||||
MustacheType GetMustacheType() const;
|
|
||||||
u8 GetMustacheScale() const;
|
|
||||||
u8 GetMustacheY() const;
|
|
||||||
GlassType GetGlassType() const;
|
|
||||||
CommonColor GetGlassColor() const;
|
|
||||||
u8 GetGlassScale() const;
|
|
||||||
u8 GetGlassY() const;
|
|
||||||
MoleType GetMoleType() const;
|
|
||||||
u8 GetMoleScale() const;
|
|
||||||
u8 GetMoleX() const;
|
|
||||||
u8 GetMoleY() const;
|
|
||||||
|
|
||||||
bool operator==(const CharInfo& info);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Common::UUID create_id;
|
|
||||||
Nickname name;
|
|
||||||
u16 null_terminator;
|
|
||||||
FontRegion font_region;
|
|
||||||
FavoriteColor favorite_color;
|
|
||||||
Gender gender;
|
|
||||||
u8 height;
|
|
||||||
u8 build;
|
|
||||||
u8 type;
|
|
||||||
u8 region_move;
|
|
||||||
FacelineType faceline_type;
|
|
||||||
FacelineColor faceline_color;
|
|
||||||
FacelineWrinkle faceline_wrinkle;
|
|
||||||
FacelineMake faceline_make;
|
|
||||||
HairType hair_type;
|
|
||||||
CommonColor hair_color;
|
|
||||||
HairFlip hair_flip;
|
|
||||||
EyeType eye_type;
|
|
||||||
CommonColor eye_color;
|
|
||||||
u8 eye_scale;
|
|
||||||
u8 eye_aspect;
|
|
||||||
u8 eye_rotate;
|
|
||||||
u8 eye_x;
|
|
||||||
u8 eye_y;
|
|
||||||
EyebrowType eyebrow_type;
|
|
||||||
CommonColor eyebrow_color;
|
|
||||||
u8 eyebrow_scale;
|
|
||||||
u8 eyebrow_aspect;
|
|
||||||
u8 eyebrow_rotate;
|
|
||||||
u8 eyebrow_x;
|
|
||||||
u8 eyebrow_y;
|
|
||||||
NoseType nose_type;
|
|
||||||
u8 nose_scale;
|
|
||||||
u8 nose_y;
|
|
||||||
MouthType mouth_type;
|
|
||||||
CommonColor mouth_color;
|
|
||||||
u8 mouth_scale;
|
|
||||||
u8 mouth_aspect;
|
|
||||||
u8 mouth_y;
|
|
||||||
CommonColor beard_color;
|
|
||||||
BeardType beard_type;
|
|
||||||
MustacheType mustache_type;
|
|
||||||
u8 mustache_scale;
|
|
||||||
u8 mustache_y;
|
|
||||||
GlassType glass_type;
|
|
||||||
CommonColor glass_color;
|
|
||||||
u8 glass_scale;
|
|
||||||
u8 glass_y;
|
|
||||||
MoleType mole_type;
|
|
||||||
u8 mole_scale;
|
|
||||||
u8 mole_x;
|
|
||||||
u8 mole_y;
|
|
||||||
u8 padding;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CharInfo) == 0x58, "CharInfo has incorrect size.");
|
|
||||||
static_assert(std::has_unique_object_representations_v<CharInfo>,
|
|
||||||
"All bits of CharInfo must contribute to its value.");
|
|
||||||
|
|
||||||
struct CharInfoElement {
|
|
||||||
CharInfo char_info{};
|
|
||||||
Source source{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CharInfoElement) == 0x5c, "CharInfoElement has incorrect size.");
|
|
||||||
|
|
||||||
}; // namespace Service::Mii
|
|
@ -1,601 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "core/hle/service/mii/mii_util.h"
|
|
||||||
#include "core/hle/service/mii/types/core_data.h"
|
|
||||||
#include "core/hle/service/mii/types/raw_data.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
void CoreData::SetDefault() {
|
|
||||||
data = {};
|
|
||||||
name = GetDefaultNickname();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::BuildRandom(Age age, Gender gender, Race race) {
|
|
||||||
if (gender == Gender::All) {
|
|
||||||
gender = MiiUtil::GetRandomValue(Gender::Max);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (age == Age::All) {
|
|
||||||
const auto random{MiiUtil::GetRandomValue<int>(10)};
|
|
||||||
if (random >= 8) {
|
|
||||||
age = Age::Old;
|
|
||||||
} else if (random >= 4) {
|
|
||||||
age = Age::Normal;
|
|
||||||
} else {
|
|
||||||
age = Age::Young;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (race == Race::All) {
|
|
||||||
const auto random{MiiUtil::GetRandomValue<int>(10)};
|
|
||||||
if (random >= 8) {
|
|
||||||
race = Race::Black;
|
|
||||||
} else if (random >= 4) {
|
|
||||||
race = Race::White;
|
|
||||||
} else {
|
|
||||||
race = Race::Asian;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetGender(gender);
|
|
||||||
SetFavoriteColor(MiiUtil::GetRandomValue(FavoriteColor::Max));
|
|
||||||
SetRegionMove(0);
|
|
||||||
SetFontRegion(FontRegion::Standard);
|
|
||||||
SetType(0);
|
|
||||||
SetHeight(64);
|
|
||||||
SetBuild(64);
|
|
||||||
|
|
||||||
u32 axis_y{};
|
|
||||||
if (gender == Gender::Female && age == Age::Young) {
|
|
||||||
axis_y = MiiUtil::GetRandomValue<u32>(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::size_t index{3 * static_cast<std::size_t>(age) +
|
|
||||||
9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
|
|
||||||
|
|
||||||
const auto& faceline_type_info{RawData::RandomMiiFaceline.at(index)};
|
|
||||||
const auto& faceline_color_info{RawData::RandomMiiFacelineColor.at(
|
|
||||||
3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
|
|
||||||
const auto& faceline_wrinkle_info{RawData::RandomMiiFacelineWrinkle.at(index)};
|
|
||||||
const auto& faceline_makeup_info{RawData::RandomMiiFacelineMakeup.at(index)};
|
|
||||||
const auto& hair_type_info{RawData::RandomMiiHairType.at(index)};
|
|
||||||
const auto& hair_color_info{RawData::RandomMiiHairColor.at(3 * static_cast<std::size_t>(race) +
|
|
||||||
static_cast<std::size_t>(age))};
|
|
||||||
const auto& eye_type_info{RawData::RandomMiiEyeType.at(index)};
|
|
||||||
const auto& eye_color_info{RawData::RandomMiiEyeColor.at(static_cast<std::size_t>(race))};
|
|
||||||
const auto& eyebrow_type_info{RawData::RandomMiiEyebrowType.at(index)};
|
|
||||||
const auto& nose_type_info{RawData::RandomMiiNoseType.at(index)};
|
|
||||||
const auto& mouth_type_info{RawData::RandomMiiMouthType.at(index)};
|
|
||||||
const auto& glasses_type_info{RawData::RandomMiiGlassType.at(static_cast<std::size_t>(age))};
|
|
||||||
|
|
||||||
data.faceline_type.Assign(
|
|
||||||
faceline_type_info
|
|
||||||
.values[MiiUtil::GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
|
|
||||||
data.faceline_color.Assign(
|
|
||||||
faceline_color_info
|
|
||||||
.values[MiiUtil::GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
|
|
||||||
data.faceline_wrinkle.Assign(
|
|
||||||
faceline_wrinkle_info
|
|
||||||
.values[MiiUtil::GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
|
|
||||||
data.faceline_makeup.Assign(
|
|
||||||
faceline_makeup_info
|
|
||||||
.values[MiiUtil::GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
|
|
||||||
|
|
||||||
data.hair_type.Assign(
|
|
||||||
hair_type_info.values[MiiUtil::GetRandomValue<std::size_t>(hair_type_info.values_count)]);
|
|
||||||
SetHairColor(RawData::GetHairColorFromVer3(
|
|
||||||
hair_color_info
|
|
||||||
.values[MiiUtil::GetRandomValue<std::size_t>(hair_color_info.values_count)]));
|
|
||||||
SetHairFlip(MiiUtil::GetRandomValue(HairFlip::Max));
|
|
||||||
|
|
||||||
data.eye_type.Assign(
|
|
||||||
eye_type_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_type_info.values_count)]);
|
|
||||||
|
|
||||||
const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
|
|
||||||
const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
|
|
||||||
const auto eye_rotate_offset{32 - RawData::EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
|
|
||||||
const auto eye_rotate{32 - RawData::EyeRotateLookup[data.eye_type]};
|
|
||||||
|
|
||||||
SetEyeColor(RawData::GetEyeColorFromVer3(
|
|
||||||
eye_color_info.values[MiiUtil::GetRandomValue<std::size_t>(eye_color_info.values_count)]));
|
|
||||||
SetEyeScale(4);
|
|
||||||
SetEyeAspect(3);
|
|
||||||
SetEyeRotate(static_cast<u8>(eye_rotate_offset - eye_rotate));
|
|
||||||
SetEyeX(2);
|
|
||||||
SetEyeY(static_cast<u8>(axis_y + 12));
|
|
||||||
|
|
||||||
data.eyebrow_type.Assign(
|
|
||||||
eyebrow_type_info
|
|
||||||
.values[MiiUtil::GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
|
|
||||||
|
|
||||||
const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
|
|
||||||
const auto eyebrow_y{race == Race::Asian ? 9 : 10};
|
|
||||||
const auto eyebrow_rotate_offset{32 - RawData::EyebrowRotateLookup[eyebrow_rotate_1] + 6};
|
|
||||||
const auto eyebrow_rotate{
|
|
||||||
32 - RawData::EyebrowRotateLookup[static_cast<std::size_t>(data.eyebrow_type.Value())]};
|
|
||||||
|
|
||||||
SetEyebrowColor(GetHairColor());
|
|
||||||
SetEyebrowScale(4);
|
|
||||||
SetEyebrowAspect(3);
|
|
||||||
SetEyebrowRotate(static_cast<u8>(eyebrow_rotate_offset - eyebrow_rotate));
|
|
||||||
SetEyebrowX(2);
|
|
||||||
SetEyebrowY(static_cast<u8>(axis_y + eyebrow_y));
|
|
||||||
|
|
||||||
data.nose_type.Assign(
|
|
||||||
nose_type_info.values[MiiUtil::GetRandomValue<std::size_t>(nose_type_info.values_count)]);
|
|
||||||
SetNoseScale(gender == Gender::Female ? 3 : 4);
|
|
||||||
SetNoseY(static_cast<u8>(axis_y + 9));
|
|
||||||
|
|
||||||
const auto mouth_color{gender == Gender::Female ? MiiUtil::GetRandomValue<int>(4) : 0};
|
|
||||||
|
|
||||||
data.mouth_type.Assign(
|
|
||||||
mouth_type_info.values[MiiUtil::GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
|
|
||||||
SetMouthColor(RawData::GetMouthColorFromVer3(mouth_color));
|
|
||||||
SetMouthScale(4);
|
|
||||||
SetMouthAspect(3);
|
|
||||||
SetMouthY(static_cast<u8>(axis_y + 13));
|
|
||||||
|
|
||||||
SetBeardColor(GetHairColor());
|
|
||||||
SetMustacheScale(4);
|
|
||||||
|
|
||||||
if (gender == Gender::Male && age != Age::Young && MiiUtil::GetRandomValue<int>(10) < 2) {
|
|
||||||
const auto mustache_and_beard_flag{MiiUtil::GetRandomValue(BeardAndMustacheFlag::All)};
|
|
||||||
|
|
||||||
auto beard_type{BeardType::None};
|
|
||||||
auto mustache_type{MustacheType::None};
|
|
||||||
|
|
||||||
if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
|
|
||||||
BeardAndMustacheFlag::Beard) {
|
|
||||||
beard_type = MiiUtil::GetRandomValue(BeardType::Min, BeardType::Max);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
|
|
||||||
BeardAndMustacheFlag::Mustache) {
|
|
||||||
mustache_type = MiiUtil::GetRandomValue(MustacheType::Min, MustacheType::Max);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetMustacheType(mustache_type);
|
|
||||||
SetBeardType(beard_type);
|
|
||||||
SetMustacheY(10);
|
|
||||||
} else {
|
|
||||||
SetMustacheType(MustacheType::None);
|
|
||||||
SetBeardType(BeardType::None);
|
|
||||||
SetMustacheY(static_cast<u8>(axis_y + 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto glasses_type_start{MiiUtil::GetRandomValue<std::size_t>(100)};
|
|
||||||
u8 glasses_type{};
|
|
||||||
while (glasses_type_start < glasses_type_info.values[glasses_type]) {
|
|
||||||
if (++glasses_type >= glasses_type_info.values_count) {
|
|
||||||
ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetGlassType(static_cast<GlassType>(glasses_type));
|
|
||||||
SetGlassColor(RawData::GetGlassColorFromVer3(0));
|
|
||||||
SetGlassScale(4);
|
|
||||||
|
|
||||||
SetMoleType(MoleType::None);
|
|
||||||
SetMoleScale(4);
|
|
||||||
SetMoleX(2);
|
|
||||||
SetMoleY(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 CoreData::IsValid() const {
|
|
||||||
// TODO: Complete this
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetFontRegion(FontRegion value) {
|
|
||||||
data.font_region.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetFavoriteColor(FavoriteColor value) {
|
|
||||||
data.favorite_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetGender(Gender value) {
|
|
||||||
data.gender.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetHeight(u8 value) {
|
|
||||||
data.height.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetBuild(u8 value) {
|
|
||||||
data.build.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetType(u8 value) {
|
|
||||||
data.type.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetRegionMove(u8 value) {
|
|
||||||
data.region_move.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetFacelineType(FacelineType value) {
|
|
||||||
data.faceline_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetFacelineColor(FacelineColor value) {
|
|
||||||
data.faceline_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetFacelineWrinkle(FacelineWrinkle value) {
|
|
||||||
data.faceline_wrinkle.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetFacelineMake(FacelineMake value) {
|
|
||||||
data.faceline_makeup.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetHairType(HairType value) {
|
|
||||||
data.hair_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetHairColor(CommonColor value) {
|
|
||||||
data.hair_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetHairFlip(HairFlip value) {
|
|
||||||
data.hair_flip.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyeType(EyeType value) {
|
|
||||||
data.eye_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyeColor(CommonColor value) {
|
|
||||||
data.eye_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyeScale(u8 value) {
|
|
||||||
data.eye_scale.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyeAspect(u8 value) {
|
|
||||||
data.eye_aspect.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyeRotate(u8 value) {
|
|
||||||
data.eye_rotate.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyeX(u8 value) {
|
|
||||||
data.eye_x.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyeY(u8 value) {
|
|
||||||
data.eye_y.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyebrowType(EyebrowType value) {
|
|
||||||
data.eyebrow_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyebrowColor(CommonColor value) {
|
|
||||||
data.eyebrow_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyebrowScale(u8 value) {
|
|
||||||
data.eyebrow_scale.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyebrowAspect(u8 value) {
|
|
||||||
data.eyebrow_aspect.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyebrowRotate(u8 value) {
|
|
||||||
data.eyebrow_rotate.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyebrowX(u8 value) {
|
|
||||||
data.eyebrow_x.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetEyebrowY(u8 value) {
|
|
||||||
data.eyebrow_y.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetNoseType(NoseType value) {
|
|
||||||
data.nose_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetNoseScale(u8 value) {
|
|
||||||
data.nose_scale.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetNoseY(u8 value) {
|
|
||||||
data.nose_y.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMouthType(u8 value) {
|
|
||||||
data.mouth_type.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMouthColor(CommonColor value) {
|
|
||||||
data.mouth_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMouthScale(u8 value) {
|
|
||||||
data.mouth_scale.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMouthAspect(u8 value) {
|
|
||||||
data.mouth_aspect.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMouthY(u8 value) {
|
|
||||||
data.mouth_y.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetBeardColor(CommonColor value) {
|
|
||||||
data.beard_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetBeardType(BeardType value) {
|
|
||||||
data.beard_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMustacheType(MustacheType value) {
|
|
||||||
data.mustache_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMustacheScale(u8 value) {
|
|
||||||
data.mustache_scale.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMustacheY(u8 value) {
|
|
||||||
data.mustache_y.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetGlassType(GlassType value) {
|
|
||||||
data.glasses_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetGlassColor(CommonColor value) {
|
|
||||||
data.glasses_color.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetGlassScale(u8 value) {
|
|
||||||
data.glasses_scale.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetGlassY(u8 value) {
|
|
||||||
data.glasses_y.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMoleType(MoleType value) {
|
|
||||||
data.mole_type.Assign(static_cast<u32>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMoleScale(u8 value) {
|
|
||||||
data.mole_scale.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMoleX(u8 value) {
|
|
||||||
data.mole_x.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetMoleY(u8 value) {
|
|
||||||
data.mole_y.Assign(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreData::SetNickname(Nickname nickname) {
|
|
||||||
name = nickname;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontRegion CoreData::GetFontRegion() const {
|
|
||||||
return static_cast<FontRegion>(data.font_region.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
FavoriteColor CoreData::GetFavoriteColor() const {
|
|
||||||
return static_cast<FavoriteColor>(data.favorite_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
Gender CoreData::GetGender() const {
|
|
||||||
return static_cast<Gender>(data.gender.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetHeight() const {
|
|
||||||
return static_cast<u8>(data.height.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetBuild() const {
|
|
||||||
return static_cast<u8>(data.build.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetType() const {
|
|
||||||
return static_cast<u8>(data.type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetRegionMove() const {
|
|
||||||
return static_cast<u8>(data.region_move.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineType CoreData::GetFacelineType() const {
|
|
||||||
return static_cast<FacelineType>(data.faceline_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineColor CoreData::GetFacelineColor() const {
|
|
||||||
return static_cast<FacelineColor>(data.faceline_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineWrinkle CoreData::GetFacelineWrinkle() const {
|
|
||||||
return static_cast<FacelineWrinkle>(data.faceline_wrinkle.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineMake CoreData::GetFacelineMake() const {
|
|
||||||
return static_cast<FacelineMake>(data.faceline_makeup.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
HairType CoreData::GetHairType() const {
|
|
||||||
return static_cast<HairType>(data.hair_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CoreData::GetHairColor() const {
|
|
||||||
return static_cast<CommonColor>(data.hair_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
HairFlip CoreData::GetHairFlip() const {
|
|
||||||
return static_cast<HairFlip>(data.hair_flip.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
EyeType CoreData::GetEyeType() const {
|
|
||||||
return static_cast<EyeType>(data.eye_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CoreData::GetEyeColor() const {
|
|
||||||
return static_cast<CommonColor>(data.eye_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyeScale() const {
|
|
||||||
return static_cast<u8>(data.eye_scale.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyeAspect() const {
|
|
||||||
return static_cast<u8>(data.eye_aspect.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyeRotate() const {
|
|
||||||
return static_cast<u8>(data.eye_rotate.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyeX() const {
|
|
||||||
return static_cast<u8>(data.eye_x.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyeY() const {
|
|
||||||
return static_cast<u8>(data.eye_y.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
EyebrowType CoreData::GetEyebrowType() const {
|
|
||||||
return static_cast<EyebrowType>(data.eyebrow_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CoreData::GetEyebrowColor() const {
|
|
||||||
return static_cast<CommonColor>(data.eyebrow_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyebrowScale() const {
|
|
||||||
return static_cast<u8>(data.eyebrow_scale.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyebrowAspect() const {
|
|
||||||
return static_cast<u8>(data.eyebrow_aspect.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyebrowRotate() const {
|
|
||||||
return static_cast<u8>(data.eyebrow_rotate.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyebrowX() const {
|
|
||||||
return static_cast<u8>(data.eyebrow_x.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetEyebrowY() const {
|
|
||||||
return static_cast<u8>(data.eyebrow_y.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
NoseType CoreData::GetNoseType() const {
|
|
||||||
return static_cast<NoseType>(data.nose_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetNoseScale() const {
|
|
||||||
return static_cast<u8>(data.nose_scale.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetNoseY() const {
|
|
||||||
return static_cast<u8>(data.nose_y.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
MouthType CoreData::GetMouthType() const {
|
|
||||||
return static_cast<MouthType>(data.mouth_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CoreData::GetMouthColor() const {
|
|
||||||
return static_cast<CommonColor>(data.mouth_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMouthScale() const {
|
|
||||||
return static_cast<u8>(data.mouth_scale.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMouthAspect() const {
|
|
||||||
return static_cast<u8>(data.mouth_aspect.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMouthY() const {
|
|
||||||
return static_cast<u8>(data.mouth_y.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CoreData::GetBeardColor() const {
|
|
||||||
return static_cast<CommonColor>(data.beard_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
BeardType CoreData::GetBeardType() const {
|
|
||||||
return static_cast<BeardType>(data.beard_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
MustacheType CoreData::GetMustacheType() const {
|
|
||||||
return static_cast<MustacheType>(data.mustache_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMustacheScale() const {
|
|
||||||
return static_cast<u8>(data.mustache_scale.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMustacheY() const {
|
|
||||||
return static_cast<u8>(data.mustache_y.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
GlassType CoreData::GetGlassType() const {
|
|
||||||
return static_cast<GlassType>(data.glasses_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor CoreData::GetGlassColor() const {
|
|
||||||
return static_cast<CommonColor>(data.glasses_color.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetGlassScale() const {
|
|
||||||
return static_cast<u8>(data.glasses_scale.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetGlassY() const {
|
|
||||||
return static_cast<u8>(data.glasses_y.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
MoleType CoreData::GetMoleType() const {
|
|
||||||
return static_cast<MoleType>(data.mole_type.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMoleScale() const {
|
|
||||||
return static_cast<u8>(data.mole_scale.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMoleX() const {
|
|
||||||
return static_cast<u8>(data.mole_x.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CoreData::GetMoleY() const {
|
|
||||||
return static_cast<u8>(data.mole_y.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
Nickname CoreData::GetNickname() const {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nickname CoreData::GetDefaultNickname() const {
|
|
||||||
return {u'n', u'o', u' ', u'n', u'a', u'm', u'e'};
|
|
||||||
}
|
|
||||||
|
|
||||||
Nickname CoreData::GetInvalidNickname() const {
|
|
||||||
return {u'?', u'?', u'?'};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Mii
|
|
@ -1,216 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/mii_types.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
struct StoreDataBitFields {
|
|
||||||
union {
|
|
||||||
u32 word_0{};
|
|
||||||
|
|
||||||
BitField<0, 8, u32> hair_type;
|
|
||||||
BitField<8, 7, u32> height;
|
|
||||||
BitField<15, 1, u32> mole_type;
|
|
||||||
BitField<16, 7, u32> build;
|
|
||||||
BitField<23, 1, u32> hair_flip;
|
|
||||||
BitField<24, 7, u32> hair_color;
|
|
||||||
BitField<31, 1, u32> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
u32 word_1{};
|
|
||||||
|
|
||||||
BitField<0, 7, u32> eye_color;
|
|
||||||
BitField<7, 1, u32> gender;
|
|
||||||
BitField<8, 7, u32> eyebrow_color;
|
|
||||||
BitField<16, 7, u32> mouth_color;
|
|
||||||
BitField<24, 7, u32> beard_color;
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
u32 word_2{};
|
|
||||||
|
|
||||||
BitField<0, 7, u32> glasses_color;
|
|
||||||
BitField<8, 6, u32> eye_type;
|
|
||||||
BitField<14, 2, u32> region_move;
|
|
||||||
BitField<16, 6, u32> mouth_type;
|
|
||||||
BitField<22, 2, u32> font_region;
|
|
||||||
BitField<24, 5, u32> eye_y;
|
|
||||||
BitField<29, 3, u32> glasses_scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
u32 word_3{};
|
|
||||||
|
|
||||||
BitField<0, 5, u32> eyebrow_type;
|
|
||||||
BitField<5, 3, u32> mustache_type;
|
|
||||||
BitField<8, 5, u32> nose_type;
|
|
||||||
BitField<13, 3, u32> beard_type;
|
|
||||||
BitField<16, 5, u32> nose_y;
|
|
||||||
BitField<21, 3, u32> mouth_aspect;
|
|
||||||
BitField<24, 5, u32> mouth_y;
|
|
||||||
BitField<29, 3, u32> eyebrow_aspect;
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
u32 word_4{};
|
|
||||||
|
|
||||||
BitField<0, 5, u32> mustache_y;
|
|
||||||
BitField<5, 3, u32> eye_rotate;
|
|
||||||
BitField<8, 5, u32> glasses_y;
|
|
||||||
BitField<13, 3, u32> eye_aspect;
|
|
||||||
BitField<16, 5, u32> mole_x;
|
|
||||||
BitField<21, 3, u32> eye_scale;
|
|
||||||
BitField<24, 5, u32> mole_y;
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
u32 word_5{};
|
|
||||||
|
|
||||||
BitField<0, 5, u32> glasses_type;
|
|
||||||
BitField<8, 4, u32> favorite_color;
|
|
||||||
BitField<12, 4, u32> faceline_type;
|
|
||||||
BitField<16, 4, u32> faceline_color;
|
|
||||||
BitField<20, 4, u32> faceline_wrinkle;
|
|
||||||
BitField<24, 4, u32> faceline_makeup;
|
|
||||||
BitField<28, 4, u32> eye_x;
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
u32 word_6{};
|
|
||||||
|
|
||||||
BitField<0, 4, u32> eyebrow_scale;
|
|
||||||
BitField<4, 4, u32> eyebrow_rotate;
|
|
||||||
BitField<8, 4, u32> eyebrow_x;
|
|
||||||
BitField<12, 4, u32> eyebrow_y;
|
|
||||||
BitField<16, 4, u32> nose_scale;
|
|
||||||
BitField<20, 4, u32> mouth_scale;
|
|
||||||
BitField<24, 4, u32> mustache_scale;
|
|
||||||
BitField<28, 4, u32> mole_scale;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(StoreDataBitFields) == 0x1c, "StoreDataBitFields has incorrect size.");
|
|
||||||
static_assert(std::is_trivially_copyable_v<StoreDataBitFields>,
|
|
||||||
"StoreDataBitFields is not trivially copyable.");
|
|
||||||
|
|
||||||
class CoreData {
|
|
||||||
public:
|
|
||||||
void SetDefault();
|
|
||||||
void BuildRandom(Age age, Gender gender, Race race);
|
|
||||||
|
|
||||||
u32 IsValid() const;
|
|
||||||
|
|
||||||
void SetFontRegion(FontRegion value);
|
|
||||||
void SetFavoriteColor(FavoriteColor value);
|
|
||||||
void SetGender(Gender value);
|
|
||||||
void SetHeight(u8 value);
|
|
||||||
void SetBuild(u8 value);
|
|
||||||
void SetType(u8 value);
|
|
||||||
void SetRegionMove(u8 value);
|
|
||||||
void SetFacelineType(FacelineType value);
|
|
||||||
void SetFacelineColor(FacelineColor value);
|
|
||||||
void SetFacelineWrinkle(FacelineWrinkle value);
|
|
||||||
void SetFacelineMake(FacelineMake value);
|
|
||||||
void SetHairType(HairType value);
|
|
||||||
void SetHairColor(CommonColor value);
|
|
||||||
void SetHairFlip(HairFlip value);
|
|
||||||
void SetEyeType(EyeType value);
|
|
||||||
void SetEyeColor(CommonColor value);
|
|
||||||
void SetEyeScale(u8 value);
|
|
||||||
void SetEyeAspect(u8 value);
|
|
||||||
void SetEyeRotate(u8 value);
|
|
||||||
void SetEyeX(u8 value);
|
|
||||||
void SetEyeY(u8 value);
|
|
||||||
void SetEyebrowType(EyebrowType value);
|
|
||||||
void SetEyebrowColor(CommonColor value);
|
|
||||||
void SetEyebrowScale(u8 value);
|
|
||||||
void SetEyebrowAspect(u8 value);
|
|
||||||
void SetEyebrowRotate(u8 value);
|
|
||||||
void SetEyebrowX(u8 value);
|
|
||||||
void SetEyebrowY(u8 value);
|
|
||||||
void SetNoseType(NoseType value);
|
|
||||||
void SetNoseScale(u8 value);
|
|
||||||
void SetNoseY(u8 value);
|
|
||||||
void SetMouthType(u8 value);
|
|
||||||
void SetMouthColor(CommonColor value);
|
|
||||||
void SetMouthScale(u8 value);
|
|
||||||
void SetMouthAspect(u8 value);
|
|
||||||
void SetMouthY(u8 value);
|
|
||||||
void SetBeardColor(CommonColor value);
|
|
||||||
void SetBeardType(BeardType value);
|
|
||||||
void SetMustacheType(MustacheType value);
|
|
||||||
void SetMustacheScale(u8 value);
|
|
||||||
void SetMustacheY(u8 value);
|
|
||||||
void SetGlassType(GlassType value);
|
|
||||||
void SetGlassColor(CommonColor value);
|
|
||||||
void SetGlassScale(u8 value);
|
|
||||||
void SetGlassY(u8 value);
|
|
||||||
void SetMoleType(MoleType value);
|
|
||||||
void SetMoleScale(u8 value);
|
|
||||||
void SetMoleX(u8 value);
|
|
||||||
void SetMoleY(u8 value);
|
|
||||||
void SetNickname(Nickname nickname);
|
|
||||||
|
|
||||||
FontRegion GetFontRegion() const;
|
|
||||||
FavoriteColor GetFavoriteColor() const;
|
|
||||||
Gender GetGender() const;
|
|
||||||
u8 GetHeight() const;
|
|
||||||
u8 GetBuild() const;
|
|
||||||
u8 GetType() const;
|
|
||||||
u8 GetRegionMove() const;
|
|
||||||
FacelineType GetFacelineType() const;
|
|
||||||
FacelineColor GetFacelineColor() const;
|
|
||||||
FacelineWrinkle GetFacelineWrinkle() const;
|
|
||||||
FacelineMake GetFacelineMake() const;
|
|
||||||
HairType GetHairType() const;
|
|
||||||
CommonColor GetHairColor() const;
|
|
||||||
HairFlip GetHairFlip() const;
|
|
||||||
EyeType GetEyeType() const;
|
|
||||||
CommonColor GetEyeColor() const;
|
|
||||||
u8 GetEyeScale() const;
|
|
||||||
u8 GetEyeAspect() const;
|
|
||||||
u8 GetEyeRotate() const;
|
|
||||||
u8 GetEyeX() const;
|
|
||||||
u8 GetEyeY() const;
|
|
||||||
EyebrowType GetEyebrowType() const;
|
|
||||||
CommonColor GetEyebrowColor() const;
|
|
||||||
u8 GetEyebrowScale() const;
|
|
||||||
u8 GetEyebrowAspect() const;
|
|
||||||
u8 GetEyebrowRotate() const;
|
|
||||||
u8 GetEyebrowX() const;
|
|
||||||
u8 GetEyebrowY() const;
|
|
||||||
NoseType GetNoseType() const;
|
|
||||||
u8 GetNoseScale() const;
|
|
||||||
u8 GetNoseY() const;
|
|
||||||
MouthType GetMouthType() const;
|
|
||||||
CommonColor GetMouthColor() const;
|
|
||||||
u8 GetMouthScale() const;
|
|
||||||
u8 GetMouthAspect() const;
|
|
||||||
u8 GetMouthY() const;
|
|
||||||
CommonColor GetBeardColor() const;
|
|
||||||
BeardType GetBeardType() const;
|
|
||||||
MustacheType GetMustacheType() const;
|
|
||||||
u8 GetMustacheScale() const;
|
|
||||||
u8 GetMustacheY() const;
|
|
||||||
GlassType GetGlassType() const;
|
|
||||||
CommonColor GetGlassColor() const;
|
|
||||||
u8 GetGlassScale() const;
|
|
||||||
u8 GetGlassY() const;
|
|
||||||
MoleType GetMoleType() const;
|
|
||||||
u8 GetMoleScale() const;
|
|
||||||
u8 GetMoleX() const;
|
|
||||||
u8 GetMoleY() const;
|
|
||||||
Nickname GetNickname() const;
|
|
||||||
Nickname GetDefaultNickname() const;
|
|
||||||
Nickname GetInvalidNickname() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
StoreDataBitFields data{};
|
|
||||||
Nickname name{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CoreData) == 0x30, "CoreData has incorrect size.");
|
|
||||||
|
|
||||||
}; // namespace Service::Mii
|
|
@ -1,73 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/mii_types.h"
|
|
||||||
|
|
||||||
namespace Service::Mii::RawData {
|
|
||||||
|
|
||||||
struct RandomMiiValues {
|
|
||||||
std::array<u8, 188> values{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
|
|
||||||
|
|
||||||
struct RandomMiiData4 {
|
|
||||||
u32 gender{};
|
|
||||||
u32 age{};
|
|
||||||
u32 race{};
|
|
||||||
u32 values_count{};
|
|
||||||
std::array<u32, 47> values{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
|
|
||||||
|
|
||||||
struct RandomMiiData3 {
|
|
||||||
u32 arg_1;
|
|
||||||
u32 arg_2;
|
|
||||||
u32 values_count;
|
|
||||||
std::array<u32, 47> values{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
|
|
||||||
|
|
||||||
struct RandomMiiData2 {
|
|
||||||
u32 arg_1;
|
|
||||||
u32 values_count;
|
|
||||||
std::array<u32, 47> values{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
|
|
||||||
|
|
||||||
extern const std::array<Service::Mii::DefaultMii, 2> BaseMii;
|
|
||||||
extern const std::array<Service::Mii::DefaultMii, 6> DefaultMii;
|
|
||||||
|
|
||||||
extern const std::array<u8, 62> EyeRotateLookup;
|
|
||||||
extern const std::array<u8, 24> EyebrowRotateLookup;
|
|
||||||
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiFaceline;
|
|
||||||
extern const std::array<RandomMiiData3, 6> RandomMiiFacelineColor;
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiFacelineWrinkle;
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiFacelineMakeup;
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiHairType;
|
|
||||||
extern const std::array<RandomMiiData3, 9> RandomMiiHairColor;
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiEyeType;
|
|
||||||
extern const std::array<RandomMiiData2, 3> RandomMiiEyeColor;
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiEyebrowType;
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiNoseType;
|
|
||||||
extern const std::array<RandomMiiData4, 18> RandomMiiMouthType;
|
|
||||||
extern const std::array<RandomMiiData2, 3> RandomMiiGlassType;
|
|
||||||
|
|
||||||
u8 FromVer3GetFacelineColor(u8 color);
|
|
||||||
u8 FromVer3GetHairColor(u8 color);
|
|
||||||
u8 FromVer3GetEyeColor(u8 color);
|
|
||||||
u8 FromVer3GetMouthlineColor(u8 color);
|
|
||||||
u8 FromVer3GetGlassColor(u8 color);
|
|
||||||
u8 FromVer3GetGlassType(u8 type);
|
|
||||||
|
|
||||||
FacelineColor GetFacelineColorFromVer3(u32 color);
|
|
||||||
CommonColor GetHairColorFromVer3(u32 color);
|
|
||||||
CommonColor GetEyeColorFromVer3(u32 color);
|
|
||||||
CommonColor GetMouthColorFromVer3(u32 color);
|
|
||||||
CommonColor GetGlassColorFromVer3(u32 color);
|
|
||||||
|
|
||||||
} // namespace Service::Mii::RawData
|
|
@ -1,643 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/mii_util.h"
|
|
||||||
#include "core/hle/service/mii/types/raw_data.h"
|
|
||||||
#include "core/hle/service/mii/types/store_data.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
void StoreData::BuildDefault(u32 mii_index) {
|
|
||||||
const auto& default_mii = RawData::DefaultMii[mii_index];
|
|
||||||
core_data.SetDefault();
|
|
||||||
|
|
||||||
core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type));
|
|
||||||
core_data.SetFacelineColor(
|
|
||||||
RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color)));
|
|
||||||
core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle));
|
|
||||||
core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup));
|
|
||||||
|
|
||||||
core_data.SetHairType(static_cast<HairType>(default_mii.hair_type));
|
|
||||||
core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color)));
|
|
||||||
core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip));
|
|
||||||
core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type));
|
|
||||||
core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color)));
|
|
||||||
core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale));
|
|
||||||
core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect));
|
|
||||||
core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate));
|
|
||||||
core_data.SetEyeX(static_cast<u8>(default_mii.eye_x));
|
|
||||||
core_data.SetEyeY(static_cast<u8>(default_mii.eye_y));
|
|
||||||
|
|
||||||
core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type));
|
|
||||||
core_data.SetEyebrowColor(
|
|
||||||
RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color)));
|
|
||||||
core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale));
|
|
||||||
core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect));
|
|
||||||
core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate));
|
|
||||||
core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x));
|
|
||||||
core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y));
|
|
||||||
|
|
||||||
core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type));
|
|
||||||
core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale));
|
|
||||||
core_data.SetNoseY(static_cast<u8>(default_mii.nose_y));
|
|
||||||
|
|
||||||
core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type));
|
|
||||||
core_data.SetMouthColor(
|
|
||||||
RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color)));
|
|
||||||
core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale));
|
|
||||||
core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect));
|
|
||||||
core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y));
|
|
||||||
|
|
||||||
core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type));
|
|
||||||
core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type));
|
|
||||||
core_data.SetBeardColor(
|
|
||||||
RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color)));
|
|
||||||
core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale));
|
|
||||||
core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y));
|
|
||||||
|
|
||||||
core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type));
|
|
||||||
core_data.SetGlassColor(
|
|
||||||
RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color)));
|
|
||||||
core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale));
|
|
||||||
core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y));
|
|
||||||
|
|
||||||
core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type));
|
|
||||||
core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale));
|
|
||||||
core_data.SetMoleX(static_cast<u8>(default_mii.mole_x));
|
|
||||||
core_data.SetMoleY(static_cast<u8>(default_mii.mole_y));
|
|
||||||
|
|
||||||
core_data.SetHeight(static_cast<u8>(default_mii.height));
|
|
||||||
core_data.SetBuild(static_cast<u8>(default_mii.weight));
|
|
||||||
core_data.SetGender(static_cast<Gender>(default_mii.gender));
|
|
||||||
core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color));
|
|
||||||
core_data.SetRegionMove(static_cast<u8>(default_mii.region_move));
|
|
||||||
core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region));
|
|
||||||
core_data.SetType(static_cast<u8>(default_mii.type));
|
|
||||||
core_data.SetNickname(default_mii.nickname);
|
|
||||||
|
|
||||||
const auto device_id = MiiUtil::GetDeviceId();
|
|
||||||
create_id = MiiUtil::MakeCreateId();
|
|
||||||
device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
|
|
||||||
data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::BuildBase(Gender gender) {
|
|
||||||
const auto& default_mii = RawData::BaseMii[gender == Gender::Female ? 1 : 0];
|
|
||||||
core_data.SetDefault();
|
|
||||||
|
|
||||||
core_data.SetFacelineType(static_cast<FacelineType>(default_mii.face_type));
|
|
||||||
core_data.SetFacelineColor(
|
|
||||||
RawData::GetFacelineColorFromVer3(static_cast<u8>(default_mii.face_color)));
|
|
||||||
core_data.SetFacelineWrinkle(static_cast<FacelineWrinkle>(default_mii.face_wrinkle));
|
|
||||||
core_data.SetFacelineMake(static_cast<FacelineMake>(default_mii.face_makeup));
|
|
||||||
|
|
||||||
core_data.SetHairType(static_cast<HairType>(default_mii.hair_type));
|
|
||||||
core_data.SetHairColor(RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.hair_color)));
|
|
||||||
core_data.SetHairFlip(static_cast<HairFlip>(default_mii.hair_flip));
|
|
||||||
core_data.SetEyeType(static_cast<EyeType>(default_mii.eye_type));
|
|
||||||
core_data.SetEyeColor(RawData::GetEyeColorFromVer3(static_cast<u8>(default_mii.eye_color)));
|
|
||||||
core_data.SetEyeScale(static_cast<u8>(default_mii.eye_scale));
|
|
||||||
core_data.SetEyeAspect(static_cast<u8>(default_mii.eye_aspect));
|
|
||||||
core_data.SetEyeRotate(static_cast<u8>(default_mii.eye_rotate));
|
|
||||||
core_data.SetEyeX(static_cast<u8>(default_mii.eye_x));
|
|
||||||
core_data.SetEyeY(static_cast<u8>(default_mii.eye_y));
|
|
||||||
|
|
||||||
core_data.SetEyebrowType(static_cast<EyebrowType>(default_mii.eyebrow_type));
|
|
||||||
core_data.SetEyebrowColor(
|
|
||||||
RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.eyebrow_color)));
|
|
||||||
core_data.SetEyebrowScale(static_cast<u8>(default_mii.eyebrow_scale));
|
|
||||||
core_data.SetEyebrowAspect(static_cast<u8>(default_mii.eyebrow_aspect));
|
|
||||||
core_data.SetEyebrowRotate(static_cast<u8>(default_mii.eyebrow_rotate));
|
|
||||||
core_data.SetEyebrowX(static_cast<u8>(default_mii.eyebrow_x));
|
|
||||||
core_data.SetEyebrowY(static_cast<u8>(default_mii.eyebrow_y));
|
|
||||||
|
|
||||||
core_data.SetNoseType(static_cast<NoseType>(default_mii.nose_type));
|
|
||||||
core_data.SetNoseScale(static_cast<u8>(default_mii.nose_scale));
|
|
||||||
core_data.SetNoseY(static_cast<u8>(default_mii.nose_y));
|
|
||||||
|
|
||||||
core_data.SetMouthType(static_cast<u8>(default_mii.mouth_type));
|
|
||||||
core_data.SetMouthColor(
|
|
||||||
RawData::GetMouthColorFromVer3(static_cast<u8>(default_mii.mouth_color)));
|
|
||||||
core_data.SetMouthScale(static_cast<u8>(default_mii.mouth_scale));
|
|
||||||
core_data.SetMouthAspect(static_cast<u8>(default_mii.mouth_aspect));
|
|
||||||
core_data.SetMouthY(static_cast<u8>(default_mii.mouth_y));
|
|
||||||
|
|
||||||
core_data.SetMustacheType(static_cast<MustacheType>(default_mii.mustache_type));
|
|
||||||
core_data.SetBeardType(static_cast<BeardType>(default_mii.beard_type));
|
|
||||||
core_data.SetBeardColor(
|
|
||||||
RawData::GetHairColorFromVer3(static_cast<u8>(default_mii.beard_color)));
|
|
||||||
core_data.SetMustacheScale(static_cast<u8>(default_mii.mustache_scale));
|
|
||||||
core_data.SetMustacheY(static_cast<u8>(default_mii.mustache_y));
|
|
||||||
|
|
||||||
core_data.SetGlassType(static_cast<GlassType>(default_mii.glasses_type));
|
|
||||||
core_data.SetGlassColor(
|
|
||||||
RawData::GetGlassColorFromVer3(static_cast<u8>(default_mii.glasses_color)));
|
|
||||||
core_data.SetGlassScale(static_cast<u8>(default_mii.glasses_scale));
|
|
||||||
core_data.SetGlassY(static_cast<u8>(default_mii.glasses_y));
|
|
||||||
|
|
||||||
core_data.SetMoleType(static_cast<MoleType>(default_mii.mole_type));
|
|
||||||
core_data.SetMoleScale(static_cast<u8>(default_mii.mole_scale));
|
|
||||||
core_data.SetMoleX(static_cast<u8>(default_mii.mole_x));
|
|
||||||
core_data.SetMoleY(static_cast<u8>(default_mii.mole_y));
|
|
||||||
|
|
||||||
core_data.SetHeight(static_cast<u8>(default_mii.height));
|
|
||||||
core_data.SetBuild(static_cast<u8>(default_mii.weight));
|
|
||||||
core_data.SetGender(static_cast<Gender>(default_mii.gender));
|
|
||||||
core_data.SetFavoriteColor(static_cast<FavoriteColor>(default_mii.favorite_color));
|
|
||||||
core_data.SetRegionMove(static_cast<u8>(default_mii.region_move));
|
|
||||||
core_data.SetFontRegion(static_cast<FontRegion>(default_mii.font_region));
|
|
||||||
core_data.SetType(static_cast<u8>(default_mii.type));
|
|
||||||
core_data.SetNickname(default_mii.nickname);
|
|
||||||
|
|
||||||
const auto device_id = MiiUtil::GetDeviceId();
|
|
||||||
create_id = MiiUtil::MakeCreateId();
|
|
||||||
device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
|
|
||||||
data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::BuildRandom(Age age, Gender gender, Race race) {
|
|
||||||
core_data.BuildRandom(age, gender, race);
|
|
||||||
const auto device_id = MiiUtil::GetDeviceId();
|
|
||||||
create_id = MiiUtil::MakeCreateId();
|
|
||||||
device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
|
|
||||||
data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetInvalidName() {
|
|
||||||
const auto& invalid_name = core_data.GetInvalidNickname();
|
|
||||||
const auto device_id = MiiUtil::GetDeviceId();
|
|
||||||
core_data.SetNickname(invalid_name);
|
|
||||||
device_crc = MiiUtil::CalculateCrc16(&device_id, sizeof(Common::UUID));
|
|
||||||
data_crc = MiiUtil::CalculateCrc16(&core_data, sizeof(CoreData));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StoreData::IsSpecial() const {
|
|
||||||
return GetType() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 StoreData::IsValid() const {
|
|
||||||
// TODO: complete this
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetFontRegion(FontRegion value) {
|
|
||||||
core_data.SetFontRegion(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetFavoriteColor(FavoriteColor value) {
|
|
||||||
core_data.SetFavoriteColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetGender(Gender value) {
|
|
||||||
core_data.SetGender(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetHeight(u8 value) {
|
|
||||||
core_data.SetHeight(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetBuild(u8 value) {
|
|
||||||
core_data.SetBuild(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetType(u8 value) {
|
|
||||||
core_data.SetType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetRegionMove(u8 value) {
|
|
||||||
core_data.SetRegionMove(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetFacelineType(FacelineType value) {
|
|
||||||
core_data.SetFacelineType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetFacelineColor(FacelineColor value) {
|
|
||||||
core_data.SetFacelineColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetFacelineWrinkle(FacelineWrinkle value) {
|
|
||||||
core_data.SetFacelineWrinkle(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetFacelineMake(FacelineMake value) {
|
|
||||||
core_data.SetFacelineMake(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetHairType(HairType value) {
|
|
||||||
core_data.SetHairType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetHairColor(CommonColor value) {
|
|
||||||
core_data.SetHairColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetHairFlip(HairFlip value) {
|
|
||||||
core_data.SetHairFlip(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyeType(EyeType value) {
|
|
||||||
core_data.SetEyeType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyeColor(CommonColor value) {
|
|
||||||
core_data.SetEyeColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyeScale(u8 value) {
|
|
||||||
core_data.SetEyeScale(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyeAspect(u8 value) {
|
|
||||||
core_data.SetEyeAspect(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyeRotate(u8 value) {
|
|
||||||
core_data.SetEyeRotate(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyeX(u8 value) {
|
|
||||||
core_data.SetEyeX(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyeY(u8 value) {
|
|
||||||
core_data.SetEyeY(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyebrowType(EyebrowType value) {
|
|
||||||
core_data.SetEyebrowType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyebrowColor(CommonColor value) {
|
|
||||||
core_data.SetEyebrowColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyebrowScale(u8 value) {
|
|
||||||
core_data.SetEyebrowScale(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyebrowAspect(u8 value) {
|
|
||||||
core_data.SetEyebrowAspect(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyebrowRotate(u8 value) {
|
|
||||||
core_data.SetEyebrowRotate(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyebrowX(u8 value) {
|
|
||||||
core_data.SetEyebrowX(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetEyebrowY(u8 value) {
|
|
||||||
core_data.SetEyebrowY(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetNoseType(NoseType value) {
|
|
||||||
core_data.SetNoseType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetNoseScale(u8 value) {
|
|
||||||
core_data.SetNoseScale(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetNoseY(u8 value) {
|
|
||||||
core_data.SetNoseY(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMouthType(u8 value) {
|
|
||||||
core_data.SetMouthType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMouthColor(CommonColor value) {
|
|
||||||
core_data.SetMouthColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMouthScale(u8 value) {
|
|
||||||
core_data.SetMouthScale(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMouthAspect(u8 value) {
|
|
||||||
core_data.SetMouthAspect(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMouthY(u8 value) {
|
|
||||||
core_data.SetMouthY(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetBeardColor(CommonColor value) {
|
|
||||||
core_data.SetBeardColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetBeardType(BeardType value) {
|
|
||||||
core_data.SetBeardType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMustacheType(MustacheType value) {
|
|
||||||
core_data.SetMustacheType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMustacheScale(u8 value) {
|
|
||||||
core_data.SetMustacheScale(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMustacheY(u8 value) {
|
|
||||||
core_data.SetMustacheY(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetGlassType(GlassType value) {
|
|
||||||
core_data.SetGlassType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetGlassColor(CommonColor value) {
|
|
||||||
core_data.SetGlassColor(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetGlassScale(u8 value) {
|
|
||||||
core_data.SetGlassScale(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetGlassY(u8 value) {
|
|
||||||
core_data.SetGlassY(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMoleType(MoleType value) {
|
|
||||||
core_data.SetMoleType(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMoleScale(u8 value) {
|
|
||||||
core_data.SetMoleScale(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMoleX(u8 value) {
|
|
||||||
core_data.SetMoleX(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetMoleY(u8 value) {
|
|
||||||
core_data.SetMoleY(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreData::SetNickname(Nickname value) {
|
|
||||||
core_data.SetNickname(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::UUID StoreData::GetCreateId() const {
|
|
||||||
return create_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontRegion StoreData::GetFontRegion() const {
|
|
||||||
return static_cast<FontRegion>(core_data.GetFontRegion());
|
|
||||||
}
|
|
||||||
|
|
||||||
FavoriteColor StoreData::GetFavoriteColor() const {
|
|
||||||
return core_data.GetFavoriteColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
Gender StoreData::GetGender() const {
|
|
||||||
return core_data.GetGender();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetHeight() const {
|
|
||||||
return core_data.GetHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetBuild() const {
|
|
||||||
return core_data.GetBuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetType() const {
|
|
||||||
return core_data.GetType();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetRegionMove() const {
|
|
||||||
return core_data.GetRegionMove();
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineType StoreData::GetFacelineType() const {
|
|
||||||
return core_data.GetFacelineType();
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineColor StoreData::GetFacelineColor() const {
|
|
||||||
return core_data.GetFacelineColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineWrinkle StoreData::GetFacelineWrinkle() const {
|
|
||||||
return core_data.GetFacelineWrinkle();
|
|
||||||
}
|
|
||||||
|
|
||||||
FacelineMake StoreData::GetFacelineMake() const {
|
|
||||||
return core_data.GetFacelineMake();
|
|
||||||
}
|
|
||||||
|
|
||||||
HairType StoreData::GetHairType() const {
|
|
||||||
return core_data.GetHairType();
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor StoreData::GetHairColor() const {
|
|
||||||
return core_data.GetHairColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
HairFlip StoreData::GetHairFlip() const {
|
|
||||||
return core_data.GetHairFlip();
|
|
||||||
}
|
|
||||||
|
|
||||||
EyeType StoreData::GetEyeType() const {
|
|
||||||
return core_data.GetEyeType();
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor StoreData::GetEyeColor() const {
|
|
||||||
return core_data.GetEyeColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyeScale() const {
|
|
||||||
return core_data.GetEyeScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyeAspect() const {
|
|
||||||
return core_data.GetEyeAspect();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyeRotate() const {
|
|
||||||
return core_data.GetEyeRotate();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyeX() const {
|
|
||||||
return core_data.GetEyeX();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyeY() const {
|
|
||||||
return core_data.GetEyeY();
|
|
||||||
}
|
|
||||||
|
|
||||||
EyebrowType StoreData::GetEyebrowType() const {
|
|
||||||
return core_data.GetEyebrowType();
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor StoreData::GetEyebrowColor() const {
|
|
||||||
return core_data.GetEyebrowColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyebrowScale() const {
|
|
||||||
return core_data.GetEyebrowScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyebrowAspect() const {
|
|
||||||
return core_data.GetEyebrowAspect();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyebrowRotate() const {
|
|
||||||
return core_data.GetEyebrowRotate();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyebrowX() const {
|
|
||||||
return core_data.GetEyebrowX();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetEyebrowY() const {
|
|
||||||
return core_data.GetEyebrowY();
|
|
||||||
}
|
|
||||||
|
|
||||||
NoseType StoreData::GetNoseType() const {
|
|
||||||
return core_data.GetNoseType();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetNoseScale() const {
|
|
||||||
return core_data.GetNoseScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetNoseY() const {
|
|
||||||
return core_data.GetNoseY();
|
|
||||||
}
|
|
||||||
|
|
||||||
MouthType StoreData::GetMouthType() const {
|
|
||||||
return core_data.GetMouthType();
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor StoreData::GetMouthColor() const {
|
|
||||||
return core_data.GetMouthColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMouthScale() const {
|
|
||||||
return core_data.GetMouthScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMouthAspect() const {
|
|
||||||
return core_data.GetMouthAspect();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMouthY() const {
|
|
||||||
return core_data.GetMouthY();
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor StoreData::GetBeardColor() const {
|
|
||||||
return core_data.GetBeardColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
BeardType StoreData::GetBeardType() const {
|
|
||||||
return core_data.GetBeardType();
|
|
||||||
}
|
|
||||||
|
|
||||||
MustacheType StoreData::GetMustacheType() const {
|
|
||||||
return core_data.GetMustacheType();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMustacheScale() const {
|
|
||||||
return core_data.GetMustacheScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMustacheY() const {
|
|
||||||
return core_data.GetMustacheY();
|
|
||||||
}
|
|
||||||
|
|
||||||
GlassType StoreData::GetGlassType() const {
|
|
||||||
return core_data.GetGlassType();
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonColor StoreData::GetGlassColor() const {
|
|
||||||
return core_data.GetGlassColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetGlassScale() const {
|
|
||||||
return core_data.GetGlassScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetGlassY() const {
|
|
||||||
return core_data.GetGlassY();
|
|
||||||
}
|
|
||||||
|
|
||||||
MoleType StoreData::GetMoleType() const {
|
|
||||||
return core_data.GetMoleType();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMoleScale() const {
|
|
||||||
return core_data.GetMoleScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMoleX() const {
|
|
||||||
return core_data.GetMoleX();
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 StoreData::GetMoleY() const {
|
|
||||||
return core_data.GetMoleY();
|
|
||||||
}
|
|
||||||
|
|
||||||
Nickname StoreData::GetNickname() const {
|
|
||||||
return core_data.GetNickname();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StoreData::operator==(const StoreData& data) {
|
|
||||||
bool is_identical = data.core_data.IsValid() == 0;
|
|
||||||
is_identical &= core_data.GetNickname().data == data.core_data.GetNickname().data;
|
|
||||||
is_identical &= GetCreateId() == data.GetCreateId();
|
|
||||||
is_identical &= GetFontRegion() == data.GetFontRegion();
|
|
||||||
is_identical &= GetFavoriteColor() == data.GetFavoriteColor();
|
|
||||||
is_identical &= GetGender() == data.GetGender();
|
|
||||||
is_identical &= GetHeight() == data.GetHeight();
|
|
||||||
is_identical &= GetBuild() == data.GetBuild();
|
|
||||||
is_identical &= GetType() == data.GetType();
|
|
||||||
is_identical &= GetRegionMove() == data.GetRegionMove();
|
|
||||||
is_identical &= GetFacelineType() == data.GetFacelineType();
|
|
||||||
is_identical &= GetFacelineColor() == data.GetFacelineColor();
|
|
||||||
is_identical &= GetFacelineWrinkle() == data.GetFacelineWrinkle();
|
|
||||||
is_identical &= GetFacelineMake() == data.GetFacelineMake();
|
|
||||||
is_identical &= GetHairType() == data.GetHairType();
|
|
||||||
is_identical &= GetHairColor() == data.GetHairColor();
|
|
||||||
is_identical &= GetHairFlip() == data.GetHairFlip();
|
|
||||||
is_identical &= GetEyeType() == data.GetEyeType();
|
|
||||||
is_identical &= GetEyeColor() == data.GetEyeColor();
|
|
||||||
is_identical &= GetEyeScale() == data.GetEyeScale();
|
|
||||||
is_identical &= GetEyeAspect() == data.GetEyeAspect();
|
|
||||||
is_identical &= GetEyeRotate() == data.GetEyeRotate();
|
|
||||||
is_identical &= GetEyeX() == data.GetEyeX();
|
|
||||||
is_identical &= GetEyeY() == data.GetEyeY();
|
|
||||||
is_identical &= GetEyebrowType() == data.GetEyebrowType();
|
|
||||||
is_identical &= GetEyebrowColor() == data.GetEyebrowColor();
|
|
||||||
is_identical &= GetEyebrowScale() == data.GetEyebrowScale();
|
|
||||||
is_identical &= GetEyebrowAspect() == data.GetEyebrowAspect();
|
|
||||||
is_identical &= GetEyebrowRotate() == data.GetEyebrowRotate();
|
|
||||||
is_identical &= GetEyebrowX() == data.GetEyebrowX();
|
|
||||||
is_identical &= GetEyebrowY() == data.GetEyebrowY();
|
|
||||||
is_identical &= GetNoseType() == data.GetNoseType();
|
|
||||||
is_identical &= GetNoseScale() == data.GetNoseScale();
|
|
||||||
is_identical &= GetNoseY() == data.GetNoseY();
|
|
||||||
is_identical &= GetMouthType() == data.GetMouthType();
|
|
||||||
is_identical &= GetMouthColor() == data.GetMouthColor();
|
|
||||||
is_identical &= GetMouthScale() == data.GetMouthScale();
|
|
||||||
is_identical &= GetMouthAspect() == data.GetMouthAspect();
|
|
||||||
is_identical &= GetMouthY() == data.GetMouthY();
|
|
||||||
is_identical &= GetBeardColor() == data.GetBeardColor();
|
|
||||||
is_identical &= GetBeardType() == data.GetBeardType();
|
|
||||||
is_identical &= GetMustacheType() == data.GetMustacheType();
|
|
||||||
is_identical &= GetMustacheScale() == data.GetMustacheScale();
|
|
||||||
is_identical &= GetMustacheY() == data.GetMustacheY();
|
|
||||||
is_identical &= GetGlassType() == data.GetGlassType();
|
|
||||||
is_identical &= GetGlassColor() == data.GetGlassColor();
|
|
||||||
is_identical &= GetGlassScale() == data.GetGlassScale();
|
|
||||||
is_identical &= GetGlassY() == data.GetGlassY();
|
|
||||||
is_identical &= GetMoleType() == data.GetMoleType();
|
|
||||||
is_identical &= GetMoleScale() == data.GetMoleScale();
|
|
||||||
is_identical &= GetMoleX() == data.GetMoleX();
|
|
||||||
is_identical &= data.GetMoleY() == data.GetMoleY();
|
|
||||||
return is_identical;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Mii
|
|
@ -1,145 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/mii_types.h"
|
|
||||||
#include "core/hle/service/mii/types/core_data.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
class StoreData {
|
|
||||||
public:
|
|
||||||
// nn::mii::detail::StoreDataRaw::BuildDefault
|
|
||||||
void BuildDefault(u32 mii_index);
|
|
||||||
// nn::mii::detail::StoreDataRaw::BuildDefault
|
|
||||||
|
|
||||||
void BuildBase(Gender gender);
|
|
||||||
// nn::mii::detail::StoreDataRaw::BuildRandom
|
|
||||||
void BuildRandom(Age age, Gender gender, Race race);
|
|
||||||
|
|
||||||
bool IsSpecial() const;
|
|
||||||
|
|
||||||
u32 IsValid() const;
|
|
||||||
|
|
||||||
void SetFontRegion(FontRegion value);
|
|
||||||
void SetFavoriteColor(FavoriteColor value);
|
|
||||||
void SetGender(Gender value);
|
|
||||||
void SetHeight(u8 value);
|
|
||||||
void SetBuild(u8 value);
|
|
||||||
void SetType(u8 value);
|
|
||||||
void SetRegionMove(u8 value);
|
|
||||||
void SetFacelineType(FacelineType value);
|
|
||||||
void SetFacelineColor(FacelineColor value);
|
|
||||||
void SetFacelineWrinkle(FacelineWrinkle value);
|
|
||||||
void SetFacelineMake(FacelineMake value);
|
|
||||||
void SetHairType(HairType value);
|
|
||||||
void SetHairColor(CommonColor value);
|
|
||||||
void SetHairFlip(HairFlip value);
|
|
||||||
void SetEyeType(EyeType value);
|
|
||||||
void SetEyeColor(CommonColor value);
|
|
||||||
void SetEyeScale(u8 value);
|
|
||||||
void SetEyeAspect(u8 value);
|
|
||||||
void SetEyeRotate(u8 value);
|
|
||||||
void SetEyeX(u8 value);
|
|
||||||
void SetEyeY(u8 value);
|
|
||||||
void SetEyebrowType(EyebrowType value);
|
|
||||||
void SetEyebrowColor(CommonColor value);
|
|
||||||
void SetEyebrowScale(u8 value);
|
|
||||||
void SetEyebrowAspect(u8 value);
|
|
||||||
void SetEyebrowRotate(u8 value);
|
|
||||||
void SetEyebrowX(u8 value);
|
|
||||||
void SetEyebrowY(u8 value);
|
|
||||||
void SetNoseType(NoseType value);
|
|
||||||
void SetNoseScale(u8 value);
|
|
||||||
void SetNoseY(u8 value);
|
|
||||||
void SetMouthType(u8 value);
|
|
||||||
void SetMouthColor(CommonColor value);
|
|
||||||
void SetMouthScale(u8 value);
|
|
||||||
void SetMouthAspect(u8 value);
|
|
||||||
void SetMouthY(u8 value);
|
|
||||||
void SetBeardColor(CommonColor value);
|
|
||||||
void SetBeardType(BeardType value);
|
|
||||||
void SetMustacheType(MustacheType value);
|
|
||||||
void SetMustacheScale(u8 value);
|
|
||||||
void SetMustacheY(u8 value);
|
|
||||||
void SetGlassType(GlassType value);
|
|
||||||
void SetGlassColor(CommonColor value);
|
|
||||||
void SetGlassScale(u8 value);
|
|
||||||
void SetGlassY(u8 value);
|
|
||||||
void SetMoleType(MoleType value);
|
|
||||||
void SetMoleScale(u8 value);
|
|
||||||
void SetMoleX(u8 value);
|
|
||||||
void SetMoleY(u8 value);
|
|
||||||
void SetNickname(Nickname nickname);
|
|
||||||
void SetInvalidName();
|
|
||||||
|
|
||||||
Common::UUID GetCreateId() const;
|
|
||||||
FontRegion GetFontRegion() const;
|
|
||||||
FavoriteColor GetFavoriteColor() const;
|
|
||||||
Gender GetGender() const;
|
|
||||||
u8 GetHeight() const;
|
|
||||||
u8 GetBuild() const;
|
|
||||||
u8 GetType() const;
|
|
||||||
u8 GetRegionMove() const;
|
|
||||||
FacelineType GetFacelineType() const;
|
|
||||||
FacelineColor GetFacelineColor() const;
|
|
||||||
FacelineWrinkle GetFacelineWrinkle() const;
|
|
||||||
FacelineMake GetFacelineMake() const;
|
|
||||||
HairType GetHairType() const;
|
|
||||||
CommonColor GetHairColor() const;
|
|
||||||
HairFlip GetHairFlip() const;
|
|
||||||
EyeType GetEyeType() const;
|
|
||||||
CommonColor GetEyeColor() const;
|
|
||||||
u8 GetEyeScale() const;
|
|
||||||
u8 GetEyeAspect() const;
|
|
||||||
u8 GetEyeRotate() const;
|
|
||||||
u8 GetEyeX() const;
|
|
||||||
u8 GetEyeY() const;
|
|
||||||
EyebrowType GetEyebrowType() const;
|
|
||||||
CommonColor GetEyebrowColor() const;
|
|
||||||
u8 GetEyebrowScale() const;
|
|
||||||
u8 GetEyebrowAspect() const;
|
|
||||||
u8 GetEyebrowRotate() const;
|
|
||||||
u8 GetEyebrowX() const;
|
|
||||||
u8 GetEyebrowY() const;
|
|
||||||
NoseType GetNoseType() const;
|
|
||||||
u8 GetNoseScale() const;
|
|
||||||
u8 GetNoseY() const;
|
|
||||||
MouthType GetMouthType() const;
|
|
||||||
CommonColor GetMouthColor() const;
|
|
||||||
u8 GetMouthScale() const;
|
|
||||||
u8 GetMouthAspect() const;
|
|
||||||
u8 GetMouthY() const;
|
|
||||||
CommonColor GetBeardColor() const;
|
|
||||||
BeardType GetBeardType() const;
|
|
||||||
MustacheType GetMustacheType() const;
|
|
||||||
u8 GetMustacheScale() const;
|
|
||||||
u8 GetMustacheY() const;
|
|
||||||
GlassType GetGlassType() const;
|
|
||||||
CommonColor GetGlassColor() const;
|
|
||||||
u8 GetGlassScale() const;
|
|
||||||
u8 GetGlassY() const;
|
|
||||||
MoleType GetMoleType() const;
|
|
||||||
u8 GetMoleScale() const;
|
|
||||||
u8 GetMoleX() const;
|
|
||||||
u8 GetMoleY() const;
|
|
||||||
Nickname GetNickname() const;
|
|
||||||
|
|
||||||
bool operator==(const StoreData& data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CoreData core_data{};
|
|
||||||
Common::UUID create_id{};
|
|
||||||
u16 data_crc{};
|
|
||||||
u16 device_crc{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(StoreData) == 0x44, "StoreData has incorrect size.");
|
|
||||||
|
|
||||||
struct StoreDataElement {
|
|
||||||
StoreData store_data{};
|
|
||||||
Source source{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(StoreDataElement) == 0x48, "StoreDataElement has incorrect size.");
|
|
||||||
|
|
||||||
}; // namespace Service::Mii
|
|
@ -1,241 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/mii_util.h"
|
|
||||||
#include "core/hle/service/mii/types/raw_data.h"
|
|
||||||
#include "core/hle/service/mii/types/store_data.h"
|
|
||||||
#include "core/hle/service/mii/types/ver3_store_data.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
|
|
||||||
void NfpStoreDataExtension::SetFromStoreData(const StoreData& store_data) {
|
|
||||||
faceline_color = static_cast<u8>(store_data.GetFacelineColor()) & 0xf;
|
|
||||||
hair_color = static_cast<u8>(store_data.GetHairColor()) & 0x7f;
|
|
||||||
eye_color = static_cast<u8>(store_data.GetEyeColor()) & 0x7f;
|
|
||||||
eyebrow_color = static_cast<u8>(store_data.GetEyebrowColor()) & 0x7f;
|
|
||||||
mouth_color = static_cast<u8>(store_data.GetMouthColor()) & 0x7f;
|
|
||||||
beard_color = static_cast<u8>(store_data.GetBeardColor()) & 0x7f;
|
|
||||||
glass_color = static_cast<u8>(store_data.GetGlassColor()) & 0x7f;
|
|
||||||
glass_type = static_cast<u8>(store_data.GetGlassType()) & 0x1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const {
|
|
||||||
out_store_data.BuildBase(Gender::Male);
|
|
||||||
|
|
||||||
if (!IsValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: We are ignoring a bunch of data from the mii_v3
|
|
||||||
|
|
||||||
out_store_data.SetGender(static_cast<Gender>(mii_information.gender.Value()));
|
|
||||||
out_store_data.SetFavoriteColor(
|
|
||||||
static_cast<FavoriteColor>(mii_information.favorite_color.Value()));
|
|
||||||
out_store_data.SetHeight(height);
|
|
||||||
out_store_data.SetBuild(build);
|
|
||||||
|
|
||||||
out_store_data.SetNickname(mii_name);
|
|
||||||
out_store_data.SetFontRegion(
|
|
||||||
static_cast<FontRegion>(static_cast<u8>(region_information.font_region)));
|
|
||||||
|
|
||||||
out_store_data.SetFacelineType(
|
|
||||||
static_cast<FacelineType>(appearance_bits1.faceline_type.Value()));
|
|
||||||
out_store_data.SetFacelineColor(
|
|
||||||
static_cast<FacelineColor>(appearance_bits1.faceline_color.Value()));
|
|
||||||
out_store_data.SetFacelineWrinkle(
|
|
||||||
static_cast<FacelineWrinkle>(appearance_bits2.faceline_wrinkle.Value()));
|
|
||||||
out_store_data.SetFacelineMake(
|
|
||||||
static_cast<FacelineMake>(appearance_bits2.faceline_make.Value()));
|
|
||||||
|
|
||||||
out_store_data.SetHairType(static_cast<HairType>(hair_type));
|
|
||||||
out_store_data.SetHairColor(static_cast<CommonColor>(appearance_bits3.hair_color.Value()));
|
|
||||||
out_store_data.SetHairFlip(static_cast<HairFlip>(appearance_bits3.hair_flip.Value()));
|
|
||||||
|
|
||||||
out_store_data.SetEyeType(static_cast<EyeType>(appearance_bits4.eye_type.Value()));
|
|
||||||
out_store_data.SetEyeColor(static_cast<CommonColor>(appearance_bits4.eye_color.Value()));
|
|
||||||
out_store_data.SetEyeScale(static_cast<u8>(appearance_bits4.eye_scale));
|
|
||||||
out_store_data.SetEyeAspect(static_cast<u8>(appearance_bits4.eye_aspect));
|
|
||||||
out_store_data.SetEyeRotate(static_cast<u8>(appearance_bits4.eye_rotate));
|
|
||||||
out_store_data.SetEyeX(static_cast<u8>(appearance_bits4.eye_x));
|
|
||||||
out_store_data.SetEyeY(static_cast<u8>(appearance_bits4.eye_y));
|
|
||||||
|
|
||||||
out_store_data.SetEyebrowType(static_cast<EyebrowType>(appearance_bits5.eyebrow_type.Value()));
|
|
||||||
out_store_data.SetEyebrowColor(
|
|
||||||
static_cast<CommonColor>(appearance_bits5.eyebrow_color.Value()));
|
|
||||||
out_store_data.SetEyebrowScale(static_cast<u8>(appearance_bits5.eyebrow_scale));
|
|
||||||
out_store_data.SetEyebrowAspect(static_cast<u8>(appearance_bits5.eyebrow_aspect));
|
|
||||||
out_store_data.SetEyebrowRotate(static_cast<u8>(appearance_bits5.eyebrow_rotate));
|
|
||||||
out_store_data.SetEyebrowX(static_cast<u8>(appearance_bits5.eyebrow_x));
|
|
||||||
out_store_data.SetEyebrowY(static_cast<u8>(appearance_bits5.eyebrow_y));
|
|
||||||
|
|
||||||
out_store_data.SetNoseType(static_cast<NoseType>(appearance_bits6.nose_type.Value()));
|
|
||||||
out_store_data.SetNoseScale(static_cast<u8>(appearance_bits6.nose_scale));
|
|
||||||
out_store_data.SetNoseY(static_cast<u8>(appearance_bits6.nose_y));
|
|
||||||
|
|
||||||
out_store_data.SetMouthType(static_cast<u8>(appearance_bits7.mouth_type));
|
|
||||||
out_store_data.SetMouthColor(static_cast<CommonColor>(appearance_bits7.mouth_color.Value()));
|
|
||||||
out_store_data.SetMouthScale(static_cast<u8>(appearance_bits7.mouth_scale));
|
|
||||||
out_store_data.SetMouthAspect(static_cast<u8>(appearance_bits7.mouth_aspect));
|
|
||||||
out_store_data.SetMouthY(static_cast<u8>(appearance_bits8.mouth_y));
|
|
||||||
|
|
||||||
out_store_data.SetMustacheType(
|
|
||||||
static_cast<MustacheType>(appearance_bits8.mustache_type.Value()));
|
|
||||||
out_store_data.SetMustacheScale(static_cast<u8>(appearance_bits9.mustache_scale));
|
|
||||||
out_store_data.SetMustacheY(static_cast<u8>(appearance_bits9.mustache_y));
|
|
||||||
|
|
||||||
out_store_data.SetBeardType(static_cast<BeardType>(appearance_bits9.beard_type.Value()));
|
|
||||||
out_store_data.SetBeardColor(static_cast<CommonColor>(appearance_bits9.beard_color.Value()));
|
|
||||||
|
|
||||||
out_store_data.SetGlassType(static_cast<GlassType>(appearance_bits10.glass_type.Value()));
|
|
||||||
out_store_data.SetGlassColor(static_cast<CommonColor>(appearance_bits10.glass_color.Value()));
|
|
||||||
out_store_data.SetGlassScale(static_cast<u8>(appearance_bits10.glass_scale));
|
|
||||||
out_store_data.SetGlassY(static_cast<u8>(appearance_bits10.glass_y));
|
|
||||||
|
|
||||||
out_store_data.SetMoleType(static_cast<MoleType>(appearance_bits11.mole_type.Value()));
|
|
||||||
out_store_data.SetMoleScale(static_cast<u8>(appearance_bits11.mole_scale));
|
|
||||||
out_store_data.SetMoleX(static_cast<u8>(appearance_bits11.mole_x));
|
|
||||||
out_store_data.SetMoleY(static_cast<u8>(appearance_bits11.mole_y));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) {
|
|
||||||
version = 1;
|
|
||||||
mii_information.gender.Assign(static_cast<u8>(store_data.GetGender()));
|
|
||||||
mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor()));
|
|
||||||
height = store_data.GetHeight();
|
|
||||||
build = store_data.GetBuild();
|
|
||||||
|
|
||||||
mii_name = store_data.GetNickname();
|
|
||||||
region_information.font_region.Assign(static_cast<u8>(store_data.GetFontRegion()));
|
|
||||||
|
|
||||||
appearance_bits1.faceline_type.Assign(static_cast<u8>(store_data.GetFacelineType()));
|
|
||||||
appearance_bits2.faceline_wrinkle.Assign(static_cast<u8>(store_data.GetFacelineWrinkle()));
|
|
||||||
appearance_bits2.faceline_make.Assign(static_cast<u8>(store_data.GetFacelineMake()));
|
|
||||||
|
|
||||||
hair_type = static_cast<u8>(store_data.GetHairType());
|
|
||||||
appearance_bits3.hair_flip.Assign(static_cast<u8>(store_data.GetHairFlip()));
|
|
||||||
|
|
||||||
appearance_bits4.eye_type.Assign(static_cast<u8>(store_data.GetEyeType()));
|
|
||||||
appearance_bits4.eye_scale.Assign(store_data.GetEyeScale());
|
|
||||||
appearance_bits4.eye_aspect.Assign(store_data.GetEyebrowAspect());
|
|
||||||
appearance_bits4.eye_rotate.Assign(store_data.GetEyeRotate());
|
|
||||||
appearance_bits4.eye_x.Assign(store_data.GetEyeX());
|
|
||||||
appearance_bits4.eye_y.Assign(store_data.GetEyeY());
|
|
||||||
|
|
||||||
appearance_bits5.eyebrow_type.Assign(static_cast<u8>(store_data.GetEyebrowType()));
|
|
||||||
appearance_bits5.eyebrow_scale.Assign(store_data.GetEyebrowScale());
|
|
||||||
appearance_bits5.eyebrow_aspect.Assign(store_data.GetEyebrowAspect());
|
|
||||||
appearance_bits5.eyebrow_rotate.Assign(store_data.GetEyebrowRotate());
|
|
||||||
appearance_bits5.eyebrow_x.Assign(store_data.GetEyebrowX());
|
|
||||||
appearance_bits5.eyebrow_y.Assign(store_data.GetEyebrowY());
|
|
||||||
|
|
||||||
appearance_bits6.nose_type.Assign(static_cast<u8>(store_data.GetNoseType()));
|
|
||||||
appearance_bits6.nose_scale.Assign(store_data.GetNoseScale());
|
|
||||||
appearance_bits6.nose_y.Assign(store_data.GetNoseY());
|
|
||||||
|
|
||||||
appearance_bits7.mouth_type.Assign(static_cast<u8>(store_data.GetMouthType()));
|
|
||||||
appearance_bits7.mouth_scale.Assign(store_data.GetMouthScale());
|
|
||||||
appearance_bits7.mouth_aspect.Assign(store_data.GetMouthAspect());
|
|
||||||
appearance_bits8.mouth_y.Assign(store_data.GetMouthY());
|
|
||||||
|
|
||||||
appearance_bits8.mustache_type.Assign(static_cast<u8>(store_data.GetMustacheType()));
|
|
||||||
appearance_bits9.mustache_scale.Assign(store_data.GetMustacheScale());
|
|
||||||
appearance_bits9.mustache_y.Assign(store_data.GetMustacheY());
|
|
||||||
|
|
||||||
appearance_bits9.beard_type.Assign(static_cast<u8>(store_data.GetBeardType()));
|
|
||||||
|
|
||||||
appearance_bits10.glass_scale.Assign(store_data.GetGlassScale());
|
|
||||||
appearance_bits10.glass_y.Assign(store_data.GetGlassY());
|
|
||||||
|
|
||||||
appearance_bits11.mole_type.Assign(static_cast<u8>(store_data.GetMoleType()));
|
|
||||||
appearance_bits11.mole_scale.Assign(store_data.GetMoleScale());
|
|
||||||
appearance_bits11.mole_x.Assign(store_data.GetMoleX());
|
|
||||||
appearance_bits11.mole_y.Assign(store_data.GetMoleY());
|
|
||||||
|
|
||||||
// These types are converted to V3 from a table
|
|
||||||
appearance_bits1.faceline_color.Assign(
|
|
||||||
RawData::FromVer3GetFacelineColor(static_cast<u8>(store_data.GetFacelineColor())));
|
|
||||||
appearance_bits3.hair_color.Assign(
|
|
||||||
RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetHairColor())));
|
|
||||||
appearance_bits4.eye_color.Assign(
|
|
||||||
RawData::FromVer3GetEyeColor(static_cast<u8>(store_data.GetEyeColor())));
|
|
||||||
appearance_bits5.eyebrow_color.Assign(
|
|
||||||
RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetEyebrowColor())));
|
|
||||||
appearance_bits7.mouth_color.Assign(
|
|
||||||
RawData::FromVer3GetMouthlineColor(static_cast<u8>(store_data.GetMouthColor())));
|
|
||||||
appearance_bits9.beard_color.Assign(
|
|
||||||
RawData::FromVer3GetHairColor(static_cast<u8>(store_data.GetBeardColor())));
|
|
||||||
appearance_bits10.glass_color.Assign(
|
|
||||||
RawData::FromVer3GetGlassColor(static_cast<u8>(store_data.GetGlassColor())));
|
|
||||||
appearance_bits10.glass_type.Assign(
|
|
||||||
RawData::FromVer3GetGlassType(static_cast<u8>(store_data.GetGlassType())));
|
|
||||||
|
|
||||||
crc = MiiUtil::CalculateCrc16(&version, sizeof(Ver3StoreData) - sizeof(u16));
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 Ver3StoreData::IsValid() const {
|
|
||||||
bool is_valid = version == 0 || version == 3;
|
|
||||||
|
|
||||||
is_valid = is_valid && (mii_name.data[0] != '\0');
|
|
||||||
|
|
||||||
is_valid = is_valid && (mii_information.birth_month < 13);
|
|
||||||
is_valid = is_valid && (mii_information.birth_day < 32);
|
|
||||||
is_valid = is_valid && (mii_information.favorite_color <= static_cast<u8>(FavoriteColor::Max));
|
|
||||||
is_valid = is_valid && (height <= MaxHeight);
|
|
||||||
is_valid = is_valid && (build <= MaxBuild);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits1.faceline_type <= static_cast<u8>(FacelineType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits1.faceline_color <= MaxVer3CommonColor - 2);
|
|
||||||
is_valid =
|
|
||||||
is_valid && (appearance_bits2.faceline_wrinkle <= static_cast<u8>(FacelineWrinkle::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits2.faceline_make <= static_cast<u8>(FacelineMake::Max));
|
|
||||||
|
|
||||||
is_valid = is_valid && (hair_type <= static_cast<u8>(HairType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits3.hair_color <= MaxVer3CommonColor);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits4.eye_type <= static_cast<u8>(EyeType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits4.eye_color <= MaxVer3CommonColor - 2);
|
|
||||||
is_valid = is_valid && (appearance_bits4.eye_scale <= MaxEyeScale);
|
|
||||||
is_valid = is_valid && (appearance_bits4.eye_aspect <= MaxEyeAspect);
|
|
||||||
is_valid = is_valid && (appearance_bits4.eye_rotate <= MaxEyeRotate);
|
|
||||||
is_valid = is_valid && (appearance_bits4.eye_x <= MaxEyeX);
|
|
||||||
is_valid = is_valid && (appearance_bits4.eye_y <= MaxEyeY);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits5.eyebrow_type <= static_cast<u8>(EyebrowType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits5.eyebrow_color <= MaxVer3CommonColor);
|
|
||||||
is_valid = is_valid && (appearance_bits5.eyebrow_scale <= MaxEyebrowScale);
|
|
||||||
is_valid = is_valid && (appearance_bits5.eyebrow_aspect <= MaxEyebrowAspect);
|
|
||||||
is_valid = is_valid && (appearance_bits5.eyebrow_rotate <= MaxEyebrowRotate);
|
|
||||||
is_valid = is_valid && (appearance_bits5.eyebrow_x <= MaxEyebrowX);
|
|
||||||
is_valid = is_valid && (appearance_bits5.eyebrow_y <= MaxEyebrowY);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits6.nose_type <= static_cast<u8>(NoseType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits6.nose_scale <= MaxNoseScale);
|
|
||||||
is_valid = is_valid && (appearance_bits6.nose_y <= MaxNoseY);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits7.mouth_type <= static_cast<u8>(MouthType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits7.mouth_color <= MaxVer3CommonColor - 3);
|
|
||||||
is_valid = is_valid && (appearance_bits7.mouth_scale <= MaxMouthScale);
|
|
||||||
is_valid = is_valid && (appearance_bits7.mouth_aspect <= MaxMoutAspect);
|
|
||||||
is_valid = is_valid && (appearance_bits8.mouth_y <= MaxMouthY);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits8.mustache_type <= static_cast<u8>(MustacheType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits9.mustache_scale < MaxMustacheScale);
|
|
||||||
is_valid = is_valid && (appearance_bits9.mustache_y <= MasMustacheY);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits9.beard_type <= static_cast<u8>(BeardType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits9.beard_color <= MaxVer3CommonColor);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits10.glass_type <= MaxVer3GlassType);
|
|
||||||
is_valid = is_valid && (appearance_bits10.glass_color <= MaxVer3CommonColor - 2);
|
|
||||||
is_valid = is_valid && (appearance_bits10.glass_scale <= MaxGlassScale);
|
|
||||||
is_valid = is_valid && (appearance_bits10.glass_y <= MaxGlassScale);
|
|
||||||
|
|
||||||
is_valid = is_valid && (appearance_bits11.mole_type <= static_cast<u8>(MoleType::Max));
|
|
||||||
is_valid = is_valid && (appearance_bits11.mole_scale <= MaxMoleScale);
|
|
||||||
is_valid = is_valid && (appearance_bits11.mole_x <= MaxMoleX);
|
|
||||||
is_valid = is_valid && (appearance_bits11.mole_y <= MaxMoleY);
|
|
||||||
|
|
||||||
return is_valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Mii
|
|
@ -1,160 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/mii/mii_types.h"
|
|
||||||
|
|
||||||
namespace Service::Mii {
|
|
||||||
class StoreData;
|
|
||||||
|
|
||||||
// This is nn::mii::Ver3StoreData
|
|
||||||
// Based on citra HLE::Applets::MiiData and PretendoNetwork.
|
|
||||||
// https://github.com/citra-emu/citra/blob/master/src/core/hle/applets/mii_selector.h#L48
|
|
||||||
// https://github.com/PretendoNetwork/mii-js/blob/master/mii.js#L299
|
|
||||||
|
|
||||||
struct NfpStoreDataExtension {
|
|
||||||
void SetFromStoreData(const StoreData& store_data);
|
|
||||||
|
|
||||||
u8 faceline_color;
|
|
||||||
u8 hair_color;
|
|
||||||
u8 eye_color;
|
|
||||||
u8 eyebrow_color;
|
|
||||||
u8 mouth_color;
|
|
||||||
u8 beard_color;
|
|
||||||
u8 glass_color;
|
|
||||||
u8 glass_type;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NfpStoreDataExtension) == 0x8, "NfpStoreDataExtension is an invalid size");
|
|
||||||
|
|
||||||
#pragma pack(push, 4)
|
|
||||||
class Ver3StoreData {
|
|
||||||
public:
|
|
||||||
void BuildToStoreData(StoreData& out_store_data) const;
|
|
||||||
void BuildFromStoreData(const StoreData& store_data);
|
|
||||||
|
|
||||||
u32 IsValid() const;
|
|
||||||
|
|
||||||
u8 version;
|
|
||||||
union {
|
|
||||||
u8 raw;
|
|
||||||
|
|
||||||
BitField<0, 1, u8> allow_copying;
|
|
||||||
BitField<1, 1, u8> profanity_flag;
|
|
||||||
BitField<2, 2, u8> region_lock;
|
|
||||||
BitField<4, 2, u8> font_region;
|
|
||||||
} region_information;
|
|
||||||
u16_be mii_id;
|
|
||||||
u64_be system_id;
|
|
||||||
u32_be specialness_and_creation_date;
|
|
||||||
std::array<u8, 6> creator_mac;
|
|
||||||
u16_be padding;
|
|
||||||
union {
|
|
||||||
u16 raw;
|
|
||||||
|
|
||||||
BitField<0, 1, u16> gender;
|
|
||||||
BitField<1, 4, u16> birth_month;
|
|
||||||
BitField<5, 5, u16> birth_day;
|
|
||||||
BitField<10, 4, u16> favorite_color;
|
|
||||||
BitField<14, 1, u16> favorite;
|
|
||||||
} mii_information;
|
|
||||||
Nickname mii_name;
|
|
||||||
u8 height;
|
|
||||||
u8 build;
|
|
||||||
union {
|
|
||||||
u8 raw;
|
|
||||||
|
|
||||||
BitField<0, 1, u8> disable_sharing;
|
|
||||||
BitField<1, 4, u8> faceline_type;
|
|
||||||
BitField<5, 3, u8> faceline_color;
|
|
||||||
} appearance_bits1;
|
|
||||||
union {
|
|
||||||
u8 raw;
|
|
||||||
|
|
||||||
BitField<0, 4, u8> faceline_wrinkle;
|
|
||||||
BitField<4, 4, u8> faceline_make;
|
|
||||||
} appearance_bits2;
|
|
||||||
u8 hair_type;
|
|
||||||
union {
|
|
||||||
u8 raw;
|
|
||||||
|
|
||||||
BitField<0, 3, u8> hair_color;
|
|
||||||
BitField<3, 1, u8> hair_flip;
|
|
||||||
} appearance_bits3;
|
|
||||||
union {
|
|
||||||
u32 raw;
|
|
||||||
|
|
||||||
BitField<0, 6, u32> eye_type;
|
|
||||||
BitField<6, 3, u32> eye_color;
|
|
||||||
BitField<9, 4, u32> eye_scale;
|
|
||||||
BitField<13, 3, u32> eye_aspect;
|
|
||||||
BitField<16, 5, u32> eye_rotate;
|
|
||||||
BitField<21, 4, u32> eye_x;
|
|
||||||
BitField<25, 5, u32> eye_y;
|
|
||||||
} appearance_bits4;
|
|
||||||
union {
|
|
||||||
u32 raw;
|
|
||||||
|
|
||||||
BitField<0, 5, u32> eyebrow_type;
|
|
||||||
BitField<5, 3, u32> eyebrow_color;
|
|
||||||
BitField<8, 4, u32> eyebrow_scale;
|
|
||||||
BitField<12, 3, u32> eyebrow_aspect;
|
|
||||||
BitField<16, 4, u32> eyebrow_rotate;
|
|
||||||
BitField<21, 4, u32> eyebrow_x;
|
|
||||||
BitField<25, 5, u32> eyebrow_y;
|
|
||||||
} appearance_bits5;
|
|
||||||
union {
|
|
||||||
u16 raw;
|
|
||||||
|
|
||||||
BitField<0, 5, u16> nose_type;
|
|
||||||
BitField<5, 4, u16> nose_scale;
|
|
||||||
BitField<9, 5, u16> nose_y;
|
|
||||||
} appearance_bits6;
|
|
||||||
union {
|
|
||||||
u16 raw;
|
|
||||||
|
|
||||||
BitField<0, 6, u16> mouth_type;
|
|
||||||
BitField<6, 3, u16> mouth_color;
|
|
||||||
BitField<9, 4, u16> mouth_scale;
|
|
||||||
BitField<13, 3, u16> mouth_aspect;
|
|
||||||
} appearance_bits7;
|
|
||||||
union {
|
|
||||||
u8 raw;
|
|
||||||
|
|
||||||
BitField<0, 5, u8> mouth_y;
|
|
||||||
BitField<5, 3, u8> mustache_type;
|
|
||||||
} appearance_bits8;
|
|
||||||
u8 allow_copying;
|
|
||||||
union {
|
|
||||||
u16 raw;
|
|
||||||
|
|
||||||
BitField<0, 3, u16> beard_type;
|
|
||||||
BitField<3, 3, u16> beard_color;
|
|
||||||
BitField<6, 4, u16> mustache_scale;
|
|
||||||
BitField<10, 5, u16> mustache_y;
|
|
||||||
} appearance_bits9;
|
|
||||||
union {
|
|
||||||
u16 raw;
|
|
||||||
|
|
||||||
BitField<0, 4, u16> glass_type;
|
|
||||||
BitField<4, 3, u16> glass_color;
|
|
||||||
BitField<7, 4, u16> glass_scale;
|
|
||||||
BitField<11, 5, u16> glass_y;
|
|
||||||
} appearance_bits10;
|
|
||||||
union {
|
|
||||||
u16 raw;
|
|
||||||
|
|
||||||
BitField<0, 1, u16> mole_type;
|
|
||||||
BitField<1, 4, u16> mole_scale;
|
|
||||||
BitField<5, 5, u16> mole_x;
|
|
||||||
BitField<10, 5, u16> mole_y;
|
|
||||||
} appearance_bits11;
|
|
||||||
|
|
||||||
Nickname author_name;
|
|
||||||
INSERT_PADDING_BYTES(0x2);
|
|
||||||
u16_be crc;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size");
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
}; // namespace Service::Mii
|
|
@ -28,6 +28,7 @@
|
|||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/mii/mii_manager.h"
|
#include "core/hle/service/mii/mii_manager.h"
|
||||||
|
#include "core/hle/service/mii/types.h"
|
||||||
#include "core/hle/service/nfc/common/amiibo_crypto.h"
|
#include "core/hle/service/nfc/common/amiibo_crypto.h"
|
||||||
#include "core/hle/service/nfc/common/device.h"
|
#include "core/hle/service/nfc/common/device.h"
|
||||||
#include "core/hle/service/nfc/mifare_result.h"
|
#include "core/hle/service/nfc/mifare_result.h"
|
||||||
@ -680,16 +681,12 @@ Result NfcDevice::GetRegisterInfo(NFP::RegisterInfo& register_info) const {
|
|||||||
return ResultRegistrationIsNotInitialized;
|
return ResultRegistrationIsNotInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mii::CharInfo char_info{};
|
Service::Mii::MiiManager manager;
|
||||||
Mii::StoreData store_data{};
|
|
||||||
tag_data.owner_mii.BuildToStoreData(store_data);
|
|
||||||
char_info.SetFromStoreData(store_data);
|
|
||||||
|
|
||||||
const auto& settings = tag_data.settings;
|
const auto& settings = tag_data.settings;
|
||||||
|
|
||||||
// TODO: Validate this data
|
// TODO: Validate this data
|
||||||
register_info = {
|
register_info = {
|
||||||
.mii_char_info = char_info,
|
.mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii),
|
||||||
.creation_date = settings.init_date.GetWriteDate(),
|
.creation_date = settings.init_date.GetWriteDate(),
|
||||||
.amiibo_name = GetAmiiboName(settings),
|
.amiibo_name = GetAmiiboName(settings),
|
||||||
.font_region = settings.settings.font_region,
|
.font_region = settings.settings.font_region,
|
||||||
@ -828,11 +825,8 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
|
|||||||
return ResultWrongDeviceState;
|
return ResultWrongDeviceState;
|
||||||
}
|
}
|
||||||
|
|
||||||
Service::Mii::StoreData store_data{};
|
Service::Mii::MiiManager manager;
|
||||||
Service::Mii::NfpStoreDataExtension extension{};
|
const auto mii = manager.BuildBase(Mii::Gender::Male);
|
||||||
store_data.BuildBase(Mii::Gender::Male);
|
|
||||||
extension.SetFromStoreData(store_data);
|
|
||||||
|
|
||||||
auto& settings = tag_data.settings;
|
auto& settings = tag_data.settings;
|
||||||
|
|
||||||
if (tag_data.settings.settings.amiibo_initialized == 0) {
|
if (tag_data.settings.settings.amiibo_initialized == 0) {
|
||||||
@ -841,8 +835,8 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetAmiiboName(settings, register_info.amiibo_name);
|
SetAmiiboName(settings, register_info.amiibo_name);
|
||||||
tag_data.owner_mii.BuildFromStoreData(store_data);
|
tag_data.owner_mii = manager.BuildFromStoreData(mii);
|
||||||
tag_data.mii_extension = extension;
|
tag_data.mii_extension = manager.SetFromStoreData(mii);
|
||||||
tag_data.unknown = 0;
|
tag_data.unknown = 0;
|
||||||
tag_data.unknown2 = {};
|
tag_data.unknown2 = {};
|
||||||
settings.country_code_id = 0;
|
settings.country_code_id = 0;
|
||||||
@ -1459,7 +1453,7 @@ void NfcDevice::UpdateRegisterInfoCrc() {
|
|||||||
|
|
||||||
void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data,
|
void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data,
|
||||||
const NFP::EncryptedNTAG215File& encrypted_file) const {
|
const NFP::EncryptedNTAG215File& encrypted_file) const {
|
||||||
Service::Mii::StoreData store_data{};
|
Service::Mii::MiiManager manager;
|
||||||
auto& settings = stubbed_tag_data.settings;
|
auto& settings = stubbed_tag_data.settings;
|
||||||
|
|
||||||
stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file);
|
stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file);
|
||||||
@ -1473,8 +1467,7 @@ void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data,
|
|||||||
SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'});
|
SetAmiiboName(settings, {'y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o'});
|
||||||
settings.settings.font_region.Assign(0);
|
settings.settings.font_region.Assign(0);
|
||||||
settings.init_date = GetAmiiboDate(GetCurrentPosixTime());
|
settings.init_date = GetAmiiboDate(GetCurrentPosixTime());
|
||||||
store_data.BuildBase(Mii::Gender::Male);
|
stubbed_tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildBase(Mii::Gender::Male));
|
||||||
stubbed_tag_data.owner_mii.BuildFromStoreData(store_data);
|
|
||||||
|
|
||||||
// Admin info
|
// Admin info
|
||||||
settings.settings.amiibo_initialized.Assign(1);
|
settings.settings.amiibo_initialized.Assign(1);
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/hle/service/mii/types/char_info.h"
|
#include "core/hle/service/mii/types.h"
|
||||||
#include "core/hle/service/mii/types/store_data.h"
|
|
||||||
#include "core/hle/service/mii/types/ver3_store_data.h"
|
|
||||||
#include "core/hle/service/nfc/nfc_types.h"
|
#include "core/hle/service/nfc/nfc_types.h"
|
||||||
|
|
||||||
namespace Service::NFP {
|
namespace Service::NFP {
|
||||||
@ -324,7 +322,7 @@ static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
|
|||||||
|
|
||||||
// This is nn::nfp::RegisterInfoPrivate
|
// This is nn::nfp::RegisterInfoPrivate
|
||||||
struct RegisterInfoPrivate {
|
struct RegisterInfoPrivate {
|
||||||
Service::Mii::StoreData mii_store_data;
|
Service::Mii::MiiStoreData mii_store_data;
|
||||||
WriteDate creation_date;
|
WriteDate creation_date;
|
||||||
AmiiboName amiibo_name;
|
AmiiboName amiibo_name;
|
||||||
u8 font_region;
|
u8 font_region;
|
||||||
|
@ -48,32 +48,15 @@ enum class CallType {
|
|||||||
|
|
||||||
using socklen_t = int;
|
using socklen_t = int;
|
||||||
|
|
||||||
SOCKET interrupt_socket = static_cast<SOCKET>(-1);
|
|
||||||
|
|
||||||
void InterruptSocketOperations() {
|
|
||||||
closesocket(interrupt_socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AcknowledgeInterrupt() {
|
|
||||||
interrupt_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Initialize() {
|
void Initialize() {
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
(void)WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
(void)WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||||
|
|
||||||
AcknowledgeInterrupt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Finalize() {
|
void Finalize() {
|
||||||
InterruptSocketOperations();
|
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET GetInterruptSocket() {
|
|
||||||
return interrupt_socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
|
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
|
||||||
sockaddr_in result;
|
sockaddr_in result;
|
||||||
|
|
||||||
@ -174,42 +157,9 @@ constexpr int SD_RECEIVE = SHUT_RD;
|
|||||||
constexpr int SD_SEND = SHUT_WR;
|
constexpr int SD_SEND = SHUT_WR;
|
||||||
constexpr int SD_BOTH = SHUT_RDWR;
|
constexpr int SD_BOTH = SHUT_RDWR;
|
||||||
|
|
||||||
int interrupt_pipe_fd[2] = {-1, -1};
|
void Initialize() {}
|
||||||
|
|
||||||
void Initialize() {
|
void Finalize() {}
|
||||||
if (pipe(interrupt_pipe_fd) != 0) {
|
|
||||||
LOG_ERROR(Network, "Failed to create interrupt pipe!");
|
|
||||||
}
|
|
||||||
int flags = fcntl(interrupt_pipe_fd[0], F_GETFL);
|
|
||||||
ASSERT_MSG(fcntl(interrupt_pipe_fd[0], F_SETFL, flags | O_NONBLOCK) == 0,
|
|
||||||
"Failed to set nonblocking state for interrupt pipe");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Finalize() {
|
|
||||||
if (interrupt_pipe_fd[0] >= 0) {
|
|
||||||
close(interrupt_pipe_fd[0]);
|
|
||||||
}
|
|
||||||
if (interrupt_pipe_fd[1] >= 0) {
|
|
||||||
close(interrupt_pipe_fd[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterruptSocketOperations() {
|
|
||||||
u8 value = 0;
|
|
||||||
ASSERT(write(interrupt_pipe_fd[1], &value, sizeof(value)) == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AcknowledgeInterrupt() {
|
|
||||||
u8 value = 0;
|
|
||||||
ssize_t ret = read(interrupt_pipe_fd[0], &value, sizeof(value));
|
|
||||||
if (ret != 1 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
|
||||||
LOG_ERROR(Network, "Failed to acknowledge interrupt on shutdown");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SOCKET GetInterruptSocket() {
|
|
||||||
return interrupt_pipe_fd[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
|
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
|
||||||
sockaddr_in result;
|
sockaddr_in result;
|
||||||
@ -540,14 +490,6 @@ NetworkInstance::~NetworkInstance() {
|
|||||||
Finalize();
|
Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CancelPendingSocketOperations() {
|
|
||||||
InterruptSocketOperations();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestartSocketOperations() {
|
|
||||||
AcknowledgeInterrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<IPv4Address> GetHostIPv4Address() {
|
std::optional<IPv4Address> GetHostIPv4Address() {
|
||||||
const auto network_interface = Network::GetSelectedNetworkInterface();
|
const auto network_interface = Network::GetSelectedNetworkInterface();
|
||||||
if (!network_interface.has_value()) {
|
if (!network_interface.has_value()) {
|
||||||
@ -618,14 +560,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
|
|||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
host_pollfds.push_back(WSAPOLLFD{
|
const int result = WSAPoll(host_pollfds.data(), static_cast<ULONG>(num), timeout);
|
||||||
.fd = GetInterruptSocket(),
|
|
||||||
.events = POLLIN,
|
|
||||||
.revents = 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const int result =
|
|
||||||
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), timeout);
|
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
ASSERT(std::all_of(host_pollfds.begin(), host_pollfds.end(),
|
ASSERT(std::all_of(host_pollfds.begin(), host_pollfds.end(),
|
||||||
[](WSAPOLLFD fd) { return fd.revents == 0; }));
|
[](WSAPOLLFD fd) { return fd.revents == 0; }));
|
||||||
@ -692,24 +627,6 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) {
|
|||||||
std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() {
|
std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() {
|
||||||
sockaddr_in addr;
|
sockaddr_in addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
std::vector<WSAPOLLFD> host_pollfds{
|
|
||||||
WSAPOLLFD{fd, POLLIN, 0},
|
|
||||||
WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const int pollres =
|
|
||||||
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
|
|
||||||
if (host_pollfds[1].revents != 0) {
|
|
||||||
// Interrupt signaled before a client could be accepted, break
|
|
||||||
return {AcceptResult{}, Errno::AGAIN};
|
|
||||||
}
|
|
||||||
if (pollres > 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SOCKET new_socket = accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
|
const SOCKET new_socket = accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
|
||||||
|
|
||||||
if (new_socket == INVALID_SOCKET) {
|
if (new_socket == INVALID_SOCKET) {
|
||||||
|
@ -96,9 +96,6 @@ public:
|
|||||||
~NetworkInstance();
|
~NetworkInstance();
|
||||||
};
|
};
|
||||||
|
|
||||||
void CancelPendingSocketOperations();
|
|
||||||
void RestartSocketOperations();
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
constexpr IPv4Address TranslateIPv4(in_addr addr) {
|
constexpr IPv4Address TranslateIPv4(in_addr addr) {
|
||||||
auto& bytes = addr.S_un.S_un_b;
|
auto& bytes = addr.S_un.S_un_b;
|
||||||
|
@ -160,8 +160,7 @@ void QtAmiiboSettingsDialog::LoadAmiiboData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto amiibo_name = std::string(register_info.amiibo_name.data());
|
const auto amiibo_name = std::string(register_info.amiibo_name.data());
|
||||||
const auto owner_name =
|
const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data());
|
||||||
Common::UTF16ToUTF8(register_info.mii_char_info.GetNickname().data.data());
|
|
||||||
const auto creation_date =
|
const auto creation_date =
|
||||||
QDate(register_info.creation_date.year, register_info.creation_date.month,
|
QDate(register_info.creation_date.year, register_info.creation_date.month,
|
||||||
register_info.creation_date.day);
|
register_info.creation_date.day);
|
||||||
|
@ -589,12 +589,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
|
|||||||
emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
|
emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
|
||||||
});
|
});
|
||||||
connect(start_game, &QAction::triggered, [this, path]() {
|
connect(start_game, &QAction::triggered, [this, path]() {
|
||||||
emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal,
|
emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal);
|
||||||
AmLaunchType::UserInitiated);
|
|
||||||
});
|
});
|
||||||
connect(start_game_global, &QAction::triggered, [this, path]() {
|
connect(start_game_global, &QAction::triggered, [this, path]() {
|
||||||
emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global,
|
emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global);
|
||||||
AmLaunchType::UserInitiated);
|
|
||||||
});
|
});
|
||||||
connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
|
connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
|
||||||
emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);
|
emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);
|
||||||
|
@ -28,7 +28,6 @@ class GameListWorker;
|
|||||||
class GameListSearchField;
|
class GameListSearchField;
|
||||||
class GameListDir;
|
class GameListDir;
|
||||||
class GMainWindow;
|
class GMainWindow;
|
||||||
enum class AmLaunchType;
|
|
||||||
enum class StartGameType;
|
enum class StartGameType;
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
@ -104,7 +103,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void BootGame(const QString& game_path, u64 program_id, std::size_t program_index,
|
void BootGame(const QString& game_path, u64 program_id, std::size_t program_index,
|
||||||
StartGameType type, AmLaunchType launch_type);
|
StartGameType type);
|
||||||
void GameChosen(const QString& game_path, const u64 title_id = 0);
|
void GameChosen(const QString& game_path, const u64 title_id = 0);
|
||||||
void ShouldCancelWorker();
|
void ShouldCancelWorker();
|
||||||
void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
|
void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include "core/loader/nca.h"
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <unistd.h> // for chdir
|
#include <unistd.h> // for chdir
|
||||||
#endif
|
#endif
|
||||||
@ -1555,7 +1554,6 @@ void GMainWindow::ConnectMenuEvents() {
|
|||||||
|
|
||||||
// Help
|
// Help
|
||||||
connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder);
|
connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder);
|
||||||
connect_menu(ui->action_Verify_installed_contents, &GMainWindow::OnVerifyInstalledContents);
|
|
||||||
connect_menu(ui->action_About, &GMainWindow::OnAbout);
|
connect_menu(ui->action_About, &GMainWindow::OnAbout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1707,8 +1705,7 @@ void GMainWindow::AllowOSSleep() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index,
|
bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) {
|
||||||
AmLaunchType launch_type) {
|
|
||||||
// Shutdown previous session if the emu thread is still active...
|
// Shutdown previous session if the emu thread is still active...
|
||||||
if (emu_thread != nullptr) {
|
if (emu_thread != nullptr) {
|
||||||
ShutdownGame();
|
ShutdownGame();
|
||||||
@ -1720,10 +1717,6 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
|
|||||||
|
|
||||||
system->SetFilesystem(vfs);
|
system->SetFilesystem(vfs);
|
||||||
|
|
||||||
if (launch_type == AmLaunchType::UserInitiated) {
|
|
||||||
system->GetUserChannel().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
system->SetAppletFrontendSet({
|
system->SetAppletFrontendSet({
|
||||||
std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings
|
std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings
|
||||||
(UISettings::values.controller_applet_disabled.GetValue() == true)
|
(UISettings::values.controller_applet_disabled.GetValue() == true)
|
||||||
@ -1863,7 +1856,7 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
|
void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
|
||||||
StartGameType type, AmLaunchType launch_type) {
|
StartGameType type) {
|
||||||
LOG_INFO(Frontend, "yuzu starting...");
|
LOG_INFO(Frontend, "yuzu starting...");
|
||||||
StoreRecentFile(filename); // Put the filename on top of the list
|
StoreRecentFile(filename); // Put the filename on top of the list
|
||||||
|
|
||||||
@ -1907,7 +1900,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LoadROM(filename, program_id, program_index, launch_type)) {
|
if (!LoadROM(filename, program_id, program_index)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3376,8 +3369,7 @@ void GMainWindow::OnLoadComplete() {
|
|||||||
|
|
||||||
void GMainWindow::OnExecuteProgram(std::size_t program_index) {
|
void GMainWindow::OnExecuteProgram(std::size_t program_index) {
|
||||||
ShutdownGame();
|
ShutdownGame();
|
||||||
BootGame(last_filename_booted, 0, program_index, StartGameType::Normal,
|
BootGame(last_filename_booted, 0, program_index);
|
||||||
AmLaunchType::ApplicationInitiated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnExit() {
|
void GMainWindow::OnExit() {
|
||||||
@ -4008,108 +4000,6 @@ void GMainWindow::OnOpenYuzuFolder() {
|
|||||||
QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::YuzuDir))));
|
QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::YuzuDir))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnVerifyInstalledContents() {
|
|
||||||
// Declare sizes.
|
|
||||||
size_t total_size = 0;
|
|
||||||
size_t processed_size = 0;
|
|
||||||
|
|
||||||
// Initialize a progress dialog.
|
|
||||||
QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this);
|
|
||||||
progress.setWindowModality(Qt::WindowModal);
|
|
||||||
progress.setMinimumDuration(100);
|
|
||||||
progress.setAutoClose(false);
|
|
||||||
progress.setAutoReset(false);
|
|
||||||
|
|
||||||
// Declare a list of file names which failed to verify.
|
|
||||||
std::vector<std::string> failed;
|
|
||||||
|
|
||||||
// Declare progress callback.
|
|
||||||
auto QtProgressCallback = [&](size_t nca_processed, size_t nca_total) {
|
|
||||||
if (progress.wasCanceled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
progress.setValue(static_cast<int>(((processed_size + nca_processed) * 100) / total_size));
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get content registries.
|
|
||||||
auto bis_contents = system->GetFileSystemController().GetSystemNANDContents();
|
|
||||||
auto user_contents = system->GetFileSystemController().GetUserNANDContents();
|
|
||||||
|
|
||||||
std::vector<FileSys::RegisteredCache*> content_providers;
|
|
||||||
if (bis_contents) {
|
|
||||||
content_providers.push_back(bis_contents);
|
|
||||||
}
|
|
||||||
if (user_contents) {
|
|
||||||
content_providers.push_back(user_contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get associated NCA files.
|
|
||||||
std::vector<FileSys::VirtualFile> nca_files;
|
|
||||||
|
|
||||||
// Get all installed IDs.
|
|
||||||
for (auto nca_provider : content_providers) {
|
|
||||||
const auto entries = nca_provider->ListEntriesFilter();
|
|
||||||
|
|
||||||
for (const auto& entry : entries) {
|
|
||||||
auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type);
|
|
||||||
if (!nca_file) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
total_size += nca_file->GetSize();
|
|
||||||
nca_files.push_back(std::move(nca_file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using the NCA loader, determine if all NCAs are valid.
|
|
||||||
for (auto& nca_file : nca_files) {
|
|
||||||
Loader::AppLoader_NCA nca_loader(nca_file);
|
|
||||||
|
|
||||||
auto status = nca_loader.VerifyIntegrity(QtProgressCallback);
|
|
||||||
if (progress.wasCanceled()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (status != Loader::ResultStatus::Success) {
|
|
||||||
FileSys::NCA nca(nca_file);
|
|
||||||
const auto title_id = nca.GetTitleId();
|
|
||||||
std::string title_name = "unknown";
|
|
||||||
|
|
||||||
const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id),
|
|
||||||
FileSys::ContentRecordType::Control);
|
|
||||||
if (control && control->GetStatus() == Loader::ResultStatus::Success) {
|
|
||||||
const FileSys::PatchManager pm{title_id, system->GetFileSystemController(),
|
|
||||||
*provider};
|
|
||||||
const auto [nacp, logo] = pm.ParseControlNCA(*control);
|
|
||||||
if (nacp) {
|
|
||||||
title_name = nacp->GetApplicationName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title_id > 0) {
|
|
||||||
failed.push_back(
|
|
||||||
fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name));
|
|
||||||
} else {
|
|
||||||
failed.push_back(fmt::format("{} (unknown)", nca_file->GetName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processed_size += nca_file->GetSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.close();
|
|
||||||
|
|
||||||
if (failed.size() > 0) {
|
|
||||||
auto failed_names = QString::fromStdString(fmt::format("{}", fmt::join(failed, "\n")));
|
|
||||||
QMessageBox::critical(
|
|
||||||
this, tr("Integrity verification failed!"),
|
|
||||||
tr("Verification failed for the following files:\n\n%1").arg(failed_names));
|
|
||||||
} else {
|
|
||||||
QMessageBox::information(this, tr("Integrity verification succeeded!"),
|
|
||||||
tr("The operation completed successfully."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnAbout() {
|
void GMainWindow::OnAbout() {
|
||||||
AboutDialog aboutDialog(this);
|
AboutDialog aboutDialog(this);
|
||||||
aboutDialog.exec();
|
aboutDialog.exec();
|
||||||
|
@ -58,11 +58,6 @@ enum class StartGameType {
|
|||||||
Global, // Only uses global configuration
|
Global, // Only uses global configuration
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AmLaunchType {
|
|
||||||
UserInitiated,
|
|
||||||
ApplicationInitiated,
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
enum class SystemResultStatus : u32;
|
enum class SystemResultStatus : u32;
|
||||||
class System;
|
class System;
|
||||||
@ -244,11 +239,9 @@ private:
|
|||||||
void PreventOSSleep();
|
void PreventOSSleep();
|
||||||
void AllowOSSleep();
|
void AllowOSSleep();
|
||||||
|
|
||||||
bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index,
|
bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index);
|
||||||
AmLaunchType launch_type);
|
|
||||||
void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0,
|
void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0,
|
||||||
StartGameType with_config = StartGameType::Normal,
|
StartGameType with_config = StartGameType::Normal);
|
||||||
AmLaunchType launch_type = AmLaunchType::UserInitiated);
|
|
||||||
void ShutdownGame();
|
void ShutdownGame();
|
||||||
|
|
||||||
void ShowTelemetryCallout();
|
void ShowTelemetryCallout();
|
||||||
@ -350,7 +343,6 @@ private slots:
|
|||||||
void OnConfigurePerGame();
|
void OnConfigurePerGame();
|
||||||
void OnLoadAmiibo();
|
void OnLoadAmiibo();
|
||||||
void OnOpenYuzuFolder();
|
void OnOpenYuzuFolder();
|
||||||
void OnVerifyInstalledContents();
|
|
||||||
void OnAbout();
|
void OnAbout();
|
||||||
void OnToggleFilterBar();
|
void OnToggleFilterBar();
|
||||||
void OnToggleStatusBar();
|
void OnToggleStatusBar();
|
||||||
|
@ -148,7 +148,6 @@
|
|||||||
<addaction name="action_Configure_Tas"/>
|
<addaction name="action_Configure_Tas"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="action_Rederive"/>
|
<addaction name="action_Rederive"/>
|
||||||
<addaction name="action_Verify_installed_contents"/>
|
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_Capture_Screenshot"/>
|
<addaction name="action_Capture_Screenshot"/>
|
||||||
<addaction name="menuTAS"/>
|
<addaction name="menuTAS"/>
|
||||||
@ -215,11 +214,6 @@
|
|||||||
<string>&Reinitialize keys...</string>
|
<string>&Reinitialize keys...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Verify_installed_contents">
|
|
||||||
<property name="text">
|
|
||||||
<string>Verify installed contents</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_About">
|
<action name="action_About">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&About yuzu</string>
|
<string>&About yuzu</string>
|
||||||
|
@ -358,7 +358,6 @@ int main(int argc, char** argv) {
|
|||||||
system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
||||||
system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>());
|
system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>());
|
||||||
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
|
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
|
||||||
system.GetUserChannel().clear();
|
|
||||||
|
|
||||||
const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath)};
|
const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath)};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user