Merge pull request #381 from Subv/savedatacheck
Implemented the SaveDataCheck archive
This commit is contained in:
		| @@ -42,6 +42,7 @@ | |||||||
| #define SDMC_DIR          "sdmc" | #define SDMC_DIR          "sdmc" | ||||||
| #define EXTSAVEDATA_DIR   "extsavedata" | #define EXTSAVEDATA_DIR   "extsavedata" | ||||||
| #define SAVEDATA_DIR      "savedata" | #define SAVEDATA_DIR      "savedata" | ||||||
|  | #define SAVEDATACHECK_DIR "savedatacheck" | ||||||
| #define SYSDATA_DIR       "sysdata" | #define SYSDATA_DIR       "sysdata" | ||||||
| #define SYSSAVEDATA_DIR   "syssavedata" | #define SYSSAVEDATA_DIR   "syssavedata" | ||||||
| #define SHADERCACHE_DIR   "shader_cache" | #define SHADERCACHE_DIR   "shader_cache" | ||||||
|   | |||||||
| @@ -678,6 +678,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||||||
|         paths[D_SDMC_IDX]           = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; |         paths[D_SDMC_IDX]           = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; | ||||||
|         paths[D_EXTSAVEDATA]        = paths[D_USER_IDX] + EXTSAVEDATA_DIR DIR_SEP; |         paths[D_EXTSAVEDATA]        = paths[D_USER_IDX] + EXTSAVEDATA_DIR DIR_SEP; | ||||||
|         paths[D_SAVEDATA_IDX]       = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP; |         paths[D_SAVEDATA_IDX]       = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP; | ||||||
|  |         paths[D_SAVEDATACHECK_IDX]  = paths[D_USER_IDX] + SAVEDATACHECK_DIR DIR_SEP; | ||||||
|         paths[D_SYSDATA_IDX]        = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP; |         paths[D_SYSDATA_IDX]        = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP; | ||||||
|         paths[D_SYSSAVEDATA_IDX]    = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP; |         paths[D_SYSSAVEDATA_IDX]    = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP; | ||||||
|         paths[D_SHADERCACHE_IDX]    = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; |         paths[D_SHADERCACHE_IDX]    = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; | ||||||
| @@ -723,6 +724,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new | |||||||
|             paths[D_SDMC_IDX]           = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; |             paths[D_SDMC_IDX]           = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; | ||||||
|             paths[D_EXTSAVEDATA]        = paths[D_USER_IDX] + EXTSAVEDATA_DIR DIR_SEP; |             paths[D_EXTSAVEDATA]        = paths[D_USER_IDX] + EXTSAVEDATA_DIR DIR_SEP; | ||||||
|             paths[D_SAVEDATA_IDX]       = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP; |             paths[D_SAVEDATA_IDX]       = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP; | ||||||
|  |             paths[D_SAVEDATACHECK_IDX]  = paths[D_USER_IDX] + SAVEDATACHECK_DIR DIR_SEP; | ||||||
|             paths[D_SYSSAVEDATA_IDX]    = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP; |             paths[D_SYSSAVEDATA_IDX]    = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP; | ||||||
|             paths[D_SHADERCACHE_IDX]    = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; |             paths[D_SHADERCACHE_IDX]    = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; | ||||||
|             paths[D_SHADERS_IDX]        = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; |             paths[D_SHADERS_IDX]        = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ enum { | |||||||
|     D_SDMC_IDX, |     D_SDMC_IDX, | ||||||
|     D_EXTSAVEDATA, |     D_EXTSAVEDATA, | ||||||
|     D_SAVEDATA_IDX, |     D_SAVEDATA_IDX, | ||||||
|  |     D_SAVEDATACHECK_IDX, | ||||||
|     D_SYSDATA_IDX, |     D_SYSDATA_IDX, | ||||||
|     D_SYSSAVEDATA_IDX, |     D_SYSSAVEDATA_IDX, | ||||||
|     D_HIRESTEXTURES_IDX, |     D_HIRESTEXTURES_IDX, | ||||||
|   | |||||||
| @@ -20,11 +20,11 @@ set(SRCS | |||||||
|             file_sys/archive_extsavedata.cpp |             file_sys/archive_extsavedata.cpp | ||||||
|             file_sys/archive_romfs.cpp |             file_sys/archive_romfs.cpp | ||||||
|             file_sys/archive_savedata.cpp |             file_sys/archive_savedata.cpp | ||||||
|  |             file_sys/archive_savedatacheck.cpp | ||||||
|             file_sys/archive_sdmc.cpp |             file_sys/archive_sdmc.cpp | ||||||
|             file_sys/archive_systemsavedata.cpp |             file_sys/archive_systemsavedata.cpp | ||||||
|             file_sys/disk_archive.cpp |             file_sys/disk_archive.cpp | ||||||
|             file_sys/file_romfs.cpp |             file_sys/ivfc_archive.cpp | ||||||
|             file_sys/directory_romfs.cpp |  | ||||||
|             hle/kernel/address_arbiter.cpp |             hle/kernel/address_arbiter.cpp | ||||||
|             hle/kernel/event.cpp |             hle/kernel/event.cpp | ||||||
|             hle/kernel/kernel.cpp |             hle/kernel/kernel.cpp | ||||||
| @@ -108,13 +108,13 @@ set(HEADERS | |||||||
|             file_sys/archive_extsavedata.h |             file_sys/archive_extsavedata.h | ||||||
|             file_sys/archive_romfs.h |             file_sys/archive_romfs.h | ||||||
|             file_sys/archive_savedata.h |             file_sys/archive_savedata.h | ||||||
|  |             file_sys/archive_savedatacheck.h | ||||||
|             file_sys/archive_sdmc.h |             file_sys/archive_sdmc.h | ||||||
|             file_sys/archive_systemsavedata.h |             file_sys/archive_systemsavedata.h | ||||||
|             file_sys/disk_archive.h |             file_sys/disk_archive.h | ||||||
|             file_sys/file_backend.h |             file_sys/file_backend.h | ||||||
|             file_sys/file_romfs.h |             file_sys/ivfc_archive.h | ||||||
|             file_sys/directory_backend.h |             file_sys/directory_backend.h | ||||||
|             file_sys/directory_romfs.h |  | ||||||
|             hle/kernel/address_arbiter.h |             hle/kernel/address_arbiter.h | ||||||
|             hle/kernel/event.h |             hle/kernel/event.h | ||||||
|             hle/kernel/kernel.h |             hle/kernel/kernel.h | ||||||
|   | |||||||
| @@ -88,6 +88,7 @@ public: | |||||||
|     const std::string DebugStr() const { |     const std::string DebugStr() const { | ||||||
|         switch (GetType()) { |         switch (GetType()) { | ||||||
|         case Invalid: |         case Invalid: | ||||||
|  |         default: | ||||||
|             return "[Invalid]"; |             return "[Invalid]"; | ||||||
|         case Empty: |         case Empty: | ||||||
|             return "[Empty]"; |             return "[Empty]"; | ||||||
| @@ -117,6 +118,7 @@ public: | |||||||
|             return {}; |             return {}; | ||||||
|         case Invalid: |         case Invalid: | ||||||
|         case Binary: |         case Binary: | ||||||
|  |         default: | ||||||
|             // TODO(yuriks): Add assert |             // TODO(yuriks): Add assert | ||||||
|             LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); |             LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); | ||||||
|             return {}; |             return {}; | ||||||
| @@ -159,6 +161,7 @@ public: | |||||||
|         case Empty: |         case Empty: | ||||||
|             return {}; |             return {}; | ||||||
|         case Invalid: |         case Invalid: | ||||||
|  |         default: | ||||||
|             // TODO(yuriks): Add assert |             // TODO(yuriks): Add assert | ||||||
|             LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); |             LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); | ||||||
|             return {}; |             return {}; | ||||||
|   | |||||||
| @@ -5,11 +5,10 @@ | |||||||
| #include <memory> | #include <memory> | ||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "common/file_util.h" | ||||||
| #include "common/make_unique.h" | #include "common/make_unique.h" | ||||||
|  |  | ||||||
| #include "core/file_sys/archive_romfs.h" | #include "core/file_sys/archive_romfs.h" | ||||||
| #include "core/file_sys/directory_romfs.h" |  | ||||||
| #include "core/file_sys/file_romfs.h" |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
| // FileSys namespace | // FileSys namespace | ||||||
| @@ -23,48 +22,4 @@ Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| std::unique_ptr<FileBackend> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { |  | ||||||
|     return Common::make_unique<File_RomFS>(this); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool Archive_RomFS::DeleteFile(const Path& path) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to delete a file from ROMFS."); |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool Archive_RomFS::RenameFile(const Path& src_path, const Path& dest_path) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS."); |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool Archive_RomFS::DeleteDirectory(const Path& path) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to delete a directory from ROMFS."); |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ResultCode Archive_RomFS::CreateFile(const Path& path, u32 size) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to create a file in ROMFS."); |  | ||||||
|     // TODO: Verify error code |  | ||||||
|     return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool Archive_RomFS::CreateDirectory(const Path& path) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to create a directory in ROMFS."); |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool Archive_RomFS::RenameDirectory(const Path& src_path, const Path& dest_path) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS."); |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| std::unique_ptr<DirectoryBackend> Archive_RomFS::OpenDirectory(const Path& path) const { |  | ||||||
|     return Common::make_unique<Directory_RomFS>(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ResultCode Archive_RomFS::Format(const Path& path) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to format ROMFS."); |  | ||||||
|     return UnimplementedFunction(ErrorModule::FS); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| } // namespace FileSys | } // namespace FileSys | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  |  | ||||||
| #include "core/file_sys/archive_backend.h" | #include "core/file_sys/ivfc_archive.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -17,82 +17,12 @@ | |||||||
| namespace FileSys { | namespace FileSys { | ||||||
|  |  | ||||||
| /// File system interface to the RomFS archive | /// File system interface to the RomFS archive | ||||||
| class Archive_RomFS final : public ArchiveBackend { | class Archive_RomFS final : public IVFCArchive { | ||||||
| public: | public: | ||||||
|     Archive_RomFS(const Loader::AppLoader& app_loader); |     Archive_RomFS(const Loader::AppLoader& app_loader); | ||||||
|  |  | ||||||
|     std::string GetName() const override { return "RomFS"; } |     std::string GetName() const override { return "RomFS"; } | ||||||
|  |     ResultCode Open(const Path& path) override { return RESULT_SUCCESS; } | ||||||
|     /** |  | ||||||
|      * Open a file specified by its path, using the specified mode |  | ||||||
|      * @param path Path relative to the archive |  | ||||||
|      * @param mode Mode to open the file with |  | ||||||
|      * @return Opened file, or nullptr |  | ||||||
|      */ |  | ||||||
|     std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Delete a file specified by its path |  | ||||||
|      * @param path Path relative to the archive |  | ||||||
|      * @return Whether the file could be deleted |  | ||||||
|      */ |  | ||||||
|     bool DeleteFile(const Path& path) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Rename a File specified by its path |  | ||||||
|      * @param src_path Source path relative to the archive |  | ||||||
|      * @param dest_path Destination path relative to the archive |  | ||||||
|      * @return Whether rename succeeded |  | ||||||
|      */ |  | ||||||
|     bool RenameFile(const Path& src_path, const Path& dest_path) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Delete a directory specified by its path |  | ||||||
|      * @param path Path relative to the archive |  | ||||||
|      * @return Whether the directory could be deleted |  | ||||||
|      */ |  | ||||||
|     bool DeleteDirectory(const Path& path) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Create a file specified by its path |  | ||||||
|      * @param path Path relative to the Archive |  | ||||||
|      * @param size The size of the new file, filled with zeroes |  | ||||||
|      * @return File creation result code |  | ||||||
|      */ |  | ||||||
|     ResultCode CreateFile(const Path& path, u32 size) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Create a directory specified by its path |  | ||||||
|      * @param path Path relative to the archive |  | ||||||
|      * @return Whether the directory could be created |  | ||||||
|      */ |  | ||||||
|     bool CreateDirectory(const Path& path) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Rename a Directory specified by its path |  | ||||||
|      * @param src_path Source path relative to the archive |  | ||||||
|      * @param dest_path Destination path relative to the archive |  | ||||||
|      * @return Whether rename succeeded |  | ||||||
|      */ |  | ||||||
|     bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Open a directory specified by its path |  | ||||||
|      * @param path Path relative to the archive |  | ||||||
|      * @return Opened directory, or nullptr |  | ||||||
|      */ |  | ||||||
|     std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; |  | ||||||
|  |  | ||||||
|     ResultCode Open(const Path& path) override { |  | ||||||
|         return RESULT_SUCCESS; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ResultCode Format(const Path& path) const override; |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     friend class File_RomFS; |  | ||||||
|  |  | ||||||
|     std::vector<u8> raw_data; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace FileSys | } // namespace FileSys | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								src/core/file_sys/archive_savedatacheck.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/core/file_sys/archive_savedatacheck.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include "common/file_util.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/archive_savedatacheck.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | Archive_SaveDataCheck::Archive_SaveDataCheck(const std::string& mount_loc) : mount_point(mount_loc) { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ResultCode Archive_SaveDataCheck::Open(const Path& path) { | ||||||
|  |     // TODO(Subv): We should not be overwriting raw_data everytime this function is called, | ||||||
|  |     // but until we use factory classes to create the archives at runtime instead of creating them beforehand | ||||||
|  |     // and allow multiple archives of the same type to be open at the same time without clobbering each other, | ||||||
|  |     // we won't be able to maintain the state of each archive, hence we overwrite it every time it's needed. | ||||||
|  |     // There are a number of problems with this, for example opening a file in this archive, then opening | ||||||
|  |     // this archive again with a different path, will corrupt the previously open file. | ||||||
|  |     auto vec = path.AsBinary(); | ||||||
|  |     const u32* data = reinterpret_cast<u32*>(vec.data()); | ||||||
|  |     std::string file_path = Common::StringFromFormat("%s%08x%08x.bin", mount_point.c_str(), data[1], data[0]); | ||||||
|  |     FileUtil::IOFile file(file_path, "rb"); | ||||||
|  |  | ||||||
|  |     std::fill(raw_data.begin(), raw_data.end(), 0); | ||||||
|  |  | ||||||
|  |     if (!file.IsOpen()) { | ||||||
|  |         return ResultCode(-1); // TODO(Subv): Find the right error code | ||||||
|  |     } | ||||||
|  |     auto size = file.GetSize(); | ||||||
|  |     raw_data.resize(size); | ||||||
|  |     file.ReadBytes(raw_data.data(), size); | ||||||
|  |     file.Close(); | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
							
								
								
									
										31
									
								
								src/core/file_sys/archive_savedatacheck.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/core/file_sys/archive_savedatacheck.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/ivfc_archive.h" | ||||||
|  | #include "core/loader/loader.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | /// File system interface to the SaveDataCheck archive | ||||||
|  | class Archive_SaveDataCheck final : public IVFCArchive { | ||||||
|  | public: | ||||||
|  |     Archive_SaveDataCheck(const std::string& mount_point); | ||||||
|  |  | ||||||
|  |     std::string GetName() const override { return "SaveDataCheck"; } | ||||||
|  |     ResultCode Open(const Path& path) override; | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     std::string mount_point; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
| @@ -1,32 +0,0 @@ | |||||||
| // Copyright 2014 Citra Emulator Project |  | ||||||
| // Licensed under GPLv2 or any later version |  | ||||||
| // Refer to the license.txt file included. |  | ||||||
|  |  | ||||||
| #include "common/common_types.h" |  | ||||||
|  |  | ||||||
| #include "core/file_sys/directory_romfs.h" |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
| // FileSys namespace |  | ||||||
|  |  | ||||||
| namespace FileSys { |  | ||||||
|  |  | ||||||
| Directory_RomFS::Directory_RomFS() { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| Directory_RomFS::~Directory_RomFS() { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool Directory_RomFS::Open() { |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| u32 Directory_RomFS::Read(const u32 count, Entry* entries) { |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool Directory_RomFS::Close() const { |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| } // namespace FileSys |  | ||||||
| @@ -1,43 +0,0 @@ | |||||||
| // Copyright 2014 Citra Emulator Project |  | ||||||
| // Licensed under GPLv2 or any later version |  | ||||||
| // Refer to the license.txt file included. |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "common/common_types.h" |  | ||||||
|  |  | ||||||
| #include "core/file_sys/directory_backend.h" |  | ||||||
| #include "core/loader/loader.h" |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
| // FileSys namespace |  | ||||||
|  |  | ||||||
| namespace FileSys { |  | ||||||
|  |  | ||||||
| class Directory_RomFS final : public DirectoryBackend { |  | ||||||
| public: |  | ||||||
|     Directory_RomFS(); |  | ||||||
|     ~Directory_RomFS() override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|     * Open the directory |  | ||||||
|     * @return true if the directory opened correctly |  | ||||||
|     */ |  | ||||||
|     bool Open() override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * List files contained in the directory |  | ||||||
|      * @param count Number of entries to return at once in entries |  | ||||||
|      * @param entries Buffer to read data into |  | ||||||
|      * @return Number of entries listed |  | ||||||
|      */ |  | ||||||
|     u32 Read(const u32 count, Entry* entries) override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Close the directory |  | ||||||
|      * @return true if the directory closed correctly |  | ||||||
|      */ |  | ||||||
|     bool Close() const override; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| } // namespace FileSys |  | ||||||
| @@ -1,43 +0,0 @@ | |||||||
| // Copyright 2014 Citra Emulator Project |  | ||||||
| // Licensed under GPLv2 or any later version |  | ||||||
| // Refer to the license.txt file included. |  | ||||||
|  |  | ||||||
| #include "common/common_types.h" |  | ||||||
|  |  | ||||||
| #include "core/file_sys/file_romfs.h" |  | ||||||
| #include "core/file_sys/archive_romfs.h" |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
| // FileSys namespace |  | ||||||
|  |  | ||||||
| namespace FileSys { |  | ||||||
|  |  | ||||||
| bool File_RomFS::Open() { |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { |  | ||||||
|     LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); |  | ||||||
|     memcpy(buffer, &archive->raw_data[(u32)offset], length); |  | ||||||
|     return length; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t File_RomFS::GetSize() const { |  | ||||||
|     return sizeof(u8) * archive->raw_data.size(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool File_RomFS::SetSize(const u64 size) const { |  | ||||||
|     LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool File_RomFS::Close() const { |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| } // namespace FileSys |  | ||||||
| @@ -1,73 +0,0 @@ | |||||||
| // Copyright 2014 Citra Emulator Project |  | ||||||
| // Licensed under GPLv2 or any later version |  | ||||||
| // Refer to the license.txt file included. |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "common/common_types.h" |  | ||||||
|  |  | ||||||
| #include "core/file_sys/file_backend.h" |  | ||||||
| #include "core/loader/loader.h" |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
| // FileSys namespace |  | ||||||
|  |  | ||||||
| namespace FileSys { |  | ||||||
|  |  | ||||||
| class Archive_RomFS; |  | ||||||
|  |  | ||||||
| class File_RomFS final : public FileBackend { |  | ||||||
| public: |  | ||||||
|     File_RomFS(const Archive_RomFS* archive) : archive(archive) {} |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Open the file |  | ||||||
|      * @return true if the file opened correctly |  | ||||||
|      */ |  | ||||||
|     bool Open() override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Read data from the file |  | ||||||
|      * @param offset Offset in bytes to start reading data from |  | ||||||
|      * @param length Length in bytes of data to read from file |  | ||||||
|      * @param buffer Buffer to read data into |  | ||||||
|      * @return Number of bytes read |  | ||||||
|      */ |  | ||||||
|     size_t Read(const u64 offset, const u32 length, u8* buffer) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Write data to the file |  | ||||||
|      * @param offset Offset in bytes to start writing data to |  | ||||||
|      * @param length Length in bytes of data to write to file |  | ||||||
|      * @param flush The flush parameters (0 == do not flush) |  | ||||||
|      * @param buffer Buffer to read data from |  | ||||||
|      * @return Number of bytes written |  | ||||||
|      */ |  | ||||||
|     size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Get the size of the file in bytes |  | ||||||
|      * @return Size of the file in bytes |  | ||||||
|      */ |  | ||||||
|     size_t GetSize() const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Set the size of the file in bytes |  | ||||||
|      * @param size New size of the file |  | ||||||
|      * @return true if successful |  | ||||||
|      */ |  | ||||||
|     bool SetSize(const u64 size) const override; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Close the file |  | ||||||
|      * @return true if the file closed correctly |  | ||||||
|      */ |  | ||||||
|     bool Close() const override; |  | ||||||
|  |  | ||||||
|     void Flush() const override { } |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     const Archive_RomFS* archive; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| } // namespace FileSys |  | ||||||
							
								
								
									
										88
									
								
								src/core/file_sys/ivfc_archive.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/core/file_sys/ivfc_archive.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <memory> | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/file_util.h" | ||||||
|  | #include "common/make_unique.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/ivfc_archive.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | IVFCArchive::IVFCArchive() { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::unique_ptr<FileBackend> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { | ||||||
|  |     return Common::make_unique<IVFCFile>(this); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool IVFCArchive::DeleteFile(const Path& path) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", GetName().c_str()); | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool IVFCArchive::DeleteDirectory(const Path& path) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", GetName().c_str()); | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ResultCode IVFCArchive::CreateFile(const Path& path, u32 size) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", GetName().c_str()); | ||||||
|  |     // TODO: Verify error code | ||||||
|  |     return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool IVFCArchive::CreateDirectory(const Path& path) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).", GetName().c_str()); | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::unique_ptr<DirectoryBackend> IVFCArchive::OpenDirectory(const Path& path) const { | ||||||
|  |     return Common::make_unique<IVFCDirectory>(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ResultCode IVFCArchive::Format(const Path& path) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to format an IVFC archive (%s).", GetName().c_str()); | ||||||
|  |     // TODO: Verify error code | ||||||
|  |     return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  | size_t IVFCFile::Read(const u64 offset, const u32 length, u8* buffer) const { | ||||||
|  |     LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); | ||||||
|  |     memcpy(buffer, &archive->raw_data[(u32)offset], length); | ||||||
|  |     return length; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to write to IVFC file in archive %s.", archive->GetName().c_str()); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t IVFCFile::GetSize() const { | ||||||
|  |     return sizeof(u8) * archive->raw_data.size(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool IVFCFile::SetSize(const u64 size) const { | ||||||
|  |     LOG_CRITICAL(Service_FS, "Attempted to set the size of an IVFC file in archive %s", archive->GetName().c_str()); | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
							
								
								
									
										66
									
								
								src/core/file_sys/ivfc_archive.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/core/file_sys/ivfc_archive.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | // Copyright 2014 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  |  | ||||||
|  | #include "core/file_sys/archive_backend.h" | ||||||
|  | #include "core/loader/loader.h" | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // FileSys namespace | ||||||
|  |  | ||||||
|  | namespace FileSys { | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Helper which implements an interface to deal with IVFC images used in some archives | ||||||
|  |  * This should be subclassed by concrete archive types, which will provide the | ||||||
|  |  * input data (load the raw IVFC archive) and override any required methods | ||||||
|  |  */ | ||||||
|  | class IVFCArchive : public ArchiveBackend { | ||||||
|  | public: | ||||||
|  |     IVFCArchive(); | ||||||
|  |  | ||||||
|  |     std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; | ||||||
|  |     bool DeleteFile(const Path& path) const override; | ||||||
|  |     bool RenameFile(const Path& src_path, const Path& dest_path) const override; | ||||||
|  |     bool DeleteDirectory(const Path& path) const override; | ||||||
|  |     ResultCode CreateFile(const Path& path, u32 size) const override; | ||||||
|  |     bool CreateDirectory(const Path& path) const override; | ||||||
|  |     bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; | ||||||
|  |     std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; | ||||||
|  |     ResultCode Format(const Path& path) const override; | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  |     friend class IVFCFile; | ||||||
|  |     std::vector<u8> raw_data; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class IVFCFile : public FileBackend { | ||||||
|  | public: | ||||||
|  |     IVFCFile(const IVFCArchive* archive) : archive(archive) {} | ||||||
|  |  | ||||||
|  |     bool Open() override { return true; } | ||||||
|  |     size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||||||
|  |     size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||||||
|  |     size_t GetSize() const override; | ||||||
|  |     bool SetSize(const u64 size) const override; | ||||||
|  |     bool Close() const override { return false; } | ||||||
|  |     void Flush() const override { } | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     const IVFCArchive* archive; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class IVFCDirectory : public DirectoryBackend { | ||||||
|  | public: | ||||||
|  |     bool Open() override { return false; } | ||||||
|  |     u32 Read(const u32 count, Entry* entries) override { return 0; } | ||||||
|  |     bool Close() const override { return false; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace FileSys | ||||||
| @@ -10,9 +10,11 @@ | |||||||
| #include "common/make_unique.h" | #include "common/make_unique.h" | ||||||
| #include "common/math_util.h" | #include "common/math_util.h" | ||||||
|  |  | ||||||
| #include "core/file_sys/archive_savedata.h" |  | ||||||
| #include "core/file_sys/archive_extsavedata.h" |  | ||||||
| #include "core/file_sys/archive_backend.h" | #include "core/file_sys/archive_backend.h" | ||||||
|  | #include "core/file_sys/archive_extsavedata.h" | ||||||
|  | #include "core/file_sys/archive_romfs.h" | ||||||
|  | #include "core/file_sys/archive_savedata.h" | ||||||
|  | #include "core/file_sys/archive_savedatacheck.h" | ||||||
| #include "core/file_sys/archive_sdmc.h" | #include "core/file_sys/archive_sdmc.h" | ||||||
| #include "core/file_sys/directory_backend.h" | #include "core/file_sys/directory_backend.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| @@ -50,6 +52,9 @@ enum class FileCommand : u32 { | |||||||
|     SetAttributes   = 0x08070040, |     SetAttributes   = 0x08070040, | ||||||
|     Close           = 0x08080000, |     Close           = 0x08080000, | ||||||
|     Flush           = 0x08090000, |     Flush           = 0x08090000, | ||||||
|  |     SetPriority     = 0x080A0040, | ||||||
|  |     GetPriority     = 0x080B0000, | ||||||
|  |     OpenLinkFile    = 0x080C0000, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Command to access directory | // Command to access directory | ||||||
| @@ -75,12 +80,13 @@ public: | |||||||
| class File : public Kernel::Session { | class File : public Kernel::Session { | ||||||
| public: | public: | ||||||
|     File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) |     File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) | ||||||
|             : path(path), backend(std::move(backend)) { |             : path(path), backend(std::move(backend)), priority(0) { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::string GetName() const override { return "Path: " + path.DebugStr(); } |     std::string GetName() const override { return "Path: " + path.DebugStr(); } | ||||||
|  |  | ||||||
|     FileSys::Path path; ///< Path of the file |     FileSys::Path path; ///< Path of the file | ||||||
|  |     u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means | ||||||
|     std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface |     std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface | ||||||
|  |  | ||||||
|     ResultVal<bool> SyncRequest() override { |     ResultVal<bool> SyncRequest() override { | ||||||
| @@ -145,6 +151,27 @@ public: | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         case FileCommand::OpenLinkFile: | ||||||
|  |         { | ||||||
|  |             LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); | ||||||
|  |             cmd_buff[3] = GetHandle(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         case FileCommand::SetPriority: | ||||||
|  |         { | ||||||
|  |             priority = cmd_buff[1]; | ||||||
|  |             LOG_TRACE(Service_FS, "SetPriority %u", priority); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         case FileCommand::GetPriority: | ||||||
|  |         { | ||||||
|  |             cmd_buff[2] = priority; | ||||||
|  |             LOG_TRACE(Service_FS, "GetPriority"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // Unknown command... |         // Unknown command... | ||||||
|         default: |         default: | ||||||
|             LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); |             LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | ||||||
| @@ -327,7 +354,7 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||||||
|                       ErrorSummary::Canceled, ErrorLevel::Status); |                       ErrorSummary::Canceled, ErrorLevel::Status); | ||||||
| } | } | ||||||
|  |  | ||||||
| ResultCode CreateFileInArchive(Handle archive_handle, const FileSys::Path& path, u32 file_size) { | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { | ||||||
|     Archive* archive = GetArchive(archive_handle); |     Archive* archive = GetArchive(archive_handle); | ||||||
|     if (archive == nullptr) |     if (archive == nullptr) | ||||||
|         return InvalidHandle(ErrorModule::FS); |         return InvalidHandle(ErrorModule::FS); | ||||||
| @@ -435,6 +462,11 @@ void ArchiveInit() { | |||||||
|     else |     else | ||||||
|         LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",  |         LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",  | ||||||
|                   sharedextsavedata_directory.c_str()); |                   sharedextsavedata_directory.c_str()); | ||||||
|  |  | ||||||
|  |     // Create the SaveDataCheck archive, basically a small variation of the RomFS archive | ||||||
|  |     std::string savedatacheck_directory = FileUtil::GetUserPath(D_SAVEDATACHECK_IDX); | ||||||
|  |     auto savedatacheck_archive = Common::make_unique<FileSys::Archive_SaveDataCheck>(savedatacheck_directory); | ||||||
|  |     CreateArchive(std::move(savedatacheck_archive), ArchiveIdCode::SaveDataCheck); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Shutdown archives | /// Shutdown archives | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ enum class ArchiveIdCode : u32 { | |||||||
|     SystemSaveData      = 0x00000008, |     SystemSaveData      = 0x00000008, | ||||||
|     SDMC                = 0x00000009, |     SDMC                = 0x00000009, | ||||||
|     SDMCWriteOnly       = 0x0000000A, |     SDMCWriteOnly       = 0x0000000A, | ||||||
|  |     SaveDataCheck       = 0x2345678A, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef u64 ArchiveHandle; | typedef u64 ArchiveHandle; | ||||||
| @@ -90,7 +91,7 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||||||
|  * @param file_size The size of the new file, filled with zeroes |  * @param file_size The size of the new file, filled with zeroes | ||||||
|  * @return File creation result code |  * @return File creation result code | ||||||
|  */ |  */ | ||||||
| ResultCode CreateFileInArchive(Handle archive_handle, const FileSys::Path& path, u32 file_size); | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Create a Directory from an Archive |  * Create a Directory from an Archive | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user