summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/file_sys/content_archive.cpp19
-rw-r--r--src/core/file_sys/romfs.cpp124
-rw-r--r--src/core/file_sys/romfs.h35
-rw-r--r--src/core/file_sys/vfs.cpp23
-rw-r--r--src/core/file_sys/vfs.h20
-rw-r--r--src/core/file_sys/vfs_offset.cpp7
-rw-r--r--src/core/file_sys/vfs_offset.h3
-rw-r--r--src/core/file_sys/vfs_real.cpp6
-rw-r--r--src/core/file_sys/vfs_real.h3
-rw-r--r--src/core/file_sys/vfs_vector.cpp83
-rw-r--r--src/core/file_sys/vfs_vector.h44
12 files changed, 351 insertions, 20 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 95dbba678..30d7667c8 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
13namespace FileSys { 14namespace FileSys {
14 15
@@ -46,21 +47,9 @@ struct PFS0Superblock {
46}; 47};
47static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size."); 48static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size.");
48 49
49struct IVFCLevel {
50 u64_le offset;
51 u64_le size;
52 u32_le block_size;
53 u32_le reserved;
54};
55static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
56
57struct RomFSSuperblock { 50struct 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};
65static_assert(sizeof(RomFSSuperblock) == 0xE8, "RomFSSuperblock has incorrect size."); 54static_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
12namespace FileSys {
13
14constexpr u32 ROMFS_ENTRY_EMPTY = 0xFFFFFFFF;
15
16struct TableLocation {
17 u64_le offset;
18 u64_le size;
19};
20static_assert(sizeof(TableLocation) == 0x10, "TableLocation has incorrect size.");
21
22struct 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};
30static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
31
32struct 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};
39static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size.");
40
41struct 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};
49static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
50
51template <typename Entry>
52static 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
62void 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
77void 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
100VirtualDir 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
12namespace FileSys {
13
14struct IVFCLevel {
15 u64_le offset;
16 u64_le size;
17 u32_le block_size;
18 u32_le reserved;
19};
20static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
21
22struct 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};
29static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
30
31// Converts a RomFS binary blob to VFS Filesystem
32// Returns nullptr on failure
33VirtualDir 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
49std::string VfsFile::GetFullPath() const {
50 if (GetContainingDirectory() == nullptr)
51 return "/" + GetName();
52
53 return GetContainingDirectory()->GetFullPath() + "/" + GetName();
54}
55
49std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const { 56std::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
253std::string VfsDirectory::GetFullPath() const {
254 if (IsRoot())
255 return GetName();
256
257 return GetParentDirectory()->GetFullPath() + "/" + GetName();
258}
259
246bool ReadOnlyVfsDirectory::IsWritable() const { 260bool ReadOnlyVfsDirectory::IsWritable() const {
247 return false; 261 return false;
248} 262}
@@ -270,4 +284,13 @@ bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) {
270bool ReadOnlyVfsDirectory::Rename(std::string_view name) { 284bool ReadOnlyVfsDirectory::Rename(std::string_view name) {
271 return false; 285 return false;
272} 286}
287
288bool 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
216protected: 230protected:
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.
251bool 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 @@
10namespace FileSys { 10namespace FileSys {
11 11
12OffsetVfsFile::OffsetVfsFile(std::shared_ptr<VfsFile> file_, size_t size_, size_t offset_, 12OffsetVfsFile::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
16std::string OffsetVfsFile::GetName() const { 17std::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
37std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() const { 38std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() const {
38 return file->GetContainingDirectory(); 39 return parent;
39} 40}
40 41
41bool OffsetVfsFile::IsWritable() const { 42bool 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.
18struct OffsetVfsFile : public VfsFile { 18struct 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
198std::string RealVfsDirectory::GetFullPath() const {
199 auto out = path;
200 std::replace(out.begin(), out.end(), '\\', '/');
201 return out;
202}
203
198bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { 204bool 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.
43struct RealVfsDirectory : public VfsDirectory { 43struct 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
58protected: 59protected:
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
8namespace FileSys {
9VectorVfsDirectory::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
15std::vector<std::shared_ptr<VfsFile>> VectorVfsDirectory::GetFiles() const {
16 return files;
17}
18
19std::vector<std::shared_ptr<VfsDirectory>> VectorVfsDirectory::GetSubdirectories() const {
20 return dirs;
21}
22
23bool VectorVfsDirectory::IsWritable() const {
24 return false;
25}
26
27bool VectorVfsDirectory::IsReadable() const {
28 return true;
29}
30
31std::string VectorVfsDirectory::GetName() const {
32 return name;
33}
34std::shared_ptr<VfsDirectory> VectorVfsDirectory::GetParentDirectory() const {
35 return parent;
36}
37
38template <typename T>
39static 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
48bool VectorVfsDirectory::DeleteSubdirectory(std::string_view name) {
49 return FindAndRemoveVectorElement(dirs, name);
50}
51
52bool VectorVfsDirectory::DeleteFile(std::string_view name) {
53 return FindAndRemoveVectorElement(files, name);
54}
55
56bool VectorVfsDirectory::Rename(std::string_view name_) {
57 name = name_;
58 return true;
59}
60
61std::shared_ptr<VfsDirectory> VectorVfsDirectory::CreateSubdirectory(std::string_view name) {
62 return nullptr;
63}
64
65std::shared_ptr<VfsFile> VectorVfsDirectory::CreateFile(std::string_view name) {
66 return nullptr;
67}
68
69void VectorVfsDirectory::AddFile(VirtualFile file) {
70 files.push_back(std::move(file));
71}
72
73void VectorVfsDirectory::AddDirectory(VirtualDir dir) {
74 dirs.push_back(std::move(dir));
75}
76
77bool 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
9namespace FileSys {
10
11// An implementation of VfsDirectory that maintains two vectors for subdirectories and files.
12// Vector data is supplied upon construction.
13struct 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
33protected:
34 bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
35
36private:
37 std::vector<VirtualFile> files;
38 std::vector<VirtualDir> dirs;
39
40 VirtualDir parent;
41 std::string name;
42};
43
44} // namespace FileSys