Merge pull request #5870 from JosJuice/lazy-filesystem
DiscIO: Use Common::Lazy more
This commit is contained in:
commit
7cb8d6612c
|
@ -21,6 +21,16 @@ public:
|
||||||
Lazy() : m_value(T()) {}
|
Lazy() : m_value(T()) {}
|
||||||
Lazy(const std::variant<T, std::function<T()>>& value) : m_value(value) {}
|
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)) {}
|
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(); }
|
||||||
const T* operator->() const { return ComputeValue(); }
|
const T* operator->() const { return ComputeValue(); }
|
||||||
T& operator*() { return *ComputeValue(); }
|
T& operator*() { return *ComputeValue(); }
|
||||||
|
|
|
@ -116,7 +116,6 @@ void Stop()
|
||||||
{
|
{
|
||||||
StopDVDThread();
|
StopDVDThread();
|
||||||
s_disc.reset();
|
s_disc.reset();
|
||||||
FileMonitor::SetFileSystem(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StopDVDThread()
|
static void StopDVDThread()
|
||||||
|
@ -160,14 +159,9 @@ void DoState(PointerWrap& p)
|
||||||
if (had_disc != HasDisc())
|
if (had_disc != HasDisc())
|
||||||
{
|
{
|
||||||
if (had_disc)
|
if (had_disc)
|
||||||
{
|
|
||||||
PanicAlertT("An inserted disc was expected but not found.");
|
PanicAlertT("An inserted disc was expected but not found.");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
s_disc.reset();
|
s_disc.reset();
|
||||||
FileMonitor::SetFileSystem(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Savestates can be smaller if the buffers of results aren't saved,
|
// 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();
|
WaitUntilIdle();
|
||||||
s_disc = std::move(disc);
|
s_disc = std::move(disc);
|
||||||
FileMonitor::SetFileSystem(s_disc.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasDisc()
|
bool HasDisc()
|
||||||
|
@ -356,7 +349,7 @@ static void DVDThread()
|
||||||
ReadRequest request;
|
ReadRequest request;
|
||||||
while (s_request_queue.Pop(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);
|
std::vector<u8> buffer(request.length);
|
||||||
if (!s_disc->Read(request.dvd_offset, request.length, buffer.data(), request.partition))
|
if (!s_disc->Read(request.dvd_offset, request.length, buffer.data(), request.partition))
|
||||||
|
|
|
@ -21,10 +21,7 @@
|
||||||
|
|
||||||
namespace FileMonitor
|
namespace FileMonitor
|
||||||
{
|
{
|
||||||
static const DiscIO::Volume* s_volume;
|
static DiscIO::Partition s_previous_partition;
|
||||||
static bool s_new_volume = false;
|
|
||||||
static std::unique_ptr<DiscIO::FileSystem> s_filesystem;
|
|
||||||
static DiscIO::Partition s_partition;
|
|
||||||
static std::string s_previous_file;
|
static std::string s_previous_file;
|
||||||
|
|
||||||
// Filtered files
|
// Filtered files
|
||||||
|
@ -53,42 +50,19 @@ static bool IsSoundFile(const std::string& filename)
|
||||||
return extensions.find(extension) != extensions.end();
|
return extensions.find(extension) != extensions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFileSystem(const DiscIO::Volume* volume)
|
void Log(const DiscIO::Volume& volume, const DiscIO::Partition& partition, u64 offset)
|
||||||
{
|
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
// Do nothing if the log isn't selected
|
// Do nothing if the log isn't selected
|
||||||
if (!LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON, LogTypes::LWARNING))
|
if (!LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON, LogTypes::LWARNING))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the volume or partition changed, load the filesystem of the new partition
|
const DiscIO::FileSystem* file_system = volume.GetFileSystem(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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do nothing if there is no valid file system
|
// Do nothing if there is no valid file system
|
||||||
if (!s_filesystem)
|
if (!file_system)
|
||||||
return;
|
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
|
// Do nothing if no file was found at that offset
|
||||||
if (!file_info)
|
if (!file_info)
|
||||||
|
@ -97,7 +71,7 @@ void Log(u64 offset, const DiscIO::Partition& partition)
|
||||||
const std::string path = file_info->GetPath();
|
const std::string path = file_info->GetPath();
|
||||||
|
|
||||||
// Do nothing if we found the same file again
|
// Do nothing if we found the same file again
|
||||||
if (s_previous_file == path)
|
if (s_previous_partition == partition && s_previous_file == path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::string size_string = ThousandSeparate(file_info->GetSize() / 1000, 7);
|
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());
|
WARN_LOG(FILEMON, "%s", log_string.c_str());
|
||||||
|
|
||||||
// Update the last accessed file
|
// Update the last accessed file
|
||||||
|
s_previous_partition = partition;
|
||||||
s_previous_file = path;
|
s_previous_file = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,5 @@ class Volume;
|
||||||
|
|
||||||
namespace FileMonitor
|
namespace FileMonitor
|
||||||
{
|
{
|
||||||
// Can be called with nullptr to set the file system to nothing. When not called
|
void Log(const DiscIO::Volume& volume, const DiscIO::Partition& partition, u64 offset);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,7 +552,7 @@ private:
|
||||||
|
|
||||||
UpdateCallback m_update_callback;
|
UpdateCallback m_update_callback;
|
||||||
std::unique_ptr<DiscIO::Volume> m_volume;
|
std::unique_ptr<DiscIO::Volume> m_volume;
|
||||||
std::unique_ptr<DiscIO::FileSystem> m_disc_fs;
|
DiscIO::Partition m_partition;
|
||||||
};
|
};
|
||||||
|
|
||||||
UpdateResult DiscSystemUpdater::DoDiscUpdate()
|
UpdateResult DiscSystemUpdater::DoDiscUpdate()
|
||||||
|
@ -578,16 +578,21 @@ UpdateResult DiscSystemUpdater::DoDiscUpdate()
|
||||||
return UpdateResult::MissingUpdatePartition;
|
return UpdateResult::MissingUpdatePartition;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_disc_fs = DiscIO::CreateFileSystem(m_volume.get(), *update_partition);
|
m_partition = *update_partition;
|
||||||
if (!m_disc_fs || !m_disc_fs->IsValid())
|
|
||||||
return UpdateResult::DiscReadFailed;
|
|
||||||
|
|
||||||
return UpdateFromManifest("__update.inf");
|
return UpdateFromManifest("__update.inf");
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateResult DiscSystemUpdater::UpdateFromManifest(const std::string& manifest_name)
|
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 ||
|
if (!update_manifest ||
|
||||||
(update_manifest->GetSize() - sizeof(ManifestHeader)) % sizeof(Entry) != 0)
|
(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)
|
for (u32 i = 0; i < num_entries; ++i)
|
||||||
{
|
{
|
||||||
const u32 offset = sizeof(ManifestHeader) + sizeof(Entry) * i;
|
const u32 offset = sizeof(ManifestHeader) + sizeof(Entry) * i;
|
||||||
if (entry.size() != DiscIO::ReadFile(*m_volume, m_disc_fs->GetPartition(),
|
if (entry.size() != DiscIO::ReadFile(*m_volume, m_partition, update_manifest.get(),
|
||||||
update_manifest.get(), entry.data(), entry.size(), offset))
|
entry.data(), entry.size(), offset))
|
||||||
{
|
{
|
||||||
ERROR_LOG(CORE, "Failed to read update information from update manifest");
|
ERROR_LOG(CORE, "Failed to read update information from update manifest");
|
||||||
return UpdateResult::DiscReadFailed;
|
return UpdateResult::DiscReadFailed;
|
||||||
|
@ -654,14 +659,13 @@ UpdateResult DiscSystemUpdater::ProcessEntry(u32 type, std::bitset<32> attrs,
|
||||||
return UpdateResult::AlreadyUpToDate;
|
return UpdateResult::AlreadyUpToDate;
|
||||||
|
|
||||||
// Import the WAD.
|
// Import the WAD.
|
||||||
const std::unique_ptr<DiscIO::FileInfo> wad_file = m_disc_fs->FindFileInfo(path);
|
auto blob = DiscIO::VolumeFileBlobReader::Create(*m_volume, m_partition, path);
|
||||||
if (!wad_file)
|
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;
|
return UpdateResult::DiscReadFailed;
|
||||||
}
|
}
|
||||||
|
const DiscIO::WiiWAD wad{std::move(blob)};
|
||||||
const DiscIO::WiiWAD wad{DiscIO::VolumeFileBlobReader::Create(*m_volume, *m_disc_fs, path)};
|
|
||||||
return InstallWAD(m_ios, wad) ? UpdateResult::Succeeded : UpdateResult::ImportFailed;
|
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;
|
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,
|
bool ExportData(const Volume& volume, const Partition& partition, u64 offset, u64 size,
|
||||||
const std::string& export_filename)
|
const std::string& export_filename)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +109,16 @@ bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo
|
||||||
export_filename);
|
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,
|
void ExportDirectory(const Volume& volume, const Partition partition, const FileInfo& directory,
|
||||||
bool recursive, const std::string& filesystem_path,
|
bool recursive, const std::string& filesystem_path,
|
||||||
const std::string& export_folder,
|
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,
|
u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* file_info,
|
||||||
u8* buffer, u64 max_buffer_size, u64 offset_in_file = 0);
|
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,
|
bool ExportData(const Volume& volume, const Partition& partition, u64 offset, u64 size,
|
||||||
const std::string& export_filename);
|
const std::string& export_filename);
|
||||||
bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo* file_info,
|
bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo* file_info,
|
||||||
const std::string& export_filename);
|
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).
|
// update_progress is called once for each child (file or directory).
|
||||||
// If update_progress returns true, the extraction gets cancelled.
|
// If update_progress returns true, the extraction gets cancelled.
|
||||||
|
|
|
@ -182,7 +182,7 @@ bool DiscScrubber::ParseDisc()
|
||||||
// Operations dealing with encrypted space are done here
|
// Operations dealing with encrypted space are done here
|
||||||
bool DiscScrubber::ParsePartitionData(const Partition& partition, PartitionHeader* header)
|
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)
|
if (!filesystem)
|
||||||
{
|
{
|
||||||
ERROR_LOG(DISCIO, "Failed to read file system for the partition at 0x%" PRIx64,
|
ERROR_LOG(DISCIO, "Failed to read file system for the partition at 0x%" PRIx64,
|
||||||
|
|
|
@ -185,19 +185,19 @@ bool FileInfoGCWii::IsValid(u64 fst_size, const FileInfoGCWii& parent_directory)
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partition)
|
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;
|
u8 offset_shift;
|
||||||
// Check if this is a GameCube or Wii disc
|
// Check if this is a GameCube or Wii disc
|
||||||
if (m_volume->ReadSwapped<u32>(0x18, m_partition) == u32(0x5D1C9EA3))
|
if (volume->ReadSwapped<u32>(0x18, partition) == u32(0x5D1C9EA3))
|
||||||
offset_shift = 2; // Wii file system
|
offset_shift = 2; // Wii file system
|
||||||
else if (m_volume->ReadSwapped<u32>(0x1c, m_partition) == u32(0xC2339F3D))
|
else if (volume->ReadSwapped<u32>(0x1c, partition) == u32(0xC2339F3D))
|
||||||
offset_shift = 0; // GameCube file system
|
offset_shift = 0; // GameCube file system
|
||||||
else
|
else
|
||||||
return; // Invalid partition (maybe someone removed its data but not its partition table entry)
|
return; // Invalid partition (maybe someone removed its data but not its partition table entry)
|
||||||
|
|
||||||
const std::optional<u64> fst_offset = GetFSTOffset(*m_volume, m_partition);
|
const std::optional<u64> fst_offset = GetFSTOffset(*volume, partition);
|
||||||
const std::optional<u64> fst_size = GetFSTSize(*m_volume, m_partition);
|
const std::optional<u64> fst_size = GetFSTSize(*volume, partition);
|
||||||
if (!fst_offset || !fst_size)
|
if (!fst_offset || !fst_size)
|
||||||
return;
|
return;
|
||||||
if (*fst_size < FST_ENTRY_SIZE)
|
if (*fst_size < FST_ENTRY_SIZE)
|
||||||
|
@ -220,7 +220,7 @@ FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partitio
|
||||||
|
|
||||||
// Read the whole FST
|
// Read the whole FST
|
||||||
m_file_system_table.resize(*fst_size);
|
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");
|
ERROR_LOG(DISCIO, "Couldn't read file system table");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,35 +3,11 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "DiscIO/Filesystem.h"
|
#include "DiscIO/Filesystem.h"
|
||||||
#include <memory>
|
|
||||||
#include "DiscIO/FileSystemGCWii.h"
|
|
||||||
#include "DiscIO/Volume.h"
|
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
FileInfo::~FileInfo() = default;
|
FileInfo::~FileInfo() = default;
|
||||||
|
|
||||||
FileSystem::FileSystem(const Volume* volume, const Partition& partition)
|
|
||||||
: m_volume(volume), m_partition(partition)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FileSystem::~FileSystem() = default;
|
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
|
} // namespace
|
||||||
|
|
|
@ -106,11 +106,9 @@ protected:
|
||||||
class FileSystem
|
class FileSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileSystem(const Volume* volume, const Partition& partition);
|
|
||||||
virtual ~FileSystem();
|
virtual ~FileSystem();
|
||||||
|
|
||||||
// If IsValid is false, GetRoot must not be called. CreateFileSystem
|
// If IsValid is false, GetRoot must not be called.
|
||||||
// takes care of this automatically, so other code is recommended to use it.
|
|
||||||
virtual bool IsValid() const = 0;
|
virtual bool IsValid() const = 0;
|
||||||
// The object returned by GetRoot and all objects created from it
|
// The object returned by GetRoot and all objects created from it
|
||||||
// are only valid for as long as the file system object is valid.
|
// are only valid for as long as the file system object is valid.
|
||||||
|
@ -119,14 +117,10 @@ public:
|
||||||
virtual std::unique_ptr<FileInfo> FindFileInfo(const std::string& path) const = 0;
|
virtual std::unique_ptr<FileInfo> FindFileInfo(const std::string& path) const = 0;
|
||||||
// Returns nullptr if not found
|
// Returns nullptr if not found
|
||||||
virtual std::unique_ptr<FileInfo> FindFileInfo(u64 disc_offset) const = 0;
|
virtual std::unique_ptr<FileInfo> FindFileInfo(u64 disc_offset) const = 0;
|
||||||
|
|
||||||
virtual const Partition GetPartition() const { return m_partition; }
|
|
||||||
protected:
|
|
||||||
const Volume* const m_volume;
|
|
||||||
const Partition m_partition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns nullptr if a valid file system could not be created
|
// Calling Volume::GetFileSystem instead of manually constructing a filesystem is recommended,
|
||||||
std::unique_ptr<FileSystem> CreateFileSystem(const Volume* volume, const Partition& partition);
|
// 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
|
} // namespace
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
enum class BlobType;
|
enum class BlobType;
|
||||||
|
class FileSystem;
|
||||||
|
|
||||||
struct Partition final
|
struct Partition final
|
||||||
{
|
{
|
||||||
|
@ -67,6 +68,8 @@ public:
|
||||||
return INVALID_TICKET;
|
return INVALID_TICKET;
|
||||||
}
|
}
|
||||||
virtual const IOS::ES::TMDReader& GetTMD(const Partition& partition) const { return INVALID_TMD; }
|
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()); }
|
std::string GetGameID() const { return GetGameID(GetGamePartition()); }
|
||||||
virtual std::string GetGameID(const Partition& partition) const = 0;
|
virtual std::string GetGameID(const Partition& partition) const = 0;
|
||||||
std::string GetMakerID() const { return GetMakerID(GetGamePartition()); }
|
std::string GetMakerID() const { return GetMakerID(GetGamePartition()); }
|
||||||
|
|
|
@ -10,23 +10,24 @@
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
std::unique_ptr<VolumeFileBlobReader> VolumeFileBlobReader::Create(const Volume& volume,
|
std::unique_ptr<VolumeFileBlobReader> VolumeFileBlobReader::Create(const Volume& volume,
|
||||||
const FileSystem& file_system,
|
const Partition& partition,
|
||||||
const std::string& file_path)
|
const std::string& file_path)
|
||||||
{
|
{
|
||||||
if (!file_system.IsValid())
|
const FileSystem* file_system = volume.GetFileSystem(partition);
|
||||||
|
if (!file_system)
|
||||||
return nullptr;
|
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())
|
if (!file_info || file_info->IsDirectory())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return std::unique_ptr<VolumeFileBlobReader>{
|
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)
|
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())
|
if (offset + length > m_file_info->GetSize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return m_volume.Read(m_file_info->GetOffset() + offset, length, out_ptr,
|
return m_volume.Read(m_file_info->GetOffset() + offset, length, out_ptr, m_partition);
|
||||||
m_file_system.GetPartition());
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
class FileInfo;
|
class FileInfo;
|
||||||
class FileSystem;
|
struct Partition;
|
||||||
class Volume;
|
class Volume;
|
||||||
|
|
||||||
class VolumeFileBlobReader final : public BlobReader
|
class VolumeFileBlobReader final : public BlobReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<VolumeFileBlobReader>
|
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; }
|
BlobType GetBlobType() const override { return BlobType::PLAIN; }
|
||||||
u64 GetDataSize() const override;
|
u64 GetDataSize() const override;
|
||||||
|
@ -28,11 +28,11 @@ public:
|
||||||
bool Read(u64 offset, u64 length, u8* out_ptr) override;
|
bool Read(u64 offset, u64 length, u8* out_ptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VolumeFileBlobReader(const Volume& volume, const FileSystem& file_system,
|
VolumeFileBlobReader(const Volume& volume, const Partition& partition,
|
||||||
std::unique_ptr<FileInfo> file_info);
|
std::unique_ptr<FileInfo> file_info);
|
||||||
|
|
||||||
const Volume& m_volume;
|
const Volume& m_volume;
|
||||||
const FileSystem& m_file_system;
|
const Partition& m_partition;
|
||||||
std::unique_ptr<FileInfo> m_file_info;
|
std::unique_ptr<FileInfo> m_file_info;
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/DiscExtractor.h"
|
#include "DiscIO/DiscExtractor.h"
|
||||||
#include "DiscIO/Enums.h"
|
#include "DiscIO/Enums.h"
|
||||||
|
#include "DiscIO/FileSystemGCWii.h"
|
||||||
#include "DiscIO/Filesystem.h"
|
#include "DiscIO/Filesystem.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
#include "DiscIO/VolumeGC.h"
|
#include "DiscIO/VolumeGC.h"
|
||||||
|
@ -29,6 +31,13 @@ namespace DiscIO
|
||||||
VolumeGC::VolumeGC(std::unique_ptr<BlobReader> reader) : m_pReader(std::move(reader))
|
VolumeGC::VolumeGC(std::unique_ptr<BlobReader> reader) : m_pReader(std::move(reader))
|
||||||
{
|
{
|
||||||
_assert_(m_pReader);
|
_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;
|
||||||
|
};
|
||||||
|
|
||||||
|
m_converted_banner = [this] { return LoadBannerFile(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeGC::~VolumeGC()
|
VolumeGC::~VolumeGC()
|
||||||
|
@ -43,6 +52,11 @@ bool VolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer, const Partition& par
|
||||||
return m_pReader->Read(_Offset, _Length, _pBuffer);
|
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
|
std::string VolumeGC::GetGameID(const Partition& partition) const
|
||||||
{
|
{
|
||||||
static const std::string NO_UID("NO_UID");
|
static const std::string NO_UID("NO_UID");
|
||||||
|
@ -113,40 +127,34 @@ std::string VolumeGC::GetInternalName(const Partition& partition) const
|
||||||
|
|
||||||
std::map<Language, std::string> VolumeGC::GetShortNames() const
|
std::map<Language, std::string> VolumeGC::GetShortNames() const
|
||||||
{
|
{
|
||||||
LoadBannerFile();
|
return m_converted_banner->short_names;
|
||||||
return m_short_names;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<Language, std::string> VolumeGC::GetLongNames() const
|
std::map<Language, std::string> VolumeGC::GetLongNames() const
|
||||||
{
|
{
|
||||||
LoadBannerFile();
|
return m_converted_banner->long_names;
|
||||||
return m_long_names;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<Language, std::string> VolumeGC::GetShortMakers() const
|
std::map<Language, std::string> VolumeGC::GetShortMakers() const
|
||||||
{
|
{
|
||||||
LoadBannerFile();
|
return m_converted_banner->short_makers;
|
||||||
return m_short_makers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<Language, std::string> VolumeGC::GetLongMakers() const
|
std::map<Language, std::string> VolumeGC::GetLongMakers() const
|
||||||
{
|
{
|
||||||
LoadBannerFile();
|
return m_converted_banner->long_makers;
|
||||||
return m_long_makers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<Language, std::string> VolumeGC::GetDescriptions() const
|
std::map<Language, std::string> VolumeGC::GetDescriptions() const
|
||||||
{
|
{
|
||||||
LoadBannerFile();
|
return m_converted_banner->descriptions;
|
||||||
return m_descriptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u32> VolumeGC::GetBanner(int* width, int* height) const
|
std::vector<u32> VolumeGC::GetBanner(int* width, int* height) const
|
||||||
{
|
{
|
||||||
LoadBannerFile();
|
*width = m_converted_banner->image_width;
|
||||||
*width = m_image_width;
|
*height = m_converted_banner->image_height;
|
||||||
*height = m_image_height;
|
return m_converted_banner->image_buffer;
|
||||||
return m_image_buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VolumeGC::GetApploaderDate(const Partition& partition) const
|
std::string VolumeGC::GetApploaderDate(const Partition& partition) const
|
||||||
|
@ -183,39 +191,19 @@ Platform VolumeGC::GetVolumeType() const
|
||||||
return Platform::GAMECUBE_DISC;
|
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;
|
GCBanner banner_file;
|
||||||
std::unique_ptr<FileSystem> file_system(CreateFileSystem(this, PARTITION_NONE));
|
const u64 file_size = ReadFile(*this, PARTITION_NONE, "opening.bnr",
|
||||||
if (!file_system)
|
reinterpret_cast<u8*>(&banner_file), sizeof(GCBanner));
|
||||||
return;
|
if (file_size < 4)
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
WARN_LOG(DISCIO, "Could not read opening.bnr.");
|
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;
|
bool is_bnr1;
|
||||||
if (banner_file.id == BNR1_MAGIC && file_size == BNR1_SIZE)
|
if (banner_file.id == BNR1_MAGIC && file_size == BNR1_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -228,14 +216,17 @@ void VolumeGC::LoadBannerFile() const
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0zx", banner_file.id, file_size);
|
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;
|
u32 number_of_languages = 0;
|
||||||
Language start_language = Language::LANGUAGE_UNKNOWN;
|
Language start_language = Language::LANGUAGE_UNKNOWN;
|
||||||
|
|
||||||
|
@ -251,11 +242,11 @@ void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr
|
||||||
start_language = Language::LANGUAGE_ENGLISH;
|
start_language = Language::LANGUAGE_ENGLISH;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_image_width = GC_BANNER_WIDTH;
|
banner.image_width = GC_BANNER_WIDTH;
|
||||||
m_image_height = GC_BANNER_HEIGHT;
|
banner.image_height = GC_BANNER_HEIGHT;
|
||||||
m_image_buffer = std::vector<u32>(m_image_width * m_image_height);
|
banner.image_buffer = std::vector<u32>(GC_BANNER_WIDTH * GC_BANNER_HEIGHT);
|
||||||
ColorUtil::decode5A3image(m_image_buffer.data(), banner_file.image, m_image_width,
|
ColorUtil::decode5A3image(banner.image_buffer.data(), banner_file.image, GC_BANNER_WIDTH,
|
||||||
m_image_height);
|
GC_BANNER_HEIGHT);
|
||||||
|
|
||||||
for (u32 i = 0; i < number_of_languages; ++i)
|
for (u32 i = 0; i < number_of_languages; ++i)
|
||||||
{
|
{
|
||||||
|
@ -264,24 +255,26 @@ void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr
|
||||||
|
|
||||||
std::string description = DecodeString(info.description);
|
std::string description = DecodeString(info.description);
|
||||||
if (!description.empty())
|
if (!description.empty())
|
||||||
m_descriptions[language] = description;
|
banner.descriptions.emplace(language, description);
|
||||||
|
|
||||||
std::string short_name = DecodeString(info.short_name);
|
std::string short_name = DecodeString(info.short_name);
|
||||||
if (!short_name.empty())
|
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);
|
std::string long_name = DecodeString(info.long_name);
|
||||||
if (!long_name.empty())
|
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);
|
std::string short_maker = DecodeString(info.short_maker);
|
||||||
if (!short_maker.empty())
|
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);
|
std::string long_maker = DecodeString(info.long_maker);
|
||||||
if (!long_maker.empty())
|
if (!long_maker.empty())
|
||||||
m_long_makers[language] = long_maker;
|
banner.long_makers.emplace(language, long_maker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return banner;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Lazy.h"
|
||||||
|
#include "DiscIO/Filesystem.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
|
|
||||||
// --- this volume type is used for GC disc images ---
|
// --- this volume type is used for GC disc images ---
|
||||||
|
@ -20,6 +22,7 @@ namespace DiscIO
|
||||||
class BlobReader;
|
class BlobReader;
|
||||||
enum class BlobType;
|
enum class BlobType;
|
||||||
enum class Country;
|
enum class Country;
|
||||||
|
class FileSystem;
|
||||||
enum class Language;
|
enum class Language;
|
||||||
enum class Region;
|
enum class Region;
|
||||||
enum class Platform;
|
enum class Platform;
|
||||||
|
@ -31,6 +34,7 @@ public:
|
||||||
~VolumeGC();
|
~VolumeGC();
|
||||||
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer,
|
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer,
|
||||||
const Partition& partition = PARTITION_NONE) const override;
|
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 GetGameID(const Partition& partition = PARTITION_NONE) const override;
|
||||||
std::string GetMakerID(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;
|
std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const override;
|
||||||
|
@ -75,23 +79,28 @@ private:
|
||||||
// (only one for BNR1 type)
|
// (only one for BNR1 type)
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoadBannerFile() const;
|
struct ConvertedGCBanner
|
||||||
void ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const;
|
{
|
||||||
|
std::map<Language, std::string> short_names;
|
||||||
|
std::map<Language, std::string> long_names;
|
||||||
|
std::map<Language, std::string> short_makers;
|
||||||
|
std::map<Language, std::string> long_makers;
|
||||||
|
std::map<Language, std::string> descriptions;
|
||||||
|
|
||||||
|
std::vector<u32> 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 BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerInformation) * 5;
|
||||||
static const size_t BNR2_SIZE = sizeof(GCBanner);
|
static const size_t BNR2_SIZE = sizeof(GCBanner);
|
||||||
|
|
||||||
mutable std::map<Language, std::string> m_short_names;
|
Common::Lazy<ConvertedGCBanner> m_converted_banner;
|
||||||
|
|
||||||
mutable std::map<Language, std::string> m_long_names;
|
Common::Lazy<std::unique_ptr<FileSystem>> m_file_system;
|
||||||
mutable std::map<Language, std::string> m_short_makers;
|
|
||||||
mutable std::map<Language, std::string> m_long_makers;
|
|
||||||
mutable std::map<Language, std::string> m_descriptions;
|
|
||||||
|
|
||||||
mutable bool m_banner_loaded = false;
|
|
||||||
mutable std::vector<u32> m_image_buffer;
|
|
||||||
mutable int m_image_height = 0;
|
|
||||||
mutable int m_image_width = 0;
|
|
||||||
|
|
||||||
std::unique_ptr<BlobReader> m_pReader;
|
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);
|
return m_reader->Read(offset, length, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FileSystem* VolumeWAD::GetFileSystem(const Partition& partition) const
|
||||||
|
{
|
||||||
|
// TODO: Implement this?
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Region VolumeWAD::GetRegion() const
|
Region VolumeWAD::GetRegion() const
|
||||||
{
|
{
|
||||||
if (!m_tmd.IsValid())
|
if (!m_tmd.IsValid())
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace DiscIO
|
||||||
class BlobReader;
|
class BlobReader;
|
||||||
enum class BlobType;
|
enum class BlobType;
|
||||||
enum class Country;
|
enum class Country;
|
||||||
|
class FileSystem;
|
||||||
enum class Language;
|
enum class Language;
|
||||||
enum class Region;
|
enum class Region;
|
||||||
enum class Platform;
|
enum class Platform;
|
||||||
|
@ -34,6 +35,7 @@ public:
|
||||||
~VolumeWAD();
|
~VolumeWAD();
|
||||||
bool Read(u64 offset, u64 length, u8* buffer,
|
bool Read(u64 offset, u64 length, u8* buffer,
|
||||||
const Partition& partition = PARTITION_NONE) const override;
|
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;
|
std::optional<u64> GetTitleID(const Partition& partition = PARTITION_NONE) const override;
|
||||||
const IOS::ES::TMDReader& GetTMD(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;
|
std::string GetGameID(const Partition& partition = PARTITION_NONE) const override;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/DiscExtractor.h"
|
#include "DiscIO/DiscExtractor.h"
|
||||||
#include "DiscIO/Enums.h"
|
#include "DiscIO/Enums.h"
|
||||||
|
#include "DiscIO/FileSystemGCWii.h"
|
||||||
#include "DiscIO/Filesystem.h"
|
#include "DiscIO/Filesystem.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
|
|
||||||
|
@ -111,10 +112,17 @@ VolumeWii::VolumeWii(std::unique_ptr<BlobReader> reader)
|
||||||
return aes_context;
|
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(
|
m_partitions.emplace(
|
||||||
partition, PartitionDetails{Common::Lazy<std::unique_ptr<mbedtls_aes_context>>(get_key),
|
partition, PartitionDetails{Common::Lazy<std::unique_ptr<mbedtls_aes_context>>(get_key),
|
||||||
Common::Lazy<IOS::ES::TicketReader>(get_ticket),
|
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;
|
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)
|
u64 VolumeWii::PartitionOffsetToRawOffset(u64 offset, const Partition& partition)
|
||||||
{
|
{
|
||||||
if (partition == PARTITION_NONE)
|
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::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::vector<u8> opening_bnr(NAMES_TOTAL_BYTES);
|
||||||
std::unique_ptr<FileInfo> file_info = file_system->FindFileInfo("opening.bnr");
|
opening_bnr.resize(ReadFile(*this, GetGamePartition(), "opening.bnr", opening_bnr.data(),
|
||||||
opening_bnr.resize(ReadFile(*this, GetGamePartition(), file_info.get(), opening_bnr.data(),
|
|
||||||
opening_bnr.size(), 0x5C));
|
opening_bnr.size(), 0x5C));
|
||||||
return ReadWiiNames(opening_bnr);
|
return ReadWiiNames(opening_bnr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,15 +14,17 @@
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Lazy.h"
|
#include "Common/Lazy.h"
|
||||||
#include "Core/IOS/ES/Formats.h"
|
#include "Core/IOS/ES/Formats.h"
|
||||||
|
#include "DiscIO/Filesystem.h"
|
||||||
#include "DiscIO/Volume.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
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
class BlobReader;
|
class BlobReader;
|
||||||
enum class BlobType;
|
enum class BlobType;
|
||||||
enum class Country;
|
enum class Country;
|
||||||
|
class FileSystem;
|
||||||
enum class Language;
|
enum class Language;
|
||||||
enum class Region;
|
enum class Region;
|
||||||
enum class Platform;
|
enum class Platform;
|
||||||
|
@ -39,6 +41,7 @@ public:
|
||||||
std::optional<u64> GetTitleID(const Partition& partition) const override;
|
std::optional<u64> GetTitleID(const Partition& partition) const override;
|
||||||
const IOS::ES::TicketReader& GetTicket(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 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 GetGameID(const Partition& partition) const override;
|
||||||
std::string GetMakerID(const Partition& partition) const override;
|
std::string GetMakerID(const Partition& partition) const override;
|
||||||
std::optional<u16> GetRevision(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<std::unique_ptr<mbedtls_aes_context>> key;
|
||||||
Common::Lazy<IOS::ES::TicketReader> ticket;
|
Common::Lazy<IOS::ES::TicketReader> ticket;
|
||||||
Common::Lazy<IOS::ES::TMDReader> tmd;
|
Common::Lazy<IOS::ES::TMDReader> tmd;
|
||||||
|
Common::Lazy<std::unique_ptr<FileSystem>> file_system;
|
||||||
u32 type;
|
u32 type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -85,8 +85,7 @@ void FilesystemWidget::PopulateView()
|
||||||
|
|
||||||
for (size_t i = 0; i < partitions.size(); i++)
|
for (size_t i = 0; i < partitions.size(); i++)
|
||||||
{
|
{
|
||||||
std::unique_ptr<DiscIO::FileSystem> file_system(
|
const DiscIO::FileSystem* file_system = m_volume->GetFileSystem(partitions[i]);
|
||||||
DiscIO::CreateFileSystem(m_volume.get(), partitions[i]));
|
|
||||||
|
|
||||||
auto* item = new QStandardItem(tr("Partition %1").arg(i));
|
auto* item = new QStandardItem(tr("Partition %1").arg(i));
|
||||||
item->setEditable(false);
|
item->setEditable(false);
|
||||||
|
@ -104,10 +103,7 @@ void FilesystemWidget::PopulateView()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (partitions.empty())
|
if (partitions.empty())
|
||||||
{
|
PopulateDirectory(-1, disc, m_volume->GetFileSystem(DiscIO::PARTITION_NONE)->GetRoot());
|
||||||
PopulateDirectory(-1, disc,
|
|
||||||
DiscIO::CreateFileSystem(m_volume.get(), DiscIO::PARTITION_NONE)->GetRoot());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilesystemWidget::PopulateDirectory(int partition_id, QStandardItem* root,
|
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,
|
void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, const QString path,
|
||||||
const QString& out)
|
const QString& out)
|
||||||
{
|
{
|
||||||
std::unique_ptr<DiscIO::FileSystem> filesystem(
|
const DiscIO::FileSystem* filesystem = m_volume->GetFileSystem(partition);
|
||||||
DiscIO::CreateFileSystem(m_volume.get(), partition));
|
|
||||||
|
|
||||||
std::unique_ptr<DiscIO::FileInfo> info = filesystem->FindFileInfo(path.toStdString());
|
std::unique_ptr<DiscIO::FileInfo> info = filesystem->FindFileInfo(path.toStdString());
|
||||||
u32 size = info->GetTotalChildren();
|
u32 size = info->GetTotalChildren();
|
||||||
|
|
||||||
|
@ -251,7 +245,7 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons
|
||||||
bool all = path.isEmpty();
|
bool all = path.isEmpty();
|
||||||
|
|
||||||
DiscIO::ExportDirectory(
|
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) {
|
[all, dialog](const std::string& current) {
|
||||||
dialog->setLabelText(
|
dialog->setLabelText(
|
||||||
(all ? QObject::tr("Extracting All Files...") : QObject::tr("Extracting Directory..."))
|
(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,
|
void FilesystemWidget::ExtractFile(const DiscIO::Partition& partition, const QString& path,
|
||||||
const QString& out)
|
const QString& out)
|
||||||
{
|
{
|
||||||
std::unique_ptr<DiscIO::FileSystem> filesystem(
|
const DiscIO::FileSystem* filesystem = m_volume->GetFileSystem(partition);
|
||||||
DiscIO::CreateFileSystem(m_volume.get(), partition));
|
|
||||||
bool success = DiscIO::ExportFile(
|
bool success = DiscIO::ExportFile(
|
||||||
*m_volume, partition, filesystem->FindFileInfo(path.toStdString()).get(), out.toStdString());
|
*m_volume, partition, filesystem->FindFileInfo(path.toStdString()).get(), out.toStdString());
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,8 @@ namespace
|
||||||
class WiiPartition final : public wxTreeItemData
|
class WiiPartition final : public wxTreeItemData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WiiPartition(std::unique_ptr<DiscIO::FileSystem> filesystem_) : filesystem{std::move(filesystem_)}
|
WiiPartition(const DiscIO::Partition& partition_) : partition(partition_) {}
|
||||||
{
|
DiscIO::Partition partition;
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<DiscIO::FileSystem> filesystem;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : int
|
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)
|
WiiPartition* FindWiiPartition(wxTreeCtrl* tree_ctrl, const wxString& label)
|
||||||
{
|
{
|
||||||
wxTreeItemIdValue cookie;
|
wxTreeItemIdValue cookie;
|
||||||
|
@ -153,31 +157,23 @@ bool FilesystemPanel::PopulateFileSystemTree()
|
||||||
if (m_has_partitions)
|
if (m_has_partitions)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < partitions.size(); ++i)
|
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(
|
wxTreeItemId partition_root = m_tree_ctrl->AppendItem(
|
||||||
m_tree_ctrl->GetRootItem(), wxString::Format(_("Partition %zu"), i), ICON_DISC);
|
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);
|
m_tree_ctrl->SetItemData(partition_root, partition);
|
||||||
CreateDirectoryTree(m_tree_ctrl, partition_root, partition->filesystem->GetRoot());
|
CreateDirectoryTree(m_tree_ctrl, partition_root, m_opened_iso->GetFileSystem(partitions[i]));
|
||||||
|
|
||||||
if (partitions[i] == m_opened_iso->GetGamePartition())
|
if (partitions[i] == m_opened_iso->GetGamePartition())
|
||||||
m_tree_ctrl->Expand(partition_root);
|
m_tree_ctrl->Expand(partition_root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_filesystem = DiscIO::CreateFileSystem(m_opened_iso.get(), DiscIO::PARTITION_NONE);
|
CreateDirectoryTree(m_tree_ctrl, m_tree_ctrl->GetRootItem(),
|
||||||
if (!m_filesystem)
|
m_opened_iso->GetFileSystem(DiscIO::PARTITION_NONE));
|
||||||
return false;
|
|
||||||
|
|
||||||
CreateDirectoryTree(m_tree_ctrl, m_tree_ctrl->GetRootItem(), m_filesystem->GetRoot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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 selection_data = m_tree_ctrl->GetItemData(m_tree_ctrl->GetSelection());
|
||||||
const auto* const wii_partition = static_cast<const WiiPartition*>(selection_data);
|
const auto* const wii_partition = static_cast<const WiiPartition*>(selection_data);
|
||||||
|
|
||||||
partition = wii_partition->filesystem->GetPartition();
|
partition = wii_partition->partition;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -293,11 +289,11 @@ void FilesystemPanel::OnExtractAll(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
const auto* const partition = static_cast<WiiPartition*>(m_tree_ctrl->GetItemData(item));
|
const auto* const partition = static_cast<WiiPartition*>(m_tree_ctrl->GetItemData(item));
|
||||||
const std::optional<u32> partition_type =
|
const std::optional<u32> partition_type =
|
||||||
*m_opened_iso->GetPartitionType(partition->filesystem->GetPartition());
|
*m_opened_iso->GetPartitionType(partition->partition);
|
||||||
if (partition_type)
|
if (partition_type)
|
||||||
{
|
{
|
||||||
const std::string partition_name = DiscIO::DirectoryNameForPartitionType(*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);
|
item = m_tree_ctrl->GetNextChild(root, cookie);
|
||||||
}
|
}
|
||||||
|
@ -305,11 +301,11 @@ void FilesystemPanel::OnExtractAll(wxCommandEvent& event)
|
||||||
else if (m_has_partitions && !first_item_selected)
|
else if (m_has_partitions && !first_item_selected)
|
||||||
{
|
{
|
||||||
const auto* const partition = static_cast<WiiPartition*>(m_tree_ctrl->GetItemData(selection));
|
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
|
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();
|
const auto selection = m_tree_ctrl->GetSelection();
|
||||||
WiiPartition* partition =
|
WiiPartition* partition =
|
||||||
static_cast<WiiPartition*>(m_tree_ctrl->GetItemData(m_tree_ctrl->GetSelection()));
|
static_cast<WiiPartition*>(m_tree_ctrl->GetItemData(m_tree_ctrl->GetSelection()));
|
||||||
std::future<bool> is_valid = std::async(std::launch::async, [&] {
|
std::future<bool> is_valid = std::async(
|
||||||
return m_opened_iso->CheckIntegrity(partition->filesystem->GetPartition());
|
std::launch::async, [&] { return m_opened_iso->CheckIntegrity(partition->partition); });
|
||||||
});
|
|
||||||
|
|
||||||
while (is_valid.wait_for(std::chrono::milliseconds(50)) != std::future_status::ready)
|
while (is_valid.wait_for(std::chrono::milliseconds(50)) != std::future_status::ready)
|
||||||
dialog.Pulse();
|
dialog.Pulse();
|
||||||
|
@ -350,23 +345,26 @@ void FilesystemPanel::OnCheckPartitionIntegrity(wxCommandEvent& WXUNUSED(event))
|
||||||
|
|
||||||
void FilesystemPanel::ExtractSingleFile(const wxString& output_file_path) const
|
void FilesystemPanel::ExtractSingleFile(const wxString& output_file_path) const
|
||||||
{
|
{
|
||||||
const std::pair<wxString, const DiscIO::FileSystem&> path = BuildFilePathFromSelection();
|
const std::pair<wxString, DiscIO::Partition> path = BuildFilePathFromSelection();
|
||||||
DiscIO::ExportFile(*m_opened_iso, path.second.GetPartition(),
|
DiscIO::ExportFile(*m_opened_iso, path.second, WxStrToStr(path.first),
|
||||||
path.second.FindFileInfo(WxStrToStr(path.first)).get(),
|
|
||||||
WxStrToStr(output_file_path));
|
WxStrToStr(output_file_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilesystemPanel::ExtractSingleDirectory(const wxString& output_folder)
|
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);
|
ExtractDirectories(WxStrToStr(path.first), WxStrToStr(output_folder), path.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilesystemPanel::ExtractDirectories(const std::string& full_path,
|
void FilesystemPanel::ExtractDirectories(const std::string& full_path,
|
||||||
const std::string& output_folder,
|
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 size = file_info->GetTotalChildren();
|
||||||
u32 progress = 0;
|
u32 progress = 0;
|
||||||
|
|
||||||
|
@ -376,7 +374,7 @@ void FilesystemPanel::ExtractDirectories(const std::string& full_path,
|
||||||
wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH);
|
wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH);
|
||||||
|
|
||||||
DiscIO::ExportDirectory(
|
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) {
|
[&](const std::string& path) {
|
||||||
dialog.SetTitle(wxString::Format(
|
dialog.SetTitle(wxString::Format(
|
||||||
"%s : %d%%", dialog_title.c_str(),
|
"%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,
|
void FilesystemPanel::ExtractPartition(const std::string& output_folder,
|
||||||
const DiscIO::FileSystem& filesystem)
|
const DiscIO::Partition& partition)
|
||||||
{
|
{
|
||||||
ExtractDirectories("", output_folder + "/files", filesystem);
|
ExtractDirectories("", output_folder + "/files", partition);
|
||||||
DiscIO::ExportSystemData(*m_opened_iso, filesystem.GetPartition(), output_folder);
|
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();
|
const wxTreeItemId root_node = m_tree_ctrl->GetRootItem();
|
||||||
wxTreeItemId node = m_tree_ctrl->GetSelection();
|
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 size_t slash_index = file_path.find('/');
|
||||||
const wxString partition_label = file_path.substr(0, slash_index);
|
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/"
|
// Remove "Partition x/"
|
||||||
file_path.erase(0, slash_index + 1);
|
file_path.erase(0, slash_index + 1);
|
||||||
|
|
||||||
return {file_path, *partition->filesystem};
|
return {file_path, partition->partition};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return {file_path, *m_filesystem};
|
return {file_path, DiscIO::PARTITION_NONE};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<wxString, const DiscIO::FileSystem&>
|
std::pair<wxString, DiscIO::Partition> FilesystemPanel::BuildDirectoryPathFromSelection() const
|
||||||
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};
|
return {result.first + DIR_SEP_CHR, result.second};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class wxTreeEvent;
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
class FileSystem;
|
struct Partition;
|
||||||
class Volume;
|
class Volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,16 +51,15 @@ private:
|
||||||
void ExtractSingleFile(const wxString& output_file_path) const;
|
void ExtractSingleFile(const wxString& output_file_path) const;
|
||||||
void ExtractSingleDirectory(const wxString& output_folder);
|
void ExtractSingleDirectory(const wxString& output_folder);
|
||||||
void ExtractDirectories(const std::string& full_path, const std::string& output_folder,
|
void ExtractDirectories(const std::string& full_path, const std::string& output_folder,
|
||||||
const DiscIO::FileSystem& filesystem);
|
const DiscIO::Partition& partition);
|
||||||
void ExtractPartition(const std::string& output_folder, const DiscIO::FileSystem& filesystem);
|
void ExtractPartition(const std::string& output_folder, const DiscIO::Partition& partition);
|
||||||
|
|
||||||
std::pair<wxString, const DiscIO::FileSystem&> BuildFilePathFromSelection() const;
|
std::pair<wxString, DiscIO::Partition> BuildFilePathFromSelection() const;
|
||||||
std::pair<wxString, const DiscIO::FileSystem&> BuildDirectoryPathFromSelection() const;
|
std::pair<wxString, DiscIO::Partition> BuildDirectoryPathFromSelection() const;
|
||||||
|
|
||||||
wxTreeCtrl* m_tree_ctrl;
|
wxTreeCtrl* m_tree_ctrl;
|
||||||
|
|
||||||
const std::unique_ptr<DiscIO::Volume>& m_opened_iso;
|
const std::unique_ptr<DiscIO::Volume>& m_opened_iso;
|
||||||
|
|
||||||
std::unique_ptr<DiscIO::FileSystem> m_filesystem;
|
|
||||||
bool m_has_partitions;
|
bool m_has_partitions;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue