summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/romfs.cpp44
-rw-r--r--src/core/file_sys/romfs.h9
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp3
-rw-r--r--src/yuzu/main.cpp2
4 files changed, 18 insertions, 40 deletions
diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp
index 1c580de57..1eb1f439a 100644
--- a/src/core/file_sys/romfs.cpp
+++ b/src/core/file_sys/romfs.cpp
@@ -35,13 +35,14 @@ struct RomFSHeader {
35static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); 35static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
36 36
37struct DirectoryEntry { 37struct DirectoryEntry {
38 u32_le parent;
38 u32_le sibling; 39 u32_le sibling;
39 u32_le child_dir; 40 u32_le child_dir;
40 u32_le child_file; 41 u32_le child_file;
41 u32_le hash; 42 u32_le hash;
42 u32_le name_length; 43 u32_le name_length;
43}; 44};
44static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size."); 45static_assert(sizeof(DirectoryEntry) == 0x18, "DirectoryEntry has incorrect size.");
45 46
46struct FileEntry { 47struct FileEntry {
47 u32_le parent; 48 u32_le parent;
@@ -64,25 +65,22 @@ std::pair<Entry, std::string> GetEntry(const VirtualFile& file, std::size_t offs
64 return {entry, string}; 65 return {entry, string};
65} 66}
66 67
67void ProcessFile(VirtualFile file, std::size_t file_offset, std::size_t data_offset, 68void ProcessFile(const VirtualFile& file, std::size_t file_offset, std::size_t data_offset,
68 u32 this_file_offset, std::shared_ptr<VectorVfsDirectory> parent) { 69 u32 this_file_offset, std::shared_ptr<VectorVfsDirectory>& parent) {
69 while (true) { 70 while (this_file_offset != ROMFS_ENTRY_EMPTY) {
70 auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset); 71 auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset);
71 72
72 parent->AddFile(std::make_shared<OffsetVfsFile>( 73 parent->AddFile(std::make_shared<OffsetVfsFile>(
73 file, entry.first.size, entry.first.offset + data_offset, entry.second)); 74 file, entry.first.size, entry.first.offset + data_offset, entry.second));
74 75
75 if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
76 break;
77
78 this_file_offset = entry.first.sibling; 76 this_file_offset = entry.first.sibling;
79 } 77 }
80} 78}
81 79
82void ProcessDirectory(VirtualFile file, std::size_t dir_offset, std::size_t file_offset, 80void ProcessDirectory(const VirtualFile& file, std::size_t dir_offset, std::size_t file_offset,
83 std::size_t data_offset, u32 this_dir_offset, 81 std::size_t data_offset, u32 this_dir_offset,
84 std::shared_ptr<VectorVfsDirectory> parent) { 82 std::shared_ptr<VectorVfsDirectory>& parent) {
85 while (true) { 83 while (this_dir_offset != ROMFS_ENTRY_EMPTY) {
86 auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset); 84 auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset);
87 auto current = std::make_shared<VectorVfsDirectory>( 85 auto current = std::make_shared<VectorVfsDirectory>(
88 std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, entry.second); 86 std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, entry.second);
@@ -97,14 +95,12 @@ void ProcessDirectory(VirtualFile file, std::size_t dir_offset, std::size_t file
97 } 95 }
98 96
99 parent->AddDirectory(current); 97 parent->AddDirectory(current);
100 if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
101 break;
102 this_dir_offset = entry.first.sibling; 98 this_dir_offset = entry.first.sibling;
103 } 99 }
104} 100}
105} // Anonymous namespace 101} // Anonymous namespace
106 102
107VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) { 103VirtualDir ExtractRomFS(VirtualFile file) {
108 RomFSHeader header{}; 104 RomFSHeader header{};
109 if (file->ReadObject(&header) != sizeof(RomFSHeader)) 105 if (file->ReadObject(&header) != sizeof(RomFSHeader))
110 return nullptr; 106 return nullptr;
@@ -113,27 +109,17 @@ VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) {
113 return nullptr; 109 return nullptr;
114 110
115 const u64 file_offset = header.file_meta.offset; 111 const u64 file_offset = header.file_meta.offset;
116 const u64 dir_offset = header.directory_meta.offset + 4; 112 const u64 dir_offset = header.directory_meta.offset;
117
118 auto root =
119 std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, std::vector<VirtualDir>{},
120 file->GetName(), file->GetContainingDirectory());
121
122 ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root);
123 113
124 VirtualDir out = std::move(root); 114 auto root_container = std::make_shared<VectorVfsDirectory>();
125 115
126 if (type == RomFSExtractionType::SingleDiscard) 116 ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root_container);
127 return out->GetSubdirectories().front();
128 117
129 while (out->GetSubdirectories().size() == 1 && out->GetFiles().empty()) { 118 if (auto root = root_container->GetSubdirectory(""); root) {
130 if (Common::ToLower(out->GetSubdirectories().front()->GetName()) == "data" && 119 return std::make_shared<CachedVfsDirectory>(std::move(root));
131 type == RomFSExtractionType::Truncated)
132 break;
133 out = out->GetSubdirectories().front();
134 } 120 }
135 121
136 return std::make_shared<CachedVfsDirectory>(std::move(out)); 122 return nullptr;
137} 123}
138 124
139VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) { 125VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h
index 5d7f0c2a8..b75ff1aad 100644
--- a/src/core/file_sys/romfs.h
+++ b/src/core/file_sys/romfs.h
@@ -7,16 +7,9 @@
7 7
8namespace FileSys { 8namespace FileSys {
9 9
10enum class RomFSExtractionType {
11 Full, // Includes data directory
12 Truncated, // Traverses into data directory
13 SingleDiscard, // Traverses into the first subdirectory of root
14};
15
16// Converts a RomFS binary blob to VFS Filesystem 10// Converts a RomFS binary blob to VFS Filesystem
17// Returns nullptr on failure 11// Returns nullptr on failure
18VirtualDir ExtractRomFS(VirtualFile file, 12VirtualDir ExtractRomFS(VirtualFile file);
19 RomFSExtractionType type = RomFSExtractionType::Truncated);
20 13
21// Converts a VFS filesystem into a RomFS binary 14// Converts a VFS filesystem into a RomFS binary
22// Returns nullptr on failure 15// Returns nullptr on failure
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 1c9a1dc29..b0ea2b381 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -330,8 +330,7 @@ void WebBrowser::ExtractOfflineRomFS() {
330 LOG_DEBUG(Service_AM, "Extracting RomFS to {}", 330 LOG_DEBUG(Service_AM, "Extracting RomFS to {}",
331 Common::FS::PathToUTF8String(offline_cache_dir)); 331 Common::FS::PathToUTF8String(offline_cache_dir));
332 332
333 const auto extracted_romfs_dir = 333 const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs);
334 FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard);
335 334
336 const auto temp_dir = system.GetFilesystem()->CreateDirectory( 335 const auto temp_dir = system.GetFilesystem()->CreateDirectory(
337 Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite); 336 Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 0df163029..db9da6dc8 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2737,7 +2737,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
2737 return; 2737 return;
2738 } 2738 }
2739 2739
2740 const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); 2740 const auto extracted = FileSys::ExtractRomFS(romfs);
2741 if (extracted == nullptr) { 2741 if (extracted == nullptr) {
2742 failed(); 2742 failed();
2743 return; 2743 return;