service: nfc: Add backup support
This commit is contained in:
		| @@ -10,6 +10,7 @@ | |||||||
|  |  | ||||||
| // Sub-directories contained within a yuzu data directory | // Sub-directories contained within a yuzu data directory | ||||||
|  |  | ||||||
|  | #define AMIIBO_DIR "amiibo" | ||||||
| #define CACHE_DIR "cache" | #define CACHE_DIR "cache" | ||||||
| #define CONFIG_DIR "config" | #define CONFIG_DIR "config" | ||||||
| #define DUMP_DIR "dump" | #define DUMP_DIR "dump" | ||||||
|   | |||||||
| @@ -114,6 +114,7 @@ public: | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|         GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path); |         GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path); | ||||||
|  |         GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR); | ||||||
|         GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache); |         GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache); | ||||||
|         GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config); |         GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config); | ||||||
|         GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR); |         GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR); | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ namespace Common::FS { | |||||||
|  |  | ||||||
| enum class YuzuPath { | enum class YuzuPath { | ||||||
|     YuzuDir,        // Where yuzu stores its data. |     YuzuDir,        // Where yuzu stores its data. | ||||||
|  |     AmiiboDir,      // Where Amiibo backups are stored. | ||||||
|     CacheDir,       // Where cached filesystem data is stored. |     CacheDir,       // Where cached filesystem data is stored. | ||||||
|     ConfigDir,      // Where config files are stored. |     ConfigDir,      // Where config files are stored. | ||||||
|     DumpDir,        // Where dumped data is stored. |     DumpDir,        // Where dumped data is stored. | ||||||
|   | |||||||
| @@ -12,6 +12,11 @@ | |||||||
| #pragma warning(pop) | #pragma warning(pop) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #include <fmt/format.h> | ||||||
|  |  | ||||||
|  | #include "common/fs/file.h" | ||||||
|  | #include "common/fs/fs.h" | ||||||
|  | #include "common/fs/path_util.h" | ||||||
| #include "common/input.h" | #include "common/input.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| @@ -136,7 +141,7 @@ bool NfcDevice::LoadNfcTag(std::span<const u8> data) { | |||||||
|     if (!NFP::AmiiboCrypto::IsKeyAvailable()) { |     if (!NFP::AmiiboCrypto::IsKeyAvailable()) { | ||||||
|         LOG_INFO(Service_NFC, "Loading amiibo without keys"); |         LOG_INFO(Service_NFC, "Loading amiibo without keys"); | ||||||
|         memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); |         memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); | ||||||
|         BuildAmiiboWithoutKeys(); |         BuildAmiiboWithoutKeys(tag_data, encrypted_tag_data); | ||||||
|         is_plain_amiibo = true; |         is_plain_amiibo = true; | ||||||
|         is_write_protected = true; |         is_write_protected = true; | ||||||
|         return true; |         return true; | ||||||
| @@ -366,16 +371,25 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target | |||||||
|  |  | ||||||
|     // The loaded amiibo is not encrypted |     // The loaded amiibo is not encrypted | ||||||
|     if (is_plain_amiibo) { |     if (is_plain_amiibo) { | ||||||
|  |         std::vector<u8> data(sizeof(NFP::NTAG215File)); | ||||||
|  |         memcpy(data.data(), &tag_data, sizeof(tag_data)); | ||||||
|  |         WriteBackupData(tag_data.uid, data); | ||||||
|  |  | ||||||
|         device_state = DeviceState::TagMounted; |         device_state = DeviceState::TagMounted; | ||||||
|         mount_target = mount_target_; |         mount_target = mount_target_; | ||||||
|         return ResultSuccess; |         return ResultSuccess; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { |     if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { | ||||||
|         LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state); |         bool has_backup = HasBackup(encrypted_tag_data.uuid.uid).IsSuccess(); | ||||||
|         return ResultCorruptedData; |         LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); | ||||||
|  |         return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); | ||||||
|  |     memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); | ||||||
|  |     WriteBackupData(encrypted_tag_data.uuid.uid, data); | ||||||
|  |  | ||||||
|     device_state = DeviceState::TagMounted; |     device_state = DeviceState::TagMounted; | ||||||
|     mount_target = mount_target_; |     mount_target = mount_target_; | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| @@ -470,6 +484,7 @@ Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) { | |||||||
|     std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); |     std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); | ||||||
|     if (is_plain_amiibo) { |     if (is_plain_amiibo) { | ||||||
|         memcpy(data.data(), &tag_data, sizeof(tag_data)); |         memcpy(data.data(), &tag_data, sizeof(tag_data)); | ||||||
|  |         WriteBackupData(tag_data.uid, data); | ||||||
|     } else { |     } else { | ||||||
|         if (!NFP::AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { |         if (!NFP::AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { | ||||||
|             LOG_ERROR(Service_NFP, "Failed to encode data"); |             LOG_ERROR(Service_NFP, "Failed to encode data"); | ||||||
| @@ -477,6 +492,7 @@ Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); |         memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); | ||||||
|  |         WriteBackupData(encrypted_tag_data.uuid.uid, data); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!npad_device->WriteNfc(data)) { |     if (!npad_device->WriteNfc(data)) { | ||||||
| @@ -488,7 +504,7 @@ Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) { | |||||||
| } | } | ||||||
|  |  | ||||||
| Result NfcDevice::Restore() { | Result NfcDevice::Restore() { | ||||||
|     if (device_state != DeviceState::TagMounted) { |     if (device_state != DeviceState::TagFound) { | ||||||
|         LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); |         LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); | ||||||
|         if (device_state == DeviceState::TagRemoved) { |         if (device_state == DeviceState::TagRemoved) { | ||||||
|             return ResultTagRemoved; |             return ResultTagRemoved; | ||||||
| @@ -496,13 +512,59 @@ Result NfcDevice::Restore() { | |||||||
|         return ResultWrongDeviceState; |         return ResultWrongDeviceState; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) { |     NFC::TagInfo tag_info{}; | ||||||
|         LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); |     std::array<u8, sizeof(NFP::EncryptedNTAG215File)> data{}; | ||||||
|         return ResultWrongDeviceState; |     Result result = GetTagInfo(tag_info, false); | ||||||
|  |  | ||||||
|  |     if (result.IsError()) { | ||||||
|  |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // TODO: Load amiibo from backup on system |     result = ReadBackupData(tag_info.uuid, data); | ||||||
|     LOG_ERROR(Service_NFP, "Not Implemented"); |  | ||||||
|  |     if (result.IsError()) { | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     NFP::NTAG215File temporary_tag_data{}; | ||||||
|  |     NFP::EncryptedNTAG215File temporary_encrypted_tag_data{}; | ||||||
|  |  | ||||||
|  |     // Fallback for encrypted amiibos without keys | ||||||
|  |     if (is_write_protected) { | ||||||
|  |         return ResultWriteAmiiboFailed; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Fallback for plain amiibos | ||||||
|  |     if (is_plain_amiibo) { | ||||||
|  |         LOG_INFO(Service_NFP, "Restoring backup of plain amiibo"); | ||||||
|  |         memcpy(&temporary_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); | ||||||
|  |         temporary_encrypted_tag_data = NFP::AmiiboCrypto::EncodedDataToNfcData(temporary_tag_data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!is_plain_amiibo) { | ||||||
|  |         LOG_INFO(Service_NFP, "Restoring backup of encrypted amiibo"); | ||||||
|  |         temporary_tag_data = {}; | ||||||
|  |         memcpy(&temporary_encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!NFP::AmiiboCrypto::IsAmiiboValid(temporary_encrypted_tag_data)) { | ||||||
|  |         return ResultNotAnAmiibo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!is_plain_amiibo) { | ||||||
|  |         if (!NFP::AmiiboCrypto::DecodeAmiibo(temporary_encrypted_tag_data, temporary_tag_data)) { | ||||||
|  |             LOG_ERROR(Service_NFP, "Can't decode amiibo"); | ||||||
|  |             return ResultCorruptedData; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Overwrite tag contents with backup and mount the tag | ||||||
|  |     tag_data = temporary_tag_data; | ||||||
|  |     encrypted_tag_data = temporary_encrypted_tag_data; | ||||||
|  |     device_state = DeviceState::TagMounted; | ||||||
|  |     mount_target = NFP::MountTarget::All; | ||||||
|  |     is_data_moddified = true; | ||||||
|  |  | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1132,13 +1194,69 @@ Result NfcDevice::BreakTag(NFP::BreakType break_type) { | |||||||
|     return FlushWithBreak(break_type); |     return FlushWithBreak(break_type); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result NfcDevice::ReadBackupData(std::span<u8> data) const { | Result NfcDevice::HasBackup(const NFC::UniqueSerialNumber& uid) const { | ||||||
|     // Not implemented |     constexpr auto backup_dir = "backup"; | ||||||
|  |     const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); | ||||||
|  |     const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, "")); | ||||||
|  |  | ||||||
|  |     if (!Common::FS::Exists(yuzu_amiibo_dir / backup_dir / file_name)) { | ||||||
|  |         return ResultUnableToAccessBackupFile; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| } | } | ||||||
|  |  | ||||||
| Result NfcDevice::WriteBackupData(std::span<const u8> data) { | Result NfcDevice::ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u8> data) const { | ||||||
|     // Not implemented |     constexpr auto backup_dir = "backup"; | ||||||
|  |     const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); | ||||||
|  |     const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, "")); | ||||||
|  |  | ||||||
|  |     const Common::FS::IOFile keys_file{yuzu_amiibo_dir / backup_dir / file_name, | ||||||
|  |                                        Common::FS::FileAccessMode::Read, | ||||||
|  |                                        Common::FS::FileType::BinaryFile}; | ||||||
|  |  | ||||||
|  |     if (!keys_file.IsOpen()) { | ||||||
|  |         LOG_ERROR(Service_NFP, "Failed to open amiibo backup"); | ||||||
|  |         return ResultUnableToAccessBackupFile; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (keys_file.Read(data) != data.size()) { | ||||||
|  |         LOG_ERROR(Service_NFP, "Failed to read amiibo backup"); | ||||||
|  |         return ResultUnableToAccessBackupFile; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ResultSuccess; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Result NfcDevice::WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span<const u8> data) { | ||||||
|  |     constexpr auto backup_dir = "backup"; | ||||||
|  |     const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir); | ||||||
|  |     const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, "")); | ||||||
|  |  | ||||||
|  |     if (HasBackup(uid).IsError()) { | ||||||
|  |         if (!Common::FS::CreateDir(yuzu_amiibo_dir / backup_dir)) { | ||||||
|  |             return ResultBackupPathAlreadyExist; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!Common::FS::NewFile(yuzu_amiibo_dir / backup_dir / file_name)) { | ||||||
|  |             return ResultBackupPathAlreadyExist; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const Common::FS::IOFile keys_file{yuzu_amiibo_dir / backup_dir / file_name, | ||||||
|  |                                        Common::FS::FileAccessMode::ReadWrite, | ||||||
|  |                                        Common::FS::FileType::BinaryFile}; | ||||||
|  |  | ||||||
|  |     if (!keys_file.IsOpen()) { | ||||||
|  |         LOG_ERROR(Service_NFP, "Failed to open amiibo backup"); | ||||||
|  |         return ResultUnableToAccessBackupFile; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (keys_file.Write(data) != data.size()) { | ||||||
|  |         LOG_ERROR(Service_NFP, "Failed to write amiibo backup"); | ||||||
|  |         return ResultUnableToAccessBackupFile; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1177,7 +1295,8 @@ NFP::AmiiboName NfcDevice::GetAmiiboName(const NFP::AmiiboSettings& settings) co | |||||||
|     return amiibo_name; |     return amiibo_name; | ||||||
| } | } | ||||||
|  |  | ||||||
| void NfcDevice::SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name) { | void NfcDevice::SetAmiiboName(NFP::AmiiboSettings& settings, | ||||||
|  |                               const NFP::AmiiboName& amiibo_name) const { | ||||||
|     std::array<char16_t, NFP::amiibo_name_length> settings_amiibo_name{}; |     std::array<char16_t, NFP::amiibo_name_length> settings_amiibo_name{}; | ||||||
|  |  | ||||||
|     // Convert from utf8 to utf16 |     // Convert from utf8 to utf16 | ||||||
| @@ -1258,22 +1377,23 @@ void NfcDevice::UpdateRegisterInfoCrc() { | |||||||
|     tag_data.register_info_crc = crc.checksum(); |     tag_data.register_info_crc = crc.checksum(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void NfcDevice::BuildAmiiboWithoutKeys() { | void NfcDevice::BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, | ||||||
|  |                                        const NFP::EncryptedNTAG215File& encrypted_file) const { | ||||||
|     Service::Mii::MiiManager manager; |     Service::Mii::MiiManager manager; | ||||||
|     auto& settings = tag_data.settings; |     auto& settings = stubbed_tag_data.settings; | ||||||
|  |  | ||||||
|     tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_tag_data); |     stubbed_tag_data = NFP::AmiiboCrypto::NfcDataToEncodedData(encrypted_file); | ||||||
|  |  | ||||||
|     // Common info |     // Common info | ||||||
|     tag_data.write_counter = 0; |     stubbed_tag_data.write_counter = 0; | ||||||
|     tag_data.amiibo_version = 0; |     stubbed_tag_data.amiibo_version = 0; | ||||||
|     settings.write_date = GetAmiiboDate(GetCurrentPosixTime()); |     settings.write_date = GetAmiiboDate(GetCurrentPosixTime()); | ||||||
|  |  | ||||||
|     // Register info |     // Register info | ||||||
|     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()); | ||||||
|     tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildDefault(0)); |     stubbed_tag_data.owner_mii = manager.BuildFromStoreData(manager.BuildDefault(0)); | ||||||
|  |  | ||||||
|     // Admin info |     // Admin info | ||||||
|     settings.settings.amiibo_initialized.Assign(1); |     settings.settings.amiibo_initialized.Assign(1); | ||||||
|   | |||||||
| @@ -86,8 +86,9 @@ public: | |||||||
|     Result GetAll(NFP::NfpData& data) const; |     Result GetAll(NFP::NfpData& data) const; | ||||||
|     Result SetAll(const NFP::NfpData& data); |     Result SetAll(const NFP::NfpData& data); | ||||||
|     Result BreakTag(NFP::BreakType break_type); |     Result BreakTag(NFP::BreakType break_type); | ||||||
|     Result ReadBackupData(std::span<u8> data) const; |     Result HasBackup(const NFC::UniqueSerialNumber& uid) const; | ||||||
|     Result WriteBackupData(std::span<const u8> data); |     Result ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u8> data) const; | ||||||
|  |     Result WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span<const u8> data); | ||||||
|     Result WriteNtf(std::span<const u8> data); |     Result WriteNtf(std::span<const u8> data); | ||||||
|  |  | ||||||
|     u64 GetHandle() const; |     u64 GetHandle() const; | ||||||
| @@ -103,14 +104,15 @@ private: | |||||||
|     void CloseNfcTag(); |     void CloseNfcTag(); | ||||||
|  |  | ||||||
|     NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const; |     NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const; | ||||||
|     void SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name); |     void SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name) const; | ||||||
|     NFP::AmiiboDate GetAmiiboDate(s64 posix_time) const; |     NFP::AmiiboDate GetAmiiboDate(s64 posix_time) const; | ||||||
|     u64 GetCurrentPosixTime() const; |     u64 GetCurrentPosixTime() const; | ||||||
|     u64 RemoveVersionByte(u64 application_id) const; |     u64 RemoveVersionByte(u64 application_id) const; | ||||||
|     void UpdateSettingsCrc(); |     void UpdateSettingsCrc(); | ||||||
|     void UpdateRegisterInfoCrc(); |     void UpdateRegisterInfoCrc(); | ||||||
|  |  | ||||||
|     void BuildAmiiboWithoutKeys(); |     void BuildAmiiboWithoutKeys(NFP::NTAG215File& stubbed_tag_data, | ||||||
|  |                                 const NFP::EncryptedNTAG215File& encrypted_file) const; | ||||||
|  |  | ||||||
|     bool is_controller_set{}; |     bool is_controller_set{}; | ||||||
|     int callback_key; |     int callback_key; | ||||||
|   | |||||||
| @@ -543,9 +543,14 @@ Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) cons | |||||||
|  |  | ||||||
|     std::shared_ptr<NfcDevice> device = nullptr; |     std::shared_ptr<NfcDevice> device = nullptr; | ||||||
|     auto result = GetDeviceHandle(device_handle, device); |     auto result = GetDeviceHandle(device_handle, device); | ||||||
|  |     NFC::TagInfo tag_info{}; | ||||||
|  |  | ||||||
|     if (result.IsSuccess()) { |     if (result.IsSuccess()) { | ||||||
|         result = device->ReadBackupData(data); |         result = device->GetTagInfo(tag_info, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (result.IsSuccess()) { | ||||||
|  |         result = device->ReadBackupData(tag_info.uuid, data); | ||||||
|         result = VerifyDeviceResult(device, result); |         result = VerifyDeviceResult(device, result); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -557,9 +562,14 @@ Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> dat | |||||||
|  |  | ||||||
|     std::shared_ptr<NfcDevice> device = nullptr; |     std::shared_ptr<NfcDevice> device = nullptr; | ||||||
|     auto result = GetDeviceHandle(device_handle, device); |     auto result = GetDeviceHandle(device_handle, device); | ||||||
|  |     NFC::TagInfo tag_info{}; | ||||||
|  |  | ||||||
|     if (result.IsSuccess()) { |     if (result.IsSuccess()) { | ||||||
|         result = device->WriteBackupData(data); |         result = device->GetTagInfo(tag_info, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (result.IsSuccess()) { | ||||||
|  |         result = device->WriteBackupData(tag_info.uuid, data); | ||||||
|         result = VerifyDeviceResult(device, result); |         result = VerifyDeviceResult(device, result); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -302,7 +302,7 @@ Result NfcInterface::TranslateResultToServiceError(Result result) const { | |||||||
|         return TranslateResultToNfp(result); |         return TranslateResultToNfp(result); | ||||||
|     } |     } | ||||||
|     default: |     default: | ||||||
|         if (result != ResultUnknown216) { |         if (result != ResultBackupPathAlreadyExist) { | ||||||
|             return result; |             return result; | ||||||
|         } |         } | ||||||
|         return ResultUnknown74; |         return ResultUnknown74; | ||||||
| @@ -343,6 +343,9 @@ Result NfcInterface::TranslateResultToNfp(Result result) const { | |||||||
|     if (result == ResultApplicationAreaIsNotInitialized) { |     if (result == ResultApplicationAreaIsNotInitialized) { | ||||||
|         return NFP::ResultApplicationAreaIsNotInitialized; |         return NFP::ResultApplicationAreaIsNotInitialized; | ||||||
|     } |     } | ||||||
|  |     if (result == ResultCorruptedDataWithBackup) { | ||||||
|  |         return NFP::ResultCorruptedDataWithBackup; | ||||||
|  |     } | ||||||
|     if (result == ResultCorruptedData) { |     if (result == ResultCorruptedData) { | ||||||
|         return NFP::ResultCorruptedData; |         return NFP::ResultCorruptedData; | ||||||
|     } |     } | ||||||
| @@ -355,6 +358,9 @@ Result NfcInterface::TranslateResultToNfp(Result result) const { | |||||||
|     if (result == ResultNotAnAmiibo) { |     if (result == ResultNotAnAmiibo) { | ||||||
|         return NFP::ResultNotAnAmiibo; |         return NFP::ResultNotAnAmiibo; | ||||||
|     } |     } | ||||||
|  |     if (result == ResultUnableToAccessBackupFile) { | ||||||
|  |         return NFP::ResultUnableToAccessBackupFile; | ||||||
|  |     } | ||||||
|     LOG_WARNING(Service_NFC, "Result conversion not handled"); |     LOG_WARNING(Service_NFC, "Result conversion not handled"); | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,20 +9,22 @@ namespace Service::NFC { | |||||||
|  |  | ||||||
| constexpr Result ResultDeviceNotFound(ErrorModule::NFC, 64); | constexpr Result ResultDeviceNotFound(ErrorModule::NFC, 64); | ||||||
| constexpr Result ResultInvalidArgument(ErrorModule::NFC, 65); | constexpr Result ResultInvalidArgument(ErrorModule::NFC, 65); | ||||||
| constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFP, 68); | constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFC, 68); | ||||||
| constexpr Result ResultWrongDeviceState(ErrorModule::NFC, 73); | constexpr Result ResultWrongDeviceState(ErrorModule::NFC, 73); | ||||||
| constexpr Result ResultUnknown74(ErrorModule::NFC, 74); | constexpr Result ResultUnknown74(ErrorModule::NFC, 74); | ||||||
| constexpr Result ResultUnknown76(ErrorModule::NFC, 76); | constexpr Result ResultUnknown76(ErrorModule::NFC, 76); | ||||||
| constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77); | constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77); | ||||||
| constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80); | constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80); | ||||||
| constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFP, 88); | constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFC, 88); | ||||||
| constexpr Result ResultTagRemoved(ErrorModule::NFC, 97); | constexpr Result ResultTagRemoved(ErrorModule::NFC, 97); | ||||||
| constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120); | constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFC, 113); | ||||||
| constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128); | constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFC, 120); | ||||||
| constexpr Result ResultCorruptedData(ErrorModule::NFP, 144); | constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFC, 128); | ||||||
| constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152); | constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136); | ||||||
| constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168); | constexpr Result ResultCorruptedData(ErrorModule::NFC, 144); | ||||||
| constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178); | constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFC, 152); | ||||||
| constexpr Result ResultUnknown216(ErrorModule::NFC, 216); | constexpr Result ResultApplicationAreaExist(ErrorModule::NFC, 168); | ||||||
|  | constexpr Result ResultNotAnAmiibo(ErrorModule::NFC, 178); | ||||||
|  | constexpr Result ResultBackupPathAlreadyExist(ErrorModule::NFC, 216); | ||||||
|  |  | ||||||
| } // namespace Service::NFC | } // namespace Service::NFC | ||||||
|   | |||||||
| @@ -126,7 +126,7 @@ void Interface::Flush(HLERequestContext& ctx) { | |||||||
| void Interface::Restore(HLERequestContext& ctx) { | void Interface::Restore(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); |     LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); | ||||||
|  |  | ||||||
|     auto result = GetManager()->Restore(device_handle); |     auto result = GetManager()->Restore(device_handle); | ||||||
|     result = TranslateResultToServiceError(result); |     result = TranslateResultToServiceError(result); | ||||||
| @@ -394,7 +394,7 @@ void Interface::BreakTag(HLERequestContext& ctx) { | |||||||
| void Interface::ReadBackupData(HLERequestContext& ctx) { | void Interface::ReadBackupData(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); |     LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); | ||||||
|  |  | ||||||
|     std::vector<u8> backup_data{}; |     std::vector<u8> backup_data{}; | ||||||
|     auto result = GetManager()->ReadBackupData(device_handle, backup_data); |     auto result = GetManager()->ReadBackupData(device_handle, backup_data); | ||||||
| @@ -412,7 +412,7 @@ void Interface::WriteBackupData(HLERequestContext& ctx) { | |||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     const auto backup_data_buffer{ctx.ReadBuffer()}; |     const auto backup_data_buffer{ctx.ReadBuffer()}; | ||||||
|     LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); |     LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); | ||||||
|  |  | ||||||
|     auto result = GetManager()->WriteBackupData(device_handle, backup_data_buffer); |     auto result = GetManager()->WriteBackupData(device_handle, backup_data_buffer); | ||||||
|     result = TranslateResultToServiceError(result); |     result = TranslateResultToServiceError(result); | ||||||
|   | |||||||
| @@ -17,9 +17,11 @@ constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFP, 88); | |||||||
| constexpr Result ResultTagRemoved(ErrorModule::NFP, 97); | constexpr Result ResultTagRemoved(ErrorModule::NFP, 97); | ||||||
| constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120); | constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120); | ||||||
| constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128); | constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128); | ||||||
|  | constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFP, 136); | ||||||
| constexpr Result ResultCorruptedData(ErrorModule::NFP, 144); | constexpr Result ResultCorruptedData(ErrorModule::NFP, 144); | ||||||
| constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152); | constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152); | ||||||
| constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168); | constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168); | ||||||
| constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178); | constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178); | ||||||
|  | constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFP, 200); | ||||||
|  |  | ||||||
| } // namespace Service::NFP | } // namespace Service::NFP | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user