From 38304da947c6b593ef94449894dc018aac633344 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 2 Aug 2017 18:16:56 +0200 Subject: [PATCH] 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 322d4bfeac..f19d5187cb 100644 --- a/Source/Core/Common/Lazy.h +++ b/Source/Core/Common/Lazy.h @@ -21,6 +21,16 @@ public: 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 221a95a451..ebaecbce7e 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 cc50d0ef61..2f4dc49652 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 f51fc70221..2b170f5082 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 14d2024dd0..639c05da06 100644 --- a/Source/Core/Core/WiiUtils.cpp +++ b/Source/Core/Core/WiiUtils.cpp @@ -552,7 +552,7 @@ private: 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 310ca41e9a..e4f52713a5 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 b3a1332c4b..8157f20273 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 b2fc397eea..dac858fcda 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 6171c3004f..4228afdb72 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 abfb19778c..3193e6ca64 100644 --- a/Source/Core/DiscIO/Filesystem.h +++ b/Source/Core/DiscIO/Filesystem.h @@ -109,8 +109,7 @@ public: 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 @@ protected: 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 b4d2965f5a..2f075495a6 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 @@ public: 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 5b243acc29..a228005436 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 e915e03560..46a988d367 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 @@ public: 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 46ac57278c..01dbd3cfd3 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 f41d58cbcb..846c01731c 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 @@ public: ~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 @@ private: 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 42c0a45bfd..4b45f0b706 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 d1964bcfa1..a97f2d078e 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 @@ public: ~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 bce96822e7..0ed2200f14 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 e702e316ae..97604887a3 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 @@ public: 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 @@ private: 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 9888036d2a..8b3d815af0 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 59da51ce95..353afdcca1 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 @@ private: 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; };