From 38304da947c6b593ef94449894dc018aac633344 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 2 Aug 2017 18:16:56 +0200 Subject: [PATCH 1/3] DiscIO: Use Common::Lazy for loading filesystems This simplifies FileMonitor a lot and also lets us clean up FilesystemPanel. --- Source/Core/Common/Lazy.h | 10 ++ Source/Core/Core/HW/DVD/DVDThread.cpp | 9 +- Source/Core/Core/HW/DVD/FileMonitor.cpp | 39 ++------ Source/Core/Core/HW/DVD/FileMonitor.h | 6 +- Source/Core/Core/WiiUtils.cpp | 28 +++--- Source/Core/DiscIO/DiscExtractor.cpp | 21 +++++ Source/Core/DiscIO/DiscExtractor.h | 4 + Source/Core/DiscIO/DiscScrubber.cpp | 2 +- Source/Core/DiscIO/Filesystem.cpp | 17 ---- Source/Core/DiscIO/Filesystem.h | 8 +- Source/Core/DiscIO/Volume.h | 3 + Source/Core/DiscIO/VolumeFileBlobReader.cpp | 16 ++-- Source/Core/DiscIO/VolumeFileBlobReader.h | 8 +- Source/Core/DiscIO/VolumeGC.cpp | 38 ++++---- Source/Core/DiscIO/VolumeGC.h | 6 ++ Source/Core/DiscIO/VolumeWad.cpp | 6 ++ Source/Core/DiscIO/VolumeWad.h | 2 + Source/Core/DiscIO/VolumeWii.cpp | 23 +++-- Source/Core/DiscIO/VolumeWii.h | 6 +- .../ISOProperties/FilesystemPanel.cpp | 91 +++++++++---------- .../DolphinWX/ISOProperties/FilesystemPanel.h | 11 +-- 21 files changed, 182 insertions(+), 172 deletions(-) diff --git a/Source/Core/Common/Lazy.h b/Source/Core/Common/Lazy.h index 322d4bfeace6..f19d5187cbe7 100644 --- a/Source/Core/Common/Lazy.h +++ b/Source/Core/Common/Lazy.h @@ -21,6 +21,16 @@ class Lazy Lazy() : m_value(T()) {} Lazy(const std::variant>& value) : m_value(value) {} Lazy(std::variant>&& value) : m_value(std::move(value)) {} + const Lazy& operator=(const std::variant>& value) + { + m_value = value; + return *this; + } + const Lazy& operator=(std::variant>&& value) + { + m_value = std::move(value); + return *this; + } const T& operator*() const { return *ComputeValue(); } const T* operator->() const { return ComputeValue(); } T& operator*() { return *ComputeValue(); } diff --git a/Source/Core/Core/HW/DVD/DVDThread.cpp b/Source/Core/Core/HW/DVD/DVDThread.cpp index 221a95a45110..ebaecbce7e70 100644 --- a/Source/Core/Core/HW/DVD/DVDThread.cpp +++ b/Source/Core/Core/HW/DVD/DVDThread.cpp @@ -116,7 +116,6 @@ void Stop() { StopDVDThread(); s_disc.reset(); - FileMonitor::SetFileSystem(nullptr); } static void StopDVDThread() @@ -160,14 +159,9 @@ void DoState(PointerWrap& p) if (had_disc != HasDisc()) { if (had_disc) - { PanicAlertT("An inserted disc was expected but not found."); - } else - { s_disc.reset(); - FileMonitor::SetFileSystem(nullptr); - } } // TODO: Savestates can be smaller if the buffers of results aren't saved, @@ -185,7 +179,6 @@ void SetDisc(std::unique_ptr disc) { WaitUntilIdle(); s_disc = std::move(disc); - FileMonitor::SetFileSystem(s_disc.get()); } bool HasDisc() @@ -356,7 +349,7 @@ static void DVDThread() ReadRequest request; while (s_request_queue.Pop(request)) { - FileMonitor::Log(request.dvd_offset, request.partition); + FileMonitor::Log(*s_disc, request.partition, request.dvd_offset); std::vector buffer(request.length); if (!s_disc->Read(request.dvd_offset, request.length, buffer.data(), request.partition)) diff --git a/Source/Core/Core/HW/DVD/FileMonitor.cpp b/Source/Core/Core/HW/DVD/FileMonitor.cpp index cc50d0ef61c2..2f4dc4965219 100644 --- a/Source/Core/Core/HW/DVD/FileMonitor.cpp +++ b/Source/Core/Core/HW/DVD/FileMonitor.cpp @@ -21,10 +21,7 @@ namespace FileMonitor { -static const DiscIO::Volume* s_volume; -static bool s_new_volume = false; -static std::unique_ptr s_filesystem; -static DiscIO::Partition s_partition; +static DiscIO::Partition s_previous_partition; static std::string s_previous_file; // Filtered files @@ -53,42 +50,19 @@ static bool IsSoundFile(const std::string& filename) return extensions.find(extension) != extensions.end(); } -void SetFileSystem(const DiscIO::Volume* volume) -{ - // Instead of creating the file system object right away, we will let Log - // create it later once we know that it actually will get used - s_volume = volume; - s_new_volume = true; -} - -// Logs access to files in the file system set by SetFileSystem -void Log(u64 offset, const DiscIO::Partition& partition) +void Log(const DiscIO::Volume& volume, const DiscIO::Partition& partition, u64 offset) { // Do nothing if the log isn't selected if (!LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON, LogTypes::LWARNING)) return; - // If the volume or partition changed, load the filesystem of the new partition - if (s_new_volume || s_partition != partition) - { - // Discs with partitions don't have PARTITION_NONE filesystems, - // so let's not waste time trying to read one - const bool reading_from_partition = partition != DiscIO::PARTITION_NONE; - const bool disc_has_partitions = !s_volume->GetPartitions().empty(); - if (reading_from_partition != disc_has_partitions) - return; - - s_new_volume = false; - s_filesystem = DiscIO::CreateFileSystem(s_volume, partition); - s_partition = partition; - s_previous_file.clear(); - } + const DiscIO::FileSystem* file_system = volume.GetFileSystem(partition); // Do nothing if there is no valid file system - if (!s_filesystem) + if (!file_system) return; - const std::unique_ptr file_info = s_filesystem->FindFileInfo(offset); + const std::unique_ptr file_info = file_system->FindFileInfo(offset); // Do nothing if no file was found at that offset if (!file_info) @@ -97,7 +71,7 @@ void Log(u64 offset, const DiscIO::Partition& partition) const std::string path = file_info->GetPath(); // Do nothing if we found the same file again - if (s_previous_file == path) + if (s_previous_partition == partition && s_previous_file == path) return; const std::string size_string = ThousandSeparate(file_info->GetSize() / 1000, 7); @@ -109,6 +83,7 @@ void Log(u64 offset, const DiscIO::Partition& partition) WARN_LOG(FILEMON, "%s", log_string.c_str()); // Update the last accessed file + s_previous_partition = partition; s_previous_file = path; } diff --git a/Source/Core/Core/HW/DVD/FileMonitor.h b/Source/Core/Core/HW/DVD/FileMonitor.h index f51fc70221a3..2b170f50824d 100644 --- a/Source/Core/Core/HW/DVD/FileMonitor.h +++ b/Source/Core/Core/HW/DVD/FileMonitor.h @@ -14,9 +14,5 @@ class Volume; namespace FileMonitor { -// Can be called with nullptr to set the file system to nothing. When not called -// with nullptr, the volume must remain valid until the next SetFileSystem call. -void SetFileSystem(const DiscIO::Volume* volume); -// Logs access to files in the file system set by SetFileSystem -void Log(u64 offset, const DiscIO::Partition& partition); +void Log(const DiscIO::Volume& volume, const DiscIO::Partition& partition, u64 offset); } diff --git a/Source/Core/Core/WiiUtils.cpp b/Source/Core/Core/WiiUtils.cpp index 14d2024dd0fe..639c05da06be 100644 --- a/Source/Core/Core/WiiUtils.cpp +++ b/Source/Core/Core/WiiUtils.cpp @@ -552,7 +552,7 @@ class DiscSystemUpdater final : public SystemUpdater UpdateCallback m_update_callback; std::unique_ptr m_volume; - std::unique_ptr m_disc_fs; + DiscIO::Partition m_partition; }; UpdateResult DiscSystemUpdater::DoDiscUpdate() @@ -578,16 +578,21 @@ UpdateResult DiscSystemUpdater::DoDiscUpdate() return UpdateResult::MissingUpdatePartition; } - m_disc_fs = DiscIO::CreateFileSystem(m_volume.get(), *update_partition); - if (!m_disc_fs || !m_disc_fs->IsValid()) - return UpdateResult::DiscReadFailed; + m_partition = *update_partition; return UpdateFromManifest("__update.inf"); } UpdateResult DiscSystemUpdater::UpdateFromManifest(const std::string& manifest_name) { - const std::unique_ptr update_manifest = m_disc_fs->FindFileInfo(manifest_name); + const DiscIO::FileSystem* disc_fs = m_volume->GetFileSystem(m_partition); + if (!disc_fs) + { + ERROR_LOG(CORE, "Could not read the update partition file system"); + return UpdateResult::DiscReadFailed; + } + + const std::unique_ptr update_manifest = disc_fs->FindFileInfo(manifest_name); if (!update_manifest || (update_manifest->GetSize() - sizeof(ManifestHeader)) % sizeof(Entry) != 0) { @@ -604,8 +609,8 @@ UpdateResult DiscSystemUpdater::UpdateFromManifest(const std::string& manifest_n for (u32 i = 0; i < num_entries; ++i) { const u32 offset = sizeof(ManifestHeader) + sizeof(Entry) * i; - if (entry.size() != DiscIO::ReadFile(*m_volume, m_disc_fs->GetPartition(), - update_manifest.get(), entry.data(), entry.size(), offset)) + if (entry.size() != DiscIO::ReadFile(*m_volume, m_partition, update_manifest.get(), + entry.data(), entry.size(), offset)) { ERROR_LOG(CORE, "Failed to read update information from update manifest"); return UpdateResult::DiscReadFailed; @@ -654,14 +659,13 @@ UpdateResult DiscSystemUpdater::ProcessEntry(u32 type, std::bitset<32> attrs, return UpdateResult::AlreadyUpToDate; // Import the WAD. - const std::unique_ptr wad_file = m_disc_fs->FindFileInfo(path); - if (!wad_file) + auto blob = DiscIO::VolumeFileBlobReader::Create(*m_volume, m_partition, path); + if (!blob) { - ERROR_LOG(CORE, "Failed to get info for %s", path.c_str()); + ERROR_LOG(CORE, "Could not find %s", path.c_str()); return UpdateResult::DiscReadFailed; } - - const DiscIO::WiiWAD wad{DiscIO::VolumeFileBlobReader::Create(*m_volume, *m_disc_fs, path)}; + const DiscIO::WiiWAD wad{std::move(blob)}; return InstallWAD(m_ios, wad) ? UpdateResult::Succeeded : UpdateResult::ImportFailed; } diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index 310ca41e9a7c..e4f52713a50d 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -61,6 +61,17 @@ u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* f return read_length; } +u64 ReadFile(const Volume& volume, const Partition& partition, const std::string& path, u8* buffer, + u64 max_buffer_size, u64 offset_in_file) +{ + const FileSystem* file_system = volume.GetFileSystem(partition); + if (!file_system) + return 0; + + return ReadFile(volume, partition, file_system->FindFileInfo(path).get(), buffer, max_buffer_size, + offset_in_file); +} + bool ExportData(const Volume& volume, const Partition& partition, u64 offset, u64 size, const std::string& export_filename) { @@ -98,6 +109,16 @@ bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo export_filename); } +bool ExportFile(const Volume& volume, const Partition& partition, const std::string& path, + const std::string& export_filename) +{ + const FileSystem* file_system = volume.GetFileSystem(partition); + if (!file_system) + return false; + + return ExportFile(volume, partition, file_system->FindFileInfo(path).get(), export_filename); +} + void ExportDirectory(const Volume& volume, const Partition partition, const FileInfo& directory, bool recursive, const std::string& filesystem_path, const std::string& export_folder, diff --git a/Source/Core/DiscIO/DiscExtractor.h b/Source/Core/DiscIO/DiscExtractor.h index b3a1332c4b09..8157f2027356 100644 --- a/Source/Core/DiscIO/DiscExtractor.h +++ b/Source/Core/DiscIO/DiscExtractor.h @@ -19,10 +19,14 @@ std::string DirectoryNameForPartitionType(u32 partition_type); u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, u8* buffer, u64 max_buffer_size, u64 offset_in_file = 0); +u64 ReadFile(const Volume& volume, const Partition& partition, const std::string& path, u8* buffer, + u64 max_buffer_size, u64 offset_in_file = 0); bool ExportData(const Volume& volume, const Partition& partition, u64 offset, u64 size, const std::string& export_filename); bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, const std::string& export_filename); +bool ExportFile(const Volume& volume, const Partition& partition, const std::string& path, + const std::string& export_filename); // update_progress is called once for each child (file or directory). // If update_progress returns true, the extraction gets cancelled. diff --git a/Source/Core/DiscIO/DiscScrubber.cpp b/Source/Core/DiscIO/DiscScrubber.cpp index b2fc397eea2d..dac858fcdaa4 100644 --- a/Source/Core/DiscIO/DiscScrubber.cpp +++ b/Source/Core/DiscIO/DiscScrubber.cpp @@ -182,7 +182,7 @@ bool DiscScrubber::ParseDisc() // Operations dealing with encrypted space are done here bool DiscScrubber::ParsePartitionData(const Partition& partition, PartitionHeader* header) { - std::unique_ptr filesystem(CreateFileSystem(m_disc.get(), partition)); + const FileSystem* filesystem = m_disc->GetFileSystem(partition); if (!filesystem) { ERROR_LOG(DISCIO, "Failed to read file system for the partition at 0x%" PRIx64, diff --git a/Source/Core/DiscIO/Filesystem.cpp b/Source/Core/DiscIO/Filesystem.cpp index 6171c3004f08..4228afdb7276 100644 --- a/Source/Core/DiscIO/Filesystem.cpp +++ b/Source/Core/DiscIO/Filesystem.cpp @@ -4,7 +4,6 @@ #include "DiscIO/Filesystem.h" #include -#include "DiscIO/FileSystemGCWii.h" #include "DiscIO/Volume.h" namespace DiscIO @@ -18,20 +17,4 @@ FileSystem::FileSystem(const Volume* volume, const Partition& partition) FileSystem::~FileSystem() = default; -std::unique_ptr CreateFileSystem(const Volume* volume, const Partition& partition) -{ - if (!volume) - return nullptr; - - std::unique_ptr filesystem = std::make_unique(volume, partition); - - if (!filesystem) - return nullptr; - - if (!filesystem->IsValid()) - filesystem.reset(); - - return filesystem; -} - } // namespace diff --git a/Source/Core/DiscIO/Filesystem.h b/Source/Core/DiscIO/Filesystem.h index abfb19778c83..3193e6ca64ff 100644 --- a/Source/Core/DiscIO/Filesystem.h +++ b/Source/Core/DiscIO/Filesystem.h @@ -109,8 +109,7 @@ class FileSystem FileSystem(const Volume* volume, const Partition& partition); virtual ~FileSystem(); - // If IsValid is false, GetRoot must not be called. CreateFileSystem - // takes care of this automatically, so other code is recommended to use it. + // If IsValid is false, GetRoot must not be called. virtual bool IsValid() const = 0; // The object returned by GetRoot and all objects created from it // are only valid for as long as the file system object is valid. @@ -126,7 +125,8 @@ class FileSystem const Partition m_partition; }; -// Returns nullptr if a valid file system could not be created -std::unique_ptr CreateFileSystem(const Volume* volume, const Partition& partition); +// Calling Volume::GetFileSystem instead of manually constructing a filesystem is recommended, +// because it will check IsValid for you, will automatically pick the right type of filesystem, +// and will cache the filesystem in case it's needed again later. } // namespace diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index b4d2965f5a5b..2f075495a642 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -21,6 +21,7 @@ namespace DiscIO { enum class BlobType; +class FileSystem; struct Partition final { @@ -67,6 +68,8 @@ class Volume return INVALID_TICKET; } virtual const IOS::ES::TMDReader& GetTMD(const Partition& partition) const { return INVALID_TMD; } + // Returns a non-owning pointer. Returns nullptr if the file system couldn't be read. + virtual const FileSystem* GetFileSystem(const Partition& partition) const = 0; std::string GetGameID() const { return GetGameID(GetGamePartition()); } virtual std::string GetGameID(const Partition& partition) const = 0; std::string GetMakerID() const { return GetMakerID(GetGamePartition()); } diff --git a/Source/Core/DiscIO/VolumeFileBlobReader.cpp b/Source/Core/DiscIO/VolumeFileBlobReader.cpp index 5b243acc2933..a22800543644 100644 --- a/Source/Core/DiscIO/VolumeFileBlobReader.cpp +++ b/Source/Core/DiscIO/VolumeFileBlobReader.cpp @@ -10,23 +10,24 @@ namespace DiscIO { std::unique_ptr VolumeFileBlobReader::Create(const Volume& volume, - const FileSystem& file_system, + const Partition& partition, const std::string& file_path) { - if (!file_system.IsValid()) + const FileSystem* file_system = volume.GetFileSystem(partition); + if (!file_system) return nullptr; - std::unique_ptr file_info = file_system.FindFileInfo(file_path); + std::unique_ptr file_info = file_system->FindFileInfo(file_path); if (!file_info || file_info->IsDirectory()) return nullptr; return std::unique_ptr{ - new VolumeFileBlobReader(volume, file_system, std::move(file_info))}; + new VolumeFileBlobReader(volume, partition, std::move(file_info))}; } -VolumeFileBlobReader::VolumeFileBlobReader(const Volume& volume, const FileSystem& file_system, +VolumeFileBlobReader::VolumeFileBlobReader(const Volume& volume, const Partition& partition, std::unique_ptr file_info) - : m_volume(volume), m_file_system(file_system), m_file_info(std::move(file_info)) + : m_volume(volume), m_partition(partition), m_file_info(std::move(file_info)) { } @@ -45,7 +46,6 @@ bool VolumeFileBlobReader::Read(u64 offset, u64 length, u8* out_ptr) if (offset + length > m_file_info->GetSize()) return false; - return m_volume.Read(m_file_info->GetOffset() + offset, length, out_ptr, - m_file_system.GetPartition()); + return m_volume.Read(m_file_info->GetOffset() + offset, length, out_ptr, m_partition); } } // namespace diff --git a/Source/Core/DiscIO/VolumeFileBlobReader.h b/Source/Core/DiscIO/VolumeFileBlobReader.h index e915e035604e..46a988d367fb 100644 --- a/Source/Core/DiscIO/VolumeFileBlobReader.h +++ b/Source/Core/DiscIO/VolumeFileBlobReader.h @@ -13,14 +13,14 @@ namespace DiscIO { class FileInfo; -class FileSystem; +struct Partition; class Volume; class VolumeFileBlobReader final : public BlobReader { public: static std::unique_ptr - Create(const Volume& volume, const FileSystem& file_system, const std::string& file_path); + Create(const Volume& volume, const Partition& partition, const std::string& file_path); BlobType GetBlobType() const override { return BlobType::PLAIN; } u64 GetDataSize() const override; @@ -28,11 +28,11 @@ class VolumeFileBlobReader final : public BlobReader bool Read(u64 offset, u64 length, u8* out_ptr) override; private: - VolumeFileBlobReader(const Volume& volume, const FileSystem& file_system, + VolumeFileBlobReader(const Volume& volume, const Partition& partition, std::unique_ptr file_info); const Volume& m_volume; - const FileSystem& m_file_system; + const Partition& m_partition; std::unique_ptr m_file_info; }; } // namespace diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index 46ac57278c7a..01dbd3cfd3ad 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include #include @@ -20,6 +21,7 @@ #include "DiscIO/Blob.h" #include "DiscIO/DiscExtractor.h" #include "DiscIO/Enums.h" +#include "DiscIO/FileSystemGCWii.h" #include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" #include "DiscIO/VolumeGC.h" @@ -29,6 +31,11 @@ namespace DiscIO VolumeGC::VolumeGC(std::unique_ptr reader) : m_pReader(std::move(reader)) { _assert_(m_pReader); + + m_file_system = [this]() -> std::unique_ptr { + auto file_system = std::make_unique(this, PARTITION_NONE); + return file_system->IsValid() ? std::move(file_system) : nullptr; + }; } VolumeGC::~VolumeGC() @@ -43,6 +50,11 @@ bool VolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer, const Partition& par return m_pReader->Read(_Offset, _Length, _pBuffer); } +const FileSystem* VolumeGC::GetFileSystem(const Partition& partition) const +{ + return m_file_system->get(); +} + std::string VolumeGC::GetGameID(const Partition& partition) const { static const std::string NO_UID("NO_UID"); @@ -192,30 +204,16 @@ void VolumeGC::LoadBannerFile() const m_banner_loaded = true; GCBanner banner_file; - std::unique_ptr file_system(CreateFileSystem(this, PARTITION_NONE)); - if (!file_system) - return; - - std::unique_ptr file_info = file_system->FindFileInfo("opening.bnr"); - if (!file_info) - return; - - size_t file_size = static_cast(file_info->GetSize()); - constexpr int BNR1_MAGIC = 0x31524e42; - constexpr int BNR2_MAGIC = 0x32524e42; - if (file_size != BNR1_SIZE && file_size != BNR2_SIZE) - { - WARN_LOG(DISCIO, "Invalid opening.bnr. Size: %0zx", file_size); - return; - } - - if (file_size != ReadFile(*this, PARTITION_NONE, file_info.get(), - reinterpret_cast(&banner_file), file_size)) + const u64 file_size = ReadFile(*this, PARTITION_NONE, "opening.bnr", + reinterpret_cast(&banner_file), sizeof(GCBanner)); + if (file_size < 4) { WARN_LOG(DISCIO, "Could not read opening.bnr."); - return; + return; // Return early so that we don't access the uninitialized banner_file.id } + constexpr u32 BNR1_MAGIC = 0x31524e42; + constexpr u32 BNR2_MAGIC = 0x32524e42; bool is_bnr1; if (banner_file.id == BNR1_MAGIC && file_size == BNR1_SIZE) { diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index f41d58cbcbd3..846c01731cae 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -11,6 +11,8 @@ #include #include "Common/CommonTypes.h" +#include "Common/Lazy.h" +#include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" // --- this volume type is used for GC disc images --- @@ -20,6 +22,7 @@ namespace DiscIO class BlobReader; enum class BlobType; enum class Country; +class FileSystem; enum class Language; enum class Region; enum class Platform; @@ -31,6 +34,7 @@ class VolumeGC : public Volume ~VolumeGC(); bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, const Partition& partition = PARTITION_NONE) const override; + const FileSystem* GetFileSystem(const Partition& partition = PARTITION_NONE) const override; std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override; std::optional GetRevision(const Partition& partition = PARTITION_NONE) const override; @@ -93,6 +97,8 @@ class VolumeGC : public Volume mutable int m_image_height = 0; mutable int m_image_width = 0; + Common::Lazy> m_file_system; + std::unique_ptr m_pReader; }; diff --git a/Source/Core/DiscIO/VolumeWad.cpp b/Source/Core/DiscIO/VolumeWad.cpp index 42c0a45bfdf8..4b45f0b706f8 100644 --- a/Source/Core/DiscIO/VolumeWad.cpp +++ b/Source/Core/DiscIO/VolumeWad.cpp @@ -65,6 +65,12 @@ bool VolumeWAD::Read(u64 offset, u64 length, u8* buffer, const Partition& partit return m_reader->Read(offset, length, buffer); } +const FileSystem* VolumeWAD::GetFileSystem(const Partition& partition) const +{ + // TODO: Implement this? + return nullptr; +} + Region VolumeWAD::GetRegion() const { if (!m_tmd.IsValid()) diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h index d1964bcfa1e9..a97f2d078ef9 100644 --- a/Source/Core/DiscIO/VolumeWad.h +++ b/Source/Core/DiscIO/VolumeWad.h @@ -23,6 +23,7 @@ namespace DiscIO class BlobReader; enum class BlobType; enum class Country; +class FileSystem; enum class Language; enum class Region; enum class Platform; @@ -34,6 +35,7 @@ class VolumeWAD : public Volume ~VolumeWAD(); bool Read(u64 offset, u64 length, u8* buffer, const Partition& partition = PARTITION_NONE) const override; + const FileSystem* GetFileSystem(const Partition& partition = PARTITION_NONE) const override; std::optional GetTitleID(const Partition& partition = PARTITION_NONE) const override; const IOS::ES::TMDReader& GetTMD(const Partition& partition = PARTITION_NONE) const override; std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; diff --git a/Source/Core/DiscIO/VolumeWii.cpp b/Source/Core/DiscIO/VolumeWii.cpp index bce96822e7e8..0ed2200f14a6 100644 --- a/Source/Core/DiscIO/VolumeWii.cpp +++ b/Source/Core/DiscIO/VolumeWii.cpp @@ -26,6 +26,7 @@ #include "DiscIO/Blob.h" #include "DiscIO/DiscExtractor.h" #include "DiscIO/Enums.h" +#include "DiscIO/FileSystemGCWii.h" #include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" @@ -111,10 +112,17 @@ VolumeWii::VolumeWii(std::unique_ptr reader) return aes_context; }; + auto get_file_system = [this, partition]() -> std::unique_ptr { + auto file_system = std::make_unique(this, partition); + return file_system->IsValid() ? std::move(file_system) : nullptr; + }; + m_partitions.emplace( partition, PartitionDetails{Common::Lazy>(get_key), Common::Lazy(get_ticket), - Common::Lazy(get_tmd), *partition_type}); + Common::Lazy(get_tmd), + Common::Lazy>(get_file_system), + *partition_type}); } } } @@ -220,6 +228,12 @@ const IOS::ES::TMDReader& VolumeWii::GetTMD(const Partition& partition) const return it != m_partitions.end() ? *it->second.tmd : INVALID_TMD; } +const FileSystem* VolumeWii::GetFileSystem(const Partition& partition) const +{ + auto it = m_partitions.find(partition); + return it != m_partitions.end() ? it->second.file_system->get() : nullptr; +} + u64 VolumeWii::PartitionOffsetToRawOffset(u64 offset, const Partition& partition) { if (partition == PARTITION_NONE) @@ -287,13 +301,8 @@ std::string VolumeWii::GetInternalName(const Partition& partition) const std::map VolumeWii::GetLongNames() const { - std::unique_ptr file_system(CreateFileSystem(this, GetGamePartition())); - if (!file_system) - return {}; - std::vector opening_bnr(NAMES_TOTAL_BYTES); - std::unique_ptr file_info = file_system->FindFileInfo("opening.bnr"); - opening_bnr.resize(ReadFile(*this, GetGamePartition(), file_info.get(), opening_bnr.data(), + opening_bnr.resize(ReadFile(*this, GetGamePartition(), "opening.bnr", opening_bnr.data(), opening_bnr.size(), 0x5C)); return ReadWiiNames(opening_bnr); } diff --git a/Source/Core/DiscIO/VolumeWii.h b/Source/Core/DiscIO/VolumeWii.h index e702e316ae58..97604887a3a3 100644 --- a/Source/Core/DiscIO/VolumeWii.h +++ b/Source/Core/DiscIO/VolumeWii.h @@ -14,15 +14,17 @@ #include "Common/CommonTypes.h" #include "Common/Lazy.h" #include "Core/IOS/ES/Formats.h" +#include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" -// --- this volume type is used for encrypted Wii images --- +// --- this volume type is used for Wii disc images --- namespace DiscIO { class BlobReader; enum class BlobType; enum class Country; +class FileSystem; enum class Language; enum class Region; enum class Platform; @@ -39,6 +41,7 @@ class VolumeWii : public Volume std::optional GetTitleID(const Partition& partition) const override; const IOS::ES::TicketReader& GetTicket(const Partition& partition) const override; const IOS::ES::TMDReader& GetTMD(const Partition& partition) const override; + const FileSystem* GetFileSystem(const Partition& partition) const override; std::string GetGameID(const Partition& partition) const override; std::string GetMakerID(const Partition& partition) const override; std::optional GetRevision(const Partition& partition) const override; @@ -72,6 +75,7 @@ class VolumeWii : public Volume Common::Lazy> key; Common::Lazy ticket; Common::Lazy tmd; + Common::Lazy> file_system; u32 type; }; diff --git a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp index 9888036d2a56..8b3d815af0dd 100644 --- a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp +++ b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp @@ -36,11 +36,8 @@ namespace class WiiPartition final : public wxTreeItemData { public: - WiiPartition(std::unique_ptr filesystem_) : filesystem{std::move(filesystem_)} - { - } - - std::unique_ptr filesystem; + WiiPartition(const DiscIO::Partition& partition_) : partition(partition_) {} + DiscIO::Partition partition; }; enum : int @@ -86,6 +83,13 @@ void CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent, } } +void CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent, + const DiscIO::FileSystem* file_system) +{ + if (file_system) + CreateDirectoryTree(tree_ctrl, parent, file_system->GetRoot()); +} + WiiPartition* FindWiiPartition(wxTreeCtrl* tree_ctrl, const wxString& label) { wxTreeItemIdValue cookie; @@ -154,30 +158,22 @@ bool FilesystemPanel::PopulateFileSystemTree() { for (size_t i = 0; i < partitions.size(); ++i) { - std::unique_ptr file_system( - DiscIO::CreateFileSystem(m_opened_iso.get(), partitions[i])); - if (file_system) - { - wxTreeItemId partition_root = m_tree_ctrl->AppendItem( - m_tree_ctrl->GetRootItem(), wxString::Format(_("Partition %zu"), i), ICON_DISC); + wxTreeItemId partition_root = m_tree_ctrl->AppendItem( + m_tree_ctrl->GetRootItem(), wxString::Format(_("Partition %zu"), i), ICON_DISC); - WiiPartition* const partition = new WiiPartition(std::move(file_system)); + WiiPartition* const partition = new WiiPartition(partitions[i]); - m_tree_ctrl->SetItemData(partition_root, partition); - CreateDirectoryTree(m_tree_ctrl, partition_root, partition->filesystem->GetRoot()); + m_tree_ctrl->SetItemData(partition_root, partition); + CreateDirectoryTree(m_tree_ctrl, partition_root, m_opened_iso->GetFileSystem(partitions[i])); - if (partitions[i] == m_opened_iso->GetGamePartition()) - m_tree_ctrl->Expand(partition_root); - } + if (partitions[i] == m_opened_iso->GetGamePartition()) + m_tree_ctrl->Expand(partition_root); } } else { - m_filesystem = DiscIO::CreateFileSystem(m_opened_iso.get(), DiscIO::PARTITION_NONE); - if (!m_filesystem) - return false; - - CreateDirectoryTree(m_tree_ctrl, m_tree_ctrl->GetRootItem(), m_filesystem->GetRoot()); + CreateDirectoryTree(m_tree_ctrl, m_tree_ctrl->GetRootItem(), + m_opened_iso->GetFileSystem(DiscIO::PARTITION_NONE)); } return true; @@ -256,7 +252,7 @@ void FilesystemPanel::OnExtractSystemData(wxCommandEvent& event) const auto* const selection_data = m_tree_ctrl->GetItemData(m_tree_ctrl->GetSelection()); const auto* const wii_partition = static_cast(selection_data); - partition = wii_partition->filesystem->GetPartition(); + partition = wii_partition->partition; } else { @@ -293,11 +289,11 @@ void FilesystemPanel::OnExtractAll(wxCommandEvent& event) { const auto* const partition = static_cast(m_tree_ctrl->GetItemData(item)); const std::optional partition_type = - *m_opened_iso->GetPartitionType(partition->filesystem->GetPartition()); + *m_opened_iso->GetPartitionType(partition->partition); if (partition_type) { const std::string partition_name = DiscIO::DirectoryNameForPartitionType(*partition_type); - ExtractPartition(std_extract_path + '/' + partition_name, *partition->filesystem); + ExtractPartition(std_extract_path + '/' + partition_name, partition->partition); } item = m_tree_ctrl->GetNextChild(root, cookie); } @@ -305,11 +301,11 @@ void FilesystemPanel::OnExtractAll(wxCommandEvent& event) else if (m_has_partitions && !first_item_selected) { const auto* const partition = static_cast(m_tree_ctrl->GetItemData(selection)); - ExtractPartition(std_extract_path, *partition->filesystem); + ExtractPartition(std_extract_path, partition->partition); } else { - ExtractPartition(std_extract_path, *m_filesystem); + ExtractPartition(std_extract_path, DiscIO::PARTITION_NONE); } } @@ -326,9 +322,8 @@ void FilesystemPanel::OnCheckPartitionIntegrity(wxCommandEvent& WXUNUSED(event)) const auto selection = m_tree_ctrl->GetSelection(); WiiPartition* partition = static_cast(m_tree_ctrl->GetItemData(m_tree_ctrl->GetSelection())); - std::future is_valid = std::async(std::launch::async, [&] { - return m_opened_iso->CheckIntegrity(partition->filesystem->GetPartition()); - }); + std::future is_valid = std::async( + std::launch::async, [&] { return m_opened_iso->CheckIntegrity(partition->partition); }); while (is_valid.wait_for(std::chrono::milliseconds(50)) != std::future_status::ready) dialog.Pulse(); @@ -350,23 +345,26 @@ void FilesystemPanel::OnCheckPartitionIntegrity(wxCommandEvent& WXUNUSED(event)) void FilesystemPanel::ExtractSingleFile(const wxString& output_file_path) const { - const std::pair path = BuildFilePathFromSelection(); - DiscIO::ExportFile(*m_opened_iso, path.second.GetPartition(), - path.second.FindFileInfo(WxStrToStr(path.first)).get(), + const std::pair path = BuildFilePathFromSelection(); + DiscIO::ExportFile(*m_opened_iso, path.second, WxStrToStr(path.first), WxStrToStr(output_file_path)); } void FilesystemPanel::ExtractSingleDirectory(const wxString& output_folder) { - const std::pair path = BuildDirectoryPathFromSelection(); + const std::pair path = BuildDirectoryPathFromSelection(); ExtractDirectories(WxStrToStr(path.first), WxStrToStr(output_folder), path.second); } void FilesystemPanel::ExtractDirectories(const std::string& full_path, const std::string& output_folder, - const DiscIO::FileSystem& filesystem) + const DiscIO::Partition& partition) { - std::unique_ptr file_info = filesystem.FindFileInfo(full_path); + const DiscIO::FileSystem* file_system = m_opened_iso->GetFileSystem(partition); + if (!file_system) + return; + + std::unique_ptr file_info = file_system->FindFileInfo(full_path); u32 size = file_info->GetTotalChildren(); u32 progress = 0; @@ -376,7 +374,7 @@ void FilesystemPanel::ExtractDirectories(const std::string& full_path, wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH); DiscIO::ExportDirectory( - *m_opened_iso, filesystem.GetPartition(), *file_info, true, full_path, output_folder, + *m_opened_iso, partition, *file_info, true, full_path, output_folder, [&](const std::string& path) { dialog.SetTitle(wxString::Format( "%s : %d%%", dialog_title.c_str(), @@ -388,13 +386,13 @@ void FilesystemPanel::ExtractDirectories(const std::string& full_path, } void FilesystemPanel::ExtractPartition(const std::string& output_folder, - const DiscIO::FileSystem& filesystem) + const DiscIO::Partition& partition) { - ExtractDirectories("", output_folder + "/files", filesystem); - DiscIO::ExportSystemData(*m_opened_iso, filesystem.GetPartition(), output_folder); + ExtractDirectories("", output_folder + "/files", partition); + DiscIO::ExportSystemData(*m_opened_iso, partition, output_folder); } -std::pair FilesystemPanel::BuildFilePathFromSelection() const +std::pair FilesystemPanel::BuildFilePathFromSelection() const { const wxTreeItemId root_node = m_tree_ctrl->GetRootItem(); wxTreeItemId node = m_tree_ctrl->GetSelection(); @@ -417,22 +415,21 @@ std::pair FilesystemPanel::BuildFilePathFro { const size_t slash_index = file_path.find('/'); const wxString partition_label = file_path.substr(0, slash_index); - const auto* const partition = FindWiiPartition(m_tree_ctrl, partition_label); + const WiiPartition* const partition = FindWiiPartition(m_tree_ctrl, partition_label); // Remove "Partition x/" file_path.erase(0, slash_index + 1); - return {file_path, *partition->filesystem}; + return {file_path, partition->partition}; } else { - return {file_path, *m_filesystem}; + return {file_path, DiscIO::PARTITION_NONE}; } } -std::pair -FilesystemPanel::BuildDirectoryPathFromSelection() const +std::pair FilesystemPanel::BuildDirectoryPathFromSelection() const { - const std::pair result = BuildFilePathFromSelection(); + const std::pair result = BuildFilePathFromSelection(); return {result.first + DIR_SEP_CHR, result.second}; } diff --git a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.h b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.h index 59da51ce9544..353afdcca126 100644 --- a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.h +++ b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.h @@ -15,7 +15,7 @@ class wxTreeEvent; namespace DiscIO { -class FileSystem; +struct Partition; class Volume; } @@ -51,16 +51,15 @@ class FilesystemPanel final : public wxPanel void ExtractSingleFile(const wxString& output_file_path) const; void ExtractSingleDirectory(const wxString& output_folder); void ExtractDirectories(const std::string& full_path, const std::string& output_folder, - const DiscIO::FileSystem& filesystem); - void ExtractPartition(const std::string& output_folder, const DiscIO::FileSystem& filesystem); + const DiscIO::Partition& partition); + void ExtractPartition(const std::string& output_folder, const DiscIO::Partition& partition); - std::pair BuildFilePathFromSelection() const; - std::pair BuildDirectoryPathFromSelection() const; + std::pair BuildFilePathFromSelection() const; + std::pair BuildDirectoryPathFromSelection() const; wxTreeCtrl* m_tree_ctrl; const std::unique_ptr& m_opened_iso; - std::unique_ptr m_filesystem; bool m_has_partitions; }; From ca36c977d9617ba188907bbe2ff2922fce121972 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 2 Aug 2017 18:34:44 +0200 Subject: [PATCH 2/3] DiscIO: Remove m_partition and m_volume from FileSystem The last commit made m_partition unnecessary, and m_volume has been unnecessary ever since the PR that added DiscExtractor. --- Source/Core/DiscIO/FileSystemGCWii.cpp | 12 ++++++------ Source/Core/DiscIO/Filesystem.cpp | 7 ------- Source/Core/DiscIO/Filesystem.h | 6 ------ 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/Source/Core/DiscIO/FileSystemGCWii.cpp b/Source/Core/DiscIO/FileSystemGCWii.cpp index 55afc907c978..e243d0ec72b1 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/FileSystemGCWii.cpp @@ -185,19 +185,19 @@ bool FileInfoGCWii::IsValid(u64 fst_size, const FileInfoGCWii& parent_directory) } FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partition) - : FileSystem(volume, partition), m_valid(false), m_root(nullptr, 0, 0, 0) + : m_valid(false), m_root(nullptr, 0, 0, 0) { u8 offset_shift; // Check if this is a GameCube or Wii disc - if (m_volume->ReadSwapped(0x18, m_partition) == u32(0x5D1C9EA3)) + if (volume->ReadSwapped(0x18, partition) == u32(0x5D1C9EA3)) offset_shift = 2; // Wii file system - else if (m_volume->ReadSwapped(0x1c, m_partition) == u32(0xC2339F3D)) + else if (volume->ReadSwapped(0x1c, partition) == u32(0xC2339F3D)) offset_shift = 0; // GameCube file system else return; // Invalid partition (maybe someone removed its data but not its partition table entry) - const std::optional fst_offset = GetFSTOffset(*m_volume, m_partition); - const std::optional fst_size = GetFSTSize(*m_volume, m_partition); + const std::optional fst_offset = GetFSTOffset(*volume, partition); + const std::optional fst_size = GetFSTSize(*volume, partition); if (!fst_offset || !fst_size) return; if (*fst_size < FST_ENTRY_SIZE) @@ -220,7 +220,7 @@ FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partitio // Read the whole FST m_file_system_table.resize(*fst_size); - if (!m_volume->Read(*fst_offset, *fst_size, m_file_system_table.data(), m_partition)) + if (!volume->Read(*fst_offset, *fst_size, m_file_system_table.data(), partition)) { ERROR_LOG(DISCIO, "Couldn't read file system table"); return; diff --git a/Source/Core/DiscIO/Filesystem.cpp b/Source/Core/DiscIO/Filesystem.cpp index 4228afdb7276..9e5336db5d1e 100644 --- a/Source/Core/DiscIO/Filesystem.cpp +++ b/Source/Core/DiscIO/Filesystem.cpp @@ -3,18 +3,11 @@ // Refer to the license.txt file included. #include "DiscIO/Filesystem.h" -#include -#include "DiscIO/Volume.h" namespace DiscIO { FileInfo::~FileInfo() = default; -FileSystem::FileSystem(const Volume* volume, const Partition& partition) - : m_volume(volume), m_partition(partition) -{ -} - FileSystem::~FileSystem() = default; } // namespace diff --git a/Source/Core/DiscIO/Filesystem.h b/Source/Core/DiscIO/Filesystem.h index 3193e6ca64ff..8d2adbd0a2fb 100644 --- a/Source/Core/DiscIO/Filesystem.h +++ b/Source/Core/DiscIO/Filesystem.h @@ -106,7 +106,6 @@ class FileInfo class FileSystem { public: - FileSystem(const Volume* volume, const Partition& partition); virtual ~FileSystem(); // If IsValid is false, GetRoot must not be called. @@ -118,11 +117,6 @@ class FileSystem virtual std::unique_ptr FindFileInfo(const std::string& path) const = 0; // Returns nullptr if not found virtual std::unique_ptr FindFileInfo(u64 disc_offset) const = 0; - - virtual const Partition GetPartition() const { return m_partition; } -protected: - const Volume* const m_volume; - const Partition m_partition; }; // Calling Volume::GetFileSystem instead of manually constructing a filesystem is recommended, From f294599e734f2391db9e74b6454752e75fdf368c Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 2 Aug 2017 19:06:32 +0200 Subject: [PATCH 3/3] DiscIO: Use Common::Lazy for loading GC banners --- Source/Core/DiscIO/VolumeGC.cpp | 65 +++++++++---------- Source/Core/DiscIO/VolumeGC.h | 29 +++++---- .../DolphinQt2/Config/FilesystemWidget.cpp | 17 ++--- 3 files changed, 51 insertions(+), 60 deletions(-) diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index 01dbd3cfd3ad..b61d273388b4 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -36,6 +36,8 @@ VolumeGC::VolumeGC(std::unique_ptr reader) : m_pReader(std::move(rea auto file_system = std::make_unique(this, PARTITION_NONE); return file_system->IsValid() ? std::move(file_system) : nullptr; }; + + m_converted_banner = [this] { return LoadBannerFile(); }; } VolumeGC::~VolumeGC() @@ -125,40 +127,34 @@ std::string VolumeGC::GetInternalName(const Partition& partition) const std::map VolumeGC::GetShortNames() const { - LoadBannerFile(); - return m_short_names; + return m_converted_banner->short_names; } std::map VolumeGC::GetLongNames() const { - LoadBannerFile(); - return m_long_names; + return m_converted_banner->long_names; } std::map VolumeGC::GetShortMakers() const { - LoadBannerFile(); - return m_short_makers; + return m_converted_banner->short_makers; } std::map VolumeGC::GetLongMakers() const { - LoadBannerFile(); - return m_long_makers; + return m_converted_banner->long_makers; } std::map VolumeGC::GetDescriptions() const { - LoadBannerFile(); - return m_descriptions; + return m_converted_banner->descriptions; } std::vector VolumeGC::GetBanner(int* width, int* height) const { - LoadBannerFile(); - *width = m_image_width; - *height = m_image_height; - return m_image_buffer; + *width = m_converted_banner->image_width; + *height = m_converted_banner->image_height; + return m_converted_banner->image_buffer; } std::string VolumeGC::GetApploaderDate(const Partition& partition) const @@ -195,21 +191,15 @@ Platform VolumeGC::GetVolumeType() const return Platform::GAMECUBE_DISC; } -void VolumeGC::LoadBannerFile() const +VolumeGC::ConvertedGCBanner VolumeGC::LoadBannerFile() const { - // If opening.bnr has been loaded already, return immediately - if (m_banner_loaded) - return; - - m_banner_loaded = true; - GCBanner banner_file; const u64 file_size = ReadFile(*this, PARTITION_NONE, "opening.bnr", reinterpret_cast(&banner_file), sizeof(GCBanner)); if (file_size < 4) { WARN_LOG(DISCIO, "Could not read opening.bnr."); - return; // Return early so that we don't access the uninitialized banner_file.id + return {}; // Return early so that we don't access the uninitialized banner_file.id } constexpr u32 BNR1_MAGIC = 0x31524e42; @@ -226,14 +216,17 @@ void VolumeGC::LoadBannerFile() const else { WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0zx", banner_file.id, file_size); - return; + return {}; } - ExtractBannerInformation(banner_file, is_bnr1); + return ExtractBannerInformation(banner_file, is_bnr1); } -void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const +VolumeGC::ConvertedGCBanner VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, + bool is_bnr1) const { + ConvertedGCBanner banner; + u32 number_of_languages = 0; Language start_language = Language::LANGUAGE_UNKNOWN; @@ -249,11 +242,11 @@ void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr start_language = Language::LANGUAGE_ENGLISH; } - m_image_width = GC_BANNER_WIDTH; - m_image_height = GC_BANNER_HEIGHT; - m_image_buffer = std::vector(m_image_width * m_image_height); - ColorUtil::decode5A3image(m_image_buffer.data(), banner_file.image, m_image_width, - m_image_height); + banner.image_width = GC_BANNER_WIDTH; + banner.image_height = GC_BANNER_HEIGHT; + banner.image_buffer = std::vector(GC_BANNER_WIDTH * GC_BANNER_HEIGHT); + ColorUtil::decode5A3image(banner.image_buffer.data(), banner_file.image, GC_BANNER_WIDTH, + GC_BANNER_HEIGHT); for (u32 i = 0; i < number_of_languages; ++i) { @@ -262,24 +255,26 @@ void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr std::string description = DecodeString(info.description); if (!description.empty()) - m_descriptions[language] = description; + banner.descriptions.emplace(language, description); std::string short_name = DecodeString(info.short_name); if (!short_name.empty()) - m_short_names[language] = short_name; + banner.short_names.emplace(language, short_name); std::string long_name = DecodeString(info.long_name); if (!long_name.empty()) - m_long_names[language] = long_name; + banner.long_names.emplace(language, long_name); std::string short_maker = DecodeString(info.short_maker); if (!short_maker.empty()) - m_short_makers[language] = short_maker; + banner.short_makers.emplace(language, short_maker); std::string long_maker = DecodeString(info.long_maker); if (!long_maker.empty()) - m_long_makers[language] = long_maker; + banner.long_makers.emplace(language, long_maker); } + + return banner; } } // namespace diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index 846c01731cae..3ba9fdb6fc95 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -79,23 +79,26 @@ class VolumeGC : public Volume // (only one for BNR1 type) }; - void LoadBannerFile() const; - void ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const; + struct ConvertedGCBanner + { + std::map short_names; + std::map long_names; + std::map short_makers; + std::map long_makers; + std::map descriptions; + + std::vector image_buffer; + int image_height = 0; + int image_width = 0; + }; + + ConvertedGCBanner LoadBannerFile() const; + ConvertedGCBanner ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const; static const size_t BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerInformation) * 5; static const size_t BNR2_SIZE = sizeof(GCBanner); - mutable std::map m_short_names; - - mutable std::map m_long_names; - mutable std::map m_short_makers; - mutable std::map m_long_makers; - mutable std::map m_descriptions; - - mutable bool m_banner_loaded = false; - mutable std::vector m_image_buffer; - mutable int m_image_height = 0; - mutable int m_image_width = 0; + Common::Lazy m_converted_banner; Common::Lazy> m_file_system; diff --git a/Source/Core/DolphinQt2/Config/FilesystemWidget.cpp b/Source/Core/DolphinQt2/Config/FilesystemWidget.cpp index efb67a2fa700..0b9fc9e0e68a 100644 --- a/Source/Core/DolphinQt2/Config/FilesystemWidget.cpp +++ b/Source/Core/DolphinQt2/Config/FilesystemWidget.cpp @@ -85,8 +85,7 @@ void FilesystemWidget::PopulateView() for (size_t i = 0; i < partitions.size(); i++) { - std::unique_ptr file_system( - DiscIO::CreateFileSystem(m_volume.get(), partitions[i])); + const DiscIO::FileSystem* file_system = m_volume->GetFileSystem(partitions[i]); auto* item = new QStandardItem(tr("Partition %1").arg(i)); item->setEditable(false); @@ -104,10 +103,7 @@ void FilesystemWidget::PopulateView() } if (partitions.empty()) - { - PopulateDirectory(-1, disc, - DiscIO::CreateFileSystem(m_volume.get(), DiscIO::PARTITION_NONE)->GetRoot()); - } + PopulateDirectory(-1, disc, m_volume->GetFileSystem(DiscIO::PARTITION_NONE)->GetRoot()); } void FilesystemWidget::PopulateDirectory(int partition_id, QStandardItem* root, @@ -237,9 +233,7 @@ void FilesystemWidget::ExtractSystemData(const DiscIO::Partition& partition, con void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, const QString path, const QString& out) { - std::unique_ptr filesystem( - DiscIO::CreateFileSystem(m_volume.get(), partition)); - + const DiscIO::FileSystem* filesystem = m_volume->GetFileSystem(partition); std::unique_ptr info = filesystem->FindFileInfo(path.toStdString()); u32 size = info->GetTotalChildren(); @@ -251,7 +245,7 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons bool all = path.isEmpty(); DiscIO::ExportDirectory( - *m_volume, filesystem->GetPartition(), *info, true, path.toStdString(), out.toStdString(), + *m_volume, partition, *info, true, path.toStdString(), out.toStdString(), [all, dialog](const std::string& current) { dialog->setLabelText( (all ? QObject::tr("Extracting All Files...") : QObject::tr("Extracting Directory...")) @@ -268,8 +262,7 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons void FilesystemWidget::ExtractFile(const DiscIO::Partition& partition, const QString& path, const QString& out) { - std::unique_ptr filesystem( - DiscIO::CreateFileSystem(m_volume.get(), partition)); + const DiscIO::FileSystem* filesystem = m_volume->GetFileSystem(partition); bool success = DiscIO::ExportFile( *m_volume, partition, filesystem->FindFileInfo(path.toStdString()).get(), out.toStdString());