DiscIO: Use Common::Lazy for loading filesystems
This simplifies FileMonitor a lot and also lets us clean up FilesystemPanel.
This commit is contained in:
parent
0d07821935
commit
38304da947
|
@ -21,6 +21,16 @@ public:
|
|||
Lazy() : m_value(T()) {}
|
||||
Lazy(const std::variant<T, std::function<T()>>& value) : m_value(value) {}
|
||||
Lazy(std::variant<T, std::function<T()>>&& value) : m_value(std::move(value)) {}
|
||||
const Lazy<T>& operator=(const std::variant<T, std::function<T()>>& value)
|
||||
{
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
const Lazy<T>& operator=(std::variant<T, std::function<T()>>&& value)
|
||||
{
|
||||
m_value = std::move(value);
|
||||
return *this;
|
||||
}
|
||||
const T& operator*() const { return *ComputeValue(); }
|
||||
const T* operator->() const { return ComputeValue(); }
|
||||
T& operator*() { return *ComputeValue(); }
|
||||
|
|
|
@ -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<DiscIO::Volume> 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<u8> buffer(request.length);
|
||||
if (!s_disc->Read(request.dvd_offset, request.length, buffer.data(), request.partition))
|
||||
|
|
|
@ -21,10 +21,7 @@
|
|||
|
||||
namespace FileMonitor
|
||||
{
|
||||
static const DiscIO::Volume* s_volume;
|
||||
static bool s_new_volume = false;
|
||||
static std::unique_ptr<DiscIO::FileSystem> 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<DiscIO::FileInfo> file_info = s_filesystem->FindFileInfo(offset);
|
||||
const std::unique_ptr<DiscIO::FileInfo> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -552,7 +552,7 @@ private:
|
|||
|
||||
UpdateCallback m_update_callback;
|
||||
std::unique_ptr<DiscIO::Volume> m_volume;
|
||||
std::unique_ptr<DiscIO::FileSystem> 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<DiscIO::FileInfo> 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<DiscIO::FileInfo> 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<DiscIO::FileInfo> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -36,11 +36,8 @@ namespace
|
|||
class WiiPartition final : public wxTreeItemData
|
||||
{
|
||||
public:
|
||||
WiiPartition(std::unique_ptr<DiscIO::FileSystem> filesystem_) : filesystem{std::move(filesystem_)}
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<DiscIO::FileSystem> 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<DiscIO::FileSystem> 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<const WiiPartition*>(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<WiiPartition*>(m_tree_ctrl->GetItemData(item));
|
||||
const std::optional<u32> 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<WiiPartition*>(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<WiiPartition*>(m_tree_ctrl->GetItemData(m_tree_ctrl->GetSelection()));
|
||||
std::future<bool> is_valid = std::async(std::launch::async, [&] {
|
||||
return m_opened_iso->CheckIntegrity(partition->filesystem->GetPartition());
|
||||
});
|
||||
std::future<bool> 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<wxString, const DiscIO::FileSystem&> path = BuildFilePathFromSelection();
|
||||
DiscIO::ExportFile(*m_opened_iso, path.second.GetPartition(),
|
||||
path.second.FindFileInfo(WxStrToStr(path.first)).get(),
|
||||
const std::pair<wxString, DiscIO::Partition> 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<wxString, const DiscIO::FileSystem&> path = BuildDirectoryPathFromSelection();
|
||||
const std::pair<wxString, DiscIO::Partition> 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<DiscIO::FileInfo> file_info = filesystem.FindFileInfo(full_path);
|
||||
const DiscIO::FileSystem* file_system = m_opened_iso->GetFileSystem(partition);
|
||||
if (!file_system)
|
||||
return;
|
||||
|
||||
std::unique_ptr<DiscIO::FileInfo> 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<wxString, const DiscIO::FileSystem&> FilesystemPanel::BuildFilePathFromSelection() const
|
||||
std::pair<wxString, DiscIO::Partition> FilesystemPanel::BuildFilePathFromSelection() const
|
||||
{
|
||||
const wxTreeItemId root_node = m_tree_ctrl->GetRootItem();
|
||||
wxTreeItemId node = m_tree_ctrl->GetSelection();
|
||||
|
@ -417,22 +415,21 @@ std::pair<wxString, const DiscIO::FileSystem&> 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<wxString, const DiscIO::FileSystem&>
|
||||
FilesystemPanel::BuildDirectoryPathFromSelection() const
|
||||
std::pair<wxString, DiscIO::Partition> FilesystemPanel::BuildDirectoryPathFromSelection() const
|
||||
{
|
||||
const std::pair<wxString, const DiscIO::FileSystem&> result = BuildFilePathFromSelection();
|
||||
const std::pair<wxString, DiscIO::Partition> result = BuildFilePathFromSelection();
|
||||
return {result.first + DIR_SEP_CHR, result.second};
|
||||
}
|
||||
|
|
|
@ -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<wxString, const DiscIO::FileSystem&> BuildFilePathFromSelection() const;
|
||||
std::pair<wxString, const DiscIO::FileSystem&> BuildDirectoryPathFromSelection() const;
|
||||
std::pair<wxString, DiscIO::Partition> BuildFilePathFromSelection() const;
|
||||
std::pair<wxString, DiscIO::Partition> BuildDirectoryPathFromSelection() const;
|
||||
|
||||
wxTreeCtrl* m_tree_ctrl;
|
||||
|
||||
const std::unique_ptr<DiscIO::Volume>& m_opened_iso;
|
||||
|
||||
std::unique_ptr<DiscIO::FileSystem> m_filesystem;
|
||||
bool m_has_partitions;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue