diff --git a/Source/Core/DiscIO/FileSystemGCWii.cpp b/Source/Core/DiscIO/FileSystemGCWii.cpp index 54b7f6a0e2..8546e4d4d1 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/FileSystemGCWii.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -277,27 +278,28 @@ std::unique_ptr FileSystemGCWii::FindFileInfo(u64 disc_offset) const if (!IsValid()) return nullptr; - return FindFileInfo(disc_offset, m_root); -} - -std::unique_ptr FileSystemGCWii::FindFileInfo(u64 disc_offset, - const FileInfo& file_info) const -{ - for (const FileInfo& child : file_info) + // Build a cache (unless there already is one) + if (m_offset_file_info_cache.empty()) { - if (child.IsDirectory()) + u32 fst_entries = m_root.GetSize(); + for (u32 i = 0; i < fst_entries; i++) { - std::unique_ptr result = FindFileInfo(disc_offset, child); - if (result) - return result; - } - else if ((file_info.GetOffset() <= disc_offset) && - ((file_info.GetOffset() + file_info.GetSize()) > disc_offset)) - { - return file_info.clone(); + FileInfoGCWii file_info(m_root, i); + if (!file_info.IsDirectory()) + m_offset_file_info_cache.emplace(file_info.GetOffset() + file_info.GetSize(), i); } } + // Get the first file that ends after disc_offset + const auto it = m_offset_file_info_cache.upper_bound(disc_offset); + if (it == m_offset_file_info_cache.end()) + return nullptr; + std::unique_ptr result(std::make_unique(m_root, it->second)); + + // If the file's start isn't after disc_offset, success + if (result->GetOffset() <= disc_offset) + return result; + return nullptr; } diff --git a/Source/Core/DiscIO/FileSystemGCWii.h b/Source/Core/DiscIO/FileSystemGCWii.h index 50782dacbf..158aa3e420 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.h +++ b/Source/Core/DiscIO/FileSystemGCWii.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include @@ -101,9 +102,10 @@ private: u32 m_offset_shift; std::vector m_file_system_table; FileInfoGCWii m_root; + // Maps the end offset of files to FST indexes + mutable std::map m_offset_file_info_cache; std::unique_ptr FindFileInfo(const std::string& path, const FileInfo& file_info) const; - std::unique_ptr FindFileInfo(u64 disc_offset, const FileInfo& file_info) const; }; } // namespace