summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO
diff options
context:
space:
mode:
authorLillyJadeKatrin <lilly.kitty.1988@gmail.com>2023-07-07 08:31:26 -0400
committerLillyJadeKatrin <lilly.kitty.1988@gmail.com>2023-10-01 09:04:06 -0400
commit335cf4f2db4160ebbf387aeb19dc637182c91c5a (patch)
tree5e0c604dad0d5591a7343da34be1aa328b6fae01 /Source/Core/DiscIO
parentf8445782bff425dd95a8c7ccba06769d9fb0adf0 (diff)
Added CopyReader to BlobReader and all subclasses
A deep-copy method CopyReader has been added to BlobReader (virtual) and all of its subclasses (override). This should create a second BlobReader to open the same set of data but with an independent read pointer so that it doesn't interfere with any reads done on the original Reader. As part of this, IOFile has added code to create a deep copy IOFile pointer onto the same file, with code based on the platform in question to find the file ID from the file pointer and open a new one. There has also been a small piece added to FileInfo to enable a deep copy, but its only subclass at this time already had a copy constructor so this was relatively minor.
Diffstat (limited to 'Source/Core/DiscIO')
-rw-r--r--Source/Core/DiscIO/Blob.h1
-rw-r--r--Source/Core/DiscIO/CISOBlob.cpp5
-rw-r--r--Source/Core/DiscIO/CISOBlob.h1
-rw-r--r--Source/Core/DiscIO/CompressedBlob.cpp5
-rw-r--r--Source/Core/DiscIO/CompressedBlob.h1
-rw-r--r--Source/Core/DiscIO/DirectoryBlob.cpp325
-rw-r--r--Source/Core/DiscIO/DirectoryBlob.h80
-rw-r--r--Source/Core/DiscIO/DiscScrubber.cpp1
-rw-r--r--Source/Core/DiscIO/DiscScrubber.h1
-rw-r--r--Source/Core/DiscIO/FileBlob.cpp5
-rw-r--r--Source/Core/DiscIO/FileBlob.h1
-rw-r--r--Source/Core/DiscIO/NFSBlob.cpp11
-rw-r--r--Source/Core/DiscIO/NFSBlob.h2
-rw-r--r--Source/Core/DiscIO/RiivolutionPatcher.cpp14
-rw-r--r--Source/Core/DiscIO/ScrubbedBlob.cpp5
-rw-r--r--Source/Core/DiscIO/ScrubbedBlob.h1
-rw-r--r--Source/Core/DiscIO/SplitFileBlob.cpp11
-rw-r--r--Source/Core/DiscIO/SplitFileBlob.h1
-rw-r--r--Source/Core/DiscIO/TGCBlob.cpp5
-rw-r--r--Source/Core/DiscIO/TGCBlob.h1
-rw-r--r--Source/Core/DiscIO/VolumeFileBlobReader.cpp6
-rw-r--r--Source/Core/DiscIO/VolumeFileBlobReader.h1
-rw-r--r--Source/Core/DiscIO/WIABlob.cpp8
-rw-r--r--Source/Core/DiscIO/WIABlob.h2
-rw-r--r--Source/Core/DiscIO/WbfsBlob.cpp12
-rw-r--r--Source/Core/DiscIO/WbfsBlob.h3
26 files changed, 294 insertions, 215 deletions
diff --git a/Source/Core/DiscIO/Blob.h b/Source/Core/DiscIO/Blob.h
index 1777f9fcaa..29f6fb5b3f 100644
--- a/Source/Core/DiscIO/Blob.h
+++ b/Source/Core/DiscIO/Blob.h
@@ -64,6 +64,7 @@ public:
virtual ~BlobReader() {}
virtual BlobType GetBlobType() const = 0;
+ virtual std::unique_ptr<BlobReader> CopyReader() const = 0;
virtual u64 GetRawSize() const = 0;
virtual u64 GetDataSize() const = 0;
diff --git a/Source/Core/DiscIO/CISOBlob.cpp b/Source/Core/DiscIO/CISOBlob.cpp
index 28408402b8..001c462694 100644
--- a/Source/Core/DiscIO/CISOBlob.cpp
+++ b/Source/Core/DiscIO/CISOBlob.cpp
@@ -40,6 +40,11 @@ std::unique_ptr<CISOFileReader> CISOFileReader::Create(File::IOFile file)
return nullptr;
}
+std::unique_ptr<BlobReader> CISOFileReader::CopyReader() const
+{
+ return Create(m_file.Duplicate("rb"));
+}
+
u64 CISOFileReader::GetDataSize() const
{
return static_cast<u64>(CISO_MAP_SIZE) * m_block_size;
diff --git a/Source/Core/DiscIO/CISOBlob.h b/Source/Core/DiscIO/CISOBlob.h
index ddbd5d0719..a3cd2ead82 100644
--- a/Source/Core/DiscIO/CISOBlob.h
+++ b/Source/Core/DiscIO/CISOBlob.h
@@ -36,6 +36,7 @@ public:
static std::unique_ptr<CISOFileReader> Create(File::IOFile file);
BlobType GetBlobType() const override { return BlobType::CISO; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override;
u64 GetDataSize() const override;
diff --git a/Source/Core/DiscIO/CompressedBlob.cpp b/Source/Core/DiscIO/CompressedBlob.cpp
index 139a1e6d17..629cedfe7c 100644
--- a/Source/Core/DiscIO/CompressedBlob.cpp
+++ b/Source/Core/DiscIO/CompressedBlob.cpp
@@ -74,6 +74,11 @@ CompressedBlobReader::~CompressedBlobReader()
{
}
+std::unique_ptr<BlobReader> CompressedBlobReader::CopyReader() const
+{
+ return Create(m_file.Duplicate("rb"), m_file_name);
+}
+
// IMPORTANT: Calling this function invalidates all earlier pointers gotten from this function.
u64 CompressedBlobReader::GetBlockCompressedSize(u64 block_num) const
{
diff --git a/Source/Core/DiscIO/CompressedBlob.h b/Source/Core/DiscIO/CompressedBlob.h
index c828b1ad2b..c7c892cd13 100644
--- a/Source/Core/DiscIO/CompressedBlob.h
+++ b/Source/Core/DiscIO/CompressedBlob.h
@@ -50,6 +50,7 @@ public:
const CompressedBlobHeader& GetHeader() const { return m_header; }
BlobType GetBlobType() const override { return BlobType::GCZ; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override { return m_file_size; }
u64 GetDataSize() const override { return m_header.data_size; }
diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp
index 193d74c244..1970d49b44 100644
--- a/Source/Core/DiscIO/DirectoryBlob.cpp
+++ b/Source/Core/DiscIO/DirectoryBlob.cpp
@@ -82,7 +82,7 @@ u64 DiscContent::GetSize() const
return m_size;
}
-bool DiscContent::Read(u64* offset, u64* length, u8** buffer) const
+bool DiscContent::Read(u64* offset, u64* length, u8** buffer, DirectoryBlobReader* blob) const
{
if (m_size == 0)
return true;
@@ -104,15 +104,15 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer) const
return false;
}
}
- else if (std::holds_alternative<const u8*>(m_content_source))
+ else if (std::holds_alternative<ContentMemory>(m_content_source))
{
- const u8* const content_pointer = std::get<const u8*>(m_content_source) + offset_in_content;
- std::copy(content_pointer, content_pointer + bytes_to_read, *buffer);
+ const auto& content = std::get<ContentMemory>(m_content_source);
+ std::copy(content->begin() + offset_in_content,
+ content->begin() + offset_in_content + bytes_to_read, *buffer);
}
else if (std::holds_alternative<ContentPartition>(m_content_source))
{
const auto& content = std::get<ContentPartition>(m_content_source);
- DirectoryBlobReader* blob = content.m_reader;
const u64 decrypted_size = m_size * VolumeWii::BLOCK_DATA_SIZE / VolumeWii::BLOCK_TOTAL_SIZE;
if (!blob->EncryptPartitionData(content.m_offset + offset_in_content, bytes_to_read, *buffer,
content.m_partition_data_offset, decrypted_size))
@@ -123,8 +123,8 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer) const
else if (std::holds_alternative<ContentVolume>(m_content_source))
{
const auto& source = std::get<ContentVolume>(m_content_source);
- if (!source.m_volume->Read(source.m_offset + offset_in_content, bytes_to_read, *buffer,
- source.m_partition))
+ if (!blob->GetWrappedVolume()->Read(source.m_offset + offset_in_content, bytes_to_read,
+ *buffer, source.m_partition))
{
return false;
}
@@ -134,12 +134,6 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer) const
const ContentFixedByte& source = std::get<ContentFixedByte>(m_content_source);
std::fill_n(*buffer, bytes_to_read, source.m_byte);
}
- else if (std::holds_alternative<ContentByteVector>(m_content_source))
- {
- const ContentByteVector& source = std::get<ContentByteVector>(m_content_source);
- std::copy(source.m_bytes.begin() + offset_in_content,
- source.m_bytes.begin() + offset_in_content + bytes_to_read, *buffer);
- }
else
{
PanicAlertFmt("DirectoryBlob: Invalid content source in DiscContent.");
@@ -174,7 +168,7 @@ u64 DiscContentContainer::CheckSizeAndAdd(u64 offset, u64 max_size, const std::s
return size;
}
-bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer) const
+bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer, DirectoryBlobReader* blob) const
{
// Determine which DiscContent the offset refers to
std::set<DiscContent>::const_iterator it = m_contents.upper_bound(DiscContent(offset));
@@ -187,7 +181,7 @@ bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer) const
if (length == 0)
return true;
- if (!it->Read(&offset, &length, &buffer))
+ if (!it->Read(&offset, &length, &buffer, blob))
return false;
++it;
@@ -388,7 +382,10 @@ DirectoryBlobReader::DirectoryBlobReader(const std::string& game_partition_root,
}
else
{
- SetNonpartitionDiscHeaderFromFile(game_partition.GetHeader(), game_partition_root);
+ std::vector<u8> disc_header(DISCHEADER_SIZE);
+ game_partition.GetContents().Read(DISCHEADER_ADDRESS, DISCHEADER_SIZE, disc_header.data(),
+ this);
+ SetNonpartitionDiscHeaderFromFile(disc_header, game_partition_root);
SetWiiRegionDataFromFile(game_partition_root);
std::vector<PartitionWithType> partitions;
@@ -426,7 +423,7 @@ DirectoryBlobReader::DirectoryBlobReader(
{
DirectoryBlobPartition game_partition(m_wrapped_volume.get(),
m_wrapped_volume->GetGamePartition(), std::nullopt,
- sys_callback, fst_callback);
+ sys_callback, fst_callback, this);
m_is_wii = game_partition.IsWii();
if (!m_is_wii)
@@ -440,11 +437,15 @@ DirectoryBlobReader::DirectoryBlobReader(
std::vector<u8> header_bin(WII_NONPARTITION_DISCHEADER_SIZE);
if (!m_wrapped_volume->Read(WII_NONPARTITION_DISCHEADER_ADDRESS,
WII_NONPARTITION_DISCHEADER_SIZE, header_bin.data(),
- PARTITION_NONE))
+ PARTITION_NONE),
+ m_wrapped_volume.get())
{
header_bin.clear();
}
- SetNonpartitionDiscHeader(game_partition.GetHeader(), std::move(header_bin));
+ std::vector<u8> disc_header(DISCHEADER_SIZE);
+ game_partition.GetContents().Read(DISCHEADER_ADDRESS, DISCHEADER_SIZE, disc_header.data(),
+ this);
+ SetNonpartitionDiscHeader(disc_header, std::move(header_bin));
std::vector<u8> wii_region_data(WII_REGION_DATA_SIZE);
if (!m_wrapped_volume->Read(WII_REGION_DATA_ADDRESS, WII_REGION_DATA_SIZE,
@@ -465,9 +466,9 @@ DirectoryBlobReader::DirectoryBlobReader(
auto type = m_wrapped_volume->GetPartitionType(partition);
if (type)
{
- partitions.emplace_back(
- DirectoryBlobPartition(m_wrapped_volume.get(), partition, m_is_wii, nullptr, nullptr),
- static_cast<PartitionType>(*type));
+ partitions.emplace_back(DirectoryBlobPartition(m_wrapped_volume.get(), partition, m_is_wii,
+ nullptr, nullptr, this),
+ static_cast<PartitionType>(*type));
}
}
@@ -475,13 +476,24 @@ DirectoryBlobReader::DirectoryBlobReader(
}
}
+DirectoryBlobReader::DirectoryBlobReader(const DirectoryBlobReader& rhs)
+ : m_gamecube_pseudopartition(rhs.m_gamecube_pseudopartition),
+ m_nonpartition_contents(rhs.m_nonpartition_contents), m_partitions(rhs.m_partitions),
+ m_encryption_cache(this), m_is_wii(rhs.m_is_wii), m_encrypted(rhs.m_encrypted),
+ m_data_size(rhs.m_data_size),
+ m_wrapped_volume(rhs.m_wrapped_volume ?
+ CreateDisc(rhs.m_wrapped_volume->GetBlobReader().CopyReader()) :
+ nullptr)
+{
+}
+
bool DirectoryBlobReader::Read(u64 offset, u64 length, u8* buffer)
{
if (offset + length > m_data_size)
return false;
return (m_is_wii ? m_nonpartition_contents : m_gamecube_pseudopartition.GetContents())
- .Read(offset, length, buffer);
+ .Read(offset, length, buffer, this);
}
const DirectoryBlobPartition* DirectoryBlobReader::GetPartition(u64 offset, u64 size,
@@ -510,7 +522,7 @@ bool DirectoryBlobReader::ReadWiiDecrypted(u64 offset, u64 size, u8* buffer,
if (!partition)
return false;
- return partition->GetContents().Read(offset, size, buffer);
+ return partition->GetContents().Read(offset, size, buffer, this);
}
bool DirectoryBlobReader::EncryptPartitionData(u64 offset, u64 size, u8* buffer,
@@ -522,7 +534,7 @@ bool DirectoryBlobReader::EncryptPartitionData(u64 offset, u64 size, u8* buffer,
return false;
if (!m_encrypted)
- return it->second.GetContents().Read(offset, size, buffer);
+ return it->second.GetContents().Read(offset, size, buffer, this);
return m_encryption_cache.EncryptGroups(offset, size, buffer, partition_data_offset,
partition_data_decrypted_size, it->second.GetKey());
@@ -533,6 +545,11 @@ BlobType DirectoryBlobReader::GetBlobType() const
return BlobType::DIRECTORY;
}
+std::unique_ptr<BlobReader> DirectoryBlobReader::CopyReader() const
+{
+ return std::unique_ptr<DirectoryBlobReader>(new DirectoryBlobReader(*this));
+}
+
u64 DirectoryBlobReader::GetRawSize() const
{
// Not implemented
@@ -558,28 +575,25 @@ void DirectoryBlobReader::SetNonpartitionDiscHeader(const std::vector<u8>& parti
std::vector<u8> header_bin)
{
const size_t header_bin_size = header_bin.size();
- m_disc_header_nonpartition = std::move(header_bin);
- m_disc_header_nonpartition.resize(WII_NONPARTITION_DISCHEADER_SIZE);
+ header_bin.resize(WII_NONPARTITION_DISCHEADER_SIZE);
// If header.bin is missing or smaller than expected, use the content of sys/boot.bin instead
- if (header_bin_size < m_disc_header_nonpartition.size())
+ if (header_bin_size < header_bin.size())
{
std::copy(partition_header.data() + header_bin_size,
- partition_header.data() + m_disc_header_nonpartition.size(),
- m_disc_header_nonpartition.data() + header_bin_size);
+ partition_header.data() + header_bin.size(), header_bin.data() + header_bin_size);
}
// 0x60 and 0x61 are the only differences between the partition and non-partition headers
if (header_bin_size < 0x60)
- m_disc_header_nonpartition[0x60] = 0;
+ header_bin[0x60] = 0;
if (header_bin_size < 0x61)
- m_disc_header_nonpartition[0x61] = 0;
+ header_bin[0x61] = 0;
- m_encrypted = std::all_of(m_disc_header_nonpartition.data() + 0x60,
- m_disc_header_nonpartition.data() + 0x64, [](u8 x) { return x == 0; });
+ m_encrypted =
+ std::all_of(header_bin.data() + 0x60, header_bin.data() + 0x64, [](u8 x) { return x == 0; });
- m_nonpartition_contents.AddReference(WII_NONPARTITION_DISCHEADER_ADDRESS,
- m_disc_header_nonpartition);
+ m_nonpartition_contents.Add(WII_NONPARTITION_DISCHEADER_ADDRESS, std::move(header_bin));
}
void DirectoryBlobReader::SetWiiRegionDataFromFile(const std::string& game_partition_root)
@@ -594,20 +608,19 @@ void DirectoryBlobReader::SetWiiRegionDataFromFile(const std::string& game_parti
void DirectoryBlobReader::SetWiiRegionData(const std::vector<u8>& wii_region_data,
const std::string& log_path)
{
- m_wii_region_data.resize(0x10, 0x00);
- m_wii_region_data.resize(WII_REGION_DATA_SIZE, 0x80);
- Write32(INVALID_REGION, 0, &m_wii_region_data);
+ std::vector<u8> region_data(0x10, 0x00);
+ region_data.resize(WII_REGION_DATA_SIZE, 0x80);
+ Write32(INVALID_REGION, 0, &region_data);
std::copy_n(wii_region_data.begin(),
- std::min<size_t>(wii_region_data.size(), WII_REGION_DATA_SIZE),
- m_wii_region_data.begin());
+ std::min<size_t>(wii_region_data.size(), WII_REGION_DATA_SIZE), region_data.begin());
if (wii_region_data.size() < 0x4)
ERROR_LOG_FMT(DISCIO, "Couldn't read region from {}", log_path);
else if (wii_region_data.size() < 0x20)
ERROR_LOG_FMT(DISCIO, "Couldn't read age ratings from {}", log_path);
- m_nonpartition_contents.AddReference(WII_REGION_DATA_ADDRESS, m_wii_region_data);
+ m_nonpartition_contents.Add(WII_REGION_DATA_ADDRESS, std::move(region_data));
}
void DirectoryBlobReader::SetPartitions(std::vector<PartitionWithType>&& partitions)
@@ -634,14 +647,14 @@ void DirectoryBlobReader::SetPartitions(std::vector<PartitionWithType>&& partiti
constexpr u32 PARTITION_TABLE_ADDRESS = 0x40000;
constexpr u32 PARTITION_SUBTABLE1_OFFSET = 0x20;
constexpr u32 PARTITION_SUBTABLE2_OFFSET = 0x40;
- m_partition_table.resize(PARTITION_SUBTABLE2_OFFSET + subtable_2_size * 8);
+ std::vector<u8> partition_table(PARTITION_SUBTABLE2_OFFSET + subtable_2_size * 8);
- Write32(subtable_1_size, 0x0, &m_partition_table);
- Write32((PARTITION_TABLE_ADDRESS + PARTITION_SUBTABLE1_OFFSET) >> 2, 0x4, &m_partition_table);
+ Write32(subtable_1_size, 0x0, &partition_table);
+ Write32((PARTITION_TABLE_ADDRESS + PARTITION_SUBTABLE1_OFFSET) >> 2, 0x4, &partition_table);
if (subtable_2_size != 0)
{
- Write32(subtable_2_size, 0x8, &m_partition_table);
- Write32((PARTITION_TABLE_ADDRESS + PARTITION_SUBTABLE2_OFFSET) >> 2, 0xC, &m_partition_table);
+ Write32(subtable_2_size, 0x8, &partition_table);
+ Write32((PARTITION_TABLE_ADDRESS + PARTITION_SUBTABLE2_OFFSET) >> 2, 0xC, &partition_table);
}
constexpr u64 STANDARD_UPDATE_PARTITION_ADDRESS = 0x50000;
@@ -656,9 +669,9 @@ void DirectoryBlobReader::SetPartitions(std::vector<PartitionWithType>&& partiti
if (partitions[i].type == PartitionType::Game)
partition_address = std::max(partition_address, STANDARD_GAME_PARTITION_ADDRESS);
- Write32(static_cast<u32>(partition_address >> 2), offset_in_table, &m_partition_table);
+ Write32(static_cast<u32>(partition_address >> 2), offset_in_table, &partition_table);
offset_in_table += 4;
- Write32(static_cast<u32>(partitions[i].type), offset_in_table, &m_partition_table);
+ Write32(static_cast<u32>(partitions[i].type), offset_in_table, &partition_table);
offset_in_table += 4;
SetPartitionHeader(&partitions[i].partition, partition_address);
@@ -671,14 +684,14 @@ void DirectoryBlobReader::SetPartitions(std::vector<PartitionWithType>&& partiti
const u64 partition_data_offset = partition_address + PARTITION_DATA_OFFSET;
m_partitions.emplace(partition_data_offset, std::move(partitions[i].partition));
m_nonpartition_contents.Add(partition_data_offset, encrypted_data_size,
- ContentPartition{this, 0, partition_data_offset});
+ ContentPartition{0, partition_data_offset});
const u64 unaligned_next_partition_address = VolumeWii::OffsetInHashedPartitionToRawOffset(
data_size, Partition(partition_address), PARTITION_DATA_OFFSET);
partition_address = Common::AlignUp(unaligned_next_partition_address, 0x10000ull);
}
m_data_size = partition_address;
- m_nonpartition_contents.AddReference(PARTITION_TABLE_ADDRESS, m_partition_table);
+ m_nonpartition_contents.Add(PARTITION_TABLE_ADDRESS, std::move(partition_table));
}
// This function sets the header that's shortly before the start of the encrypted
@@ -695,13 +708,12 @@ void DirectoryBlobReader::SetPartitionHeader(DirectoryBlobPartition* partition,
u64 ticket_size;
if (wrapped_partition)
{
- const auto& ticket = m_wrapped_volume->GetTicket(*wrapped_partition).GetBytes();
- auto& new_ticket = m_extra_data.emplace_back(ticket);
+ std::vector<u8> new_ticket = m_wrapped_volume->GetTicket(*wrapped_partition).GetBytes();
if (new_ticket.size() > WII_PARTITION_TICKET_SIZE)
new_ticket.resize(WII_PARTITION_TICKET_SIZE);
ticket_size = new_ticket.size();
- m_nonpartition_contents.AddReference(partition_address + WII_PARTITION_TICKET_ADDRESS,
- new_ticket);
+ m_nonpartition_contents.Add(partition_address + WII_PARTITION_TICKET_ADDRESS,
+ std::move(new_ticket));
}
else
{
@@ -713,12 +725,11 @@ void DirectoryBlobReader::SetPartitionHeader(DirectoryBlobPartition* partition,
u64 tmd_size;
if (wrapped_partition)
{
- const auto& tmd = m_wrapped_volume->GetTMD(*wrapped_partition).GetBytes();
- auto& new_tmd = m_extra_data.emplace_back(tmd);
+ std::vector<u8> new_tmd = m_wrapped_volume->GetTMD(*wrapped_partition).GetBytes();
if (new_tmd.size() > IOS::ES::MAX_TMD_SIZE)
new_tmd.resize(IOS::ES::MAX_TMD_SIZE);
tmd_size = new_tmd.size();
- m_nonpartition_contents.AddReference(partition_address + TMD_OFFSET, new_tmd);
+ m_nonpartition_contents.Add(partition_address + TMD_OFFSET, std::move(new_tmd));
}
else
{
@@ -732,12 +743,11 @@ void DirectoryBlobReader::SetPartitionHeader(DirectoryBlobPartition* partition,
u64 cert_size;
if (wrapped_partition)
{
- const auto& cert = m_wrapped_volume->GetCertificateChain(*wrapped_partition);
- auto& new_cert = m_extra_data.emplace_back(cert);
+ std::vector<u8> new_cert = m_wrapped_volume->GetCertificateChain(*wrapped_partition);
if (new_cert.size() > max_cert_size)
new_cert.resize(max_cert_size);
cert_size = new_cert.size();
- m_nonpartition_contents.AddReference(partition_address + cert_offset, new_cert);
+ m_nonpartition_contents.Add(partition_address + cert_offset, std::move(new_cert));
}
else
{
@@ -753,11 +763,11 @@ void DirectoryBlobReader::SetPartitionHeader(DirectoryBlobPartition* partition,
wrapped_partition->offset + WII_PARTITION_H3_OFFSET_ADDRESS, PARTITION_NONE);
if (offset)
{
- auto& new_h3 = m_extra_data.emplace_back(WII_PARTITION_H3_SIZE);
+ std::vector<u8> new_h3(WII_PARTITION_H3_SIZE);
if (m_wrapped_volume->Read(wrapped_partition->offset + *offset, new_h3.size(),
new_h3.data(), PARTITION_NONE))
{
- m_nonpartition_contents.AddReference(partition_address + H3_OFFSET, new_h3);
+ m_nonpartition_contents.Add(partition_address + H3_OFFSET, std::move(new_h3));
}
}
}
@@ -770,7 +780,7 @@ void DirectoryBlobReader::SetPartitionHeader(DirectoryBlobPartition* partition,
constexpr u32 PARTITION_HEADER_SIZE = 0x1c;
const u64 data_size = Common::AlignUp(partition->GetDataSize(), 0x7c00) / 0x7c00 * 0x8000;
- std::vector<u8>& partition_header = m_extra_data.emplace_back(PARTITION_HEADER_SIZE);
+ std::vector<u8> partition_header(PARTITION_HEADER_SIZE);
Write32(static_cast<u32>(tmd_size), 0x0, &partition_header);
Write32(TMD_OFFSET >> 2, 0x4, &partition_header);
Write32(static_cast<u32>(cert_size), 0x8, &partition_header);
@@ -779,12 +789,12 @@ void DirectoryBlobReader::SetPartitionHeader(DirectoryBlobPartition* partition,
Write32(PARTITION_DATA_OFFSET >> 2, 0x14, &partition_header);
Write32(static_cast<u32>(data_size >> 2), 0x18, &partition_header);
- m_nonpartition_contents.AddReference(partition_address + WII_PARTITION_TICKET_SIZE,
- partition_header);
+ m_nonpartition_contents.Add(partition_address + WII_PARTITION_TICKET_SIZE,
+ std::move(partition_header));
std::vector<u8> ticket_buffer(ticket_size);
m_nonpartition_contents.Read(partition_address + WII_PARTITION_TICKET_ADDRESS, ticket_size,
- ticket_buffer.data());
+ ticket_buffer.data(), this);
IOS::ES::TicketReader ticket(std::move(ticket_buffer));
if (ticket.IsValid())
partition->SetKey(ticket.GetTitleKey());
@@ -807,8 +817,8 @@ static void GenerateBuilderNodesFromFileSystem(const DiscIO::VolumeDisc& volume,
else
{
std::vector<BuilderContentSource> source;
- source.emplace_back(BuilderContentSource{
- 0, file_info.GetSize(), ContentVolume{file_info.GetOffset(), &volume, partition}});
+ source.emplace_back(BuilderContentSource{0, file_info.GetSize(),
+ ContentVolume{file_info.GetOffset(), partition}});
nodes->emplace_back(
FSTBuilderNode{file_info.GetName(), file_info.GetSize(), std::move(source)});
}
@@ -819,19 +829,26 @@ DirectoryBlobPartition::DirectoryBlobPartition(const std::string& root_directory
std::optional<bool> is_wii)
: m_root_directory(root_directory)
{
- SetDiscHeaderFromFile(m_root_directory + "sys/boot.bin");
- SetDiscType(is_wii);
+ std::vector<u8> disc_header(DISCHEADER_SIZE);
+ if (ReadFileToVector(m_root_directory + "sys/boot.bin", &disc_header) < 0x20)
+ ERROR_LOG_FMT(DISCIO, "{} doesn't exist or is too small", m_root_directory + "sys/boot.bin");
+
+ SetDiscType(is_wii, disc_header);
SetBI2FromFile(m_root_directory + "sys/bi2.bin");
const u64 dol_address = SetApploaderFromFile(m_root_directory + "sys/apploader.img");
- const u64 fst_address = SetDOLFromFile(m_root_directory + "sys/main.dol", dol_address);
- BuildFSTFromFolder(m_root_directory + "files/", fst_address);
+ const u64 fst_address =
+ SetDOLFromFile(m_root_directory + "sys/main.dol", dol_address, &disc_header);
+ BuildFSTFromFolder(m_root_directory + "files/", fst_address, &disc_header);
+
+ m_contents.Add(DISCHEADER_ADDRESS, disc_header);
}
static void FillSingleFileNode(FSTBuilderNode* node, std::vector<u8> data)
{
std::vector<BuilderContentSource> contents;
const size_t size = data.size();
- contents.emplace_back(BuilderContentSource{0, size, ContentByteVector{std::move(data)}});
+ contents.emplace_back(
+ BuilderContentSource{0, size, std::make_shared<std::vector<u8>>(std::move(data))});
node->m_size = size;
node->m_content = std::move(contents);
}
@@ -844,7 +861,8 @@ static FSTBuilderNode BuildSingleFileNode(std::string filename, std::vector<u8>
return node;
}
-static std::vector<u8> ExtractNodeToVector(std::vector<FSTBuilderNode>* nodes, void* userdata)
+static std::vector<u8> ExtractNodeToVector(std::vector<FSTBuilderNode>* nodes, void* userdata,
+ DirectoryBlobReader* blob)
{
std::vector<u8> data;
const auto it =
@@ -858,7 +876,7 @@ static std::vector<u8> ExtractNodeToVector(std::vector<FSTBuilderNode>* nodes, v
for (auto& content : it->GetFileContent())
tmp.Add(content.m_offset, content.m_size, std::move(content.m_source));
data.resize(it->m_size);
- tmp.Read(0, it->m_size, data.data());
+ tmp.Read(0, it->m_size, data.data(), blob);
return data;
}
@@ -866,7 +884,8 @@ DirectoryBlobPartition::DirectoryBlobPartition(
DiscIO::VolumeDisc* volume, const DiscIO::Partition& partition, std::optional<bool> is_wii,
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes)>& sys_callback,
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes, FSTBuilderNode* dol_node)>&
- fst_callback)
+ fst_callback,
+ DirectoryBlobReader* blob)
: m_wrapped_partition(partition)
{
std::vector<FSTBuilderNode> sys_nodes;
@@ -874,17 +893,16 @@ DirectoryBlobPartition::DirectoryBlobPartition(
std::vector<u8> disc_header(DISCHEADER_SIZE);
if (!volume->Read(DISCHEADER_ADDRESS, DISCHEADER_SIZE, disc_header.data(), partition))
disc_header.clear();
- sys_nodes.emplace_back(BuildSingleFileNode("boot.bin", std::move(disc_header), &m_disc_header));
+ sys_nodes.emplace_back(BuildSingleFileNode("boot.bin", std::move(disc_header), &disc_header));
std::vector<u8> bi2(BI2_SIZE);
if (!volume->Read(BI2_ADDRESS, BI2_SIZE, bi2.data(), partition))
bi2.clear();
- sys_nodes.emplace_back(BuildSingleFileNode("bi2.bin", std::move(bi2), &m_bi2));
+ sys_nodes.emplace_back(BuildSingleFileNode("bi2.bin", std::move(bi2), &bi2));
std::vector<u8> apploader;
const auto apploader_size = GetApploaderSize(*volume, partition);
- auto& apploader_node =
- sys_nodes.emplace_back(FSTBuilderNode{"apploader.img", 0, {}, &m_apploader});
+ auto& apploader_node = sys_nodes.emplace_back(FSTBuilderNode{"apploader.img", 0, {}, &apploader});
if (apploader_size)
{
apploader.resize(*apploader_size);
@@ -896,11 +914,12 @@ DirectoryBlobPartition::DirectoryBlobPartition(
if (sys_callback)
sys_callback(&sys_nodes);
- SetDiscHeader(ExtractNodeToVector(&sys_nodes, &m_disc_header));
- SetDiscType(is_wii);
- SetBI2(ExtractNodeToVector(&sys_nodes, &m_bi2));
+ disc_header = ExtractNodeToVector(&sys_nodes, &disc_header, blob);
+ disc_header.resize(DISCHEADER_SIZE);
+ SetDiscType(is_wii, disc_header);
+ SetBI2(ExtractNodeToVector(&sys_nodes, &bi2, blob));
const u64 new_dol_address =
- SetApploader(ExtractNodeToVector(&sys_nodes, &m_apploader), "apploader");
+ SetApploader(ExtractNodeToVector(&sys_nodes, &apploader, blob), "apploader");
FSTBuilderNode dol_node{"main.dol", 0, {}};
const auto dol_offset = GetBootDOLOffset(*volume, partition);
@@ -911,7 +930,7 @@ DirectoryBlobPartition::DirectoryBlobPartition(
{
std::vector<BuilderContentSource> dol_contents;
dol_contents.emplace_back(
- BuilderContentSource{0, *dol_size, ContentVolume{*dol_offset, volume, partition}});
+ BuilderContentSource{0, *dol_size, ContentVolume{*dol_offset, partition}});
dol_node.m_size = *dol_size;
dol_node.m_content = std::move(dol_contents);
}
@@ -926,27 +945,14 @@ DirectoryBlobPartition::DirectoryBlobPartition(
if (fst_callback)
fst_callback(&nodes, &dol_node);
- const u64 new_fst_address = SetDOL(std::move(dol_node), new_dol_address);
- BuildFST(std::move(nodes), new_fst_address);
-}
-
-void DirectoryBlobPartition::SetDiscHeaderFromFile(const std::string& boot_bin_path)
-{
- m_disc_header.resize(DISCHEADER_SIZE);
- if (ReadFileToVector(boot_bin_path, &m_disc_header) < 0x20)
- ERROR_LOG_FMT(DISCIO, "{} doesn't exist or is too small", boot_bin_path);
-
- m_contents.AddReference(DISCHEADER_ADDRESS, m_disc_header);
-}
+ const u64 new_fst_address = SetDOL(std::move(dol_node), new_dol_address, &disc_header);
+ BuildFST(std::move(nodes), new_fst_address, &disc_header);
-void DirectoryBlobPartition::SetDiscHeader(std::vector<u8> boot_bin)
-{
- m_disc_header = std::move(boot_bin);
- m_disc_header.resize(DISCHEADER_SIZE);
- m_contents.AddReference(DISCHEADER_ADDRESS, m_disc_header);
+ m_contents.Add(DISCHEADER_ADDRESS, disc_header);
}
-void DirectoryBlobPartition::SetDiscType(std::optional<bool> is_wii)
+void DirectoryBlobPartition::SetDiscType(std::optional<bool> is_wii,
+ const std::vector<u8>& disc_header)
{
if (is_wii.has_value())
{
@@ -954,8 +960,8 @@ void DirectoryBlobPartition::SetDiscType(std::optional<bool> is_wii)
}
else
{
- m_is_wii = Common::swap32(&m_disc_header[0x18]) == WII_DISC_MAGIC;
- const bool is_gc = Common::swap32(&m_disc_header[0x1c]) == GAMECUBE_DISC_MAGIC;
+ m_is_wii = Common::swap32(&disc_header[0x18]) == WII_DISC_MAGIC;
+ const bool is_gc = Common::swap32(&disc_header[0x1c]) == GAMECUBE_DISC_MAGIC;
if (m_is_wii == is_gc)
{
ERROR_LOG_FMT(DISCIO, "Couldn't detect disc type based on disc header; assuming {}",
@@ -968,28 +974,27 @@ void DirectoryBlobPartition::SetDiscType(std::optional<bool> is_wii)
void DirectoryBlobPartition::SetBI2FromFile(const std::string& bi2_path)
{
- m_bi2.resize(BI2_SIZE);
+ std::vector<u8> bi2(BI2_SIZE);
if (!m_is_wii)
- Write32(INVALID_REGION, 0x18, &m_bi2);
+ Write32(INVALID_REGION, 0x18, &bi2);
- const size_t bytes_read = ReadFileToVector(bi2_path, &m_bi2);
+ const size_t bytes_read = ReadFileToVector(bi2_path, &bi2);
if (!m_is_wii && bytes_read < 0x1C)
ERROR_LOG_FMT(DISCIO, "Couldn't read region from {}", bi2_path);
- m_contents.AddReference(BI2_ADDRESS, m_bi2);
+ m_contents.Add(BI2_ADDRESS, std::move(bi2));
}
void DirectoryBlobPartition::SetBI2(std::vector<u8> bi2)
{
const size_t bi2_size = bi2.size();
- m_bi2 = std::move(bi2);
- m_bi2.resize(BI2_SIZE);
+ bi2.resize(BI2_SIZE);
if (!m_is_wii && bi2_size < 0x1C)
- Write32(INVALID_REGION, 0x18, &m_bi2);
+ Write32(INVALID_REGION, 0x18, &bi2);
- m_contents.AddReference(BI2_ADDRESS, m_bi2);
+ m_contents.Add(BI2_ADDRESS, std::move(bi2));
}
u64 DirectoryBlobPartition::SetApploaderFromFile(const std::string& path)
@@ -1004,16 +1009,15 @@ u64 DirectoryBlobPartition::SetApploader(std::vector<u8> apploader, const std::s
{
bool success = false;
- m_apploader = std::move(apploader);
- if (m_apploader.size() < 0x20)
+ if (apploader.size() < 0x20)
{
ERROR_LOG_FMT(DISCIO, "{} couldn't be accessed or is too small", log_path);
}
else
{
- const size_t apploader_size = 0x20 + Common::swap32(*(u32*)&m_apploader[0x14]) +
- Common::swap32(*(u32*)&m_apploader[0x18]);
- if (apploader_size != m_apploader.size())
+ const size_t apploader_size =
+ 0x20 + Common::swap32(*(u32*)&apploader[0x14]) + Common::swap32(*(u32*)&apploader[0x18]);
+ if (apploader_size != apploader.size())
ERROR_LOG_FMT(DISCIO, "{} is the wrong size... Is it really an apploader?", log_path);
else
success = true;
@@ -1021,33 +1025,36 @@ u64 DirectoryBlobPartition::SetApploader(std::vector<u8> apploader, const std::s
if (!success)
{
- m_apploader.resize(0x20);
+ apploader.resize(0x20);
// Make sure BS2 HLE doesn't try to run the apploader
- Write32(static_cast<u32>(-1), 0x10, &m_apploader);
+ Write32(static_cast<u32>(-1), 0x10, &apploader);
}
- m_contents.AddReference(APPLOADER_ADDRESS, m_apploader);
+ size_t apploader_size = apploader.size();
+ m_contents.Add(APPLOADER_ADDRESS, std::move(apploader));
// Return DOL address, 32 byte aligned (plus 32 byte padding)
- return Common::AlignUp(APPLOADER_ADDRESS + m_apploader.size() + 0x20, 0x20ull);
+ return Common::AlignUp(APPLOADER_ADDRESS + apploader_size + 0x20, 0x20ull);
}
-u64 DirectoryBlobPartition::SetDOLFromFile(const std::string& path, u64 dol_address)
+u64 DirectoryBlobPartition::SetDOLFromFile(const std::string& path, u64 dol_address,
+ std::vector<u8>* disc_header)
{
const u64 dol_size = m_contents.CheckSizeAndAdd(dol_address, path);
- Write32(static_cast<u32>(dol_address >> m_address_shift), 0x0420, &m_disc_header);
+ Write32(static_cast<u32>(dol_address >> m_address_shift), 0x0420, disc_header);
// Return FST address, 32 byte aligned (plus 32 byte padding)
return Common::AlignUp(dol_address + dol_size + 0x20, 0x20ull);
}
-u64 DirectoryBlobPartition::SetDOL(FSTBuilderNode dol_node, u64 dol_address)
+u64 DirectoryBlobPartition::SetDOL(FSTBuilderNode dol_node, u64 dol_address,
+ std::vector<u8>* disc_header)
{
for (auto& content : dol_node.GetFileContent())
m_contents.Add(dol_address + content.m_offset, content.m_size, std::move(content.m_source));
- Write32(static_cast<u32>(dol_address >> m_address_shift), 0x0420, &m_disc_header);
+ Write32(static_cast<u32>(dol_address >> m_address_shift), 0x0420, disc_header);
// Return FST address, 32 byte aligned (plus 32 byte padding)
return Common::AlignUp(dol_address + dol_node.m_size + 0x20, 0x20ull);
@@ -1075,10 +1082,11 @@ static std::vector<FSTBuilderNode> ConvertFSTEntriesToBuilderNodes(const File::F
return nodes;
}
-void DirectoryBlobPartition::BuildFSTFromFolder(const std::string& fst_root_path, u64 fst_address)
+void DirectoryBlobPartition::BuildFSTFromFolder(const std::string& fst_root_path, u64 fst_address,
+ std::vector<u8>* disc_header)
{
auto nodes = ConvertFSTEntriesToBuilderNodes(File::ScanDirectoryTree(fst_root_path, true));
- BuildFST(std::move(nodes), fst_address);
+ BuildFST(std::move(nodes), fst_address, disc_header);
}
static void ConvertUTF8NamesToSHIFTJIS(std::vector<FSTBuilderNode>* fst)
@@ -1118,10 +1126,9 @@ static size_t RecalculateFolderSizes(std::vector<FSTBuilderNode>* fst)
return size;
}
-void DirectoryBlobPartition::BuildFST(std::vector<FSTBuilderNode> root_nodes, u64 fst_address)
+void DirectoryBlobPartition::BuildFST(std::vector<FSTBuilderNode> root_nodes, u64 fst_address,
+ std::vector<u8>* disc_header)
{
- m_fst_data.clear();
-
ConvertUTF8NamesToSHIFTJIS(&root_nodes);
u32 name_table_size = Common::AlignUp(ComputeNameSize(root_nodes), 1ull << m_address_shift);
@@ -1130,59 +1137,61 @@ void DirectoryBlobPartition::BuildFST(std::vector<FSTBuilderNode> root_nodes, u6
u64 total_entries = RecalculateFolderSizes(&root_nodes) + 1;
const u64 name_table_offset = total_entries * ENTRY_SIZE;
- m_fst_data.resize(name_table_offset + name_table_size);
+ std::vector<u8> fst_data(name_table_offset + name_table_size);
// 32 KiB aligned start of data on disc
- u64 current_data_address = Common::AlignUp(fst_address + m_fst_data.size(), 0x8000ull);
+ u64 current_data_address = Common::AlignUp(fst_address + fst_data.size(), 0x8000ull);
u32 fst_offset = 0; // Offset within FST data
u32 name_offset = 0; // Offset within name table
u32 root_offset = 0; // Offset of root of FST
// write root entry
- WriteEntryData(&fst_offset, DIRECTORY_ENTRY, 0, 0, total_entries, m_address_shift);
+ WriteEntryData(&fst_data, &fst_offset, DIRECTORY_ENTRY, 0, 0, total_entries, m_address_shift);
- WriteDirectory(&root_nodes, &fst_offset, &name_offset, &current_data_address, root_offset,
- name_table_offset);
+ WriteDirectory(&fst_data, &root_nodes, &fst_offset, &name_offset, &current_data_address,
+ root_offset, name_table_offset);
// overflow check, compare the aligned name offset with the aligned name table size
ASSERT(Common::AlignUp(name_offset, 1ull << m_address_shift) == name_table_size);
// write FST size and location
- Write32((u32)(fst_address >> m_address_shift), 0x0424, &m_disc_header);
- Write32((u32)(m_fst_data.size() >> m_address_shift), 0x0428, &m_disc_header);
- Write32((u32)(m_fst_data.size() >> m_address_shift), 0x042c, &m_disc_header);
+ Write32((u32)(fst_address >> m_address_shift), 0x0424, disc_header);
+ Write32((u32)(fst_data.size() >> m_address_shift), 0x0428, disc_header);
+ Write32((u32)(fst_data.size() >> m_address_shift), 0x042c, disc_header);
- m_contents.AddReference(fst_address, m_fst_data);
+ m_contents.Add(fst_address, std::move(fst_data));
m_data_size = current_data_address;
}
-void DirectoryBlobPartition::WriteEntryData(u32* entry_offset, u8 type, u32 name_offset,
- u64 data_offset, u64 length, u32 address_shift)
+void DirectoryBlobPartition::WriteEntryData(std::vector<u8>* fst_data, u32* entry_offset, u8 type,
+ u32 name_offset, u64 data_offset, u64 length,
+ u32 address_shift)
{
- m_fst_data[(*entry_offset)++] = type;
+ (*fst_data)[(*entry_offset)++] = type;
- m_fst_data[(*entry_offset)++] = (name_offset >> 16) & 0xff;
- m_fst_data[(*entry_offset)++] = (name_offset >> 8) & 0xff;
- m_fst_data[(*entry_offset)++] = (name_offset)&0xff;
+ (*fst_data)[(*entry_offset)++] = (name_offset >> 16) & 0xff;
+ (*fst_data)[(*entry_offset)++] = (name_offset >> 8) & 0xff;
+ (*fst_data)[(*entry_offset)++] = (name_offset)&0xff;
- Write32((u32)(data_offset >> address_shift), *entry_offset, &m_fst_data);
+ Write32((u32)(data_offset >> address_shift), *entry_offset, fst_data);
*entry_offset += 4;
- Write32((u32)length, *entry_offset, &m_fst_data);
+ Write32((u32)length, *entry_offset, fst_data);
*entry_offset += 4;
}
-void DirectoryBlobPartition::WriteEntryName(u32* name_offset, const std::string& name,
- u64 name_table_offset)
+void DirectoryBlobPartition::WriteEntryName(std::vector<u8>* fst_data, u32* name_offset,
+ const std::string& name, u64 name_table_offset)
{
- strncpy((char*)&m_fst_data[*name_offset + name_table_offset], name.c_str(), name.length() + 1);
+ strncpy((char*)&(*fst_data)[*name_offset + name_table_offset], name.c_str(), name.length() + 1);
*name_offset += (u32)(name.length() + 1);
}
-void DirectoryBlobPartition::WriteDirectory(std::vector<FSTBuilderNode>* parent_entries,
+void DirectoryBlobPartition::WriteDirectory(std::vector<u8>* fst_data,
+ std::vector<FSTBuilderNode>* parent_entries,
u32* fst_offset, u32* name_offset, u64* data_offset,
u32 parent_entry_index, u64 name_table_offset)
{
@@ -1204,20 +1213,20 @@ void DirectoryBlobPartition::WriteDirectory(std::vector<FSTBuilderNode>* parent_
if (entry.IsFolder())
{
u32 entry_index = *fst_offset / ENTRY_SIZE;
- WriteEntryData(fst_offset, DIRECTORY_ENTRY, *name_offset, parent_entry_index,
+ WriteEntryData(fst_data, fst_offset, DIRECTORY_ENTRY, *name_offset, parent_entry_index,
entry_index + entry.m_size + 1, 0);
- WriteEntryName(name_offset, entry.m_filename, name_table_offset);
+ WriteEntryName(fst_data, name_offset, entry.m_filename, name_table_offset);
auto& child_nodes = entry.GetFolderContent();
- WriteDirectory(&child_nodes, fst_offset, name_offset, data_offset, entry_index,
+ WriteDirectory(fst_data, &child_nodes, fst_offset, name_offset, data_offset, entry_index,
name_table_offset);
}
else
{
// put entry in FST
- WriteEntryData(fst_offset, FILE_ENTRY, *name_offset, *data_offset, entry.m_size,
+ WriteEntryData(fst_data, fst_offset, FILE_ENTRY, *name_offset, *data_offset, entry.m_size,
m_address_shift);
- WriteEntryName(name_offset, entry.m_filename, name_table_offset);
+ WriteEntryName(fst_data, name_offset, entry.m_filename, name_table_offset);
// write entry to virtual disc
auto& contents = entry.GetFileContent();
diff --git a/Source/Core/DiscIO/DirectoryBlob.h b/Source/Core/DiscIO/DirectoryBlob.h
index 16c3cc4609..39fe05b163 100644
--- a/Source/Core/DiscIO/DirectoryBlob.h
+++ b/Source/Core/DiscIO/DirectoryBlob.h
@@ -46,13 +46,13 @@ struct ContentFile
u64 m_offset = 0;
};
+// Content chunk that's just a direct block of memory
+typedef std::shared_ptr<std::vector<u8>> ContentMemory;
+
// Content chunk that loads data from a DirectoryBlobReader.
// Intented for representing a partition within a disc.
struct ContentPartition
{
- // The reader to read data from.
- DirectoryBlobReader* m_reader;
-
// Offset from the start of the partition for the first byte represented by this chunk.
u64 m_offset = 0;
@@ -66,9 +66,6 @@ struct ContentVolume
// Offset from the start of the volume for the first byte represented by this chunk.
u64 m_offset = 0;
- // The volume to read data from.
- const Volume* m_volume = nullptr;
-
// The partition passed to the Volume's Read() method.
Partition m_partition;
};
@@ -80,18 +77,11 @@ struct ContentFixedByte
u8 m_byte = 0;
};
-// Content chunk representing an arbitrary byte sequence that's stored within the struct itself.
-struct ContentByteVector
-{
- std::vector<u8> m_bytes;
-};
-
using ContentSource = std::variant<ContentFile, // File
- const u8*, // Memory
+ ContentMemory, // Memory/Byte Sequence
ContentPartition, // Partition
ContentVolume, // Volume
- ContentFixedByte, // Fixed value padding
- ContentByteVector // Byte sequence
+ ContentFixedByte // Fixed value padding
>;
struct BuilderContentSource
@@ -147,7 +137,7 @@ public:
u64 GetOffset() const;
u64 GetEndOffset() const;
u64 GetSize() const;
- bool Read(u64* offset, u64* length, u8** buffer) const;
+ bool Read(u64* offset, u64* length, u8** buffer, DirectoryBlobReader* blob) const;
bool operator==(const DiscContent& other) const { return GetEndOffset() == other.GetEndOffset(); }
bool operator!=(const DiscContent& other) const { return !(*this == other); }
@@ -170,16 +160,16 @@ private:
class DiscContentContainer
{
public:
- template <typename T>
- void AddReference(u64 offset, const std::vector<T>& vector)
+ void Add(u64 offset, std::vector<u8> vector)
{
- return Add(offset, vector.size() * sizeof(T), reinterpret_cast<const u8*>(vector.data()));
+ size_t vector_size = vector.size();
+ return Add(offset, vector_size, std::make_shared<std::vector<u8>>(std::move(vector)));
}
void Add(u64 offset, u64 size, ContentSource source);
u64 CheckSizeAndAdd(u64 offset, const std::string& path);
u64 CheckSizeAndAdd(u64 offset, u64 max_size, const std::string& path);
- bool Read(u64 offset, u64 length, u8* buffer) const;
+ bool Read(u64 offset, u64 length, u8* buffer, DirectoryBlobReader* blob) const;
private:
std::set<DiscContent> m_contents;
@@ -194,11 +184,11 @@ public:
DiscIO::VolumeDisc* volume, const DiscIO::Partition& partition, std::optional<bool> is_wii,
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes)>& sys_callback,
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes, FSTBuilderNode* dol_node)>&
- fst_callback);
+ fst_callback,
+ DirectoryBlobReader* blob);
- // We do not allow copying, because it might mess up the pointers inside DiscContents
- DirectoryBlobPartition(const DirectoryBlobPartition&) = delete;
- DirectoryBlobPartition& operator=(const DirectoryBlobPartition&) = delete;
+ DirectoryBlobPartition(const DirectoryBlobPartition&) = default;
+ DirectoryBlobPartition& operator=(const DirectoryBlobPartition&) = default;
DirectoryBlobPartition(DirectoryBlobPartition&&) = default;
DirectoryBlobPartition& operator=(DirectoryBlobPartition&&) = default;
@@ -206,7 +196,6 @@ public:
u64 GetDataSize() const { return m_data_size; }
void SetDataSize(u64 size) { m_data_size = size; }
const std::string& GetRootDirectory() const { return m_root_directory; }
- const std::vector<u8>& GetHeader() const { return m_disc_header; }
const DiscContentContainer& GetContents() const { return m_contents; }
const std::optional<DiscIO::Partition>& GetWrappedPartition() const
{
@@ -217,9 +206,7 @@ public:
void SetKey(std::array<u8, VolumeWii::AES_KEY_SIZE> key) { m_key = key; }
private:
- void SetDiscHeaderFromFile(const std::string& boot_bin_path);
- void SetDiscHeader(std::vector<u8> boot_bin);
- void SetDiscType(std::optional<bool> is_wii);
+ void SetDiscType(std::optional<bool> is_wii, const std::vector<u8>& disc_header);
void SetBI2FromFile(const std::string& bi2_path);
void SetBI2(std::vector<u8> bi2);
@@ -227,25 +214,24 @@ private:
u64 SetApploaderFromFile(const std::string& path);
u64 SetApploader(std::vector<u8> apploader, const std::string& log_path);
// Returns FST address
- u64 SetDOLFromFile(const std::string& path, u64 dol_address);
- u64 SetDOL(FSTBuilderNode dol_node, u64 dol_address);
+ u64 SetDOLFromFile(const std::string& path, u64 dol_address, std::vector<u8>* disc_header);
+ u64 SetDOL(FSTBuilderNode dol_node, u64 dol_address, std::vector<u8>* disc_header);
- void BuildFSTFromFolder(const std::string& fst_root_path, u64 fst_address);
- void BuildFST(std::vector<FSTBuilderNode> root_nodes, u64 fst_address);
+ void BuildFSTFromFolder(const std::string& fst_root_path, u64 fst_address,
+ std::vector<u8>* disc_header);
+ void BuildFST(std::vector<FSTBuilderNode> root_nodes, u64 fst_address,
+ std::vector<u8>* disc_header);
// FST creation
- void WriteEntryData(u32* entry_offset, u8 type, u32 name_offset, u64 data_offset, u64 length,
- u32 address_shift);
- void WriteEntryName(u32* name_offset, const std::string& name, u64 name_table_offset);
- void WriteDirectory(std::vector<FSTBuilderNode>* parent_entries, u32* fst_offset,
- u32* name_offset, u64* data_offset, u32 parent_entry_index,
+ void WriteEntryData(std::vector<u8>* fst_data, u32* entry_offset, u8 type, u32 name_offset,
+ u64 data_offset, u64 length, u32 address_shift);
+ void WriteEntryName(std::vector<u8>* fst_data, u32* name_offset, const std::string& name,
+ u64 name_table_offset);
+ void WriteDirectory(std::vector<u8>* fst_data, std::vector<FSTBuilderNode>* parent_entries,
+ u32* fst_offset, u32* name_offset, u64* data_offset, u32 parent_entry_index,
u64 name_table_offset);
DiscContentContainer m_contents;
- std::vector<u8> m_disc_header;
- std::vector<u8> m_bi2;
- std::vector<u8> m_apploader;
- std::vector<u8> m_fst_data;
std::array<u8, VolumeWii::AES_KEY_SIZE> m_key{};
@@ -271,9 +257,6 @@ public:
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes, FSTBuilderNode* dol_node)>&
fst_callback);
- // We do not allow copying, because it might mess up the pointers inside DiscContents
- DirectoryBlobReader(const DirectoryBlobReader&) = delete;
- DirectoryBlobReader& operator=(const DirectoryBlobReader&) = delete;
DirectoryBlobReader(DirectoryBlobReader&&) = default;
DirectoryBlobReader& operator=(DirectoryBlobReader&&) = default;
@@ -282,6 +265,7 @@ public:
bool ReadWiiDecrypted(u64 offset, u64 size, u8* buffer, u64 partition_data_offset) override;
BlobType GetBlobType() const override;
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override;
u64 GetDataSize() const override;
@@ -311,6 +295,7 @@ private:
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes)>& sys_callback,
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes, FSTBuilderNode* dol_node)>&
fst_callback);
+ explicit DirectoryBlobReader(const DirectoryBlobReader& rhs);
const DirectoryBlobPartition* GetPartition(u64 offset, u64 size, u64 partition_data_offset) const;
@@ -326,6 +311,8 @@ private:
void SetPartitions(std::vector<PartitionWithType>&& partitions);
void SetPartitionHeader(DirectoryBlobPartition* partition, u64 partition_address);
+ DiscIO::VolumeDisc* GetWrappedVolume() { return m_wrapped_volume.get(); }
+
// For GameCube:
DirectoryBlobPartition m_gamecube_pseudopartition;
@@ -337,11 +324,6 @@ private:
bool m_is_wii;
bool m_encrypted;
- std::vector<u8> m_disc_header_nonpartition;
- std::vector<u8> m_partition_table;
- std::vector<u8> m_wii_region_data;
- std::vector<std::vector<u8>> m_extra_data;
-
u64 m_data_size;
std::unique_ptr<DiscIO::VolumeDisc> m_wrapped_volume;
diff --git a/Source/Core/DiscIO/DiscScrubber.cpp b/Source/Core/DiscIO/DiscScrubber.cpp
index 957fde32b9..41d59a03c2 100644
--- a/Source/Core/DiscIO/DiscScrubber.cpp
+++ b/Source/Core/DiscIO/DiscScrubber.cpp
@@ -22,7 +22,6 @@
namespace DiscIO
{
DiscScrubber::DiscScrubber() = default;
-DiscScrubber::~DiscScrubber() = default;
bool DiscScrubber::SetupScrub(const Volume& disc)
{
diff --git a/Source/Core/DiscIO/DiscScrubber.h b/Source/Core/DiscIO/DiscScrubber.h
index 87528fba3b..cf69615fdd 100644
--- a/Source/Core/DiscIO/DiscScrubber.h
+++ b/Source/Core/DiscIO/DiscScrubber.h
@@ -27,7 +27,6 @@ class DiscScrubber final
{
public:
DiscScrubber();
- ~DiscScrubber();
bool SetupScrub(const Volume& disc);
diff --git a/Source/Core/DiscIO/FileBlob.cpp b/Source/Core/DiscIO/FileBlob.cpp
index 6011f45ca9..97b95d1b8d 100644
--- a/Source/Core/DiscIO/FileBlob.cpp
+++ b/Source/Core/DiscIO/FileBlob.cpp
@@ -28,6 +28,11 @@ std::unique_ptr<PlainFileReader> PlainFileReader::Create(File::IOFile file)
return nullptr;
}
+std::unique_ptr<BlobReader> PlainFileReader::CopyReader() const
+{
+ return Create(m_file.Duplicate("rb"));
+}
+
bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
{
if (m_file.Seek(offset, File::SeekOrigin::Begin) && m_file.ReadBytes(out_ptr, nbytes))
diff --git a/Source/Core/DiscIO/FileBlob.h b/Source/Core/DiscIO/FileBlob.h
index 1f8bb8bcf6..66514e8a4b 100644
--- a/Source/Core/DiscIO/FileBlob.h
+++ b/Source/Core/DiscIO/FileBlob.h
@@ -19,6 +19,7 @@ public:
static std::unique_ptr<PlainFileReader> Create(File::IOFile file);
BlobType GetBlobType() const override { return BlobType::PLAIN; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override { return m_size; }
u64 GetDataSize() const override { return m_size; }
diff --git a/Source/Core/DiscIO/NFSBlob.cpp b/Source/Core/DiscIO/NFSBlob.cpp
index 3960fff75e..4b33596802 100644
--- a/Source/Core/DiscIO/NFSBlob.cpp
+++ b/Source/Core/DiscIO/NFSBlob.cpp
@@ -160,11 +160,20 @@ std::unique_ptr<NFSFileReader> NFSFileReader::Create(File::IOFile first_file,
NFSFileReader::NFSFileReader(std::vector<NFSLBARange> lba_ranges, std::vector<File::IOFile> files,
Key key, u64 raw_size)
: m_lba_ranges(std::move(lba_ranges)), m_files(std::move(files)),
- m_aes_context(Common::AES::CreateContextDecrypt(key.data())), m_raw_size(raw_size)
+ m_aes_context(Common::AES::CreateContextDecrypt(key.data())), m_raw_size(raw_size), m_key(key)
{
m_data_size = CalculateExpectedDataSize(m_lba_ranges);
}
+std::unique_ptr<BlobReader> NFSFileReader::CopyReader() const
+{
+ std::vector<File::IOFile> new_files{};
+ for (const File::IOFile& file : m_files)
+ new_files.push_back(file.Duplicate("rb"));
+ return std::unique_ptr<NFSFileReader>(
+ new NFSFileReader(m_lba_ranges, std::move(new_files), m_key, m_raw_size));
+}
+
u64 NFSFileReader::GetDataSize() const
{
return m_data_size;
diff --git a/Source/Core/DiscIO/NFSBlob.h b/Source/Core/DiscIO/NFSBlob.h
index c17687471d..78f7b871cb 100644
--- a/Source/Core/DiscIO/NFSBlob.h
+++ b/Source/Core/DiscIO/NFSBlob.h
@@ -45,6 +45,7 @@ public:
const std::string& directory_path);
BlobType GetBlobType() const override { return BlobType::NFS; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override;
u64 GetDataSize() const override;
@@ -86,6 +87,7 @@ private:
std::unique_ptr<Common::AES::Context> m_aes_context;
u64 m_raw_size;
u64 m_data_size;
+ Key m_key;
};
} // namespace DiscIO
diff --git a/Source/Core/DiscIO/RiivolutionPatcher.cpp b/Source/Core/DiscIO/RiivolutionPatcher.cpp
index 309e9e5ea1..9362a3930a 100644
--- a/Source/Core/DiscIO/RiivolutionPatcher.cpp
+++ b/Source/Core/DiscIO/RiivolutionPatcher.cpp
@@ -234,13 +234,23 @@ static void SplitAt(BuilderContentSource* before, BuilderContentSource* after, u
after->m_offset += before->m_size;
after->m_size = end - split_at;
if (std::holds_alternative<ContentFile>(after->m_source))
+ {
std::get<ContentFile>(after->m_source).m_offset += before->m_size;
- else if (std::holds_alternative<const u8*>(after->m_source))
- std::get<const u8*>(after->m_source) += before->m_size;
+ }
+ else if (std::holds_alternative<ContentMemory>(after->m_source))
+ {
+ after->m_source = std::make_shared<std::vector<u8>>(
+ std::get<ContentMemory>(after->m_source)->begin() + before->m_size,
+ std::get<ContentMemory>(after->m_source)->end());
+ }
else if (std::holds_alternative<ContentPartition>(after->m_source))
+ {
std::get<ContentPartition>(after->m_source).m_offset += before->m_size;
+ }
else if (std::holds_alternative<ContentVolume>(after->m_source))
+ {
std::get<ContentVolume>(after->m_source).m_offset += before->m_size;
+ }
}
static void ApplyPatchToFile(const Patch& patch, DiscIO::FSTBuilderNode* file_node,
diff --git a/Source/Core/DiscIO/ScrubbedBlob.cpp b/Source/Core/DiscIO/ScrubbedBlob.cpp
index 84a123e4de..dd8908e303 100644
--- a/Source/Core/DiscIO/ScrubbedBlob.cpp
+++ b/Source/Core/DiscIO/ScrubbedBlob.cpp
@@ -37,6 +37,11 @@ std::unique_ptr<ScrubbedBlob> ScrubbedBlob::Create(const std::string& path)
return std::unique_ptr<ScrubbedBlob>(new ScrubbedBlob(std::move(blob), std::move(scrubber)));
}
+std::unique_ptr<BlobReader> ScrubbedBlob::CopyReader() const
+{
+ return std::unique_ptr<ScrubbedBlob>(new ScrubbedBlob(m_blob_reader->CopyReader(), m_scrubber));
+}
+
bool ScrubbedBlob::Read(u64 offset, u64 size, u8* out_ptr)
{
while (size > 0)
diff --git a/Source/Core/DiscIO/ScrubbedBlob.h b/Source/Core/DiscIO/ScrubbedBlob.h
index fa5648630b..bd129f65b0 100644
--- a/Source/Core/DiscIO/ScrubbedBlob.h
+++ b/Source/Core/DiscIO/ScrubbedBlob.h
@@ -19,6 +19,7 @@ public:
static std::unique_ptr<ScrubbedBlob> Create(const std::string& path);
BlobType GetBlobType() const override { return m_blob_reader->GetBlobType(); }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override { return m_blob_reader->GetRawSize(); }
u64 GetDataSize() const override { return m_blob_reader->GetDataSize(); }
diff --git a/Source/Core/DiscIO/SplitFileBlob.cpp b/Source/Core/DiscIO/SplitFileBlob.cpp
index f3a0895614..4756088a40 100644
--- a/Source/Core/DiscIO/SplitFileBlob.cpp
+++ b/Source/Core/DiscIO/SplitFileBlob.cpp
@@ -56,6 +56,17 @@ std::unique_ptr<SplitPlainFileReader> SplitPlainFileReader::Create(std::string_v
return std::unique_ptr<SplitPlainFileReader>(new SplitPlainFileReader(std::move(files)));
}
+std::unique_ptr<BlobReader> SplitPlainFileReader::CopyReader() const
+{
+ std::vector<SingleFile> new_files{};
+ for (const SingleFile& file : m_files)
+ {
+ new_files.push_back(
+ {.file = file.file.Duplicate("rb"), .offset = file.offset, .size = file.size});
+ }
+ return std::unique_ptr<SplitPlainFileReader>(new SplitPlainFileReader(std::move(new_files)));
+}
+
bool SplitPlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
{
if (offset >= m_size)
diff --git a/Source/Core/DiscIO/SplitFileBlob.h b/Source/Core/DiscIO/SplitFileBlob.h
index 4b3c635150..d3268dca80 100644
--- a/Source/Core/DiscIO/SplitFileBlob.h
+++ b/Source/Core/DiscIO/SplitFileBlob.h
@@ -21,6 +21,7 @@ public:
static std::unique_ptr<SplitPlainFileReader> Create(std::string_view first_file_path);
BlobType GetBlobType() const override { return BlobType::SPLIT_PLAIN; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override { return m_size; }
u64 GetDataSize() const override { return m_size; }
diff --git a/Source/Core/DiscIO/TGCBlob.cpp b/Source/Core/DiscIO/TGCBlob.cpp
index c61d0763a4..94ad394861 100644
--- a/Source/Core/DiscIO/TGCBlob.cpp
+++ b/Source/Core/DiscIO/TGCBlob.cpp
@@ -98,6 +98,11 @@ TGCFileReader::TGCFileReader(File::IOFile file) : m_file(std::move(file))
}
}
+std::unique_ptr<BlobReader> TGCFileReader::CopyReader() const
+{
+ return Create(m_file.Duplicate("rb"));
+}
+
u64 TGCFileReader::GetDataSize() const
{
return m_size - Common::swap32(m_header.tgc_header_size);
diff --git a/Source/Core/DiscIO/TGCBlob.h b/Source/Core/DiscIO/TGCBlob.h
index 2db1c9e8b7..2952f2809f 100644
--- a/Source/Core/DiscIO/TGCBlob.h
+++ b/Source/Core/DiscIO/TGCBlob.h
@@ -42,6 +42,7 @@ public:
static std::unique_ptr<TGCFileReader> Create(File::IOFile file);
BlobType GetBlobType() const override { return BlobType::TGC; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override { return m_size; }
u64 GetDataSize() const override;
diff --git a/Source/Core/DiscIO/VolumeFileBlobReader.cpp b/Source/Core/DiscIO/VolumeFileBlobReader.cpp
index f6be7e3a34..7cbc06e589 100644
--- a/Source/Core/DiscIO/VolumeFileBlobReader.cpp
+++ b/Source/Core/DiscIO/VolumeFileBlobReader.cpp
@@ -33,6 +33,12 @@ VolumeFileBlobReader::VolumeFileBlobReader(const Volume& volume, const Partition
{
}
+std::unique_ptr<BlobReader> VolumeFileBlobReader::CopyReader() const
+{
+ ASSERT_MSG(DISCIO, false, "Unimplemented");
+ return nullptr;
+}
+
u64 VolumeFileBlobReader::GetDataSize() const
{
return m_file_info->GetSize();
diff --git a/Source/Core/DiscIO/VolumeFileBlobReader.h b/Source/Core/DiscIO/VolumeFileBlobReader.h
index 89b87a9470..58d349a0d4 100644
--- a/Source/Core/DiscIO/VolumeFileBlobReader.h
+++ b/Source/Core/DiscIO/VolumeFileBlobReader.h
@@ -22,6 +22,7 @@ public:
Create(const Volume& volume, const Partition& partition, std::string_view file_path);
BlobType GetBlobType() const override { return BlobType::PLAIN; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override;
u64 GetDataSize() const override;
diff --git a/Source/Core/DiscIO/WIABlob.cpp b/Source/Core/DiscIO/WIABlob.cpp
index 65c6aaa484..a9496fe5a0 100644
--- a/Source/Core/DiscIO/WIABlob.cpp
+++ b/Source/Core/DiscIO/WIABlob.cpp
@@ -79,7 +79,7 @@ std::pair<int, int> GetAllowedCompressionLevels(WIARVZCompressionType compressio
template <bool RVZ>
WIARVZFileReader<RVZ>::WIARVZFileReader(File::IOFile file, const std::string& path)
- : m_file(std::move(file)), m_encryption_cache(this)
+ : m_file(std::move(file)), m_path(path), m_encryption_cache(this)
{
m_valid = Initialize(path);
}
@@ -287,6 +287,12 @@ BlobType WIARVZFileReader<RVZ>::GetBlobType() const
}
template <bool RVZ>
+std::unique_ptr<BlobReader> WIARVZFileReader<RVZ>::CopyReader() const
+{
+ return Create(m_file.Duplicate("rb"), m_path);
+}
+
+template <bool RVZ>
std::string WIARVZFileReader<RVZ>::GetCompressionMethod() const
{
switch (m_compression_type)
diff --git a/Source/Core/DiscIO/WIABlob.h b/Source/Core/DiscIO/WIABlob.h
index 633c5801ce..c5a5476c09 100644
--- a/Source/Core/DiscIO/WIABlob.h
+++ b/Source/Core/DiscIO/WIABlob.h
@@ -49,6 +49,7 @@ public:
static std::unique_ptr<WIARVZFileReader> Create(File::IOFile file, const std::string& path);
BlobType GetBlobType() const override;
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override { return Common::swap64(m_header_1.wia_file_size); }
u64 GetDataSize() const override { return Common::swap64(m_header_1.iso_file_size); }
@@ -365,6 +366,7 @@ private:
WIARVZCompressionType m_compression_type;
File::IOFile m_file;
+ std::string m_path;
Chunk m_cached_chunk;
u64 m_cached_chunk_offset = std::numeric_limits<u64>::max();
WiiEncryptionCache m_encryption_cache;
diff --git a/Source/Core/DiscIO/WbfsBlob.cpp b/Source/Core/DiscIO/WbfsBlob.cpp
index d35b0b76a4..d61799a77a 100644
--- a/Source/Core/DiscIO/WbfsBlob.cpp
+++ b/Source/Core/DiscIO/WbfsBlob.cpp
@@ -29,7 +29,8 @@ WbfsFileReader::WbfsFileReader(File::IOFile file, const std::string& path)
{
if (!AddFileToList(std::move(file)))
return;
- OpenAdditionalFiles(path);
+ if (!path.empty())
+ OpenAdditionalFiles(path);
if (!ReadHeader())
return;
m_good = true;
@@ -47,6 +48,15 @@ WbfsFileReader::~WbfsFileReader()
{
}
+std::unique_ptr<BlobReader> WbfsFileReader::CopyReader() const
+{
+ auto retval =
+ std::unique_ptr<WbfsFileReader>(new WbfsFileReader(m_files[0].file.Duplicate("rb")));
+ for (size_t ix = 1; ix < m_files.size(); ix++)
+ retval->AddFileToList(m_files[ix].file.Duplicate("rb"));
+ return retval;
+}
+
u64 WbfsFileReader::GetDataSize() const
{
return WII_SECTOR_COUNT * WII_SECTOR_SIZE;
diff --git a/Source/Core/DiscIO/WbfsBlob.h b/Source/Core/DiscIO/WbfsBlob.h
index a981790f1c..52af3f9e06 100644
--- a/Source/Core/DiscIO/WbfsBlob.h
+++ b/Source/Core/DiscIO/WbfsBlob.h
@@ -23,6 +23,7 @@ public:
static std::unique_ptr<WbfsFileReader> Create(File::IOFile file, const std::string& path);
BlobType GetBlobType() const override { return BlobType::WBFS; }
+ std::unique_ptr<BlobReader> CopyReader() const override;
u64 GetRawSize() const override { return m_size; }
u64 GetDataSize() const override;
@@ -36,7 +37,7 @@ public:
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
private:
- WbfsFileReader(File::IOFile file, const std::string& path);
+ WbfsFileReader(File::IOFile file, const std::string& path = "");
void OpenAdditionalFiles(const std::string& path);
bool AddFileToList(File::IOFile file);