HLE/FS: Change the error code returned when an ExtSaveData archive is not found.
This allows Fire Emblem to boot again.
This commit is contained in:
		| @@ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "common/swap.h" | ||||||
|  |  | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
|  |  | ||||||
| @@ -63,9 +64,9 @@ private: | |||||||
| }; | }; | ||||||
|  |  | ||||||
| struct ArchiveFormatInfo { | struct ArchiveFormatInfo { | ||||||
|     u32 total_size; ///< The pre-defined size of the archive, as specified in the Create or Format call |     u32_le total_size; ///< The pre-defined size of the archive, as specified in the Create or Format call | ||||||
|     u32 number_directories; ///< The pre-defined number of directories in the archive, as specified in the Create or Format call |     u32_le number_directories; ///< The pre-defined number of directories in the archive, as specified in the Create or Format call | ||||||
|     u32 number_files; ///< The pre-defined number of files in the archive, as specified in the Create or Format call |     u32_le number_files; ///< The pre-defined number of files in the archive, as specified in the Create or Format call | ||||||
|     u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the Create or Format call |     u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the Create or Format call | ||||||
| }; | }; | ||||||
| static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD"); | static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD"); | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { | |||||||
| } | } | ||||||
|  |  | ||||||
| ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared) | ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared) | ||||||
|         : mount_point(GetExtDataContainerPath(mount_location, shared)) { |         : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { | ||||||
|     LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); |     LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -74,10 +74,16 @@ bool ArchiveFactory_ExtSaveData::Initialize() { | |||||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) { | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) { | ||||||
|     std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/"; |     std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/"; | ||||||
|     if (!FileUtil::Exists(fullpath)) { |     if (!FileUtil::Exists(fullpath)) { | ||||||
|         // TODO(Subv): Check error code, this one is probably wrong |         // TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData. | ||||||
|  |         // ExtSaveData seems to return FS_NotFound (120) when the archive doesn't exist. | ||||||
|  |         if (!shared) { | ||||||
|  |             return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, | ||||||
|  |                               ErrorSummary::InvalidState, ErrorLevel::Status); | ||||||
|  |         } else { | ||||||
|             return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, |             return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, | ||||||
|                               ErrorSummary::InvalidState, ErrorLevel::Status); |                               ErrorSummary::InvalidState, ErrorLevel::Status); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|     auto archive = Common::make_unique<DiskArchive>(fullpath); |     auto archive = Common::make_unique<DiskArchive>(fullpath); | ||||||
|     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||||||
| } | } | ||||||
| @@ -93,33 +99,33 @@ ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, const FileSys::A | |||||||
|     std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; |     std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; | ||||||
|     FileUtil::IOFile file(metadata_path, "wb"); |     FileUtil::IOFile file(metadata_path, "wb"); | ||||||
|  |  | ||||||
|     if (file.IsOpen()) { |     if (!file.IsOpen()) { | ||||||
|         file.WriteBytes(&format_info, sizeof(format_info)); |  | ||||||
|         return RESULT_SUCCESS; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|         // TODO(Subv): Find the correct error code |         // TODO(Subv): Find the correct error code | ||||||
|         return ResultCode(-1); |         return ResultCode(-1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     file.WriteBytes(&format_info, sizeof(format_info)); | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  |  | ||||||
| ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Path& path) const { | ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Path& path) const { | ||||||
|     std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; |     std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; | ||||||
|     FileUtil::IOFile file(metadata_path, "rb"); |     FileUtil::IOFile file(metadata_path, "rb"); | ||||||
|  |  | ||||||
|     if (file.IsOpen()) { |     if (!file.IsOpen()) { | ||||||
|         ArchiveFormatInfo info; |  | ||||||
|         file.ReadBytes(&info, sizeof(info)); |  | ||||||
|         return MakeResult<ArchiveFormatInfo>(info); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|         LOG_ERROR(Service_FS, "Could not open metadata information for archive"); |         LOG_ERROR(Service_FS, "Could not open metadata information for archive"); | ||||||
|         // TODO(Subv): Verify error code |         // TODO(Subv): Verify error code | ||||||
|         return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); |         return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, u32 icon_size) { |     ArchiveFormatInfo info = {}; | ||||||
|  |     file.ReadBytes(&info, sizeof(info)); | ||||||
|  |     return MakeResult<ArchiveFormatInfo>(info); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, size_t icon_size) { | ||||||
|     std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); |     std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); | ||||||
|     FileUtil::IOFile icon_file(game_path + "icon", "wb+"); |     FileUtil::IOFile icon_file(game_path + "icon", "wb"); | ||||||
|     icon_file.WriteBytes(icon_data, icon_size); |     icon_file.WriteBytes(icon_data, icon_size); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ public: | |||||||
|      * @param icon_data Binary data of the icon |      * @param icon_data Binary data of the icon | ||||||
|      * @param icon_size Size of the icon data |      * @param icon_size Size of the icon data | ||||||
|      */ |      */ | ||||||
|     void WriteIcon(const Path& path, const u8* icon_data, u32 icon_size); |     void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     /** |     /** | ||||||
| @@ -51,6 +51,7 @@ private: | |||||||
|      * See GetExtSaveDataPath for the code that extracts this data from an archive path. |      * See GetExtSaveDataPath for the code that extracts this data from an archive path. | ||||||
|      */ |      */ | ||||||
|     std::string mount_point; |     std::string mount_point; | ||||||
|  |     bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData archive | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -77,15 +77,15 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& | |||||||
|     std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); |     std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); | ||||||
|     FileUtil::IOFile file(metadata_path, "rb"); |     FileUtil::IOFile file(metadata_path, "rb"); | ||||||
|  |  | ||||||
|     if (file.IsOpen()) { |     if (!file.IsOpen()) { | ||||||
|         ArchiveFormatInfo info; |  | ||||||
|         file.ReadBytes(&info, sizeof(info)); |  | ||||||
|         return MakeResult<ArchiveFormatInfo>(info); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|         LOG_ERROR(Service_FS, "Could not open metadata information for archive"); |         LOG_ERROR(Service_FS, "Could not open metadata information for archive"); | ||||||
|         // TODO(Subv): Verify error code |         // TODO(Subv): Verify error code | ||||||
|         return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); |         return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     ArchiveFormatInfo info = {}; | ||||||
|  |     file.ReadBytes(&info, sizeof(info)); | ||||||
|  |     return MakeResult<ArchiveFormatInfo>(info); | ||||||
|  | } | ||||||
|  |  | ||||||
| } // namespace FileSys | } // namespace FileSys | ||||||
|   | |||||||
| @@ -103,14 +103,18 @@ ResultVal<bool> File::SyncRequest() { | |||||||
|             u32 address = cmd_buff[5]; |             u32 address = cmd_buff[5]; | ||||||
|             LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", |             LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", | ||||||
|                       GetTypeName().c_str(), GetName().c_str(), offset, length, address); |                       GetTypeName().c_str(), GetName().c_str(), offset, length, address); | ||||||
|             if (offset + length > backend->GetSize()) |  | ||||||
|                 LOG_ERROR(Service_FS, "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX", offset, length, backend->GetSize()); |             if (offset + length > backend->GetSize()) { | ||||||
|  |                 LOG_ERROR(Service_FS, "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX", | ||||||
|  |                           offset, length, backend->GetSize()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             ResultVal<size_t> read = backend->Read(offset, length, Memory::GetPointer(address)); |             ResultVal<size_t> read = backend->Read(offset, length, Memory::GetPointer(address)); | ||||||
|             if (read.Failed()) { |             if (read.Failed()) { | ||||||
|                 cmd_buff[1] = read.Code().raw; |                 cmd_buff[1] = read.Code().raw; | ||||||
|                 return read.Code(); |                 return read.Code(); | ||||||
|             } |             } | ||||||
|             cmd_buff[2] = static_cast<u32>(read.MoveFrom()); |             cmd_buff[2] = static_cast<u32>(*read); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -129,7 +133,7 @@ ResultVal<bool> File::SyncRequest() { | |||||||
|                 cmd_buff[1] = written.Code().raw; |                 cmd_buff[1] = written.Code().raw; | ||||||
|                 return written.Code(); |                 return written.Code(); | ||||||
|             } |             } | ||||||
|             cmd_buff[2] = static_cast<u32>(written.MoveFrom()); |             cmd_buff[2] = static_cast<u32>(*written); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user