mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 17:19:44 -06:00
DiscIO: Use Common::Lazy for loading filesystems
This simplifies FileMonitor a lot and also lets us clean up FilesystemPanel.
This commit is contained in:
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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> 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,
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "DiscIO/Filesystem.h"
|
||||
#include <memory>
|
||||
#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<FileSystem> CreateFileSystem(const Volume* volume, const Partition& partition)
|
||||
{
|
||||
if (!volume)
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<FileSystem> filesystem = std::make_unique<FileSystemGCWii>(volume, partition);
|
||||
|
||||
if (!filesystem)
|
||||
return nullptr;
|
||||
|
||||
if (!filesystem->IsValid())
|
||||
filesystem.reset();
|
||||
|
||||
return filesystem;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -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<FileSystem> 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
|
||||
|
@ -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()); }
|
||||
|
@ -10,23 +10,24 @@
|
||||
namespace DiscIO
|
||||
{
|
||||
std::unique_ptr<VolumeFileBlobReader> 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<FileInfo> file_info = file_system.FindFileInfo(file_path);
|
||||
std::unique_ptr<FileInfo> file_info = file_system->FindFileInfo(file_path);
|
||||
if (!file_info || file_info->IsDirectory())
|
||||
return nullptr;
|
||||
|
||||
return std::unique_ptr<VolumeFileBlobReader>{
|
||||
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<FileInfo> 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
|
||||
|
@ -13,14 +13,14 @@
|
||||
namespace DiscIO
|
||||
{
|
||||
class FileInfo;
|
||||
class FileSystem;
|
||||
struct Partition;
|
||||
class Volume;
|
||||
|
||||
class VolumeFileBlobReader final : public BlobReader
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<VolumeFileBlobReader>
|
||||
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<FileInfo> file_info);
|
||||
|
||||
const Volume& m_volume;
|
||||
const FileSystem& m_file_system;
|
||||
const Partition& m_partition;
|
||||
std::unique_ptr<FileInfo> m_file_info;
|
||||
};
|
||||
} // namespace
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@ -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<BlobReader> reader) : m_pReader(std::move(reader))
|
||||
{
|
||||
_assert_(m_pReader);
|
||||
|
||||
m_file_system = [this]() -> std::unique_ptr<FileSystem> {
|
||||
auto file_system = std::make_unique<FileSystemGCWii>(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<FileSystem> file_system(CreateFileSystem(this, PARTITION_NONE));
|
||||
if (!file_system)
|
||||
return;
|
||||
|
||||
std::unique_ptr<FileInfo> file_info = file_system->FindFileInfo("opening.bnr");
|
||||
if (!file_info)
|
||||
return;
|
||||
|
||||
size_t file_size = static_cast<size_t>(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<u8*>(&banner_file), file_size))
|
||||
const u64 file_size = ReadFile(*this, PARTITION_NONE, "opening.bnr",
|
||||
reinterpret_cast<u8*>(&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)
|
||||
{
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <vector>
|
||||
|
||||
#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<u16> 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<std::unique_ptr<FileSystem>> m_file_system;
|
||||
|
||||
std::unique_ptr<BlobReader> m_pReader;
|
||||
};
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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<u64> 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;
|
||||
|
@ -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<BlobReader> reader)
|
||||
return aes_context;
|
||||
};
|
||||
|
||||
auto get_file_system = [this, partition]() -> std::unique_ptr<FileSystem> {
|
||||
auto file_system = std::make_unique<FileSystemGCWii>(this, partition);
|
||||
return file_system->IsValid() ? std::move(file_system) : nullptr;
|
||||
};
|
||||
|
||||
m_partitions.emplace(
|
||||
partition, PartitionDetails{Common::Lazy<std::unique_ptr<mbedtls_aes_context>>(get_key),
|
||||
Common::Lazy<IOS::ES::TicketReader>(get_ticket),
|
||||
Common::Lazy<IOS::ES::TMDReader>(get_tmd), *partition_type});
|
||||
Common::Lazy<IOS::ES::TMDReader>(get_tmd),
|
||||
Common::Lazy<std::unique_ptr<FileSystem>>(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<Language, std::string> VolumeWii::GetLongNames() const
|
||||
{
|
||||
std::unique_ptr<FileSystem> file_system(CreateFileSystem(this, GetGamePartition()));
|
||||
if (!file_system)
|
||||
return {};
|
||||
|
||||
std::vector<u8> opening_bnr(NAMES_TOTAL_BYTES);
|
||||
std::unique_ptr<FileInfo> 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);
|
||||
}
|
||||
|
@ -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<u64> 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<u16> GetRevision(const Partition& partition) const override;
|
||||
@ -72,6 +75,7 @@ private:
|
||||
Common::Lazy<std::unique_ptr<mbedtls_aes_context>> key;
|
||||
Common::Lazy<IOS::ES::TicketReader> ticket;
|
||||
Common::Lazy<IOS::ES::TMDReader> tmd;
|
||||
Common::Lazy<std::unique_ptr<FileSystem>> file_system;
|
||||
u32 type;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user