From 026fe2e4f4128f4c81a07e25cb646620f7643a75 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 14 Mar 2023 22:00:38 -0600 Subject: [PATCH 1/4] service: nfp: Actually write correct crc --- src/core/hle/service/mii/mii_manager.cpp | 2 + src/core/hle/service/mii/types.h | 3 +- src/core/hle/service/nfp/amiibo_crypto.cpp | 4 +- src/core/hle/service/nfp/nfp_device.cpp | 53 ++++++++++++++-------- src/core/hle/service/nfp/nfp_device.h | 1 + src/core/hle/service/nfp/nfp_types.h | 4 +- 6 files changed, 44 insertions(+), 23 deletions(-) diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index 3a2fe938f..9d31a080c 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -585,6 +585,8 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits11.mole_x_position.Assign(mii.mole_x); mii_v3.appearance_bits11.mole_y_position.Assign(mii.mole_y); + mii_v3.crc = GenerateCrc16(&mii_v3, sizeof(Ver3StoreData) - sizeof(u16)); + // TODO: Validate mii_v3 data return mii_v3; diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h index 9e3247397..1f53e6af3 100644 --- a/src/core/hle/service/mii/types.h +++ b/src/core/hle/service/mii/types.h @@ -365,7 +365,8 @@ struct Ver3StoreData { } appearance_bits11; std::array author_name; - INSERT_PADDING_BYTES(0x4); + INSERT_PADDING_BYTES(0x2); + u16_be crc; }; static_assert(sizeof(Ver3StoreData) == 0x60, "Ver3StoreData is an invalid size"); diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp index ad73edbda..66773d26c 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.cpp +++ b/src/core/hle/service/nfp/amiibo_crypto.cpp @@ -89,7 +89,7 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte; encoded_data.unknown = nfc_data.user_memory.unknown; encoded_data.unknown2 = nfc_data.user_memory.unknown2; - encoded_data.application_area_crc = nfc_data.user_memory.application_area_crc; + encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc; encoded_data.application_area = nfc_data.user_memory.application_area; encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; encoded_data.lock_bytes = nfc_data.uuid.lock_bytes; @@ -123,7 +123,7 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte; nfc_data.user_memory.unknown = encoded_data.unknown; nfc_data.user_memory.unknown2 = encoded_data.unknown2; - nfc_data.user_memory.application_area_crc = encoded_data.application_area_crc; + nfc_data.user_memory.register_info_crc = encoded_data.register_info_crc; nfc_data.user_memory.application_area = encoded_data.application_area; nfc_data.user_memory.hmac_tag = encoded_data.hmac_tag; nfc_data.user_memory.model_info = encoded_data.model_info; diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index ddff90d6a..53bc56814 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -448,7 +448,7 @@ Result NfpDevice::DeleteRegisterInfo() { rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8)); rng.GenerateRandomBytes(&tag_data.unknown2[0], sizeof(u32)); rng.GenerateRandomBytes(&tag_data.unknown2[1], sizeof(u32)); - rng.GenerateRandomBytes(&tag_data.application_area_crc, sizeof(u32)); + rng.GenerateRandomBytes(&tag_data.register_info_crc, sizeof(u32)); rng.GenerateRandomBytes(&tag_data.settings.init_date, sizeof(u32)); tag_data.settings.settings.font_region.Assign(0); tag_data.settings.settings.amiibo_initialized.Assign(0); @@ -486,9 +486,7 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { settings.settings.font_region.Assign(0); settings.settings.amiibo_initialized.Assign(1); - // TODO: this is a mix of tag.file input - std::array unknown_input{}; - tag_data.application_area_crc = CalculateCrc(unknown_input); + UpdateRegisterInfoCrc(); return Flush(); } @@ -716,9 +714,7 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span dat tag_data.application_area_id = access_id; tag_data.unknown = {}; - // TODO: this is a mix of tag_data input - std::array unknown_input{}; - tag_data.application_area_crc = CalculateCrc(unknown_input); + UpdateRegisterInfoCrc(); return Flush(); } @@ -838,6 +834,29 @@ void NfpDevice::UpdateSettingsCrc() { settings.crc = CalculateCrc(unknown_input); } +void NfpDevice::UpdateRegisterInfoCrc() { +#pragma pack(push, 1) + struct CrcData { + Mii::Ver3StoreData mii; + u8 application_id_byte; + u8 unknown; + std::array unknown2; + }; + static_assert(sizeof(CrcData) == 0x7e, "CrcData is an invalid size"); +#pragma pack(pop) + + const CrcData crc_data{ + .mii = tag_data.owner_mii, + .application_id_byte = tag_data.application_id_byte, + .unknown = tag_data.unknown, + .unknown2 = tag_data.unknown2, + }; + + std::array data{}; + memcpy(data.data(), &crc_data, sizeof(CrcData)); + tag_data.register_info_crc = CalculateCrc(data); +} + u32 NfpDevice::CalculateCrc(std::span data) { constexpr u32 magic = 0xedb88320; u32 crc = 0xffffffff; @@ -847,17 +866,15 @@ u32 NfpDevice::CalculateCrc(std::span data) { } for (u8 input : data) { - u32 temp = (crc ^ input) >> 1; - if (((crc ^ input) & 1) != 0) { - temp = temp ^ magic; - } - - for (std::size_t step = 0; step < 7; ++step) { - crc = temp >> 1; - if ((temp & 1) != 0) { - crc = temp >> 1 ^ magic; - } - } + crc ^= input; + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); + crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); } return ~crc; diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index 06386401d..fc7fbd578 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -80,6 +80,7 @@ private: AmiiboDate GetAmiiboDate(s64 posix_time) const; u64 RemoveVersionByte(u64 application_id) const; void UpdateSettingsCrc(); + void UpdateRegisterInfoCrc(); u32 CalculateCrc(std::span); bool is_controller_set{}; diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 142343d6e..5f4a5d7f9 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -260,7 +260,7 @@ struct EncryptedAmiiboFile { u8 application_id_byte; u8 unknown; std::array unknown2; - u32_be application_area_crc; + u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data }; static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); @@ -281,7 +281,7 @@ struct NTAG215File { u8 application_id_byte; u8 unknown; std::array unknown2; - u32_be application_area_crc; + u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data HashData hmac_tag; // Hash UniqueSerialNumber uid; // Unique serial number From 5031f5b8b07dcabf727cf5530f2e00c396de7ea0 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Wed, 15 Mar 2023 01:39:11 -0600 Subject: [PATCH 2/4] service: nfp: Convert mii colors to v3 --- src/core/hle/service/mii/mii_manager.cpp | 33 +++++++++---- src/core/hle/service/mii/mii_manager.h | 7 ++- src/core/hle/service/mii/types.h | 57 ++++++++++++++++++++++ src/core/hle/service/nfp/amiibo_crypto.cpp | 2 + src/core/hle/service/nfp/nfp_device.cpp | 10 ++-- src/core/hle/service/nfp/nfp_types.h | 6 ++- 6 files changed, 100 insertions(+), 15 deletions(-) diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index 9d31a080c..c920650f5 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -510,7 +510,7 @@ CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const { return mii; } -Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { +Ver3StoreData MiiManager::BuildFromStoreData(const CharInfo& mii) const { Service::Mii::MiiManager manager; Ver3StoreData mii_v3{}; @@ -534,16 +534,13 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.region_information.character_set.Assign(mii.font_region); mii_v3.appearance_bits1.face_shape.Assign(mii.faceline_type); - mii_v3.appearance_bits1.skin_color.Assign(mii.faceline_color); 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.hair_color.Assign(mii.hair_color); 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_color.Assign(mii.eye_color); 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); @@ -551,7 +548,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { 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_color.Assign(mii.eyebrow_color); 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); @@ -563,7 +559,6 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { 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_color.Assign(mii.mouth_color); 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); @@ -573,10 +568,7 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { mii_v3.appearance_bits9.mustache_y_position.Assign(mii.mustache_y); mii_v3.appearance_bits9.bear_type.Assign(mii.beard_type); - mii_v3.appearance_bits9.facial_hair_color.Assign(mii.beard_color); - mii_v3.appearance_bits10.glasses_type.Assign(mii.glasses_type); - mii_v3.appearance_bits10.glasses_color.Assign(mii.glasses_color); mii_v3.appearance_bits10.glasses_scale.Assign(mii.glasses_scale); mii_v3.appearance_bits10.glasses_y_position.Assign(mii.glasses_y); @@ -585,6 +577,16 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { 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 @@ -592,6 +594,19 @@ Ver3StoreData MiiManager::ConvertCharInfoToV3(const CharInfo& mii) const { return mii_v3; } +NfpStoreDataExtension MiiManager::SetFromStoreData(const CharInfo& mii) const { + return { + .faceline_color = static_cast(mii.faceline_color & 0xf), + .hair_color = static_cast(mii.hair_color & 0x7f), + .eye_color = static_cast(mii.eyebrow_color & 0x7f), + .eyebrow_color = static_cast(mii.eyebrow_color & 0x7f), + .mouth_color = static_cast(mii.mouth_color & 0x7f), + .beard_color = static_cast(mii.beard_color & 0x7f), + .glass_color = static_cast(mii.glasses_color & 0x7f), + .glass_type = static_cast(mii.glasses_type & 0x1f), + }; +} + bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { bool is_valid = mii_v3.version == 0 || mii_v3.version == 3; diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index 83ad3d343..5525fcd1c 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h @@ -23,11 +23,16 @@ public: CharInfo BuildRandom(Age age, Gender gender, Race race); CharInfo BuildDefault(std::size_t index); CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; - Ver3StoreData ConvertCharInfoToV3(const CharInfo& mii) const; bool ValidateV3Info(const Ver3StoreData& mii_v3) const; ResultVal> GetDefault(SourceFlag source_flag); Result GetIndex(const CharInfo& info, u32& index); + // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData + Ver3StoreData BuildFromStoreData(const CharInfo& mii) const; + + // This is nn::mii::detail::NfpStoreDataExtentionRaw::SetFromStoreData + NfpStoreDataExtension SetFromStoreData(const CharInfo& mii) const; + private: const Common::UUID user_id{}; u64 update_counter{}; diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h index 1f53e6af3..c48d08d79 100644 --- a/src/core/hle/service/mii/types.h +++ b/src/core/hle/service/mii/types.h @@ -370,6 +370,63 @@ struct Ver3StoreData { }; 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 Ver3FacelineColorTable{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x0, 0x1, 0x5, 0x5, +}; + +constexpr std::array 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 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 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 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 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; diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp index 66773d26c..bba862fb2 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.cpp +++ b/src/core/hle/service/nfp/amiibo_crypto.cpp @@ -88,6 +88,7 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { encoded_data.application_area_id = nfc_data.user_memory.application_area_id; encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte; encoded_data.unknown = nfc_data.user_memory.unknown; + encoded_data.mii_extension = nfc_data.user_memory.mii_extension; encoded_data.unknown2 = nfc_data.user_memory.unknown2; encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc; encoded_data.application_area = nfc_data.user_memory.application_area; @@ -122,6 +123,7 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { nfc_data.user_memory.application_area_id = encoded_data.application_area_id; nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte; nfc_data.user_memory.unknown = encoded_data.unknown; + nfc_data.user_memory.mii_extension = encoded_data.mii_extension; nfc_data.user_memory.unknown2 = encoded_data.unknown2; nfc_data.user_memory.register_info_crc = encoded_data.register_info_crc; nfc_data.user_memory.application_area = encoded_data.application_area; diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index 53bc56814..c5d8ceeff 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -471,6 +471,7 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { } Service::Mii::MiiManager manager; + const auto mii = manager.BuildDefault(0); auto& settings = tag_data.settings; if (tag_data.settings.settings.amiibo_initialized == 0) { @@ -479,9 +480,10 @@ Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { } SetAmiiboName(settings, amiibo_name); - tag_data.owner_mii = manager.ConvertCharInfoToV3(manager.BuildDefault(0)); + tag_data.owner_mii = manager.BuildFromStoreData(mii); + tag_data.mii_extension = manager.SetFromStoreData(mii); tag_data.unknown = 0; - tag_data.unknown2[6] = 0; + tag_data.unknown2 = {}; settings.country_code_id = 0; settings.settings.font_region.Assign(0); settings.settings.amiibo_initialized.Assign(1); @@ -840,7 +842,8 @@ void NfpDevice::UpdateRegisterInfoCrc() { Mii::Ver3StoreData mii; u8 application_id_byte; u8 unknown; - std::array unknown2; + Mii::NfpStoreDataExtension mii_extension; + std::array unknown2; }; static_assert(sizeof(CrcData) == 0x7e, "CrcData is an invalid size"); #pragma pack(pop) @@ -849,6 +852,7 @@ void NfpDevice::UpdateRegisterInfoCrc() { .mii = tag_data.owner_mii, .application_id_byte = tag_data.application_id_byte, .unknown = tag_data.unknown, + .mii_extension = tag_data.mii_extension, .unknown2 = tag_data.unknown2, }; diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 5f4a5d7f9..b3599a513 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -259,7 +259,8 @@ struct EncryptedAmiiboFile { u32_be application_area_id; // Encrypted Game id u8 application_id_byte; u8 unknown; - std::array unknown2; + Service::Mii::NfpStoreDataExtension mii_extension; + std::array unknown2; u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data }; @@ -280,7 +281,8 @@ struct NTAG215File { u32_be application_area_id; u8 application_id_byte; u8 unknown; - std::array unknown2; + Service::Mii::NfpStoreDataExtension mii_extension; + std::array unknown2; u32_be register_info_crc; ApplicationArea application_area; // Encrypted Game data HashData hmac_tag; // Hash From 7187732454e7382009e35b4b62d0da16861ec3f8 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Wed, 15 Mar 2023 10:45:55 -0600 Subject: [PATCH 3/4] service: nfp: Close app area and recreate crc --- src/core/hle/service/nfp/nfp_device.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index c5d8ceeff..61a7ea7ac 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -685,6 +685,11 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span dat return WrongDeviceState; } + if (is_app_area_open) { + LOG_ERROR(Service_NFP, "Application area is open"); + return WrongDeviceState; + } + if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); return WrongDeviceState; @@ -715,6 +720,7 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span dat tag_data.settings.settings.appdata_initialized.Assign(1); tag_data.application_area_id = access_id; tag_data.unknown = {}; + tag_data.unknown2 = {}; UpdateRegisterInfoCrc(); @@ -750,6 +756,10 @@ Result NfpDevice::DeleteApplicationArea() { rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8)); tag_data.settings.settings.appdata_initialized.Assign(0); tag_data.unknown = {}; + tag_data.unknown2 = {}; + is_app_area_open = false; + + UpdateRegisterInfoCrc(); return Flush(); } From 075a3d11723d629148e016d089e2c533264ae831 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 16 Mar 2023 17:47:32 -0600 Subject: [PATCH 4/4] service: nfp: Replace crc function with boost equivalent --- src/core/hle/service/nfp/nfp_device.cpp | 44 ++++++++++--------------- src/core/hle/service/nfp/nfp_device.h | 1 - 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index 61a7ea7ac..268337d2e 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -3,6 +3,17 @@ #include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #include "common/input.h" #include "common/logging/log.h" #include "common/string_util.h" @@ -843,7 +854,9 @@ void NfpDevice::UpdateSettingsCrc() { // TODO: this reads data from a global, find what it is std::array unknown_input{}; - settings.crc = CalculateCrc(unknown_input); + boost::crc_32_type crc; + crc.process_bytes(&unknown_input, sizeof(unknown_input)); + settings.crc = crc.checksum(); } void NfpDevice::UpdateRegisterInfoCrc() { @@ -866,32 +879,9 @@ void NfpDevice::UpdateRegisterInfoCrc() { .unknown2 = tag_data.unknown2, }; - std::array data{}; - memcpy(data.data(), &crc_data, sizeof(CrcData)); - tag_data.register_info_crc = CalculateCrc(data); -} - -u32 NfpDevice::CalculateCrc(std::span data) { - constexpr u32 magic = 0xedb88320; - u32 crc = 0xffffffff; - - if (data.size() == 0) { - return 0; - } - - for (u8 input : data) { - crc ^= input; - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - crc = crc >> 1 ^ ((crc & 1) ? magic : 0x0); - } - - return ~crc; + boost::crc_32_type crc; + crc.process_bytes(&crc_data, sizeof(CrcData)); + tag_data.register_info_crc = crc.checksum(); } } // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index fc7fbd578..8813df998 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -81,7 +81,6 @@ private: u64 RemoveVersionByte(u64 application_id) const; void UpdateSettingsCrc(); void UpdateRegisterInfoCrc(); - u32 CalculateCrc(std::span); bool is_controller_set{}; int callback_key;