From 6e6c437a5276f4d60cc511da6bdc8a40f5b3c3e9 Mon Sep 17 00:00:00 2001 From: fearlessTobi Date: Sat, 29 Sep 2018 13:58:51 +0200 Subject: [PATCH 1/3] applets: stub mii selector to always return a standard mii To obtain the data, the LLEd mii selector of system version 11.8.0 was used. In AppletManager::GlanceParameter, the following code was added to write the returned buffer data to a file: if (parameter.buffer.size() == 132) { std::u16string name(10, '\0'); std::memcpy(name.data(), parameter.buffer.data() + 0x26, 10 * sizeof(u16)); name = std::u16string(name.data()); FileUtil::IOFile file{fmt::format("{}.mii", Common::UTF16ToUTF8(name)), "wb"}; file.WriteBytes(parameter.buffer.data(), parameter.buffer.size()); } Then "xxd -i" was used on the file to convert it to a hex array. --- src/core/hle/applets/mii_selector.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index dd57f0efd..594eeb4ab 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp @@ -18,6 +18,19 @@ namespace HLE { namespace Applets { +// This data was obtained by writing the returned buffer in AppletManager::GlanceParameter of the +// LLEd Mii picker of version system version 11.8.0 to a file +static const std::array mii = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x10, + 0x30, 0xd2, 0x85, 0xb6, 0xb3, 0x00, 0xc8, 0x85, 0x0a, 0x98, 0x39, 0x1e, 0xe4, 0x40, 0xf4, + 0x07, 0xb7, 0x37, 0x10, 0x00, 0x00, 0xa6, 0x00, 0x43, 0x00, 0x69, 0x00, 0x74, 0x00, 0x72, + 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, + 0x00, 0x00, 0x21, 0x01, 0x02, 0x68, 0x44, 0x18, 0x26, 0x34, 0x46, 0x14, 0x81, 0x12, 0x17, + 0x68, 0x0d, 0x00, 0x00, 0x29, 0x00, 0x52, 0x48, 0x50, 0x66, 0x00, 0x6c, 0x00, 0x54, 0x00, + 0x6f, 0x00, 0x62, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) { if (parameter.signal != Service::APT::SignalType::Request) { LOG_ERROR(Service_APT, "unsupported signal {}", static_cast(parameter.signal)); @@ -57,17 +70,13 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { is_running = true; - // TODO(Subv): Set the expected fields in the response buffer before resending it to the - // application. // TODO(Subv): Reverse the parameter format for the Mii Selector memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); - // TODO(Subv): Find more about this structure, result code 0 is enough to let most games - // continue. + // TODO(Subv): Find more about this structure MiiResult result; - memset(&result, 0, sizeof(result)); - result.return_code = 0; + std::memcpy(&result, mii.data(), mii.size()); // Let the application know that we're closing Service::APT::MessageParameter message; From fe99e5a51e29a5379f637b2e17030b414913c365 Mon Sep 17 00:00:00 2001 From: fearlessTobi Date: Sat, 24 Nov 2018 14:35:06 +0100 Subject: [PATCH 2/3] mii_selector: map raw data to the MiiResult struct --- src/core/hle/applets/mii_selector.cpp | 47 ++++++++++++++++++--------- src/core/hle/applets/mii_selector.h | 41 ++++++++++++++++++----- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index 594eeb4ab..0c333ce74 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp @@ -18,19 +18,6 @@ namespace HLE { namespace Applets { -// This data was obtained by writing the returned buffer in AppletManager::GlanceParameter of the -// LLEd Mii picker of version system version 11.8.0 to a file -static const std::array mii = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x10, - 0x30, 0xd2, 0x85, 0xb6, 0xb3, 0x00, 0xc8, 0x85, 0x0a, 0x98, 0x39, 0x1e, 0xe4, 0x40, 0xf4, - 0x07, 0xb7, 0x37, 0x10, 0x00, 0x00, 0xa6, 0x00, 0x43, 0x00, 0x69, 0x00, 0x74, 0x00, 0x72, - 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, - 0x00, 0x00, 0x21, 0x01, 0x02, 0x68, 0x44, 0x18, 0x26, 0x34, 0x46, 0x14, 0x81, 0x12, 0x17, - 0x68, 0x0d, 0x00, 0x00, 0x29, 0x00, 0x52, 0x48, 0x50, 0x66, 0x00, 0x6c, 0x00, 0x54, 0x00, - 0x6f, 0x00, 0x62, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) { if (parameter.signal != Service::APT::SignalType::Request) { LOG_ERROR(Service_APT, "unsupported signal {}", static_cast(parameter.signal)); @@ -74,9 +61,39 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); - // TODO(Subv): Find more about this structure + // This data was obtained by writing the returned buffer in AppletManager::GlanceParameter of + // the LLEd Mii picker of version system version 11.8.0 to a file and then matching the values + // to the members of the MiiResult struct + MiiData mii_data; + mii_data.mii_id = 0x03001030; + mii_data.system_id = 0xD285B6B300C8850A; + mii_data.specialness_and_creation_date = 0x98391EE4; + mii_data.creator_mac = {0x40, 0xF4, 0x07, 0xB7, 0x37, 0x10}; + mii_data.padding = 0x0; + mii_data.mii_information = 0xA600; + mii_data.mii_name = {'C', 'i', 't', 'r', 'a', 0x0, 0x0, 0x0, 0x0, 0x0}; + mii_data.width_height = 0x4040; + mii_data.appearance_bits1 = 0x0; + mii_data.appearance_bits2 = 0x0; + mii_data.hair_style = 0x21; + mii_data.appearance_bits3 = 0x01; + mii_data.unknown1 = 0x02684418; + mii_data.appearance_bits4 = 0x26; + mii_data.appearance_bits5 = 0x34; + mii_data.appearance_bits6 = 0x4614; + mii_data.unknown2 = 0x81121768; + mii_data.allow_copying = 0x0D; + mii_data.unknown3 = {0x0, 0x0, 0x29, 0x0, 0x52, 0x48, 0x50}; + mii_data.author_name = {'f', 'l', 'T', 'o', 'b', 'i', 0x0, 0x0, 0x0, 0x0}; + MiiResult result; - std::memcpy(&result, mii.data(), mii.size()); + result.return_code = 0x0; + result.is_guest_mii_selected = 0x0; + result.selected_guest_mii_index = 0xFFFFFFFF; + result.selected_mii_data = mii_data; + result.unknown1 = 0x0; + result.mii_data_checksum = 0x056C; + result.guest_mii_name.fill(0x0); // Let the application know that we're closing Service::APT::MessageParameter message; diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index c2f68da56..22afc90d7 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h @@ -40,15 +40,40 @@ ASSERT_REG_POSITION(initially_selected_mii_index, 0x90); ASSERT_REG_POSITION(guest_mii_whitelist, 0x94); #undef ASSERT_REG_POSITION +#pragma pack(push, 1) +struct MiiData { + u32_be mii_id; + u64_be system_id; + u32_be specialness_and_creation_date; + std::array creator_mac; + u16_be padding; + u16_be mii_information; + std::array mii_name; + u16_be width_height; + u8 appearance_bits1; + u8 appearance_bits2; + u8 hair_style; + u8 appearance_bits3; + u32_be unknown1; + u8 appearance_bits4; + u8 appearance_bits5; + u16_be appearance_bits6; + u32_be unknown2; + u8 allow_copying; + std::array unknown3; + std::array author_name; +}; +static_assert(sizeof(MiiData) == 0x5C, "MiiData structure has incorrect size"); +#pragma pack(pop) + struct MiiResult { - u32 return_code; - u32 is_guest_mii_selected; - u32 selected_guest_mii_index; - // TODO(mailwl): expand to Mii Format structure: https://www.3dbrew.org/wiki/Mii - u8 selected_mii_data[0x5C]; - INSERT_PADDING_BYTES(2); - u16 mii_data_checksum; - u16 guest_mii_name[0xC]; + u32_be return_code; + u32_be is_guest_mii_selected; + u32_be selected_guest_mii_index; + MiiData selected_mii_data; + u16_be unknown1; + u16_be mii_data_checksum; + std::array guest_mii_name; }; static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); #define ASSERT_REG_POSITION(field_name, position) \ From 48239be22ce36b0d07468f7196128e181ae9daf0 Mon Sep 17 00:00:00 2001 From: fearlessTobi Date: Tue, 27 Nov 2018 14:57:51 +0100 Subject: [PATCH 3/3] mii_selector: Use BitField where possible --- src/core/hle/applets/mii_selector.cpp | 13 ++++++---- src/core/hle/applets/mii_selector.h | 36 +++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index 0c333ce74..93987d323 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp @@ -73,13 +73,16 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa mii_data.mii_information = 0xA600; mii_data.mii_name = {'C', 'i', 't', 'r', 'a', 0x0, 0x0, 0x0, 0x0, 0x0}; mii_data.width_height = 0x4040; - mii_data.appearance_bits1 = 0x0; - mii_data.appearance_bits2 = 0x0; + mii_data.appearance_bits1.raw = 0x0; + mii_data.appearance_bits2.raw = 0x0; mii_data.hair_style = 0x21; - mii_data.appearance_bits3 = 0x01; + mii_data.appearance_bits3.hair_color.Assign(0x1); + mii_data.appearance_bits3.flip_hair.Assign(0x0); mii_data.unknown1 = 0x02684418; - mii_data.appearance_bits4 = 0x26; - mii_data.appearance_bits5 = 0x34; + mii_data.appearance_bits4.eyebrow_style.Assign(0x6); + mii_data.appearance_bits4.eyebrow_color.Assign(0x1); + mii_data.appearance_bits5.eyebrow_scale.Assign(0x4); + mii_data.appearance_bits5.eyebrow_yscale.Assign(0x3); mii_data.appearance_bits6 = 0x4614; mii_data.unknown2 = 0x81121768; mii_data.allow_copying = 0x0D; diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index 22afc90d7..bef711f6a 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h @@ -50,13 +50,39 @@ struct MiiData { u16_be mii_information; std::array mii_name; u16_be width_height; - u8 appearance_bits1; - u8 appearance_bits2; + 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; - u8 appearance_bits3; + union { + u8 raw; + + BitField<0, 3, u8> hair_color; + BitField<3, 1, u8> flip_hair; + } appearance_bits3; u32_be unknown1; - u8 appearance_bits4; - u8 appearance_bits5; + union { + u8 raw; + + BitField<0, 5, u8> eyebrow_style; + BitField<5, 3, u8> eyebrow_color; + } appearance_bits4; + union { + u8 raw; + + BitField<0, 4, u8> eyebrow_scale; + BitField<4, 3, u8> eyebrow_yscale; + } appearance_bits5; u16_be appearance_bits6; u32_be unknown2; u8 allow_copying;