diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/archive_backend.h | 18 | ||||
| -rw-r--r-- | src/core/file_sys/archive_extsavedata.cpp | 36 | ||||
| -rw-r--r-- | src/core/file_sys/archive_extsavedata.h | 11 | ||||
| -rw-r--r-- | src/core/file_sys/archive_romfs.cpp | 8 | ||||
| -rw-r--r-- | src/core/file_sys/archive_romfs.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedata.cpp | 32 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedata.h | 4 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedatacheck.cpp | 8 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedatacheck.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/archive_sdmc.cpp | 7 | ||||
| -rw-r--r-- | src/core/file_sys/archive_sdmc.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/archive_systemsavedata.cpp | 8 | ||||
| -rw-r--r-- | src/core/file_sys/archive_systemsavedata.h | 3 | ||||
| -rw-r--r-- | src/core/hle/result.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/cfg/cfg.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 48 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.h | 15 | ||||
| -rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 107 | ||||
| -rw-r--r-- | src/core/hle/service/ptm/ptm.cpp | 2 |
19 files changed, 257 insertions, 62 deletions
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h index 60108b4b0..800ac1541 100644 --- a/src/core/file_sys/archive_backend.h +++ b/src/core/file_sys/archive_backend.h | |||
| @@ -62,6 +62,14 @@ private: | |||
| 62 | std::u16string u16str; | 62 | std::u16string u16str; |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | struct ArchiveFormatInfo { | ||
| 66 | u32 total_size; ///< The pre-defined size of the archive, as specified in the Create or Format call | ||
| 67 | u32 number_directories; ///< The pre-defined number of directories in the archive, as specified in the Create or Format call | ||
| 68 | u32 number_files; ///< The pre-defined number of files in the archive, as specified in the Create or Format call | ||
| 69 | u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the Create or Format call | ||
| 70 | }; | ||
| 71 | static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD"); | ||
| 72 | |||
| 65 | class ArchiveBackend : NonCopyable { | 73 | class ArchiveBackend : NonCopyable { |
| 66 | public: | 74 | public: |
| 67 | virtual ~ArchiveBackend() { | 75 | virtual ~ArchiveBackend() { |
| @@ -159,9 +167,17 @@ public: | |||
| 159 | /** | 167 | /** |
| 160 | * Deletes the archive contents and then re-creates the base folder | 168 | * Deletes the archive contents and then re-creates the base folder |
| 161 | * @param path Path to the archive | 169 | * @param path Path to the archive |
| 170 | * @param format_info Format information for the new archive | ||
| 162 | * @return ResultCode of the operation, 0 on success | 171 | * @return ResultCode of the operation, 0 on success |
| 163 | */ | 172 | */ |
| 164 | virtual ResultCode Format(const Path& path) = 0; | 173 | virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) = 0; |
| 174 | |||
| 175 | /* | ||
| 176 | * Retrieves the format info about the archive with the specified path | ||
| 177 | * @param path Path to the archive | ||
| 178 | * @return Format information about the archive or error code | ||
| 179 | */ | ||
| 180 | virtual ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const = 0; | ||
| 165 | }; | 181 | }; |
| 166 | 182 | ||
| 167 | } // namespace FileSys | 183 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index 92dad8e6f..e83a6153d 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp | |||
| @@ -82,13 +82,45 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons | |||
| 82 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 82 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path) { | 85 | ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { |
| 86 | // These folders are always created with the ExtSaveData | 86 | // These folders are always created with the ExtSaveData |
| 87 | std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; | 87 | std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; |
| 88 | std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; | 88 | std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; |
| 89 | FileUtil::CreateFullPath(user_path); | 89 | FileUtil::CreateFullPath(user_path); |
| 90 | FileUtil::CreateFullPath(boss_path); | 90 | FileUtil::CreateFullPath(boss_path); |
| 91 | return RESULT_SUCCESS; | 91 | |
| 92 | // Write the format metadata | ||
| 93 | std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; | ||
| 94 | FileUtil::IOFile file(metadata_path, "wb"); | ||
| 95 | |||
| 96 | if (file.IsOpen()) { | ||
| 97 | file.WriteBytes(&format_info, sizeof(format_info)); | ||
| 98 | return RESULT_SUCCESS; | ||
| 99 | } | ||
| 100 | |||
| 101 | // TODO(Subv): Find the correct error code | ||
| 102 | return ResultCode(-1); | ||
| 103 | } | ||
| 104 | |||
| 105 | ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Path& path) const { | ||
| 106 | std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; | ||
| 107 | FileUtil::IOFile file(metadata_path, "rb"); | ||
| 108 | |||
| 109 | if (file.IsOpen()) { | ||
| 110 | ArchiveFormatInfo info; | ||
| 111 | file.ReadBytes(&info, sizeof(info)); | ||
| 112 | return MakeResult<ArchiveFormatInfo>(info); | ||
| 113 | } | ||
| 114 | |||
| 115 | LOG_ERROR(Service_FS, "Could not open metadata information for archive"); | ||
| 116 | // TODO(Subv): Verify error code | ||
| 117 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); | ||
| 118 | } | ||
| 119 | |||
| 120 | void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, u8* icon_data, u32 icon_size) { | ||
| 121 | std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); | ||
| 122 | FileUtil::IOFile icon_file(game_path + "icon", "wb+"); | ||
| 123 | icon_file.WriteBytes(icon_data, icon_size); | ||
| 92 | } | 124 | } |
| 93 | 125 | ||
| 94 | } // namespace FileSys | 126 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h index ec8d770fc..48e092ee7 100644 --- a/src/core/file_sys/archive_extsavedata.h +++ b/src/core/file_sys/archive_extsavedata.h | |||
| @@ -31,10 +31,19 @@ public: | |||
| 31 | std::string GetName() const override { return "ExtSaveData"; } | 31 | std::string GetName() const override { return "ExtSaveData"; } |
| 32 | 32 | ||
| 33 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 33 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 34 | ResultCode Format(const Path& path) override; | 34 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 35 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 35 | 36 | ||
| 36 | const std::string& GetMountPoint() const { return mount_point; } | 37 | const std::string& GetMountPoint() const { return mount_point; } |
| 37 | 38 | ||
| 39 | /* | ||
| 40 | * Writes the SMDH icon of the ExtSaveData to file | ||
| 41 | * @param path Path of this ExtSaveData | ||
| 42 | * @param icon_data Binary data of the icon | ||
| 43 | * @param icon_size Size of the icon data | ||
| 44 | */ | ||
| 45 | void WriteIcon(const Path& path, u8* icon_data, u32 icon_size); | ||
| 46 | |||
| 38 | private: | 47 | private: |
| 39 | /** | 48 | /** |
| 40 | * This holds the full directory path for this archive, it is only set after a successful call | 49 | * This holds the full directory path for this archive, it is only set after a successful call |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index 696b51a94..a9a29ebde 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -29,11 +29,17 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path | |||
| 29 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 29 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | ResultCode ArchiveFactory_RomFS::Format(const Path& path) { | 32 | ResultCode ArchiveFactory_RomFS::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { |
| 33 | LOG_ERROR(Service_FS, "Attempted to format a RomFS archive."); | 33 | LOG_ERROR(Service_FS, "Attempted to format a RomFS archive."); |
| 34 | // TODO: Verify error code | 34 | // TODO: Verify error code |
| 35 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, | 35 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, |
| 36 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | 36 | ErrorSummary::NotSupported, ErrorLevel::Permanent); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | ResultVal<ArchiveFormatInfo> ArchiveFactory_RomFS::GetFormatInfo(const Path& path) const { | ||
| 40 | // TODO(Subv): Implement | ||
| 41 | LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); | ||
| 42 | return ResultCode(-1); | ||
| 43 | } | ||
| 44 | |||
| 39 | } // namespace FileSys | 45 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index 2bedfa9c6..c5a329122 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -26,7 +26,8 @@ public: | |||
| 26 | 26 | ||
| 27 | std::string GetName() const override { return "RomFS"; } | 27 | std::string GetName() const override { return "RomFS"; } |
| 28 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 28 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 29 | ResultCode Format(const Path& path) override; | 29 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 30 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 30 | 31 | ||
| 31 | private: | 32 | private: |
| 32 | std::shared_ptr<FileUtil::IOFile> romfs_file; | 33 | std::shared_ptr<FileUtil::IOFile> romfs_file; |
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp index 12876899f..82f49af5d 100644 --- a/src/core/file_sys/archive_savedata.cpp +++ b/src/core/file_sys/archive_savedata.cpp | |||
| @@ -31,6 +31,12 @@ static std::string GetSaveDataPath(const std::string& mount_location, u64 progra | |||
| 31 | return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); | 31 | return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { | ||
| 35 | u32 high = program_id >> 32; | ||
| 36 | u32 low = program_id & 0xFFFFFFFF; | ||
| 37 | return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), high, low); | ||
| 38 | } | ||
| 39 | |||
| 34 | ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) | 40 | ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) |
| 35 | : mount_point(GetSaveDataContainerPath(sdmc_directory)) { | 41 | : mount_point(GetSaveDataContainerPath(sdmc_directory)) { |
| 36 | LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); | 42 | LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); |
| @@ -51,11 +57,35 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const P | |||
| 51 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 57 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 52 | } | 58 | } |
| 53 | 59 | ||
| 54 | ResultCode ArchiveFactory_SaveData::Format(const Path& path) { | 60 | ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { |
| 55 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); | 61 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); |
| 56 | FileUtil::DeleteDirRecursively(concrete_mount_point); | 62 | FileUtil::DeleteDirRecursively(concrete_mount_point); |
| 57 | FileUtil::CreateFullPath(concrete_mount_point); | 63 | FileUtil::CreateFullPath(concrete_mount_point); |
| 64 | |||
| 65 | // Write the format metadata | ||
| 66 | std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); | ||
| 67 | FileUtil::IOFile file(metadata_path, "wb"); | ||
| 68 | |||
| 69 | if (file.IsOpen()) { | ||
| 70 | file.WriteBytes(&format_info, sizeof(format_info)); | ||
| 71 | return RESULT_SUCCESS; | ||
| 72 | } | ||
| 58 | return RESULT_SUCCESS; | 73 | return RESULT_SUCCESS; |
| 59 | } | 74 | } |
| 60 | 75 | ||
| 76 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { | ||
| 77 | std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); | ||
| 78 | FileUtil::IOFile file(metadata_path, "rb"); | ||
| 79 | |||
| 80 | if (file.IsOpen()) { | ||
| 81 | ArchiveFormatInfo info; | ||
| 82 | file.ReadBytes(&info, sizeof(info)); | ||
| 83 | return MakeResult<ArchiveFormatInfo>(info); | ||
| 84 | } | ||
| 85 | |||
| 86 | LOG_ERROR(Service_FS, "Could not open metadata information for archive"); | ||
| 87 | // TODO(Subv): Verify error code | ||
| 88 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); | ||
| 89 | } | ||
| 90 | |||
| 61 | } // namespace FileSys | 91 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h index 1f65297dd..7a5a24089 100644 --- a/src/core/file_sys/archive_savedata.h +++ b/src/core/file_sys/archive_savedata.h | |||
| @@ -23,7 +23,9 @@ public: | |||
| 23 | std::string GetName() const override { return "SaveData"; } | 23 | std::string GetName() const override { return "SaveData"; } |
| 24 | 24 | ||
| 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 26 | ResultCode Format(const Path& path) override; | 26 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 27 | |||
| 28 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 27 | 29 | ||
| 28 | private: | 30 | private: |
| 29 | std::string mount_point; | 31 | std::string mount_point; |
diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp index ea1dfe2c7..3db11c500 100644 --- a/src/core/file_sys/archive_savedatacheck.cpp +++ b/src/core/file_sys/archive_savedatacheck.cpp | |||
| @@ -48,11 +48,17 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(co | |||
| 48 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 48 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path) { | 51 | ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { |
| 52 | LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive."); | 52 | LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive."); |
| 53 | // TODO: Verify error code | 53 | // TODO: Verify error code |
| 54 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, | 54 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, |
| 55 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | 55 | ErrorSummary::NotSupported, ErrorLevel::Permanent); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveDataCheck::GetFormatInfo(const Path& path) const { | ||
| 59 | // TODO(Subv): Implement | ||
| 60 | LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); | ||
| 61 | return ResultCode(-1); | ||
| 62 | } | ||
| 63 | |||
| 58 | } // namespace FileSys | 64 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_savedatacheck.h b/src/core/file_sys/archive_savedatacheck.h index b14aefe8b..ea2624d64 100644 --- a/src/core/file_sys/archive_savedatacheck.h +++ b/src/core/file_sys/archive_savedatacheck.h | |||
| @@ -23,7 +23,8 @@ public: | |||
| 23 | std::string GetName() const override { return "SaveDataCheck"; } | 23 | std::string GetName() const override { return "SaveDataCheck"; } |
| 24 | 24 | ||
| 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 26 | ResultCode Format(const Path& path) override; | 26 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 27 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 27 | 28 | ||
| 28 | private: | 29 | private: |
| 29 | std::string mount_point; | 30 | std::string mount_point; |
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 5c825f429..657221cbf 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -40,9 +40,14 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& | |||
| 40 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 40 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | ResultCode ArchiveFactory_SDMC::Format(const Path& path) { | 43 | ResultCode ArchiveFactory_SDMC::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { |
| 44 | // This is kind of an undesirable operation, so let's just ignore it. :) | 44 | // This is kind of an undesirable operation, so let's just ignore it. :) |
| 45 | return RESULT_SUCCESS; | 45 | return RESULT_SUCCESS; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMC::GetFormatInfo(const Path& path) const { | ||
| 49 | // TODO(Subv): Implement | ||
| 50 | LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); | ||
| 51 | return ResultCode(-1); | ||
| 52 | } | ||
| 48 | } // namespace FileSys | 53 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 10b273bdb..35c0f3725 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -29,7 +29,8 @@ public: | |||
| 29 | std::string GetName() const override { return "SDMC"; } | 29 | std::string GetName() const override { return "SDMC"; } |
| 30 | 30 | ||
| 31 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 31 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 32 | ResultCode Format(const Path& path) override; | 32 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 33 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 33 | 34 | ||
| 34 | private: | 35 | private: |
| 35 | std::string sdmc_directory; | 36 | std::string sdmc_directory; |
diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp index 896f89529..e1780de2f 100644 --- a/src/core/file_sys/archive_systemsavedata.cpp +++ b/src/core/file_sys/archive_systemsavedata.cpp | |||
| @@ -63,11 +63,17 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(c | |||
| 63 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 63 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path) { | 66 | ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { |
| 67 | std::string fullpath = GetSystemSaveDataPath(base_path, path); | 67 | std::string fullpath = GetSystemSaveDataPath(base_path, path); |
| 68 | FileUtil::DeleteDirRecursively(fullpath); | 68 | FileUtil::DeleteDirRecursively(fullpath); |
| 69 | FileUtil::CreateFullPath(fullpath); | 69 | FileUtil::CreateFullPath(fullpath); |
| 70 | return RESULT_SUCCESS; | 70 | return RESULT_SUCCESS; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const Path& path) const { | ||
| 74 | // TODO(Subv): Implement | ||
| 75 | LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); | ||
| 76 | return ResultCode(-1); | ||
| 77 | } | ||
| 78 | |||
| 73 | } // namespace FileSys | 79 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h index afc689848..2bc13d4ee 100644 --- a/src/core/file_sys/archive_systemsavedata.h +++ b/src/core/file_sys/archive_systemsavedata.h | |||
| @@ -23,7 +23,8 @@ public: | |||
| 23 | ArchiveFactory_SystemSaveData(const std::string& mount_point); | 23 | ArchiveFactory_SystemSaveData(const std::string& mount_point); |
| 24 | 24 | ||
| 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 26 | ResultCode Format(const Path& path) override; | 26 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 27 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 27 | 28 | ||
| 28 | std::string GetName() const override { return "SystemSaveData"; } | 29 | std::string GetName() const override { return "SystemSaveData"; } |
| 29 | 30 | ||
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index b68c0ff0d..0cb76ba1c 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -24,6 +24,7 @@ enum class ErrorDescription : u32 { | |||
| 24 | FS_InvalidOpenFlags = 230, | 24 | FS_InvalidOpenFlags = 230, |
| 25 | FS_NotAFile = 250, | 25 | FS_NotAFile = 250, |
| 26 | FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive | 26 | FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive |
| 27 | FS_InvalidPath = 702, | ||
| 27 | InvalidSection = 1000, | 28 | InvalidSection = 1000, |
| 28 | TooLarge = 1001, | 29 | TooLarge = 1001, |
| 29 | NotAuthorized = 1002, | 30 | NotAuthorized = 1002, |
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 4c82a58e4..7bcedc0ae 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp | |||
| @@ -407,7 +407,7 @@ void Init() { | |||
| 407 | // If the archive didn't exist, create the files inside | 407 | // If the archive didn't exist, create the files inside |
| 408 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { | 408 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { |
| 409 | // Format the archive to create the directories | 409 | // Format the archive to create the directories |
| 410 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | 410 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, FileSys::ArchiveFormatInfo(), archive_path); |
| 411 | 411 | ||
| 412 | // Open it again to get a valid archive now that the folder exists | 412 | // Open it again to get a valid archive now that the folder exists |
| 413 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | 413 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index b034de8f1..63381250a 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -421,49 +421,45 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle) { | |||
| 421 | return MakeResult<u64>(archive->GetFreeBytes()); | 421 | return MakeResult<u64>(archive->GetFreeBytes()); |
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) { | 424 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path) { |
| 425 | auto archive_itr = id_code_map.find(id_code); | 425 | auto archive_itr = id_code_map.find(id_code); |
| 426 | if (archive_itr == id_code_map.end()) { | 426 | if (archive_itr == id_code_map.end()) { |
| 427 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error | 427 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | return archive_itr->second->Format(path); | 430 | return archive_itr->second->Format(path, format_info); |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size) { | 433 | ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path) { |
| 434 | auto archive = id_code_map.find(id_code); | ||
| 435 | if (archive == id_code_map.end()) { | ||
| 436 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error | ||
| 437 | } | ||
| 438 | |||
| 439 | return archive->second->GetFormatInfo(archive_path); | ||
| 440 | } | ||
| 441 | |||
| 442 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) { | ||
| 434 | // Construct the binary path to the archive first | 443 | // Construct the binary path to the archive first |
| 435 | FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); | 444 | FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); |
| 436 | 445 | ||
| 437 | std::string media_type_directory; | 446 | auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData : ArchiveIdCode::ExtSaveData); |
| 438 | if (media_type == MediaType::NAND) { | 447 | |
| 439 | media_type_directory = FileUtil::GetUserPath(D_NAND_IDX); | 448 | if (archive == id_code_map.end()) { |
| 440 | } else if (media_type == MediaType::SDMC) { | 449 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error |
| 441 | media_type_directory = FileUtil::GetUserPath(D_SDMC_IDX); | ||
| 442 | } else { | ||
| 443 | LOG_ERROR(Service_FS, "Unsupported media type %u", media_type); | ||
| 444 | return ResultCode(-1); // TODO(Subv): Find the right error code | ||
| 445 | } | 450 | } |
| 446 | 451 | ||
| 447 | std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); | 452 | auto ext_savedata = static_cast<FileSys::ArchiveFactory_ExtSaveData*>(archive->second.get()); |
| 448 | std::string game_path = FileSys::GetExtSaveDataPath(base_path, path); | 453 | |
| 449 | // These two folders are always created with the ExtSaveData | 454 | ResultCode result = ext_savedata->Format(path, format_info); |
| 450 | std::string user_path = game_path + "user/"; | 455 | if (result.IsError()) |
| 451 | std::string boss_path = game_path + "boss/"; | 456 | return result; |
| 452 | if (!FileUtil::CreateFullPath(user_path)) | ||
| 453 | return ResultCode(-1); // TODO(Subv): Find the right error code | ||
| 454 | if (!FileUtil::CreateFullPath(boss_path)) | ||
| 455 | return ResultCode(-1); // TODO(Subv): Find the right error code | ||
| 456 | 457 | ||
| 457 | u8* smdh_icon = Memory::GetPointer(icon_buffer); | 458 | u8* smdh_icon = Memory::GetPointer(icon_buffer); |
| 458 | if (!smdh_icon) | 459 | if (!smdh_icon) |
| 459 | return ResultCode(-1); // TODO(Subv): Find the right error code | 460 | return ResultCode(-1); // TODO(Subv): Find the right error code |
| 460 | 461 | ||
| 461 | // Create the icon | 462 | ext_savedata->WriteIcon(path, smdh_icon, icon_size); |
| 462 | FileUtil::IOFile icon_file(game_path + "icon", "wb+"); | ||
| 463 | if (!icon_file.IsGood()) | ||
| 464 | return ResultCode(-1); // TODO(Subv): Find the right error code | ||
| 465 | |||
| 466 | icon_file.WriteBytes(smdh_icon, icon_size); | ||
| 467 | return RESULT_SUCCESS; | 463 | return RESULT_SUCCESS; |
| 468 | } | 464 | } |
| 469 | 465 | ||
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 430dc2ef9..b17d7c902 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -177,10 +177,20 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle); | |||
| 177 | * Erases the contents of the physical folder that contains the archive | 177 | * Erases the contents of the physical folder that contains the archive |
| 178 | * identified by the specified id code and path | 178 | * identified by the specified id code and path |
| 179 | * @param id_code The id of the archive to format | 179 | * @param id_code The id of the archive to format |
| 180 | * @param format_info Format information about the new archive | ||
| 180 | * @param path The path to the archive, if relevant. | 181 | * @param path The path to the archive, if relevant. |
| 181 | * @return ResultCode 0 on success or the corresponding code on error | 182 | * @return ResultCode 0 on success or the corresponding code on error |
| 182 | */ | 183 | */ |
| 183 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = FileSys::Path()); | 184 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path = FileSys::Path()); |
| 185 | |||
| 186 | /* | ||
| 187 | * Retrieves the format info about the archive of the specified type and path. | ||
| 188 | * The format info is supplied by the client code when creating archives. | ||
| 189 | * @param id_code The id of the archive | ||
| 190 | * @param archive_path The path of the archive, if relevant | ||
| 191 | * @return The format info of the archive, or the corresponding error code if failed. | ||
| 192 | */ | ||
| 193 | ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path); | ||
| 184 | 194 | ||
| 185 | /** | 195 | /** |
| 186 | * Creates a blank SharedExtSaveData archive for the specified extdata ID | 196 | * Creates a blank SharedExtSaveData archive for the specified extdata ID |
| @@ -189,9 +199,10 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = File | |||
| 189 | * @param low The low word of the extdata id to create | 199 | * @param low The low word of the extdata id to create |
| 190 | * @param icon_buffer VAddr of the SMDH icon for this ExtSaveData | 200 | * @param icon_buffer VAddr of the SMDH icon for this ExtSaveData |
| 191 | * @param icon_size Size of the SMDH icon | 201 | * @param icon_size Size of the SMDH icon |
| 202 | * @param format_info Format information about the new archive | ||
| 192 | * @return ResultCode 0 on success or the corresponding code on error | 203 | * @return ResultCode 0 on success or the corresponding code on error |
| 193 | */ | 204 | */ |
| 194 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size); | 205 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info); |
| 195 | 206 | ||
| 196 | /** | 207 | /** |
| 197 | * Deletes the SharedExtSaveData archive for the specified extdata ID | 208 | * Deletes the SharedExtSaveData archive for the specified extdata ID |
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 12ed609e9..ff7a9975e 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp | |||
| @@ -443,17 +443,22 @@ static void IsSdmcWriteable(Service::Interface* self) { | |||
| 443 | * Inputs: | 443 | * Inputs: |
| 444 | * 0 : 0x084C0242 | 444 | * 0 : 0x084C0242 |
| 445 | * 1 : Archive ID | 445 | * 1 : Archive ID |
| 446 | * 2 : Archive low path type | 446 | * 2 : Archive path type |
| 447 | * 3 : Archive low path size | 447 | * 3 : Archive path size |
| 448 | * 10 : (LowPathSize << 14) | 2 | 448 | * 4 : Size in Blocks (1 block = 512 bytes) |
| 449 | * 5 : Number of directories | ||
| 450 | * 6 : Number of files | ||
| 451 | * 7 : Directory bucket count | ||
| 452 | * 8 : File bucket count | ||
| 453 | * 9 : Duplicate data | ||
| 454 | * 10 : (PathSize << 14) | 2 | ||
| 449 | * 11 : Archive low path | 455 | * 11 : Archive low path |
| 450 | * Outputs: | 456 | * Outputs: |
| 451 | * 1 : Result of function, 0 on success, otherwise error code | 457 | * 1 : Result of function, 0 on success, otherwise error code |
| 452 | */ | 458 | */ |
| 453 | static void FormatSaveData(Service::Interface* self) { | 459 | static void FormatSaveData(Service::Interface* self) { |
| 454 | // TODO(Subv): Find out what the other inputs and outputs of this function are | ||
| 455 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 460 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 456 | LOG_DEBUG(Service_FS, "(STUBBED)"); | 461 | LOG_WARNING(Service_FS, "(STUBBED)"); |
| 457 | 462 | ||
| 458 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); | 463 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); |
| 459 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); | 464 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); |
| @@ -464,9 +469,9 @@ static void FormatSaveData(Service::Interface* self) { | |||
| 464 | LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str()); | 469 | LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str()); |
| 465 | 470 | ||
| 466 | if (archive_id != FS::ArchiveIdCode::SaveData) { | 471 | if (archive_id != FS::ArchiveIdCode::SaveData) { |
| 467 | // TODO(Subv): What should happen if somebody attempts to format a different archive? | 472 | LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id); |
| 468 | LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", cmd_buff[1]); | 473 | cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS, |
| 469 | cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; | 474 | ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; |
| 470 | return; | 475 | return; |
| 471 | } | 476 | } |
| 472 | 477 | ||
| @@ -477,23 +482,40 @@ static void FormatSaveData(Service::Interface* self) { | |||
| 477 | return; | 482 | return; |
| 478 | } | 483 | } |
| 479 | 484 | ||
| 480 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; | 485 | FileSys::ArchiveFormatInfo format_info; |
| 486 | format_info.duplicate_data = cmd_buff[9] & 0xFF; | ||
| 487 | format_info.number_directories = cmd_buff[5]; | ||
| 488 | format_info.number_files = cmd_buff[6]; | ||
| 489 | format_info.total_size = cmd_buff[4] * 512; | ||
| 490 | |||
| 491 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData, format_info).raw; | ||
| 481 | } | 492 | } |
| 482 | 493 | ||
| 483 | /** | 494 | /** |
| 484 | * FS_User::FormatThisUserSaveData service function | 495 | * FS_User::FormatThisUserSaveData service function |
| 485 | * Inputs: | 496 | * Inputs: |
| 486 | * 0: 0x080F0180 | 497 | * 0: 0x080F0180 |
| 498 | * 1 : Size in Blocks (1 block = 512 bytes) | ||
| 499 | * 2 : Number of directories | ||
| 500 | * 3 : Number of files | ||
| 501 | * 4 : Directory bucket count | ||
| 502 | * 5 : File bucket count | ||
| 503 | * 6 : Duplicate data | ||
| 487 | * Outputs: | 504 | * Outputs: |
| 488 | * 1 : Result of function, 0 on success, otherwise error code | 505 | * 1 : Result of function, 0 on success, otherwise error code |
| 489 | */ | 506 | */ |
| 490 | static void FormatThisUserSaveData(Service::Interface* self) { | 507 | static void FormatThisUserSaveData(Service::Interface* self) { |
| 491 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 508 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 492 | LOG_DEBUG(Service_FS, "(STUBBED)"); | ||
| 493 | 509 | ||
| 494 | // TODO(Subv): Find out what the inputs and outputs of this function are | 510 | FileSys::ArchiveFormatInfo format_info; |
| 511 | format_info.duplicate_data = cmd_buff[6] & 0xFF; | ||
| 512 | format_info.number_directories = cmd_buff[2]; | ||
| 513 | format_info.number_files = cmd_buff[3]; | ||
| 514 | format_info.total_size = cmd_buff[1] * 512; | ||
| 495 | 515 | ||
| 496 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; | 516 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData, format_info).raw; |
| 517 | |||
| 518 | LOG_TRACE(Service_FS, "called"); | ||
| 497 | } | 519 | } |
| 498 | 520 | ||
| 499 | /** | 521 | /** |
| @@ -531,10 +553,9 @@ static void GetFreeBytes(Service::Interface* self) { | |||
| 531 | * 2 : Low word of the saveid to create | 553 | * 2 : Low word of the saveid to create |
| 532 | * 3 : High word of the saveid to create | 554 | * 3 : High word of the saveid to create |
| 533 | * 4 : Unknown | 555 | * 4 : Unknown |
| 534 | * 5 : Unknown | 556 | * 5 : Number of directories |
| 535 | * 6 : Unknown | 557 | * 6 : Number of files |
| 536 | * 7 : Unknown | 558 | * 7-8 : Size limit |
| 537 | * 8 : Unknown | ||
| 538 | * 9 : Size of the SMDH icon | 559 | * 9 : Size of the SMDH icon |
| 539 | * 10: (SMDH Size << 4) | 0x0000000A | 560 | * 10: (SMDH Size << 4) | 0x0000000A |
| 540 | * 11: Pointer to the SMDH icon for the new ExtSaveData | 561 | * 11: Pointer to the SMDH icon for the new ExtSaveData |
| @@ -556,7 +577,12 @@ static void CreateExtSaveData(Service::Interface* self) { | |||
| 556 | cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size, | 577 | cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size, |
| 557 | cmd_buff[10], icon_buffer); | 578 | cmd_buff[10], icon_buffer); |
| 558 | 579 | ||
| 559 | cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size).raw; | 580 | FileSys::ArchiveFormatInfo format_info; |
| 581 | format_info.number_directories = cmd_buff[5]; | ||
| 582 | format_info.number_files = cmd_buff[6]; | ||
| 583 | format_info.duplicate_data = false; | ||
| 584 | format_info.total_size = 0; | ||
| 585 | cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw; | ||
| 560 | } | 586 | } |
| 561 | 587 | ||
| 562 | /** | 588 | /** |
| @@ -731,6 +757,51 @@ static void GetArchiveResource(Service::Interface* self) { | |||
| 731 | cmd_buff[5] = 0x80000; // 8GiB free | 757 | cmd_buff[5] = 0x80000; // 8GiB free |
| 732 | } | 758 | } |
| 733 | 759 | ||
| 760 | /** | ||
| 761 | * FS_User::GetFormatInfo service function. | ||
| 762 | * Inputs: | ||
| 763 | * 0 : 0x084500C2 | ||
| 764 | * 1 : Archive ID | ||
| 765 | * 2 : Archive path type | ||
| 766 | * 3 : Archive path size | ||
| 767 | * 4 : (PathSize << 14) | 2 | ||
| 768 | * 5 : Archive low path | ||
| 769 | * Outputs: | ||
| 770 | * 0 : 0x08450140 | ||
| 771 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 772 | * 2 : Total size | ||
| 773 | * 3 : Number of directories | ||
| 774 | * 4 : Number of files | ||
| 775 | * 5 : Duplicate data | ||
| 776 | */ | ||
| 777 | static void GetFormatInfo(Service::Interface* self) { | ||
| 778 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 779 | |||
| 780 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); | ||
| 781 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); | ||
| 782 | u32 archivename_size = cmd_buff[3]; | ||
| 783 | u32 archivename_ptr = cmd_buff[5]; | ||
| 784 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); | ||
| 785 | |||
| 786 | LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str()); | ||
| 787 | |||
| 788 | cmd_buff[0] = IPC::MakeHeader(0x0845, 5, 0); | ||
| 789 | |||
| 790 | auto format_info = GetArchiveFormatInfo(archive_id, archive_path); | ||
| 791 | |||
| 792 | if (format_info.Failed()) { | ||
| 793 | LOG_ERROR(Service_FS, "Failed to retrieve the format info"); | ||
| 794 | cmd_buff[1] = format_info.Code().raw; | ||
| 795 | return; | ||
| 796 | } | ||
| 797 | |||
| 798 | cmd_buff[1] = RESULT_SUCCESS.raw; | ||
| 799 | cmd_buff[2] = format_info->total_size; | ||
| 800 | cmd_buff[3] = format_info->number_directories; | ||
| 801 | cmd_buff[4] = format_info->number_files; | ||
| 802 | cmd_buff[5] = format_info->duplicate_data; | ||
| 803 | } | ||
| 804 | |||
| 734 | const Interface::FunctionInfo FunctionTable[] = { | 805 | const Interface::FunctionInfo FunctionTable[] = { |
| 735 | {0x000100C6, nullptr, "Dummy1"}, | 806 | {0x000100C6, nullptr, "Dummy1"}, |
| 736 | {0x040100C4, nullptr, "Control"}, | 807 | {0x040100C4, nullptr, "Control"}, |
| @@ -802,7 +873,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 802 | {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, | 873 | {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, |
| 803 | {0x08430000, nullptr, "InitializeCtrFileSystem"}, | 874 | {0x08430000, nullptr, "InitializeCtrFileSystem"}, |
| 804 | {0x08440000, nullptr, "CreateSeed"}, | 875 | {0x08440000, nullptr, "CreateSeed"}, |
| 805 | {0x084500C2, nullptr, "GetFormatInfo"}, | 876 | {0x084500C2, GetFormatInfo, "GetFormatInfo"}, |
| 806 | {0x08460102, nullptr, "GetLegacyRomHeader2"}, | 877 | {0x08460102, nullptr, "GetLegacyRomHeader2"}, |
| 807 | {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, | 878 | {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, |
| 808 | {0x08480042, nullptr, "GetSdmcCtrRootPath"}, | 879 | {0x08480042, nullptr, "GetSdmcCtrRootPath"}, |
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 6bdee4d9e..94f494690 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp | |||
| @@ -103,7 +103,7 @@ void Init() { | |||
| 103 | // If the archive didn't exist, create the files inside | 103 | // If the archive didn't exist, create the files inside |
| 104 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { | 104 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { |
| 105 | // Format the archive to create the directories | 105 | // Format the archive to create the directories |
| 106 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); | 106 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, FileSys::ArchiveFormatInfo(), archive_path); |
| 107 | // Open it again to get a valid archive now that the folder exists | 107 | // Open it again to get a valid archive now that the folder exists |
| 108 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); | 108 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); |
| 109 | ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); | 109 | ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); |