Merge pull request #12036 from LillyJadeKatrin/deep-copy-volume
Added CopyReader to BlobReader and all subclasses
This commit is contained in:
commit
cd366c4f46
|
@ -101,6 +101,15 @@ bool IOFile::Close()
|
|||
return m_good;
|
||||
}
|
||||
|
||||
IOFile IOFile::Duplicate(const char openmode[]) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return IOFile(_fdopen(_dup(_fileno(m_file)), openmode));
|
||||
#else // _WIN32
|
||||
return IOFile(fdopen(dup(fileno(m_file)), openmode));
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
void IOFile::SetHandle(std::FILE* file)
|
||||
{
|
||||
Close();
|
||||
|
|
|
@ -51,6 +51,8 @@ public:
|
|||
SharedAccess sh = SharedAccess::Default);
|
||||
bool Close();
|
||||
|
||||
IOFile Duplicate(const char openmode[]) const;
|
||||
|
||||
template <typename T>
|
||||
bool ReadArray(T* elements, size_t count, size_t* num_read = nullptr)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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, ®ion_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);
|
||||
const u64 new_fst_address = SetDOL(std::move(dol_node), new_dol_address, &disc_header);
|
||||
BuildFST(std::move(nodes), new_fst_address, &disc_header);
|
||||
|
||||
m_contents.Add(DISCHEADER_ADDRESS, disc_header);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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, ¤t_data_address, root_offset,
|
||||
name_table_offset);
|
||||
WriteDirectory(&fst_data, &root_nodes, &fst_offset, &name_offset, ¤t_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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
namespace DiscIO
|
||||
{
|
||||
DiscScrubber::DiscScrubber() = default;
|
||||
DiscScrubber::~DiscScrubber() = default;
|
||||
|
||||
bool DiscScrubber::SetupScrub(const Volume& disc)
|
||||
{
|
||||
|
|
|
@ -27,7 +27,6 @@ class DiscScrubber final
|
|||
{
|
||||
public:
|
||||
DiscScrubber();
|
||||
~DiscScrubber();
|
||||
|
||||
bool SetupScrub(const Volume& disc);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -286,6 +286,12 @@ BlobType WIARVZFileReader<RVZ>::GetBlobType() const
|
|||
return RVZ ? BlobType::RVZ : BlobType::WIA;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue