| |
| |
| |
|
|
| #pragma once |
|
|
| #include <boost/serialization/export.hpp> |
| #include "common/bit_field.h" |
| #include "common/common_types.h" |
|
|
| namespace Mii { |
|
|
| using Nickname = std::array<char16_t, 10>; |
|
|
| #pragma pack(push, 1) |
| |
| struct MiiData { |
| u8 version; |
|
|
| |
| union { |
| u8 raw; |
|
|
| BitField<0, 1, u8> allow_copying; |
| BitField<1, 1, u8> is_private_name; |
| BitField<2, 2, u8> region_lock; |
| BitField<4, 2, u8> char_set; |
| } mii_options; |
|
|
| |
| union { |
| u8 raw; |
|
|
| BitField<0, 4, u8> page_index; |
| BitField<4, 4, u8> slot_index; |
| } mii_pos; |
|
|
| |
| union { |
| u8 raw; |
|
|
| BitField<0, 4, u8> unknown0; |
| BitField<4, 3, u8> |
| origin_console; |
| } console_identity; |
|
|
| u64_be system_id; |
| u32_be mii_id; |
| std::array<u8, 6> mac; |
| u16 pad; |
|
|
| |
| union { |
| u16_be raw; |
|
|
| BitField<0, 1, u16> gender; |
| BitField<1, 4, u16> bday_month; |
| BitField<5, 5, u16> bday_day; |
| BitField<10, 4, u16> favorite_color; |
| BitField<14, 1, u16> favorite; |
| } mii_details; |
|
|
| Nickname mii_name; |
| u8 height; |
| u8 width; |
|
|
| |
| union { |
| u8 raw; |
|
|
| BitField<0, 1, u8> disable_sharing; |
| BitField<1, 4, u8> type; |
| BitField<5, 3, u8> skin_color; |
| } face_style; |
|
|
| |
| union { |
| u8 raw; |
|
|
| BitField<0, 4, u8> wrinkles; |
| BitField<4, 4, u8> makeup; |
| } face_details; |
|
|
| u8 hair_style; |
|
|
| |
| union { |
| u8 raw; |
|
|
| BitField<0, 3, u8> color; |
| BitField<3, 1, u8> flip; |
| } hair_details; |
|
|
| |
| union { |
| u32_be raw; |
|
|
| BitField<0, 6, u32> type; |
| BitField<6, 3, u32> color; |
| BitField<9, 4, u32> scale; |
| BitField<13, 3, u32> aspect; |
| BitField<16, 5, u32> rotate; |
| BitField<21, 4, u32> x; |
| BitField<25, 5, u32> y; |
| } eye_details; |
|
|
| |
| union { |
| u32_be raw; |
|
|
| BitField<0, 5, u32> style; |
| BitField<5, 3, u32> color; |
| BitField<8, 4, u32> scale; |
| BitField<12, 3, u32> aspect; |
| BitField<16, 5, u32> rotate; |
| BitField<21, 4, u32> x; |
| BitField<25, 5, u32> y; |
| } eyebrow_details; |
|
|
| |
| union { |
| u16_be raw; |
|
|
| BitField<0, 5, u16> type; |
| BitField<5, 4, u16> scale; |
| BitField<9, 5, u16> y; |
| } nose_details; |
|
|
| |
| union { |
| u16_be raw; |
|
|
| BitField<0, 6, u16> type; |
| BitField<6, 3, u16> color; |
| BitField<9, 4, u16> scale; |
| BitField<13, 3, u16> aspect; |
| } mouth_details; |
|
|
| |
| union { |
| u16_be raw; |
|
|
| BitField<0, 5, u16> mouth_y; |
| BitField<5, 3, u16> mustache_type; |
| } mustache_details; |
|
|
| |
| union { |
| u16_be raw; |
|
|
| BitField<0, 3, u16> type; |
| BitField<3, 3, u16> color; |
| BitField<6, 4, u16> scale; |
| BitField<10, 5, u16> y; |
| } beard_details; |
|
|
| |
| union { |
| u16_be raw; |
|
|
| BitField<0, 4, u16> type; |
| BitField<4, 3, u16> color; |
| BitField<7, 4, u16> scale; |
| BitField<11, 5, u16> y; |
| } glasses_details; |
|
|
| |
| union { |
| u16_be raw; |
|
|
| BitField<0, 1, u16> type; |
| BitField<1, 4, u16> scale; |
| BitField<5, 5, u16> x; |
| BitField<10, 5, u16> y; |
| } mole_details; |
|
|
| Nickname author_name; |
| private: |
| template <class Archive> |
| void serialize(Archive& ar, const unsigned int); |
| friend class boost::serialization::access; |
| }; |
|
|
| static_assert(sizeof(MiiData) == 0x5C, "MiiData structure has incorrect size"); |
| static_assert(std::is_trivial_v<MiiData>, "MiiData must be trivial."); |
| static_assert(std::is_trivially_copyable_v<MiiData>, "MiiData must be trivially copyable."); |
|
|
| struct ChecksummedMiiData { |
| private: |
| MiiData mii_data; |
| u16 padding; |
| u16_be crc16; |
|
|
| public: |
| ChecksummedMiiData& operator=(const MiiData& data) { |
| mii_data = data; |
| padding = 0; |
| FixChecksum(); |
| return *this; |
| } |
|
|
| ChecksummedMiiData& operator=(MiiData&& data) { |
| mii_data = std::move(data); |
| padding = 0; |
| FixChecksum(); |
| return *this; |
| } |
|
|
| void SetMiiData(MiiData data) { |
| mii_data = data; |
| FixChecksum(); |
| } |
|
|
| operator MiiData() const { |
| return mii_data; |
| } |
|
|
| bool IsChecksumValid() { |
| return crc16 == CalculateChecksum(); |
| } |
|
|
| u16 CalculateChecksum(); |
|
|
| void FixChecksum() { |
| crc16 = CalculateChecksum(); |
| } |
|
|
| private: |
| template <class Archive> |
| void serialize(Archive& ar, const unsigned int); |
| friend class boost::serialization::access; |
| }; |
| #pragma pack(pop) |
| static_assert(sizeof(ChecksummedMiiData) == 0x60, |
| "ChecksummedMiiData structure has incorrect size"); |
| static_assert(std::is_trivial_v<ChecksummedMiiData>, "ChecksummedMiiData must be trivial."); |
| static_assert(std::is_trivially_copyable_v<ChecksummedMiiData>, |
| "ChecksummedMiiData must be trivially copyable."); |
| } |
|
|
| BOOST_CLASS_EXPORT_KEY(Mii::MiiData) |
| BOOST_CLASS_EXPORT_KEY(Mii::ChecksummedMiiData) |
|
|