forked from eden-emu/eden
		
	romfs: fix extraction of single-directory root
This commit is contained in:
		
							parent
							
								
									c60204e255
								
							
						
					
					
						commit
						b0c6bf497a
					
				
					 4 changed files with 18 additions and 40 deletions
				
			
		|  | @ -35,13 +35,14 @@ struct RomFSHeader { | |||
| static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); | ||||
| 
 | ||||
| struct DirectoryEntry { | ||||
|     u32_le parent; | ||||
|     u32_le sibling; | ||||
|     u32_le child_dir; | ||||
|     u32_le child_file; | ||||
|     u32_le hash; | ||||
|     u32_le name_length; | ||||
| }; | ||||
| static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size."); | ||||
| static_assert(sizeof(DirectoryEntry) == 0x18, "DirectoryEntry has incorrect size."); | ||||
| 
 | ||||
| struct FileEntry { | ||||
|     u32_le parent; | ||||
|  | @ -64,25 +65,22 @@ std::pair<Entry, std::string> GetEntry(const VirtualFile& file, std::size_t offs | |||
|     return {entry, string}; | ||||
| } | ||||
| 
 | ||||
| void ProcessFile(VirtualFile file, std::size_t file_offset, std::size_t data_offset, | ||||
|                  u32 this_file_offset, std::shared_ptr<VectorVfsDirectory> parent) { | ||||
|     while (true) { | ||||
| void ProcessFile(const VirtualFile& file, std::size_t file_offset, std::size_t data_offset, | ||||
|                  u32 this_file_offset, std::shared_ptr<VectorVfsDirectory>& parent) { | ||||
|     while (this_file_offset != ROMFS_ENTRY_EMPTY) { | ||||
|         auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset); | ||||
| 
 | ||||
|         parent->AddFile(std::make_shared<OffsetVfsFile>( | ||||
|             file, entry.first.size, entry.first.offset + data_offset, entry.second)); | ||||
| 
 | ||||
|         if (entry.first.sibling == ROMFS_ENTRY_EMPTY) | ||||
|             break; | ||||
| 
 | ||||
|         this_file_offset = entry.first.sibling; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ProcessDirectory(VirtualFile file, std::size_t dir_offset, std::size_t file_offset, | ||||
| void ProcessDirectory(const VirtualFile& file, std::size_t dir_offset, std::size_t file_offset, | ||||
|                       std::size_t data_offset, u32 this_dir_offset, | ||||
|                       std::shared_ptr<VectorVfsDirectory> parent) { | ||||
|     while (true) { | ||||
|                       std::shared_ptr<VectorVfsDirectory>& parent) { | ||||
|     while (this_dir_offset != ROMFS_ENTRY_EMPTY) { | ||||
|         auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset); | ||||
|         auto current = std::make_shared<VectorVfsDirectory>( | ||||
|             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 | |||
|         } | ||||
| 
 | ||||
|         parent->AddDirectory(current); | ||||
|         if (entry.first.sibling == ROMFS_ENTRY_EMPTY) | ||||
|             break; | ||||
|         this_dir_offset = entry.first.sibling; | ||||
|     } | ||||
| } | ||||
| } // Anonymous namespace
 | ||||
| 
 | ||||
| VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) { | ||||
| VirtualDir ExtractRomFS(VirtualFile file) { | ||||
|     RomFSHeader header{}; | ||||
|     if (file->ReadObject(&header) != sizeof(RomFSHeader)) | ||||
|         return nullptr; | ||||
|  | @ -113,27 +109,17 @@ VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) { | |||
|         return nullptr; | ||||
| 
 | ||||
|     const u64 file_offset = header.file_meta.offset; | ||||
|     const u64 dir_offset = header.directory_meta.offset + 4; | ||||
|     const u64 dir_offset = header.directory_meta.offset; | ||||
| 
 | ||||
|     auto root = | ||||
|         std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, | ||||
|                                              file->GetName(), file->GetContainingDirectory()); | ||||
|     auto root_container = std::make_shared<VectorVfsDirectory>(); | ||||
| 
 | ||||
|     ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root); | ||||
|     ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root_container); | ||||
| 
 | ||||
|     VirtualDir out = std::move(root); | ||||
| 
 | ||||
|     if (type == RomFSExtractionType::SingleDiscard) | ||||
|         return out->GetSubdirectories().front(); | ||||
| 
 | ||||
|     while (out->GetSubdirectories().size() == 1 && out->GetFiles().empty()) { | ||||
|         if (Common::ToLower(out->GetSubdirectories().front()->GetName()) == "data" && | ||||
|             type == RomFSExtractionType::Truncated) | ||||
|             break; | ||||
|         out = out->GetSubdirectories().front(); | ||||
|     if (auto root = root_container->GetSubdirectory(""); root) { | ||||
|         return std::make_shared<CachedVfsDirectory>(std::move(root)); | ||||
|     } | ||||
| 
 | ||||
|     return std::make_shared<CachedVfsDirectory>(std::move(out)); | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) { | ||||
|  |  | |||
|  | @ -7,16 +7,9 @@ | |||
| 
 | ||||
| namespace FileSys { | ||||
| 
 | ||||
| enum class RomFSExtractionType { | ||||
|     Full,          // Includes data directory
 | ||||
|     Truncated,     // Traverses into data directory
 | ||||
|     SingleDiscard, // Traverses into the first subdirectory of root
 | ||||
| }; | ||||
| 
 | ||||
| // Converts a RomFS binary blob to VFS Filesystem
 | ||||
| // Returns nullptr on failure
 | ||||
| VirtualDir ExtractRomFS(VirtualFile file, | ||||
|                         RomFSExtractionType type = RomFSExtractionType::Truncated); | ||||
| VirtualDir ExtractRomFS(VirtualFile file); | ||||
| 
 | ||||
| // Converts a VFS filesystem into a RomFS binary
 | ||||
| // Returns nullptr on failure
 | ||||
|  |  | |||
|  | @ -330,8 +330,7 @@ void WebBrowser::ExtractOfflineRomFS() { | |||
|     LOG_DEBUG(Service_AM, "Extracting RomFS to {}", | ||||
|               Common::FS::PathToUTF8String(offline_cache_dir)); | ||||
| 
 | ||||
|     const auto extracted_romfs_dir = | ||||
|         FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard); | ||||
|     const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs); | ||||
| 
 | ||||
|     const auto temp_dir = system.GetFilesystem()->CreateDirectory( | ||||
|         Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite); | ||||
|  |  | |||
|  | @ -2737,7 +2737,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); | ||||
|     const auto extracted = FileSys::ExtractRomFS(romfs); | ||||
|     if (extracted == nullptr) { | ||||
|         failed(); | ||||
|         return; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Liam
						Liam