mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Move MiiData to its own namespace and add ChecksummedMiiData (#6824)
* Move mii to own namespace and add checksummed mii data * Fix compile issues * Make mii classes trivial and add cast operator * Fix Android side * Add new line at the end of files. * Make miidata a struct and crc16 a u32_be as per switch code. * Apply suggestions * Change back crc to u16 and set padding to 0.
This commit is contained in:
		
							parent
							
								
									f8b8b6e53c
								
							
						
					
					
						commit
						35e208b447
					
				
					 13 changed files with 308 additions and 133 deletions
				
			
		|  | @ -53,7 +53,7 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) { | |||
|     const u32 return_code = static_cast<u32>( | ||||
|         env->GetLongField(data, env->GetFieldID(s_mii_selector_data_class, "return_code", "J"))); | ||||
|     if (return_code == 1) { | ||||
|         Finalize(return_code, HLE::Applets::MiiData{}); | ||||
|         Finalize(return_code, Mii::MiiData{}); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -67,6 +67,5 @@ void QtMiiSelector::OpenDialog() { | |||
|              dialog.return_code, index); | ||||
| 
 | ||||
|     const auto mii_data = dialog.miis.at(index); | ||||
|     Finalize(dialog.return_code, | ||||
|              dialog.return_code == 0 ? std::move(mii_data) : HLE::Applets::MiiData{}); | ||||
|     Finalize(dialog.return_code, dialog.return_code == 0 ? std::move(mii_data) : Mii::MiiData{}); | ||||
| } | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ private: | |||
|     QVBoxLayout* layout; | ||||
|     QtMiiSelector* mii_selector; | ||||
|     u32 return_code = 0; | ||||
|     std::vector<HLE::Applets::MiiData> miis; | ||||
|     std::vector<Mii::MiiData> miis; | ||||
| 
 | ||||
|     friend class QtMiiSelector; | ||||
| }; | ||||
|  |  | |||
|  | @ -184,6 +184,8 @@ add_library(citra_core STATIC | |||
|     hle/kernel/wait_object.h | ||||
|     hle/lock.cpp | ||||
|     hle/lock.h | ||||
|     hle/mii.h | ||||
|     hle/mii.cpp | ||||
|     hle/result.h | ||||
|     hle/romfs.cpp | ||||
|     hle/romfs.h | ||||
|  |  | |||
|  | @ -11,12 +11,12 @@ | |||
| 
 | ||||
| namespace Frontend { | ||||
| 
 | ||||
| void MiiSelector::Finalize(u32 return_code, HLE::Applets::MiiData mii) { | ||||
| void MiiSelector::Finalize(u32 return_code, Mii::MiiData mii) { | ||||
|     data = {return_code, mii}; | ||||
| } | ||||
| 
 | ||||
| std::vector<HLE::Applets::MiiData> LoadMiis() { | ||||
|     std::vector<HLE::Applets::MiiData> miis; | ||||
| std::vector<Mii::MiiData> LoadMiis() { | ||||
|     std::vector<Mii::MiiData> miis; | ||||
| 
 | ||||
|     std::string nand_directory{FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)}; | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); | ||||
|  | @ -36,7 +36,7 @@ std::vector<HLE::Applets::MiiData> LoadMiis() { | |||
|             u32 saved_miis_offset = 0x8; | ||||
|             // The Mii Maker has a 100 Mii limit on the 3ds
 | ||||
|             for (int i = 0; i < 100; ++i) { | ||||
|                 HLE::Applets::MiiData mii; | ||||
|                 Mii::MiiData mii; | ||||
|                 std::array<u8, sizeof(mii)> mii_raw; | ||||
|                 file->Read(saved_miis_offset, sizeof(mii), mii_raw.data()); | ||||
|                 std::memcpy(&mii, mii_raw.data(), sizeof(mii)); | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ struct MiiSelectorConfig { | |||
| 
 | ||||
| struct MiiSelectorData { | ||||
|     u32 return_code; | ||||
|     HLE::Applets::MiiData mii; | ||||
|     Mii::MiiData mii; | ||||
| }; | ||||
| 
 | ||||
| class MiiSelector { | ||||
|  | @ -43,14 +43,14 @@ public: | |||
|      * Stores the data so that the HLE applet in core can | ||||
|      * send this to the calling application | ||||
|      */ | ||||
|     void Finalize(u32 return_code, HLE::Applets::MiiData mii); | ||||
|     void Finalize(u32 return_code, Mii::MiiData mii); | ||||
| 
 | ||||
| protected: | ||||
|     MiiSelectorConfig config; | ||||
|     MiiSelectorData data; | ||||
| }; | ||||
| 
 | ||||
| std::vector<HLE::Applets::MiiData> LoadMiis(); | ||||
| std::vector<Mii::MiiData> LoadMiis(); | ||||
| 
 | ||||
| class DefaultMiiSelector final : public MiiSelector { | ||||
| public: | ||||
|  |  | |||
|  | @ -71,9 +71,6 @@ void MiiSelector::Update() { | |||
|     const MiiSelectorData& data = frontend_applet->ReceiveData(); | ||||
|     result.return_code = data.return_code; | ||||
|     result.selected_mii_data = data.mii; | ||||
|     // Calculate the checksum of the selected Mii, see https://www.3dbrew.org/wiki/Mii#Checksum
 | ||||
|     result.mii_data_checksum = boost::crc<16, 0x1021, 0, 0, false, false>( | ||||
|         &result.selected_mii_data, sizeof(HLE::Applets::MiiData) + sizeof(result.unknown1)); | ||||
|     result.selected_guest_mii_index = 0xFFFFFFFF; | ||||
| 
 | ||||
|     // TODO(Subv): We're finalizing the applet immediately after it's started,
 | ||||
|  | @ -92,29 +89,31 @@ MiiResult MiiSelector::GetStandardMiiResult() { | |||
|     // 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::MiiData mii_data; | ||||
|     mii_data.magic = 0x03; | ||||
|     mii_data.mii_options.raw = 0x00; | ||||
|     mii_data.mii_pos.raw = 0x10; | ||||
|     mii_data.console_identity.raw = 0x30; | ||||
|     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_id = 0x98391EE4; | ||||
|     mii_data.mac = {0x40, 0xF4, 0x07, 0xB7, 0x37, 0x10}; | ||||
|     mii_data.pad = 0x0000; | ||||
|     mii_data.mii_details.raw = 0xA600; | ||||
|     mii_data.mii_name = {'C', 'i', 't', 'r', 'a', 0x0, 0x0, 0x0, 0x0, 0x0}; | ||||
|     mii_data.width_height = 0x4040; | ||||
|     mii_data.appearance_bits1.raw = 0x0; | ||||
|     mii_data.appearance_bits2.raw = 0x0; | ||||
|     mii_data.height = 0x40; | ||||
|     mii_data.width = 0x40; | ||||
|     mii_data.face_style.raw = 0x00; | ||||
|     mii_data.face_details.raw = 0x00; | ||||
|     mii_data.hair_style = 0x21; | ||||
|     mii_data.appearance_bits3.hair_color.Assign(0x1); | ||||
|     mii_data.appearance_bits3.flip_hair.Assign(0x0); | ||||
|     mii_data.unknown1 = 0x02684418; | ||||
|     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; | ||||
|     mii_data.unknown3 = {0x0, 0x0, 0x29, 0x0, 0x52, 0x48, 0x50}; | ||||
|     mii_data.hair_details.raw = 0x01; | ||||
|     mii_data.eye_details.raw = 0x02684418; | ||||
|     mii_data.eyebrow_details.raw = 0x26344614; | ||||
|     mii_data.nose_details.raw = 0x8112; | ||||
|     mii_data.mouth_details.raw = 0x1768; | ||||
|     mii_data.mustache_details.raw = 0x0D00; | ||||
|     mii_data.beard_details.raw = 0x0029; | ||||
|     mii_data.glasses_details.raw = 0x0052; | ||||
|     mii_data.mole_details.raw = 0x4850; | ||||
|     mii_data.author_name = {'f', 'l', 'T', 'o', 'b', 'i', 0x0, 0x0, 0x0, 0x0}; | ||||
| 
 | ||||
|     MiiResult result; | ||||
|  | @ -122,8 +121,6 @@ MiiResult MiiSelector::GetStandardMiiResult() { | |||
|     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); | ||||
| 
 | ||||
|     return result; | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include "common/common_types.h" | ||||
| #include "core/hle/applets/applet.h" | ||||
| #include "core/hle/kernel/shared_memory.h" | ||||
| #include "core/hle/mii.h" | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/service/apt/apt.h" | ||||
| 
 | ||||
|  | @ -44,65 +45,11 @@ 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<u8, 0x6> creator_mac; | ||||
|     u16_be padding; | ||||
|     u16_be mii_information; | ||||
|     std::array<u16_le, 0xA> mii_name; | ||||
|     u16_be width_height; | ||||
|     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; | ||||
|     u32_be unknown1; | ||||
|     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; | ||||
|     std::array<u8, 0x7> unknown3; | ||||
|     std::array<u16_le, 0xA> author_name; | ||||
| }; | ||||
| static_assert(sizeof(MiiData) == 0x5C, "MiiData structure has incorrect size"); | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| struct MiiResult { | ||||
|     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; | ||||
|     Mii::ChecksummedMiiData selected_mii_data; | ||||
|     std::array<u16_le, 0xC> guest_mii_name; | ||||
| }; | ||||
| static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); | ||||
|  |  | |||
							
								
								
									
										13
									
								
								src/core/hle/mii.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/core/hle/mii.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| // Copyright 2023 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <boost/crc.hpp> | ||||
| #include "core/hle/mii.h" | ||||
| 
 | ||||
| namespace Mii { | ||||
| u16 ChecksummedMiiData::CalculateChecksum() { | ||||
|     // Calculate the checksum of the selected Mii, see https://www.3dbrew.org/wiki/Mii#Checksum
 | ||||
|     return boost::crc<16, 0x1021, 0, 0, false, false>(this, offsetof(ChecksummedMiiData, crc16)); | ||||
| } | ||||
| } // namespace Mii
 | ||||
							
								
								
									
										239
									
								
								src/core/hle/mii.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								src/core/hle/mii.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,239 @@ | |||
| // Copyright 2023 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <boost/serialization/base_object.hpp> | ||||
| #include <boost/serialization/binary_object.hpp> | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Mii { | ||||
| 
 | ||||
| #pragma pack(push, 1) | ||||
| // Reference: https://github.com/devkitPro/libctru/blob/master/libctru/include/3ds/mii.h
 | ||||
| struct MiiData { | ||||
|     u8 magic; ///< Always 3?
 | ||||
| 
 | ||||
|     /// Mii options
 | ||||
|     union { | ||||
|         u8 raw; | ||||
| 
 | ||||
|         BitField<0, 1, u8> allow_copying;   ///< True if copying is allowed
 | ||||
|         BitField<1, 1, u8> is_private_name; ///< Private name?
 | ||||
|         BitField<2, 2, u8> region_lock;     ///< Region lock (0=no lock, 1=JPN, 2=USA, 3=EUR)
 | ||||
|         BitField<4, 2, u8> char_set;        ///< Character set (0=JPN+USA+EUR, 1=CHN, 2=KOR, 3=TWN)
 | ||||
|     } mii_options; | ||||
| 
 | ||||
|     /// Mii position in Mii selector or Mii maker
 | ||||
|     union { | ||||
|         u8 raw; | ||||
| 
 | ||||
|         BitField<0, 4, u8> page_index; ///< Page index of Mii
 | ||||
|         BitField<4, 4, u8> slot_index; ///< Slot offset of Mii on its Page
 | ||||
|     } mii_pos; | ||||
| 
 | ||||
|     /// Console Identity
 | ||||
|     union { | ||||
|         u8 raw; | ||||
| 
 | ||||
|         BitField<0, 4, u8> unknown0; ///< Mabye padding (always seems to be 0)?
 | ||||
|         BitField<4, 3, u8> | ||||
|             origin_console; ///< Console that the Mii was created on (1=WII, 2=DSI, 3=3DS)
 | ||||
|     } console_identity; | ||||
| 
 | ||||
|     u64_be system_id;      ///< Identifies the system that the Mii was created on (Determines pants)
 | ||||
|     u32_be mii_id;         ///< ID of Mii
 | ||||
|     std::array<u8, 6> mac; ///< Creator's system's full MAC address
 | ||||
|     u16 pad;               ///< Padding
 | ||||
| 
 | ||||
|     /// Mii details
 | ||||
|     union { | ||||
|         u16_be raw; | ||||
| 
 | ||||
|         BitField<0, 1, u16> sex;          ///< Sex of Mii (False=Male, True=Female)
 | ||||
|         BitField<1, 4, u16> bday_month;   ///< Month of Mii's birthday
 | ||||
|         BitField<5, 5, u16> bday_day;     ///< Day of Mii's birthday
 | ||||
|         BitField<10, 4, u16> shirt_color; ///< Color of Mii's shirt
 | ||||
|         BitField<14, 1, u16> favorite;    ///< Whether the Mii is one of your 10 favorite Mii's
 | ||||
|     } mii_details; | ||||
| 
 | ||||
|     std::array<u16_le, 10> mii_name; ///< Name of Mii (Encoded using UTF16)
 | ||||
|     u8 height;                       ///< How tall the Mii is
 | ||||
|     u8 width;                        ///< How wide the Mii is
 | ||||
| 
 | ||||
|     /// Face style
 | ||||
|     union { | ||||
|         u8 raw; | ||||
| 
 | ||||
|         BitField<0, 1, u8> disable_sharing; ///< Whether or not Sharing of the Mii is allowed
 | ||||
|         BitField<1, 4, u8> shape;           ///< Face shape
 | ||||
|         BitField<5, 3, u8> skin_color;      ///< Color of skin
 | ||||
|     } face_style; | ||||
| 
 | ||||
|     /// Face details
 | ||||
|     union { | ||||
|         u8 raw; | ||||
| 
 | ||||
|         BitField<0, 4, u8> wrinkles; | ||||
|         BitField<4, 4, u8> makeup; | ||||
|     } face_details; | ||||
| 
 | ||||
|     u8 hair_style; | ||||
| 
 | ||||
|     /// Hair details
 | ||||
|     union { | ||||
|         u8 raw; | ||||
| 
 | ||||
|         BitField<0, 3, u8> color; | ||||
|         BitField<3, 1, u8> flip; | ||||
|     } hair_details; | ||||
| 
 | ||||
|     /// Eye details
 | ||||
|     union { | ||||
|         u32_be raw; | ||||
| 
 | ||||
|         BitField<0, 6, u32> style; | ||||
|         BitField<6, 3, u32> color; | ||||
|         BitField<9, 4, u32> scale; | ||||
|         BitField<13, 3, u32> y_scale; | ||||
|         BitField<16, 5, u32> rotation; | ||||
|         BitField<21, 4, u32> x_spacing; | ||||
|         BitField<25, 5, u32> y_position; | ||||
|     } eye_details; | ||||
| 
 | ||||
|     /// Eyebrow details
 | ||||
|     union { | ||||
|         u32_be raw; | ||||
| 
 | ||||
|         BitField<0, 5, u32> style; | ||||
|         BitField<5, 3, u32> color; | ||||
|         BitField<8, 4, u32> scale; | ||||
|         BitField<12, 3, u32> y_scale; | ||||
|         BitField<15, 1, u32> pad; | ||||
|         BitField<16, 5, u32> rotation; | ||||
|         BitField<21, 4, u32> x_spacing; | ||||
|         BitField<25, 5, u32> y_position; | ||||
|     } eyebrow_details; | ||||
| 
 | ||||
|     /// Nose details
 | ||||
|     union { | ||||
|         u16_be raw; | ||||
| 
 | ||||
|         BitField<0, 5, u16> style; | ||||
|         BitField<5, 4, u16> scale; | ||||
|         BitField<9, 5, u16> y_position; | ||||
|     } nose_details; | ||||
| 
 | ||||
|     /// Mouth details
 | ||||
|     union { | ||||
|         u16_be raw; | ||||
| 
 | ||||
|         BitField<0, 6, u16> style; | ||||
|         BitField<6, 3, u16> color; | ||||
|         BitField<9, 4, u16> scale; | ||||
|         BitField<13, 3, u16> y_scale; | ||||
|     } mouth_details; | ||||
| 
 | ||||
|     /// Mustache details
 | ||||
|     union { | ||||
|         u16_be raw; | ||||
| 
 | ||||
|         BitField<0, 5, u16> mouth_yposition; | ||||
|         BitField<5, 3, u16> mustach_style; | ||||
|         BitField<8, 2, u16> pad; | ||||
|     } mustache_details; | ||||
| 
 | ||||
|     /// Beard details
 | ||||
|     union { | ||||
|         u16_be raw; | ||||
| 
 | ||||
|         BitField<0, 3, u16> style; | ||||
|         BitField<3, 3, u16> color; | ||||
|         BitField<6, 4, u16> scale; | ||||
|         BitField<10, 5, u16> y_pos; | ||||
|     } beard_details; | ||||
| 
 | ||||
|     /// Glasses details
 | ||||
|     union { | ||||
|         u16_be raw; | ||||
| 
 | ||||
|         BitField<0, 4, u16> style; | ||||
|         BitField<4, 3, u16> color; | ||||
|         BitField<7, 4, u16> scale; | ||||
|         BitField<11, 5, u16> y_pos; | ||||
|     } glasses_details; | ||||
| 
 | ||||
|     /// Mole details
 | ||||
|     union { | ||||
|         u16_be raw; | ||||
| 
 | ||||
|         BitField<0, 1, u16> enable; | ||||
|         BitField<1, 5, u16> scale; | ||||
|         BitField<6, 5, u16> x_pos; | ||||
|         BitField<11, 5, u16> y_pos; | ||||
|     } mole_details; | ||||
| 
 | ||||
|     std::array<u16_le, 10> author_name; ///< Name of Mii's author (Encoded using UTF16)
 | ||||
| private: | ||||
|     template <class Archive> | ||||
|     void serialize(Archive& ar, const unsigned int) { | ||||
|         ar& boost::serialization::make_binary_object(this, sizeof(MiiData)); | ||||
|     } | ||||
|     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; | ||||
|     } | ||||
| 
 | ||||
|     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) { | ||||
|         ar& boost::serialization::make_binary_object(this, sizeof(ChecksummedMiiData)); | ||||
|     } | ||||
|     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."); | ||||
| } // namespace Mii
 | ||||
|  | @ -86,8 +86,6 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { | |||
|     encoded_data.amiibo_version = nfc_data.user_memory.amiibo_version; | ||||
|     encoded_data.settings = nfc_data.user_memory.settings; | ||||
|     encoded_data.owner_mii = nfc_data.user_memory.owner_mii; | ||||
|     encoded_data.padding = nfc_data.user_memory.padding; | ||||
|     encoded_data.owner_mii_aes_ccm = nfc_data.user_memory.owner_mii_aes_ccm; | ||||
|     encoded_data.application_id = nfc_data.user_memory.application_id; | ||||
|     encoded_data.application_write_counter = nfc_data.user_memory.application_write_counter; | ||||
|     encoded_data.application_area_id = nfc_data.user_memory.application_area_id; | ||||
|  | @ -123,8 +121,6 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { | |||
|     nfc_data.user_memory.amiibo_version = encoded_data.amiibo_version; | ||||
|     nfc_data.user_memory.settings = encoded_data.settings; | ||||
|     nfc_data.user_memory.owner_mii = encoded_data.owner_mii; | ||||
|     nfc_data.user_memory.padding = encoded_data.padding; | ||||
|     nfc_data.user_memory.owner_mii_aes_ccm = encoded_data.owner_mii_aes_ccm; | ||||
|     nfc_data.user_memory.application_id = encoded_data.application_id; | ||||
|     nfc_data.user_memory.application_write_counter = encoded_data.application_write_counter; | ||||
|     nfc_data.user_memory.application_area_id = encoded_data.application_area_id; | ||||
|  |  | |||
|  | @ -539,7 +539,6 @@ ResultCode NfcDevice::GetRegisterInfo(RegisterInfo& register_info) const { | |||
|     // TODO: Validate this data
 | ||||
|     register_info = { | ||||
|         .mii_data = tag.file.owner_mii, | ||||
|         .owner_mii_aes_ccm = tag.file.owner_mii_aes_ccm, | ||||
|         .amiibo_name = settings.amiibo_name, | ||||
|         .flags = static_cast<u8>(settings.settings.raw & 0xf), | ||||
|         .font_region = settings.country_code_id, | ||||
|  | @ -628,8 +627,7 @@ ResultCode NfcDevice::DeleteRegisterInfo() { | |||
|     } | ||||
| 
 | ||||
|     CryptoPP::AutoSeededRandomPool rng; | ||||
|     const std::size_t mii_data_size = | ||||
|         sizeof(tag.file.owner_mii) + sizeof(tag.file.padding) + sizeof(tag.file.owner_mii_aes_ccm); | ||||
|     const std::size_t mii_data_size = sizeof(tag.file.owner_mii); | ||||
|     std::array<CryptoPP::byte, mii_data_size> buffer{}; | ||||
|     rng.GenerateBlock(buffer.data(), mii_data_size); | ||||
| 
 | ||||
|  | @ -664,12 +662,9 @@ ResultCode NfcDevice::SetRegisterInfoPrivate(const RegisterInfoPrivate& register | |||
|         settings.write_date = GetAmiiboDate(); | ||||
|     } | ||||
| 
 | ||||
|     // Calculate mii CRC with the padding
 | ||||
|     tag.file.owner_mii_aes_ccm = boost::crc<16, 0x1021, 0, 0, false, false>( | ||||
|         ®ister_info.mii_data, sizeof(HLE::Applets::MiiData) + sizeof(u16)); | ||||
| 
 | ||||
|     settings.amiibo_name = register_info.amiibo_name; | ||||
|     tag.file.owner_mii = register_info.mii_data; | ||||
|     tag.file.owner_mii.FixChecksum(); | ||||
|     tag.file.mii_extension = {}; | ||||
|     tag.file.unknown = 0; | ||||
|     tag.file.unknown2 = {}; | ||||
|  | @ -1061,9 +1056,7 @@ void NfcDevice::UpdateSettingsCrc() { | |||
| void NfcDevice::UpdateRegisterInfoCrc() { | ||||
| #pragma pack(push, 1) | ||||
|     struct CrcData { | ||||
|         HLE::Applets::MiiData mii; | ||||
|         INSERT_PADDING_BYTES(0x2); | ||||
|         u16 mii_crc; | ||||
|         Mii::ChecksummedMiiData mii; | ||||
|         u8 application_id_byte; | ||||
|         u8 unknown; | ||||
|         u64 mii_extension; | ||||
|  | @ -1074,7 +1067,6 @@ void NfcDevice::UpdateRegisterInfoCrc() { | |||
| 
 | ||||
|     const CrcData crc_data{ | ||||
|         .mii = tag.file.owner_mii, | ||||
|         .mii_crc = tag.file.owner_mii_aes_ccm, | ||||
|         .application_id_byte = tag.file.application_id_byte, | ||||
|         .unknown = tag.file.unknown, | ||||
|         .mii_extension = tag.file.mii_extension, | ||||
|  | @ -1102,8 +1094,6 @@ void NfcDevice::BuildAmiiboWithoutKeys() { | |||
|     settings.settings.font_region.Assign(0); | ||||
|     settings.init_date = GetAmiiboDate(); | ||||
|     tag.file.owner_mii = default_mii.selected_mii_data; | ||||
|     tag.file.padding = default_mii.unknown1; | ||||
|     tag.file.owner_mii_aes_ccm = default_mii.mii_data_checksum; | ||||
| 
 | ||||
|     // Admin info
 | ||||
|     settings.settings.amiibo_initialized.Assign(1); | ||||
|  |  | |||
|  | @ -269,20 +269,18 @@ static_assert(sizeof(NTAG215Password) == 0x8, "NTAG215Password is an invalid siz | |||
| 
 | ||||
| #pragma pack(1) | ||||
| struct EncryptedAmiiboFile { | ||||
|     u8 constant_value;                // Must be A5
 | ||||
|     u16_be write_counter;             // Number of times the amiibo has been written?
 | ||||
|     u8 amiibo_version;                // Amiibo file version
 | ||||
|     AmiiboSettings settings;          // Encrypted amiibo settings
 | ||||
|     HashData hmac_tag;                // Hash
 | ||||
|     AmiiboModelInfo model_info;       // Encrypted amiibo model info
 | ||||
|     HashData keygen_salt;             // Salt
 | ||||
|     HashData hmac_data;               // Hash
 | ||||
|     HLE::Applets::MiiData owner_mii;  // Encrypted Mii data
 | ||||
|     u16 padding;                      // Mii Padding
 | ||||
|     u16_be owner_mii_aes_ccm;         // Mii data AES-CCM MAC
 | ||||
|     u64_be application_id;            // Encrypted Game id
 | ||||
|     u16_be application_write_counter; // Encrypted Counter
 | ||||
|     u32_be application_area_id;       // Encrypted Game id
 | ||||
|     u8 constant_value;                 // Must be A5
 | ||||
|     u16_be write_counter;              // Number of times the amiibo has been written?
 | ||||
|     u8 amiibo_version;                 // Amiibo file version
 | ||||
|     AmiiboSettings settings;           // Encrypted amiibo settings
 | ||||
|     HashData hmac_tag;                 // Hash
 | ||||
|     AmiiboModelInfo model_info;        // Encrypted amiibo model info
 | ||||
|     HashData keygen_salt;              // Salt
 | ||||
|     HashData hmac_data;                // Hash
 | ||||
|     Mii::ChecksummedMiiData owner_mii; // Encrypted Mii data
 | ||||
|     u64_be application_id;             // Encrypted Game id
 | ||||
|     u16_be application_write_counter;  // Encrypted Counter
 | ||||
|     u32_be application_area_id;        // Encrypted Game id
 | ||||
|     u8 application_id_byte; | ||||
|     u8 unknown; | ||||
|     u64 mii_extension; | ||||
|  | @ -301,11 +299,9 @@ struct NTAG215File { | |||
|     u16_be write_counter;      // Number of times the amiibo has been written?
 | ||||
|     u8 amiibo_version;         // Amiibo file version
 | ||||
|     AmiiboSettings settings; | ||||
|     HLE::Applets::MiiData owner_mii;  // Mii data
 | ||||
|     u16 padding;                      // Mii Padding
 | ||||
|     u16_be owner_mii_aes_ccm;         // Mii data AES-CCM MAC
 | ||||
|     u64_be application_id;            // Game id
 | ||||
|     u16_be application_write_counter; // Counter
 | ||||
|     Mii::ChecksummedMiiData owner_mii; // Mii data
 | ||||
|     u64_be application_id;             // Game id
 | ||||
|     u16_be application_write_counter;  // Counter
 | ||||
|     u32_be application_area_id; | ||||
|     u8 application_id_byte; | ||||
|     u8 unknown; | ||||
|  | @ -417,9 +413,7 @@ struct ModelInfo { | |||
| static_assert(sizeof(ModelInfo) == 0x36, "ModelInfo is an invalid size"); | ||||
| 
 | ||||
| struct RegisterInfo { | ||||
|     HLE::Applets::MiiData mii_data; | ||||
|     INSERT_PADDING_BYTES(0x2); | ||||
|     u16_be owner_mii_aes_ccm; // Mii data AES-CCM MAC
 | ||||
|     Mii::ChecksummedMiiData mii_data; | ||||
|     AmiiboName amiibo_name; | ||||
|     INSERT_PADDING_BYTES(0x2); // Zero string terminator
 | ||||
|     u8 flags; | ||||
|  | @ -430,9 +424,7 @@ struct RegisterInfo { | |||
| static_assert(sizeof(RegisterInfo) == 0xA8, "RegisterInfo is an invalid size"); | ||||
| 
 | ||||
| struct RegisterInfoPrivate { | ||||
|     HLE::Applets::MiiData mii_data; | ||||
|     INSERT_PADDING_BYTES(0x2); | ||||
|     u16_be owner_mii_aes_ccm; // Mii data AES-CCM MAC
 | ||||
|     Mii::ChecksummedMiiData mii_data; | ||||
|     AmiiboName amiibo_name; | ||||
|     INSERT_PADDING_BYTES(0x2); // Zero string terminator
 | ||||
|     u8 flags; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue