mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 22:50:04 +00:00
layered_fs: Make LoadFile and LoadDirectory less recursive
The deep recursion has caused issues in certain games with large numbers of files, especially with MSVC builds. Previously the recursion depth is about equal to the number of files present. With this the depth should be about equal to the maximum depth of the directory structure of the RomFS.
This commit is contained in:
parent
a576eb633f
commit
faf9162dbd
@ -82,7 +82,7 @@ void LayeredFS::Load() {
|
|||||||
|
|
||||||
LayeredFS::~LayeredFS() = default;
|
LayeredFS::~LayeredFS() = default;
|
||||||
|
|
||||||
void LayeredFS::LoadDirectory(Directory& current, u32 offset) {
|
u32 LayeredFS::LoadDirectory(Directory& current, u32 offset) {
|
||||||
DirectoryMetadata metadata;
|
DirectoryMetadata metadata;
|
||||||
romfs->ReadFile(header.directory_metadata_table.offset + offset, sizeof(metadata),
|
romfs->ReadFile(header.directory_metadata_table.offset + offset, sizeof(metadata),
|
||||||
reinterpret_cast<u8*>(&metadata));
|
reinterpret_cast<u8*>(&metadata));
|
||||||
@ -92,28 +92,24 @@ void LayeredFS::LoadDirectory(Directory& current, u32 offset) {
|
|||||||
current.path = current.parent->path + current.name + DIR_SEP;
|
current.path = current.parent->path + current.name + DIR_SEP;
|
||||||
directory_path_map.emplace(current.path, ¤t);
|
directory_path_map.emplace(current.path, ¤t);
|
||||||
|
|
||||||
if (metadata.first_file_offset != 0xFFFFFFFF) {
|
u32 file_offset = metadata.first_file_offset;
|
||||||
LoadFile(current, metadata.first_file_offset);
|
while (file_offset != 0xFFFFFFFF) {
|
||||||
|
file_offset = LoadFile(current, file_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metadata.first_child_directory_offset != 0xFFFFFFFF) {
|
u32 child_directory_offset = metadata.first_child_directory_offset;
|
||||||
|
while (child_directory_offset != 0xFFFFFFFF) {
|
||||||
auto child = std::make_unique<Directory>();
|
auto child = std::make_unique<Directory>();
|
||||||
auto& directory = *child;
|
auto& directory = *child;
|
||||||
directory.parent = ¤t;
|
directory.parent = ¤t;
|
||||||
current.directories.emplace_back(std::move(child));
|
current.directories.emplace_back(std::move(child));
|
||||||
LoadDirectory(directory, metadata.first_child_directory_offset);
|
child_directory_offset = LoadDirectory(directory, child_directory_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metadata.next_sibling_offset != 0xFFFFFFFF) {
|
return metadata.next_sibling_offset;
|
||||||
auto sibling = std::make_unique<Directory>();
|
|
||||||
auto& directory = *sibling;
|
|
||||||
directory.parent = current.parent;
|
|
||||||
current.parent->directories.emplace_back(std::move(sibling));
|
|
||||||
LoadDirectory(directory, metadata.next_sibling_offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayeredFS::LoadFile(Directory& parent, u32 offset) {
|
u32 LayeredFS::LoadFile(Directory& parent, u32 offset) {
|
||||||
FileMetadata metadata;
|
FileMetadata metadata;
|
||||||
romfs->ReadFile(header.file_metadata_table.offset + offset, sizeof(metadata),
|
romfs->ReadFile(header.file_metadata_table.offset + offset, sizeof(metadata),
|
||||||
reinterpret_cast<u8*>(&metadata));
|
reinterpret_cast<u8*>(&metadata));
|
||||||
@ -129,9 +125,7 @@ void LayeredFS::LoadFile(Directory& parent, u32 offset) {
|
|||||||
file_path_map.emplace(file->path, file.get());
|
file_path_map.emplace(file->path, file.get());
|
||||||
parent.files.emplace_back(std::move(file));
|
parent.files.emplace_back(std::move(file));
|
||||||
|
|
||||||
if (metadata.next_sibling_offset != 0xFFFFFFFF) {
|
return metadata.next_sibling_offset;
|
||||||
LoadFile(parent, metadata.next_sibling_offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LayeredFS::ReadName(u32 offset, u32 name_length) {
|
std::string LayeredFS::ReadName(u32 offset, u32 name_length) {
|
||||||
|
@ -65,11 +65,13 @@ private:
|
|||||||
|
|
||||||
std::string ReadName(u32 offset, u32 name_length);
|
std::string ReadName(u32 offset, u32 name_length);
|
||||||
|
|
||||||
// Loads the current directory, then its siblings, and then its children.
|
// Loads the current directory, then its children.
|
||||||
void LoadDirectory(Directory& current, u32 offset);
|
// Returns offset of the next sibling directory to load (0xFFFFFFFF if the last directory)
|
||||||
|
u32 LoadDirectory(Directory& current, u32 offset);
|
||||||
|
|
||||||
// Load the file at offset, and then its siblings.
|
// Load the file at offset.
|
||||||
void LoadFile(Directory& parent, u32 offset);
|
// Returns offset of the next sibling file to load (0xFFFFFFFF if the last file)
|
||||||
|
u32 LoadFile(Directory& parent, u32 offset);
|
||||||
|
|
||||||
// Load replace/create relocations
|
// Load replace/create relocations
|
||||||
void LoadRelocations();
|
void LoadRelocations();
|
||||||
|
Loading…
Reference in New Issue
Block a user