diff options
| author | 2015-02-10 18:27:16 -0500 | |
|---|---|---|
| committer | 2015-02-10 18:27:16 -0500 | |
| commit | 27e6e6b3cb2ee1ab3a996c2b4be1d9a3c4e6b75d (patch) | |
| tree | fd8b0290d4a0353c11c0e168200b20b5a89e297c /src/core/hle | |
| parent | Merge pull request #553 from lioncash/denorm (diff) | |
| parent | PTM: Fixed a problem with the gamecoin PTM file. (diff) | |
| download | yuzu-27e6e6b3cb2ee1ab3a996c2b4be1d9a3c4e6b75d.tar.gz yuzu-27e6e6b3cb2ee1ab3a996c2b4be1d9a3c4e6b75d.tar.xz yuzu-27e6e6b3cb2ee1ab3a996c2b4be1d9a3c4e6b75d.zip | |
Merge pull request #540 from yuriks/multi-archives
FS: Allow multiple instances of the same archive type to be open at once
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/result.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 191 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.h | 45 | ||||
| -rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/ptm_u.cpp | 35 |
5 files changed, 140 insertions, 147 deletions
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 948b9e38e..9c6ca29e5 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -307,14 +307,14 @@ public: | |||
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | ResultVal& operator=(const ResultVal& o) { | 309 | ResultVal& operator=(const ResultVal& o) { |
| 310 | if (*this) { | 310 | if (!empty()) { |
| 311 | if (o) { | 311 | if (!o.empty()) { |
| 312 | *GetPointer() = *o.GetPointer(); | 312 | *GetPointer() = *o.GetPointer(); |
| 313 | } else { | 313 | } else { |
| 314 | GetPointer()->~T(); | 314 | GetPointer()->~T(); |
| 315 | } | 315 | } |
| 316 | } else { | 316 | } else { |
| 317 | if (o) { | 317 | if (!o.empty()) { |
| 318 | new (&storage) T(*o.GetPointer()); | 318 | new (&storage) T(*o.GetPointer()); |
| 319 | } | 319 | } |
| 320 | } | 320 | } |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index ccf132f31..e197d3599 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <unordered_map> | 6 | #include <unordered_map> |
| 7 | 7 | ||
| 8 | #include <boost/container/flat_map.hpp> | ||
| 9 | |||
| 8 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 9 | #include "common/file_util.h" | 11 | #include "common/file_util.h" |
| 10 | #include "common/make_unique.h" | 12 | #include "common/make_unique.h" |
| @@ -18,7 +20,6 @@ | |||
| 18 | #include "core/file_sys/archive_sdmc.h" | 20 | #include "core/file_sys/archive_sdmc.h" |
| 19 | #include "core/file_sys/directory_backend.h" | 21 | #include "core/file_sys/directory_backend.h" |
| 20 | #include "core/hle/service/fs/archive.h" | 22 | #include "core/hle/service/fs/archive.h" |
| 21 | #include "core/hle/kernel/session.h" | ||
| 22 | #include "core/hle/result.h" | 23 | #include "core/hle/result.h" |
| 23 | 24 | ||
| 24 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. | 25 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. |
| @@ -74,43 +75,19 @@ enum class DirectoryCommand : u32 { | |||
| 74 | Close = 0x08020000, | 75 | Close = 0x08020000, |
| 75 | }; | 76 | }; |
| 76 | 77 | ||
| 77 | class Archive { | 78 | ResultVal<bool> File::SyncRequest() { |
| 78 | public: | 79 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 79 | Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) | 80 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 80 | : id_code(id_code), backend(std::move(backend)) { | 81 | switch (cmd) { |
| 81 | } | ||
| 82 | |||
| 83 | std::string GetName() const { return "Archive: " + backend->GetName(); } | ||
| 84 | |||
| 85 | ArchiveIdCode id_code; ///< Id code of the archive | ||
| 86 | std::unique_ptr<FileSys::ArchiveBackend> backend; ///< Archive backend interface | ||
| 87 | }; | ||
| 88 | |||
| 89 | class File : public Kernel::Session { | ||
| 90 | public: | ||
| 91 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) | ||
| 92 | : path(path), priority(0), backend(std::move(backend)) { | ||
| 93 | } | ||
| 94 | |||
| 95 | std::string GetName() const override { return "Path: " + path.DebugStr(); } | ||
| 96 | |||
| 97 | FileSys::Path path; ///< Path of the file | ||
| 98 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means | ||
| 99 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface | ||
| 100 | |||
| 101 | ResultVal<bool> SyncRequest() override { | ||
| 102 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 103 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | ||
| 104 | switch (cmd) { | ||
| 105 | 82 | ||
| 106 | // Read from file... | 83 | // Read from file... |
| 107 | case FileCommand::Read: | 84 | case FileCommand::Read: |
| 108 | { | 85 | { |
| 109 | u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; | 86 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; |
| 110 | u32 length = cmd_buff[3]; | 87 | u32 length = cmd_buff[3]; |
| 111 | u32 address = cmd_buff[5]; | 88 | u32 address = cmd_buff[5]; |
| 112 | LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", | 89 | LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", |
| 113 | GetTypeName().c_str(), GetName().c_str(), offset, length, address); | 90 | GetTypeName().c_str(), GetName().c_str(), offset, length, address); |
| 114 | cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); | 91 | cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); |
| 115 | break; | 92 | break; |
| 116 | } | 93 | } |
| @@ -118,12 +95,12 @@ public: | |||
| 118 | // Write to file... | 95 | // Write to file... |
| 119 | case FileCommand::Write: | 96 | case FileCommand::Write: |
| 120 | { | 97 | { |
| 121 | u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; | 98 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; |
| 122 | u32 length = cmd_buff[3]; | 99 | u32 length = cmd_buff[3]; |
| 123 | u32 flush = cmd_buff[4]; | 100 | u32 flush = cmd_buff[4]; |
| 124 | u32 address = cmd_buff[6]; | 101 | u32 address = cmd_buff[6]; |
| 125 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", | 102 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", |
| 126 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); | 103 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); |
| 127 | cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); | 104 | cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); |
| 128 | break; | 105 | break; |
| 129 | } | 106 | } |
| @@ -141,7 +118,7 @@ public: | |||
| 141 | { | 118 | { |
| 142 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | 119 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); |
| 143 | LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", | 120 | LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", |
| 144 | GetTypeName().c_str(), GetName().c_str(), size); | 121 | GetTypeName().c_str(), GetName().c_str(), size); |
| 145 | backend->SetSize(size); | 122 | backend->SetSize(size); |
| 146 | break; | 123 | break; |
| 147 | } | 124 | } |
| @@ -187,27 +164,15 @@ public: | |||
| 187 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 164 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 188 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 165 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 189 | return error; | 166 | return error; |
| 190 | } | ||
| 191 | cmd_buff[1] = 0; // No error | ||
| 192 | return MakeResult<bool>(false); | ||
| 193 | } | 167 | } |
| 194 | }; | 168 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 195 | 169 | return MakeResult<bool>(false); | |
| 196 | class Directory : public Kernel::Session { | 170 | } |
| 197 | public: | ||
| 198 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) | ||
| 199 | : path(path), backend(std::move(backend)) { | ||
| 200 | } | ||
| 201 | |||
| 202 | std::string GetName() const override { return "Directory: " + path.DebugStr(); } | ||
| 203 | |||
| 204 | FileSys::Path path; ///< Path of the directory | ||
| 205 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface | ||
| 206 | 171 | ||
| 207 | ResultVal<bool> SyncRequest() override { | 172 | ResultVal<bool> Directory::SyncRequest() { |
| 208 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 173 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 209 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | 174 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); |
| 210 | switch (cmd) { | 175 | switch (cmd) { |
| 211 | 176 | ||
| 212 | // Read from directory... | 177 | // Read from directory... |
| 213 | case DirectoryCommand::Read: | 178 | case DirectoryCommand::Read: |
| @@ -216,7 +181,7 @@ public: | |||
| 216 | u32 address = cmd_buff[3]; | 181 | u32 address = cmd_buff[3]; |
| 217 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | 182 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); |
| 218 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", | 183 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", |
| 219 | GetTypeName().c_str(), GetName().c_str(), count); | 184 | GetTypeName().c_str(), GetName().c_str(), count); |
| 220 | 185 | ||
| 221 | // Number of entries actually read | 186 | // Number of entries actually read |
| 222 | cmd_buff[2] = backend->Read(count, entries); | 187 | cmd_buff[2] = backend->Read(count, entries); |
| @@ -236,29 +201,31 @@ public: | |||
| 236 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 201 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 237 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 202 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 238 | return MakeResult<bool>(false); | 203 | return MakeResult<bool>(false); |
| 239 | } | ||
| 240 | cmd_buff[1] = 0; // No error | ||
| 241 | return MakeResult<bool>(false); | ||
| 242 | } | 204 | } |
| 243 | }; | 205 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 206 | return MakeResult<bool>(false); | ||
| 207 | } | ||
| 244 | 208 | ||
| 245 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 209 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 246 | 210 | ||
| 211 | using FileSys::ArchiveBackend; | ||
| 212 | using FileSys::ArchiveFactory; | ||
| 213 | |||
| 247 | /** | 214 | /** |
| 248 | * Map of registered archives, identified by id code. Once an archive is registered here, it is | 215 | * Map of registered archives, identified by id code. Once an archive is registered here, it is |
| 249 | * never removed until the FS service is shut down. | 216 | * never removed until the FS service is shut down. |
| 250 | */ | 217 | */ |
| 251 | static std::unordered_map<ArchiveIdCode, std::unique_ptr<Archive>> id_code_map; | 218 | static boost::container::flat_map<ArchiveIdCode, std::unique_ptr<ArchiveFactory>> id_code_map; |
| 252 | 219 | ||
| 253 | /** | 220 | /** |
| 254 | * Map of active archive handles. Values are pointers to the archives in `idcode_map`. | 221 | * Map of active archive handles. Values are pointers to the archives in `idcode_map`. |
| 255 | */ | 222 | */ |
| 256 | static std::unordered_map<ArchiveHandle, Archive*> handle_map; | 223 | static std::unordered_map<ArchiveHandle, std::unique_ptr<ArchiveBackend>> handle_map; |
| 257 | static ArchiveHandle next_handle; | 224 | static ArchiveHandle next_handle; |
| 258 | 225 | ||
| 259 | static Archive* GetArchive(ArchiveHandle handle) { | 226 | static ArchiveBackend* GetArchive(ArchiveHandle handle) { |
| 260 | auto itr = handle_map.find(handle); | 227 | auto itr = handle_map.find(handle); |
| 261 | return (itr == handle_map.end()) ? nullptr : itr->second; | 228 | return (itr == handle_map.end()) ? nullptr : itr->second.get(); |
| 262 | } | 229 | } |
| 263 | 230 | ||
| 264 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { | 231 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { |
| @@ -271,15 +238,13 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi | |||
| 271 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 238 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 272 | } | 239 | } |
| 273 | 240 | ||
| 274 | ResultCode res = itr->second->backend->Open(archive_path); | 241 | CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); |
| 275 | if (!res.IsSuccess()) | ||
| 276 | return res; | ||
| 277 | 242 | ||
| 278 | // This should never even happen in the first place with 64-bit handles, | 243 | // This should never even happen in the first place with 64-bit handles, |
| 279 | while (handle_map.count(next_handle) != 0) { | 244 | while (handle_map.count(next_handle) != 0) { |
| 280 | ++next_handle; | 245 | ++next_handle; |
| 281 | } | 246 | } |
| 282 | handle_map.emplace(next_handle, itr->second.get()); | 247 | handle_map.emplace(next_handle, std::move(res)); |
| 283 | return MakeResult<ArchiveHandle>(next_handle++); | 248 | return MakeResult<ArchiveHandle>(next_handle++); |
| 284 | } | 249 | } |
| 285 | 250 | ||
| @@ -292,39 +257,39 @@ ResultCode CloseArchive(ArchiveHandle handle) { | |||
| 292 | 257 | ||
| 293 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in | 258 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in |
| 294 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 | 259 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 |
| 295 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { | 260 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { |
| 296 | auto result = id_code_map.emplace(id_code, Common::make_unique<Archive>(std::move(backend), id_code)); | 261 | auto result = id_code_map.emplace(id_code, std::move(factory)); |
| 297 | 262 | ||
| 298 | bool inserted = result.second; | 263 | bool inserted = result.second; |
| 299 | _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); | 264 | _assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); |
| 300 | 265 | ||
| 301 | auto& archive = result.first->second; | 266 | auto& archive = result.first->second; |
| 302 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); | 267 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); |
| 303 | return RESULT_SUCCESS; | 268 | return RESULT_SUCCESS; |
| 304 | } | 269 | } |
| 305 | 270 | ||
| 306 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, | 271 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, |
| 307 | const FileSys::Path& path, const FileSys::Mode mode) { | 272 | const FileSys::Path& path, const FileSys::Mode mode) { |
| 308 | Archive* archive = GetArchive(archive_handle); | 273 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 309 | if (archive == nullptr) | 274 | if (archive == nullptr) |
| 310 | return ERR_INVALID_HANDLE; | 275 | return ERR_INVALID_HANDLE; |
| 311 | 276 | ||
| 312 | std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); | 277 | std::unique_ptr<FileSys::FileBackend> backend = archive->OpenFile(path, mode); |
| 313 | if (backend == nullptr) { | 278 | if (backend == nullptr) { |
| 314 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, | 279 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, |
| 315 | ErrorSummary::NotFound, ErrorLevel::Status); | 280 | ErrorSummary::NotFound, ErrorLevel::Status); |
| 316 | } | 281 | } |
| 317 | 282 | ||
| 318 | auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path)); | 283 | auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path)); |
| 319 | return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(file)); | 284 | return MakeResult<Kernel::SharedPtr<File>>(std::move(file)); |
| 320 | } | 285 | } |
| 321 | 286 | ||
| 322 | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | 287 | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 323 | Archive* archive = GetArchive(archive_handle); | 288 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 324 | if (archive == nullptr) | 289 | if (archive == nullptr) |
| 325 | return ERR_INVALID_HANDLE; | 290 | return ERR_INVALID_HANDLE; |
| 326 | 291 | ||
| 327 | if (archive->backend->DeleteFile(path)) | 292 | if (archive->DeleteFile(path)) |
| 328 | return RESULT_SUCCESS; | 293 | return RESULT_SUCCESS; |
| 329 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 294 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 330 | ErrorSummary::Canceled, ErrorLevel::Status); | 295 | ErrorSummary::Canceled, ErrorLevel::Status); |
| @@ -332,13 +297,13 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa | |||
| 332 | 297 | ||
| 333 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 298 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 334 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | 299 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { |
| 335 | Archive* src_archive = GetArchive(src_archive_handle); | 300 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); |
| 336 | Archive* dest_archive = GetArchive(dest_archive_handle); | 301 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); |
| 337 | if (src_archive == nullptr || dest_archive == nullptr) | 302 | if (src_archive == nullptr || dest_archive == nullptr) |
| 338 | return ERR_INVALID_HANDLE; | 303 | return ERR_INVALID_HANDLE; |
| 339 | 304 | ||
| 340 | if (src_archive == dest_archive) { | 305 | if (src_archive == dest_archive) { |
| 341 | if (src_archive->backend->RenameFile(src_path, dest_path)) | 306 | if (src_archive->RenameFile(src_path, dest_path)) |
| 342 | return RESULT_SUCCESS; | 307 | return RESULT_SUCCESS; |
| 343 | } else { | 308 | } else { |
| 344 | // TODO: Implement renaming across archives | 309 | // TODO: Implement renaming across archives |
| @@ -352,30 +317,30 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil | |||
| 352 | } | 317 | } |
| 353 | 318 | ||
| 354 | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | 319 | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 355 | Archive* archive = GetArchive(archive_handle); | 320 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 356 | if (archive == nullptr) | 321 | if (archive == nullptr) |
| 357 | return ERR_INVALID_HANDLE; | 322 | return ERR_INVALID_HANDLE; |
| 358 | 323 | ||
| 359 | if (archive->backend->DeleteDirectory(path)) | 324 | if (archive->DeleteDirectory(path)) |
| 360 | return RESULT_SUCCESS; | 325 | return RESULT_SUCCESS; |
| 361 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 326 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 362 | ErrorSummary::Canceled, ErrorLevel::Status); | 327 | ErrorSummary::Canceled, ErrorLevel::Status); |
| 363 | } | 328 | } |
| 364 | 329 | ||
| 365 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { | 330 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { |
| 366 | Archive* archive = GetArchive(archive_handle); | 331 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 367 | if (archive == nullptr) | 332 | if (archive == nullptr) |
| 368 | return ERR_INVALID_HANDLE; | 333 | return ERR_INVALID_HANDLE; |
| 369 | 334 | ||
| 370 | return archive->backend->CreateFile(path, file_size); | 335 | return archive->CreateFile(path, file_size); |
| 371 | } | 336 | } |
| 372 | 337 | ||
| 373 | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | 338 | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 374 | Archive* archive = GetArchive(archive_handle); | 339 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 375 | if (archive == nullptr) | 340 | if (archive == nullptr) |
| 376 | return ERR_INVALID_HANDLE; | 341 | return ERR_INVALID_HANDLE; |
| 377 | 342 | ||
| 378 | if (archive->backend->CreateDirectory(path)) | 343 | if (archive->CreateDirectory(path)) |
| 379 | return RESULT_SUCCESS; | 344 | return RESULT_SUCCESS; |
| 380 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 345 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 381 | ErrorSummary::Canceled, ErrorLevel::Status); | 346 | ErrorSummary::Canceled, ErrorLevel::Status); |
| @@ -383,13 +348,13 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||
| 383 | 348 | ||
| 384 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 349 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 385 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | 350 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { |
| 386 | Archive* src_archive = GetArchive(src_archive_handle); | 351 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); |
| 387 | Archive* dest_archive = GetArchive(dest_archive_handle); | 352 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); |
| 388 | if (src_archive == nullptr || dest_archive == nullptr) | 353 | if (src_archive == nullptr || dest_archive == nullptr) |
| 389 | return ERR_INVALID_HANDLE; | 354 | return ERR_INVALID_HANDLE; |
| 390 | 355 | ||
| 391 | if (src_archive == dest_archive) { | 356 | if (src_archive == dest_archive) { |
| 392 | if (src_archive->backend->RenameDirectory(src_path, dest_path)) | 357 | if (src_archive->RenameDirectory(src_path, dest_path)) |
| 393 | return RESULT_SUCCESS; | 358 | return RESULT_SUCCESS; |
| 394 | } else { | 359 | } else { |
| 395 | // TODO: Implement renaming across archives | 360 | // TODO: Implement renaming across archives |
| @@ -402,31 +367,29 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons | |||
| 402 | ErrorSummary::NothingHappened, ErrorLevel::Status); | 367 | ErrorSummary::NothingHappened, ErrorLevel::Status); |
| 403 | } | 368 | } |
| 404 | 369 | ||
| 405 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, | 370 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, |
| 406 | const FileSys::Path& path) { | 371 | const FileSys::Path& path) { |
| 407 | Archive* archive = GetArchive(archive_handle); | 372 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 408 | if (archive == nullptr) | 373 | if (archive == nullptr) |
| 409 | return ERR_INVALID_HANDLE; | 374 | return ERR_INVALID_HANDLE; |
| 410 | 375 | ||
| 411 | std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path); | 376 | std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); |
| 412 | if (backend == nullptr) { | 377 | if (backend == nullptr) { |
| 413 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 378 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 414 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 379 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 415 | } | 380 | } |
| 416 | 381 | ||
| 417 | auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); | 382 | auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); |
| 418 | return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(directory)); | 383 | return MakeResult<Kernel::SharedPtr<Directory>>(std::move(directory)); |
| 419 | } | 384 | } |
| 420 | 385 | ||
| 421 | ResultCode FormatSaveData() { | 386 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) { |
| 422 | // Do not create the archive again if it already exists | 387 | auto archive_itr = id_code_map.find(id_code); |
| 423 | auto archive_itr = id_code_map.find(ArchiveIdCode::SaveData); | ||
| 424 | if (archive_itr == id_code_map.end()) { | 388 | if (archive_itr == id_code_map.end()) { |
| 425 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error | 389 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error |
| 426 | } | 390 | } |
| 427 | 391 | ||
| 428 | // Use an empty path, we do not use it when formatting the savedata | 392 | return archive_itr->second->Format(path); |
| 429 | return archive_itr->second->backend->Format(FileSys::Path()); | ||
| 430 | } | 393 | } |
| 431 | 394 | ||
| 432 | ResultCode CreateExtSaveData(u32 high, u32 low) { | 395 | ResultCode CreateExtSaveData(u32 high, u32 low) { |
| @@ -460,32 +423,32 @@ void ArchiveInit() { | |||
| 460 | 423 | ||
| 461 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); | 424 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); |
| 462 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); | 425 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); |
| 463 | auto sdmc_archive = Common::make_unique<FileSys::Archive_SDMC>(sdmc_directory); | 426 | auto sdmc_factory = Common::make_unique<FileSys::ArchiveFactory_SDMC>(sdmc_directory); |
| 464 | if (sdmc_archive->Initialize()) | 427 | if (sdmc_factory->Initialize()) |
| 465 | CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC); | 428 | RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); |
| 466 | else | 429 | else |
| 467 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | 430 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); |
| 468 | 431 | ||
| 469 | // Create the SaveData archive | 432 | // Create the SaveData archive |
| 470 | auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(sdmc_directory); | 433 | auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); |
| 471 | CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); | 434 | RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); |
| 472 | 435 | ||
| 473 | auto extsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(sdmc_directory, false); | 436 | auto extsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); |
| 474 | if (extsavedata_archive->Initialize()) | 437 | if (extsavedata_factory->Initialize()) |
| 475 | CreateArchive(std::move(extsavedata_archive), ArchiveIdCode::ExtSaveData); | 438 | RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); |
| 476 | else | 439 | else |
| 477 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_archive->GetMountPoint().c_str()); | 440 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); |
| 478 | 441 | ||
| 479 | auto sharedextsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); | 442 | auto sharedextsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); |
| 480 | if (sharedextsavedata_archive->Initialize()) | 443 | if (sharedextsavedata_factory->Initialize()) |
| 481 | CreateArchive(std::move(sharedextsavedata_archive), ArchiveIdCode::SharedExtSaveData); | 444 | RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); |
| 482 | else | 445 | else |
| 483 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", | 446 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", |
| 484 | sharedextsavedata_archive->GetMountPoint().c_str()); | 447 | sharedextsavedata_factory->GetMountPoint().c_str()); |
| 485 | 448 | ||
| 486 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive | 449 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive |
| 487 | auto savedatacheck_archive = Common::make_unique<FileSys::Archive_SaveDataCheck>(nand_directory); | 450 | auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); |
| 488 | CreateArchive(std::move(savedatacheck_archive), ArchiveIdCode::SaveDataCheck); | 451 | RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); |
| 489 | } | 452 | } |
| 490 | 453 | ||
| 491 | /// Shutdown archives | 454 | /// Shutdown archives |
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index ab5ea4da8..c490327d0 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include "core/file_sys/archive_backend.h" | 9 | #include "core/file_sys/archive_backend.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/session.h" | ||
| 11 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 12 | 13 | ||
| 13 | /// The unique system identifier hash, also known as ID0 | 14 | /// The unique system identifier hash, also known as ID0 |
| @@ -36,6 +37,35 @@ enum class ArchiveIdCode : u32 { | |||
| 36 | 37 | ||
| 37 | typedef u64 ArchiveHandle; | 38 | typedef u64 ArchiveHandle; |
| 38 | 39 | ||
| 40 | class File : public Kernel::Session { | ||
| 41 | public: | ||
| 42 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) | ||
| 43 | : path(path), priority(0), backend(std::move(backend)) { | ||
| 44 | } | ||
| 45 | |||
| 46 | std::string GetName() const override { return "Path: " + path.DebugStr(); } | ||
| 47 | |||
| 48 | FileSys::Path path; ///< Path of the file | ||
| 49 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means | ||
| 50 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface | ||
| 51 | |||
| 52 | ResultVal<bool> SyncRequest() override; | ||
| 53 | }; | ||
| 54 | |||
| 55 | class Directory : public Kernel::Session { | ||
| 56 | public: | ||
| 57 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) | ||
| 58 | : path(path), backend(std::move(backend)) { | ||
| 59 | } | ||
| 60 | |||
| 61 | std::string GetName() const override { return "Directory: " + path.DebugStr(); } | ||
| 62 | |||
| 63 | FileSys::Path path; ///< Path of the directory | ||
| 64 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface | ||
| 65 | |||
| 66 | ResultVal<bool> SyncRequest() override; | ||
| 67 | }; | ||
| 68 | |||
| 39 | /** | 69 | /** |
| 40 | * Opens an archive | 70 | * Opens an archive |
| 41 | * @param id_code IdCode of the archive to open | 71 | * @param id_code IdCode of the archive to open |
| @@ -51,11 +81,11 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi | |||
| 51 | ResultCode CloseArchive(ArchiveHandle handle); | 81 | ResultCode CloseArchive(ArchiveHandle handle); |
| 52 | 82 | ||
| 53 | /** | 83 | /** |
| 54 | * Creates an Archive | 84 | * Registers an Archive type, instances of which can later be opened using its IdCode. |
| 55 | * @param backend File system backend interface to the archive | 85 | * @param backend File system backend interface to the archive |
| 56 | * @param id_code Id code used to access this type of archive | 86 | * @param id_code Id code used to access this type of archive |
| 57 | */ | 87 | */ |
| 58 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code); | 88 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); |
| 59 | 89 | ||
| 60 | /** | 90 | /** |
| 61 | * Open a File from an Archive | 91 | * Open a File from an Archive |
| @@ -64,7 +94,7 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc | |||
| 64 | * @param mode Mode under which to open the File | 94 | * @param mode Mode under which to open the File |
| 65 | * @return The opened File object as a Session | 95 | * @return The opened File object as a Session |
| 66 | */ | 96 | */ |
| 67 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, | 97 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, |
| 68 | const FileSys::Path& path, const FileSys::Mode mode); | 98 | const FileSys::Path& path, const FileSys::Mode mode); |
| 69 | 99 | ||
| 70 | /** | 100 | /** |
| @@ -128,14 +158,17 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons | |||
| 128 | * @param path Path to the Directory inside of the Archive | 158 | * @param path Path to the Directory inside of the Archive |
| 129 | * @return The opened Directory object as a Session | 159 | * @return The opened Directory object as a Session |
| 130 | */ | 160 | */ |
| 131 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, | 161 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, |
| 132 | const FileSys::Path& path); | 162 | const FileSys::Path& path); |
| 133 | 163 | ||
| 134 | /** | 164 | /** |
| 135 | * Creates a blank SaveData archive. | 165 | * Erases the contents of the physical folder that contains the archive |
| 166 | * identified by the specified id code and path | ||
| 167 | * @param id_code The id of the archive to format | ||
| 168 | * @param path The path to the archive, if relevant. | ||
| 136 | * @return ResultCode 0 on success or the corresponding code on error | 169 | * @return ResultCode 0 on success or the corresponding code on error |
| 137 | */ | 170 | */ |
| 138 | ResultCode FormatSaveData(); | 171 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = FileSys::Path()); |
| 139 | 172 | ||
| 140 | /** | 173 | /** |
| 141 | * Creates a blank SharedExtSaveData archive for the specified extdata ID | 174 | * Creates a blank 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 94a3a31c8..71ee4ff55 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp | |||
| @@ -61,7 +61,7 @@ static void OpenFile(Service::Interface* self) { | |||
| 61 | 61 | ||
| 62 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); | 62 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); |
| 63 | 63 | ||
| 64 | ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); | 64 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); |
| 65 | cmd_buff[1] = file_res.Code().raw; | 65 | cmd_buff[1] = file_res.Code().raw; |
| 66 | if (file_res.Succeeded()) { | 66 | if (file_res.Succeeded()) { |
| 67 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); | 67 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); |
| @@ -117,7 +117,7 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
| 117 | } | 117 | } |
| 118 | SCOPE_EXIT({ CloseArchive(*archive_handle); }); | 118 | SCOPE_EXIT({ CloseArchive(*archive_handle); }); |
| 119 | 119 | ||
| 120 | ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); | 120 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); |
| 121 | cmd_buff[1] = file_res.Code().raw; | 121 | cmd_buff[1] = file_res.Code().raw; |
| 122 | if (file_res.Succeeded()) { | 122 | if (file_res.Succeeded()) { |
| 123 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); | 123 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); |
| @@ -337,7 +337,7 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 337 | 337 | ||
| 338 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 338 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
| 339 | 339 | ||
| 340 | ResultVal<SharedPtr<Session>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); | 340 | ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); |
| 341 | cmd_buff[1] = dir_res.Code().raw; | 341 | cmd_buff[1] = dir_res.Code().raw; |
| 342 | if (dir_res.Succeeded()) { | 342 | if (dir_res.Succeeded()) { |
| 343 | cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); | 343 | cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); |
| @@ -468,7 +468,7 @@ static void FormatSaveData(Service::Interface* self) { | |||
| 468 | return; | 468 | return; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | cmd_buff[1] = FormatSaveData().raw; | 471 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | /** | 474 | /** |
| @@ -484,7 +484,7 @@ static void FormatThisUserSaveData(Service::Interface* self) { | |||
| 484 | 484 | ||
| 485 | // TODO(Subv): Find out what the inputs and outputs of this function are | 485 | // TODO(Subv): Find out what the inputs and outputs of this function are |
| 486 | 486 | ||
| 487 | cmd_buff[1] = FormatSaveData().raw; | 487 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | static void CreateExtSaveData(Service::Interface* self) { | 490 | static void CreateExtSaveData(Service::Interface* self) { |
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index 7b465a348..7c8d9ce8c 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/log.h" | 5 | #include "common/log.h" |
| 6 | #include "common/make_unique.h" | 6 | #include "common/make_unique.h" |
| 7 | #include "core/file_sys/archive_extsavedata.h" | 7 | |
| 8 | #include "core/hle/hle.h" | 8 | #include "core/hle/hle.h" |
| 9 | #include "core/hle/service/fs/archive.h" | ||
| 9 | #include "core/hle/service/ptm_u.h" | 10 | #include "core/hle/service/ptm_u.h" |
| 10 | 11 | ||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -28,7 +29,6 @@ struct GameCoin { | |||
| 28 | u8 day; | 29 | u8 day; |
| 29 | }; | 30 | }; |
| 30 | static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; | 31 | static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; |
| 31 | static std::unique_ptr<FileSys::Archive_ExtSaveData> ptm_shared_extsavedata; | ||
| 32 | static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; | 32 | static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; |
| 33 | 33 | ||
| 34 | /// Charge levels used by PTM functions | 34 | /// Charge levels used by PTM functions |
| @@ -138,31 +138,28 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 138 | 138 | ||
| 139 | Interface::Interface() { | 139 | Interface::Interface() { |
| 140 | Register(FunctionTable); | 140 | Register(FunctionTable); |
| 141 | // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file | 141 | |
| 142 | // TODO(Subv): In the future we should use the FS service to query this archive | 142 | // Open the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file |
| 143 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); | ||
| 144 | ptm_shared_extsavedata = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); | ||
| 145 | if (!ptm_shared_extsavedata->Initialize()) { | ||
| 146 | LOG_CRITICAL(Service_PTM, "Could not initialize SharedExtSaveData archive for the PTM:U service"); | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | FileSys::Path archive_path(ptm_shared_extdata_id); | 143 | FileSys::Path archive_path(ptm_shared_extdata_id); |
| 150 | ResultCode result = ptm_shared_extsavedata->Open(archive_path); | 144 | auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); |
| 151 | // If the archive didn't exist, create the files inside | 145 | // If the archive didn't exist, create the files inside |
| 152 | if (result.description == ErrorDescription::FS_NotFormatted) { | 146 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { |
| 153 | // Format the archive to clear the directories | 147 | // Format the archive to create the directories |
| 154 | ptm_shared_extsavedata->Format(archive_path); | 148 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); |
| 155 | // Open it again to get a valid archive now that the folder exists | 149 | // Open it again to get a valid archive now that the folder exists |
| 156 | ptm_shared_extsavedata->Open(archive_path); | 150 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); |
| 151 | _assert_msg_(Service_PTM, archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); | ||
| 152 | |||
| 157 | FileSys::Path gamecoin_path("gamecoin.dat"); | 153 | FileSys::Path gamecoin_path("gamecoin.dat"); |
| 158 | FileSys::Mode open_mode = {}; | 154 | FileSys::Mode open_mode = {}; |
| 159 | open_mode.write_flag = 1; | 155 | open_mode.write_flag = 1; |
| 160 | open_mode.create_flag = 1; | 156 | open_mode.create_flag = 1; |
| 161 | // Open the file and write the default gamecoin information | 157 | // Open the file and write the default gamecoin information |
| 162 | auto gamecoin = ptm_shared_extsavedata->OpenFile(gamecoin_path, open_mode); | 158 | auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); |
| 163 | if (gamecoin != nullptr) { | 159 | if (gamecoin_result.Succeeded()) { |
| 164 | gamecoin->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); | 160 | auto gamecoin = gamecoin_result.MoveFrom(); |
| 165 | gamecoin->Close(); | 161 | gamecoin->backend->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); |
| 162 | gamecoin->backend->Close(); | ||
| 166 | } | 163 | } |
| 167 | } | 164 | } |
| 168 | } | 165 | } |