diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 19 | ||||
| -rw-r--r-- | src/core/file_sys/romfs.cpp | 124 | ||||
| -rw-r--r-- | src/core/file_sys/romfs.h | 35 | ||||
| -rw-r--r-- | src/core/file_sys/vfs.cpp | 23 | ||||
| -rw-r--r-- | src/core/file_sys/vfs.h | 20 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_offset.cpp | 7 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_offset.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.cpp | 6 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_vector.cpp | 83 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_vector.h | 44 |
12 files changed, 351 insertions, 20 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b367c2a27..f389897d4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -23,6 +23,8 @@ add_library(core STATIC | |||
| 23 | file_sys/partition_filesystem.h | 23 | file_sys/partition_filesystem.h |
| 24 | file_sys/program_metadata.cpp | 24 | file_sys/program_metadata.cpp |
| 25 | file_sys/program_metadata.h | 25 | file_sys/program_metadata.h |
| 26 | file_sys/romfs.cpp | ||
| 27 | file_sys/romfs.h | ||
| 26 | file_sys/romfs_factory.cpp | 28 | file_sys/romfs_factory.cpp |
| 27 | file_sys/romfs_factory.h | 29 | file_sys/romfs_factory.h |
| 28 | file_sys/savedata_factory.cpp | 30 | file_sys/savedata_factory.cpp |
| @@ -35,6 +37,8 @@ add_library(core STATIC | |||
| 35 | file_sys/vfs_offset.h | 37 | file_sys/vfs_offset.h |
| 36 | file_sys/vfs_real.cpp | 38 | file_sys/vfs_real.cpp |
| 37 | file_sys/vfs_real.h | 39 | file_sys/vfs_real.h |
| 40 | file_sys/vfs_vector.cpp | ||
| 41 | file_sys/vfs_vector.h | ||
| 38 | frontend/emu_window.cpp | 42 | frontend/emu_window.cpp |
| 39 | frontend/emu_window.h | 43 | frontend/emu_window.h |
| 40 | frontend/framebuffer_layout.cpp | 44 | frontend/framebuffer_layout.cpp |
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index d6b20c047..61cb0bbe3 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/file_sys/content_archive.h" | 9 | #include "core/file_sys/content_archive.h" |
| 10 | #include "core/file_sys/vfs_offset.h" | 10 | #include "core/file_sys/vfs_offset.h" |
| 11 | #include "core/loader/loader.h" | 11 | #include "core/loader/loader.h" |
| 12 | #include "romfs.h" | ||
| 12 | 13 | ||
| 13 | namespace FileSys { | 14 | namespace FileSys { |
| 14 | 15 | ||
| @@ -46,21 +47,9 @@ struct PFS0Superblock { | |||
| 46 | }; | 47 | }; |
| 47 | static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size."); | 48 | static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size."); |
| 48 | 49 | ||
| 49 | struct IVFCLevel { | ||
| 50 | u64_le offset; | ||
| 51 | u64_le size; | ||
| 52 | u32_le block_size; | ||
| 53 | u32_le reserved; | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size."); | ||
| 56 | |||
| 57 | struct RomFSSuperblock { | 50 | struct RomFSSuperblock { |
| 58 | NCASectionHeaderBlock header_block; | 51 | NCASectionHeaderBlock header_block; |
| 59 | u32_le magic; | 52 | IVFCHeader ivfc; |
| 60 | u32_le magic_number; | ||
| 61 | INSERT_PADDING_BYTES(8); | ||
| 62 | std::array<IVFCLevel, 6> levels; | ||
| 63 | INSERT_PADDING_BYTES(64); | ||
| 64 | }; | 53 | }; |
| 65 | static_assert(sizeof(RomFSSuperblock) == 0xE8, "RomFSSuperblock has incorrect size."); | 54 | static_assert(sizeof(RomFSSuperblock) == 0xE8, "RomFSSuperblock has incorrect size."); |
| 66 | 55 | ||
| @@ -92,8 +81,8 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) { | |||
| 92 | 81 | ||
| 93 | const size_t romfs_offset = | 82 | const size_t romfs_offset = |
| 94 | header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER + | 83 | header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER + |
| 95 | sb.levels[IVFC_MAX_LEVEL - 1].offset; | 84 | sb.ivfc.levels[IVFC_MAX_LEVEL - 1].offset; |
| 96 | const size_t romfs_size = sb.levels[IVFC_MAX_LEVEL - 1].size; | 85 | const size_t romfs_size = sb.ivfc.levels[IVFC_MAX_LEVEL - 1].size; |
| 97 | files.emplace_back(std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset)); | 86 | files.emplace_back(std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset)); |
| 98 | romfs = files.back(); | 87 | romfs = files.back(); |
| 99 | } else if (block.filesystem_type == NCASectionFilesystemType::PFS0) { | 88 | } else if (block.filesystem_type == NCASectionFilesystemType::PFS0) { |
diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp new file mode 100644 index 000000000..ff3ddb29c --- /dev/null +++ b/src/core/file_sys/romfs.cpp | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "common/swap.h" | ||
| 7 | #include "core/file_sys/romfs.h" | ||
| 8 | #include "core/file_sys/vfs.h" | ||
| 9 | #include "core/file_sys/vfs_offset.h" | ||
| 10 | #include "core/file_sys/vfs_vector.h" | ||
| 11 | |||
| 12 | namespace FileSys { | ||
| 13 | |||
| 14 | constexpr u32 ROMFS_ENTRY_EMPTY = 0xFFFFFFFF; | ||
| 15 | |||
| 16 | struct TableLocation { | ||
| 17 | u64_le offset; | ||
| 18 | u64_le size; | ||
| 19 | }; | ||
| 20 | static_assert(sizeof(TableLocation) == 0x10, "TableLocation has incorrect size."); | ||
| 21 | |||
| 22 | struct RomFSHeader { | ||
| 23 | u64_le header_size; | ||
| 24 | TableLocation directory_hash; | ||
| 25 | TableLocation directory_meta; | ||
| 26 | TableLocation file_hash; | ||
| 27 | TableLocation file_meta; | ||
| 28 | u64_le data_offset; | ||
| 29 | }; | ||
| 30 | static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); | ||
| 31 | |||
| 32 | struct DirectoryEntry { | ||
| 33 | u32_le sibling; | ||
| 34 | u32_le child_dir; | ||
| 35 | u32_le child_file; | ||
| 36 | u32_le hash; | ||
| 37 | u32_le name_length; | ||
| 38 | }; | ||
| 39 | static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size."); | ||
| 40 | |||
| 41 | struct FileEntry { | ||
| 42 | u32_le parent; | ||
| 43 | u32_le sibling; | ||
| 44 | u64_le offset; | ||
| 45 | u64_le size; | ||
| 46 | u32_le hash; | ||
| 47 | u32_le name_length; | ||
| 48 | }; | ||
| 49 | static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size."); | ||
| 50 | |||
| 51 | template <typename Entry> | ||
| 52 | static std::pair<Entry, std::string> GetEntry(const VirtualFile& file, size_t offset) { | ||
| 53 | Entry entry{}; | ||
| 54 | if (file->ReadObject(&entry, offset) != sizeof(Entry)) | ||
| 55 | return {}; | ||
| 56 | std::string string(entry.name_length, '\0'); | ||
| 57 | if (file->ReadArray(&string[0], string.size(), offset + sizeof(Entry)) != string.size()) | ||
| 58 | return {}; | ||
| 59 | return {entry, string}; | ||
| 60 | } | ||
| 61 | |||
| 62 | void ProcessFile(VirtualFile file, size_t file_offset, size_t data_offset, u32 this_file_offset, | ||
| 63 | std::shared_ptr<VectorVfsDirectory> parent) { | ||
| 64 | while (true) { | ||
| 65 | auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset); | ||
| 66 | |||
| 67 | parent->AddFile(std::make_shared<OffsetVfsFile>( | ||
| 68 | file, entry.first.size, entry.first.offset + data_offset, entry.second, parent)); | ||
| 69 | |||
| 70 | if (entry.first.sibling == ROMFS_ENTRY_EMPTY) | ||
| 71 | break; | ||
| 72 | |||
| 73 | this_file_offset = entry.first.sibling; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | void ProcessDirectory(VirtualFile file, size_t dir_offset, size_t file_offset, size_t data_offset, | ||
| 78 | u32 this_dir_offset, std::shared_ptr<VectorVfsDirectory> parent) { | ||
| 79 | while (true) { | ||
| 80 | auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset); | ||
| 81 | auto current = std::make_shared<VectorVfsDirectory>( | ||
| 82 | std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, parent, entry.second); | ||
| 83 | |||
| 84 | if (entry.first.child_file != ROMFS_ENTRY_EMPTY) { | ||
| 85 | ProcessFile(file, file_offset, data_offset, entry.first.child_file, current); | ||
| 86 | } | ||
| 87 | |||
| 88 | if (entry.first.child_dir != ROMFS_ENTRY_EMPTY) { | ||
| 89 | ProcessDirectory(file, dir_offset, file_offset, data_offset, entry.first.child_dir, | ||
| 90 | current); | ||
| 91 | } | ||
| 92 | |||
| 93 | parent->AddDirectory(current); | ||
| 94 | if (entry.first.sibling == ROMFS_ENTRY_EMPTY) | ||
| 95 | break; | ||
| 96 | this_dir_offset = entry.first.sibling; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | VirtualDir ExtractRomFS(VirtualFile file) { | ||
| 101 | RomFSHeader header{}; | ||
| 102 | if (file->ReadObject(&header) != sizeof(RomFSHeader)) | ||
| 103 | return nullptr; | ||
| 104 | |||
| 105 | if (header.header_size != sizeof(RomFSHeader)) | ||
| 106 | return nullptr; | ||
| 107 | |||
| 108 | const u64 file_offset = header.file_meta.offset; | ||
| 109 | const u64 dir_offset = header.directory_meta.offset + 4; | ||
| 110 | |||
| 111 | const auto root = | ||
| 112 | std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, | ||
| 113 | file->GetContainingDirectory(), file->GetName()); | ||
| 114 | |||
| 115 | ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root); | ||
| 116 | |||
| 117 | VirtualDir out = std::move(root); | ||
| 118 | |||
| 119 | while (out->GetSubdirectory("") != nullptr) | ||
| 120 | out = out->GetSubdirectory(""); | ||
| 121 | |||
| 122 | return out; | ||
| 123 | } | ||
| 124 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h new file mode 100644 index 000000000..03a876d22 --- /dev/null +++ b/src/core/file_sys/romfs.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "common/swap.h" | ||
| 10 | #include "core/file_sys/vfs.h" | ||
| 11 | |||
| 12 | namespace FileSys { | ||
| 13 | |||
| 14 | struct IVFCLevel { | ||
| 15 | u64_le offset; | ||
| 16 | u64_le size; | ||
| 17 | u32_le block_size; | ||
| 18 | u32_le reserved; | ||
| 19 | }; | ||
| 20 | static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size."); | ||
| 21 | |||
| 22 | struct IVFCHeader { | ||
| 23 | u32_le magic; | ||
| 24 | u32_le magic_number; | ||
| 25 | INSERT_PADDING_BYTES(8); | ||
| 26 | std::array<IVFCLevel, 6> levels; | ||
| 27 | INSERT_PADDING_BYTES(64); | ||
| 28 | }; | ||
| 29 | static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size."); | ||
| 30 | |||
| 31 | // Converts a RomFS binary blob to VFS Filesystem | ||
| 32 | // Returns nullptr on failure | ||
| 33 | VirtualDir ExtractRomFS(VirtualFile file); | ||
| 34 | |||
| 35 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index b99a4fd5b..84a6a7397 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp | |||
| @@ -46,6 +46,13 @@ size_t VfsFile::WriteBytes(const std::vector<u8>& data, size_t offset) { | |||
| 46 | return Write(data.data(), data.size(), offset); | 46 | return Write(data.data(), data.size(), offset); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | std::string VfsFile::GetFullPath() const { | ||
| 50 | if (GetContainingDirectory() == nullptr) | ||
| 51 | return "/" + GetName(); | ||
| 52 | |||
| 53 | return GetContainingDirectory()->GetFullPath() + "/" + GetName(); | ||
| 54 | } | ||
| 55 | |||
| 49 | std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const { | 56 | std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const { |
| 50 | auto vec = FileUtil::SplitPathComponents(path); | 57 | auto vec = FileUtil::SplitPathComponents(path); |
| 51 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), | 58 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), |
| @@ -243,6 +250,13 @@ bool VfsDirectory::Copy(std::string_view src, std::string_view dest) { | |||
| 243 | return f2->WriteBytes(f1->ReadAllBytes()) == f1->GetSize(); | 250 | return f2->WriteBytes(f1->ReadAllBytes()) == f1->GetSize(); |
| 244 | } | 251 | } |
| 245 | 252 | ||
| 253 | std::string VfsDirectory::GetFullPath() const { | ||
| 254 | if (IsRoot()) | ||
| 255 | return GetName(); | ||
| 256 | |||
| 257 | return GetParentDirectory()->GetFullPath() + "/" + GetName(); | ||
| 258 | } | ||
| 259 | |||
| 246 | bool ReadOnlyVfsDirectory::IsWritable() const { | 260 | bool ReadOnlyVfsDirectory::IsWritable() const { |
| 247 | return false; | 261 | return false; |
| 248 | } | 262 | } |
| @@ -270,4 +284,13 @@ bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) { | |||
| 270 | bool ReadOnlyVfsDirectory::Rename(std::string_view name) { | 284 | bool ReadOnlyVfsDirectory::Rename(std::string_view name) { |
| 271 | return false; | 285 | return false; |
| 272 | } | 286 | } |
| 287 | |||
| 288 | bool VfsRawCopy(VirtualFile src, VirtualFile dest) { | ||
| 289 | if (src == nullptr || dest == nullptr) | ||
| 290 | return false; | ||
| 291 | if (!dest->Resize(src->GetSize())) | ||
| 292 | return false; | ||
| 293 | std::vector<u8> data = src->ReadAllBytes(); | ||
| 294 | return dest->WriteBytes(data, 0) == data.size(); | ||
| 295 | } | ||
| 273 | } // namespace FileSys | 296 | } // namespace FileSys |
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index 4a13b8378..cf871edd6 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h | |||
| @@ -113,6 +113,9 @@ struct VfsFile : NonCopyable { | |||
| 113 | 113 | ||
| 114 | // Renames the file to name. Returns whether or not the operation was successsful. | 114 | // Renames the file to name. Returns whether or not the operation was successsful. |
| 115 | virtual bool Rename(std::string_view name) = 0; | 115 | virtual bool Rename(std::string_view name) = 0; |
| 116 | |||
| 117 | // Returns the full path of this file as a string, recursively | ||
| 118 | virtual std::string GetFullPath() const; | ||
| 116 | }; | 119 | }; |
| 117 | 120 | ||
| 118 | // A class representing a directory in an abstract filesystem. | 121 | // A class representing a directory in an abstract filesystem. |
| @@ -213,6 +216,17 @@ struct VfsDirectory : NonCopyable { | |||
| 213 | return ReplaceFileWithSubdirectory(file_p, std::make_shared<Directory>(file_p)); | 216 | return ReplaceFileWithSubdirectory(file_p, std::make_shared<Directory>(file_p)); |
| 214 | } | 217 | } |
| 215 | 218 | ||
| 219 | bool InterpretAsDirectory(const std::function<VirtualDir(VirtualFile)>& function, | ||
| 220 | const std::string& file) { | ||
| 221 | auto file_p = GetFile(file); | ||
| 222 | if (file_p == nullptr) | ||
| 223 | return false; | ||
| 224 | return ReplaceFileWithSubdirectory(file_p, function(file_p)); | ||
| 225 | } | ||
| 226 | |||
| 227 | // Returns the full path of this directory as a string, recursively | ||
| 228 | virtual std::string GetFullPath() const; | ||
| 229 | |||
| 216 | protected: | 230 | protected: |
| 217 | // Backend for InterpretAsDirectory. | 231 | // Backend for InterpretAsDirectory. |
| 218 | // Removes all references to file and adds a reference to dir in the directory's implementation. | 232 | // Removes all references to file and adds a reference to dir in the directory's implementation. |
| @@ -230,4 +244,10 @@ struct ReadOnlyVfsDirectory : public VfsDirectory { | |||
| 230 | bool DeleteFile(std::string_view name) override; | 244 | bool DeleteFile(std::string_view name) override; |
| 231 | bool Rename(std::string_view name) override; | 245 | bool Rename(std::string_view name) override; |
| 232 | }; | 246 | }; |
| 247 | |||
| 248 | // A method that copies the raw data between two different implementations of VirtualFile. If you | ||
| 249 | // are using the same implementation, it is probably better to use the Copy method in the parent | ||
| 250 | // directory of src/dest. | ||
| 251 | bool VfsRawCopy(VirtualFile src, VirtualFile dest); | ||
| 252 | |||
| 233 | } // namespace FileSys | 253 | } // namespace FileSys |
diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp index a40331cef..847cde2f5 100644 --- a/src/core/file_sys/vfs_offset.cpp +++ b/src/core/file_sys/vfs_offset.cpp | |||
| @@ -10,8 +10,9 @@ | |||
| 10 | namespace FileSys { | 10 | namespace FileSys { |
| 11 | 11 | ||
| 12 | OffsetVfsFile::OffsetVfsFile(std::shared_ptr<VfsFile> file_, size_t size_, size_t offset_, | 12 | OffsetVfsFile::OffsetVfsFile(std::shared_ptr<VfsFile> file_, size_t size_, size_t offset_, |
| 13 | std::string name_) | 13 | std::string name_, VirtualDir parent_) |
| 14 | : file(std::move(file_)), offset(offset_), size(size_), name(std::move(name_)) {} | 14 | : file(file_), offset(offset_), size(size_), name(std::move(name_)), |
| 15 | parent(parent_ == nullptr ? file->GetContainingDirectory() : std::move(parent_)) {} | ||
| 15 | 16 | ||
| 16 | std::string OffsetVfsFile::GetName() const { | 17 | std::string OffsetVfsFile::GetName() const { |
| 17 | return name.empty() ? file->GetName() : name; | 18 | return name.empty() ? file->GetName() : name; |
| @@ -35,7 +36,7 @@ bool OffsetVfsFile::Resize(size_t new_size) { | |||
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() const { | 38 | std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() const { |
| 38 | return file->GetContainingDirectory(); | 39 | return parent; |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | bool OffsetVfsFile::IsWritable() const { | 42 | bool OffsetVfsFile::IsWritable() const { |
diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h index 4f471e3ba..235970dc5 100644 --- a/src/core/file_sys/vfs_offset.h +++ b/src/core/file_sys/vfs_offset.h | |||
| @@ -17,7 +17,7 @@ namespace FileSys { | |||
| 17 | // the size of this wrapper. | 17 | // the size of this wrapper. |
| 18 | struct OffsetVfsFile : public VfsFile { | 18 | struct OffsetVfsFile : public VfsFile { |
| 19 | OffsetVfsFile(std::shared_ptr<VfsFile> file, size_t size, size_t offset = 0, | 19 | OffsetVfsFile(std::shared_ptr<VfsFile> file, size_t size, size_t offset = 0, |
| 20 | std::string new_name = ""); | 20 | std::string new_name = "", VirtualDir new_parent = nullptr); |
| 21 | 21 | ||
| 22 | std::string GetName() const override; | 22 | std::string GetName() const override; |
| 23 | size_t GetSize() const override; | 23 | size_t GetSize() const override; |
| @@ -44,6 +44,7 @@ private: | |||
| 44 | size_t offset; | 44 | size_t offset; |
| 45 | size_t size; | 45 | size_t size; |
| 46 | std::string name; | 46 | std::string name; |
| 47 | VirtualDir parent; | ||
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 49 | } // namespace FileSys | 50 | } // namespace FileSys |
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 9ce2e1efa..82d54da4a 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -195,6 +195,12 @@ bool RealVfsDirectory::Rename(std::string_view name) { | |||
| 195 | return FileUtil::Rename(path, new_name); | 195 | return FileUtil::Rename(path, new_name); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | std::string RealVfsDirectory::GetFullPath() const { | ||
| 199 | auto out = path; | ||
| 200 | std::replace(out.begin(), out.end(), '\\', '/'); | ||
| 201 | return out; | ||
| 202 | } | ||
| 203 | |||
| 198 | bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { | 204 | bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { |
| 199 | const auto iter = std::find(files.begin(), files.end(), file); | 205 | const auto iter = std::find(files.begin(), files.end(), file); |
| 200 | if (iter == files.end()) | 206 | if (iter == files.end()) |
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index 2151211c9..243d58576 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h | |||
| @@ -41,7 +41,7 @@ private: | |||
| 41 | 41 | ||
| 42 | // An implementation of VfsDirectory that represents a directory on the user's computer. | 42 | // An implementation of VfsDirectory that represents a directory on the user's computer. |
| 43 | struct RealVfsDirectory : public VfsDirectory { | 43 | struct RealVfsDirectory : public VfsDirectory { |
| 44 | RealVfsDirectory(const std::string& path, Mode perms); | 44 | RealVfsDirectory(const std::string& path, Mode perms = Mode::Read); |
| 45 | 45 | ||
| 46 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; | 46 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; |
| 47 | std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; | 47 | std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; |
| @@ -54,6 +54,7 @@ struct RealVfsDirectory : public VfsDirectory { | |||
| 54 | bool DeleteSubdirectory(std::string_view name) override; | 54 | bool DeleteSubdirectory(std::string_view name) override; |
| 55 | bool DeleteFile(std::string_view name) override; | 55 | bool DeleteFile(std::string_view name) override; |
| 56 | bool Rename(std::string_view name) override; | 56 | bool Rename(std::string_view name) override; |
| 57 | std::string GetFullPath() const override; | ||
| 57 | 58 | ||
| 58 | protected: | 59 | protected: |
| 59 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; | 60 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; |
diff --git a/src/core/file_sys/vfs_vector.cpp b/src/core/file_sys/vfs_vector.cpp new file mode 100644 index 000000000..4c6337e3a --- /dev/null +++ b/src/core/file_sys/vfs_vector.cpp | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include "core/file_sys/vfs_vector.h" | ||
| 7 | |||
| 8 | namespace FileSys { | ||
| 9 | VectorVfsDirectory::VectorVfsDirectory(std::vector<VirtualFile> files_, | ||
| 10 | std::vector<VirtualDir> dirs_, VirtualDir parent_, | ||
| 11 | std::string name_) | ||
| 12 | : files(std::move(files_)), dirs(std::move(dirs_)), parent(std::move(parent_)), | ||
| 13 | name(std::move(name_)) {} | ||
| 14 | |||
| 15 | std::vector<std::shared_ptr<VfsFile>> VectorVfsDirectory::GetFiles() const { | ||
| 16 | return files; | ||
| 17 | } | ||
| 18 | |||
| 19 | std::vector<std::shared_ptr<VfsDirectory>> VectorVfsDirectory::GetSubdirectories() const { | ||
| 20 | return dirs; | ||
| 21 | } | ||
| 22 | |||
| 23 | bool VectorVfsDirectory::IsWritable() const { | ||
| 24 | return false; | ||
| 25 | } | ||
| 26 | |||
| 27 | bool VectorVfsDirectory::IsReadable() const { | ||
| 28 | return true; | ||
| 29 | } | ||
| 30 | |||
| 31 | std::string VectorVfsDirectory::GetName() const { | ||
| 32 | return name; | ||
| 33 | } | ||
| 34 | std::shared_ptr<VfsDirectory> VectorVfsDirectory::GetParentDirectory() const { | ||
| 35 | return parent; | ||
| 36 | } | ||
| 37 | |||
| 38 | template <typename T> | ||
| 39 | static bool FindAndRemoveVectorElement(std::vector<T>& vec, std::string_view name) { | ||
| 40 | auto iter = std::find_if(vec.begin(), vec.end(), [name](T e) { return e->GetName() == name; }); | ||
| 41 | if (iter == vec.end()) | ||
| 42 | return false; | ||
| 43 | auto old_size = vec.size(); | ||
| 44 | vec.erase(iter); | ||
| 45 | return true; | ||
| 46 | } | ||
| 47 | |||
| 48 | bool VectorVfsDirectory::DeleteSubdirectory(std::string_view name) { | ||
| 49 | return FindAndRemoveVectorElement(dirs, name); | ||
| 50 | } | ||
| 51 | |||
| 52 | bool VectorVfsDirectory::DeleteFile(std::string_view name) { | ||
| 53 | return FindAndRemoveVectorElement(files, name); | ||
| 54 | } | ||
| 55 | |||
| 56 | bool VectorVfsDirectory::Rename(std::string_view name_) { | ||
| 57 | name = name_; | ||
| 58 | return true; | ||
| 59 | } | ||
| 60 | |||
| 61 | std::shared_ptr<VfsDirectory> VectorVfsDirectory::CreateSubdirectory(std::string_view name) { | ||
| 62 | return nullptr; | ||
| 63 | } | ||
| 64 | |||
| 65 | std::shared_ptr<VfsFile> VectorVfsDirectory::CreateFile(std::string_view name) { | ||
| 66 | return nullptr; | ||
| 67 | } | ||
| 68 | |||
| 69 | void VectorVfsDirectory::AddFile(VirtualFile file) { | ||
| 70 | files.push_back(std::move(file)); | ||
| 71 | } | ||
| 72 | |||
| 73 | void VectorVfsDirectory::AddDirectory(VirtualDir dir) { | ||
| 74 | dirs.push_back(std::move(dir)); | ||
| 75 | } | ||
| 76 | |||
| 77 | bool VectorVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { | ||
| 78 | if (!DeleteFile(file->GetName())) | ||
| 79 | return false; | ||
| 80 | dirs.emplace_back(dir); | ||
| 81 | return true; | ||
| 82 | } | ||
| 83 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h new file mode 100644 index 000000000..ba469647b --- /dev/null +++ b/src/core/file_sys/vfs_vector.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/file_sys/vfs.h" | ||
| 8 | |||
| 9 | namespace FileSys { | ||
| 10 | |||
| 11 | // An implementation of VfsDirectory that maintains two vectors for subdirectories and files. | ||
| 12 | // Vector data is supplied upon construction. | ||
| 13 | struct VectorVfsDirectory : public VfsDirectory { | ||
| 14 | explicit VectorVfsDirectory(std::vector<VirtualFile> files = {}, | ||
| 15 | std::vector<VirtualDir> dirs = {}, VirtualDir parent = nullptr, | ||
| 16 | std::string name = ""); | ||
| 17 | |||
| 18 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; | ||
| 19 | std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; | ||
| 20 | bool IsWritable() const override; | ||
| 21 | bool IsReadable() const override; | ||
| 22 | std::string GetName() const override; | ||
| 23 | std::shared_ptr<VfsDirectory> GetParentDirectory() const override; | ||
| 24 | bool DeleteSubdirectory(std::string_view name) override; | ||
| 25 | bool DeleteFile(std::string_view name) override; | ||
| 26 | bool Rename(std::string_view name) override; | ||
| 27 | std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override; | ||
| 28 | std::shared_ptr<VfsFile> CreateFile(std::string_view name) override; | ||
| 29 | |||
| 30 | virtual void AddFile(VirtualFile file); | ||
| 31 | virtual void AddDirectory(VirtualDir dir); | ||
| 32 | |||
| 33 | protected: | ||
| 34 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; | ||
| 35 | |||
| 36 | private: | ||
| 37 | std::vector<VirtualFile> files; | ||
| 38 | std::vector<VirtualDir> dirs; | ||
| 39 | |||
| 40 | VirtualDir parent; | ||
| 41 | std::string name; | ||
| 42 | }; | ||
| 43 | |||
| 44 | } // namespace FileSys | ||