From d6260e02ce5561a614fc051c7340fe6c803399cd Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 1 Aug 2017 17:45:46 +0200 Subject: DirectoryBlob: Replace std::set with a new class --- Source/Core/DiscIO/DirectoryBlob.cpp | 144 ++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 71 deletions(-) (limited to 'Source/Core/DiscIO/DirectoryBlob.cpp') diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index 364405aa01..e017bfca78 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -33,10 +32,6 @@ namespace DiscIO { -static const DiscContent& AddFileToContents(std::set* contents, - const std::string& path, u64 offset, - u64 max_size = UINT64_MAX); - // Reads as many bytes as the vector fits (or less, if the file is smaller). // Returns the number of bytes read. static size_t ReadFileToVector(const std::string& path, std::vector* vector); @@ -120,6 +115,58 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer) const return true; } +const DiscContent& DiscContentContainer::Add(u64 offset, u64 size, const std::string& path) +{ + return *(m_contents.emplace(offset, size, path).first); +} + +const DiscContent& DiscContentContainer::Add(u64 offset, u64 size, const u8* data) +{ + return *(m_contents.emplace(offset, size, data).first); +} + +const DiscContent& DiscContentContainer::CheckSizeAndAdd(u64 offset, const std::string& path) +{ + return Add(offset, File::GetSize(path), path); +} + +const DiscContent& DiscContentContainer::CheckSizeAndAdd(u64 offset, u64 max_size, + const std::string& path) +{ + return Add(offset, std::min(File::GetSize(path), max_size), path); +} + +bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer) const +{ + if (m_contents.empty()) + return true; + + // Determine which DiscContent the offset refers to + std::set::const_iterator it = m_contents.lower_bound(DiscContent(offset)); + if (it->GetOffset() > offset && it != m_contents.begin()) + --it; + + // zero fill to start of file data + PadToAddress(it->GetOffset(), &offset, &length, &buffer); + + while (it != m_contents.end() && length > 0) + { + _dbg_assert_(DISCIO, it->GetOffset() <= offset); + if (!it->Read(&offset, &length, &buffer)) + return false; + + ++it; + + if (it != m_contents.end()) + { + _dbg_assert_(DISCIO, it->GetOffset() >= offset); + PadToAddress(it->GetOffset(), &offset, &length, &buffer); + } + } + + return true; +} + static std::optional ParsePartitionDirectoryName(const std::string& name) { if (name.size() < 2) @@ -322,45 +369,11 @@ DirectoryBlobReader::DirectoryBlobReader(const std::string& game_partition_root, } } -bool DirectoryBlobReader::ReadInternal(u64 offset, u64 length, u8* buffer, - const std::set& contents) -{ - if (contents.empty()) - return true; - - // Determine which DiscContent the offset refers to - std::set::const_iterator it = contents.lower_bound(DiscContent(offset)); - if (it->GetOffset() > offset && it != contents.begin()) - --it; - - // zero fill to start of file data - PadToAddress(it->GetOffset(), &offset, &length, &buffer); - - while (it != contents.end() && length > 0) - { - _dbg_assert_(DISCIO, it->GetOffset() <= offset); - if (!it->Read(&offset, &length, &buffer)) - return false; - - ++it; - - if (it != contents.end()) - { - _dbg_assert_(DISCIO, it->GetOffset() >= offset); - PadToAddress(it->GetOffset(), &offset, &length, &buffer); - } - } - - return true; -} - bool DirectoryBlobReader::Read(u64 offset, u64 length, u8* buffer) { // TODO: We don't handle raw access to the encrypted area of Wii discs correctly. - - const std::set& contents = - m_is_wii ? m_nonpartition_contents : m_gamecube_pseudopartition.GetContents(); - return ReadInternal(offset, length, buffer, contents); + return (m_is_wii ? m_nonpartition_contents : m_gamecube_pseudopartition.GetContents()) + .Read(offset, length, buffer); } bool DirectoryBlobReader::SupportsReadWiiDecrypted() const @@ -377,7 +390,7 @@ bool DirectoryBlobReader::ReadWiiDecrypted(u64 offset, u64 size, u8* buffer, u64 if (it == m_partitions.end()) return false; - return ReadInternal(offset, size, buffer, it->second.GetContents()); + return it->second.GetContents().Read(offset, size, buffer); } BlobType DirectoryBlobReader::GetBlobType() const @@ -417,8 +430,7 @@ void DirectoryBlobReader::SetNonpartitionDiscHeader(const std::vector& parti if (header_bin_bytes_read < 0x61) m_disc_header_nonpartition[0x61] = 0; - m_nonpartition_contents.emplace(NONPARTITION_DISCHEADER_ADDRESS, NONPARTITION_DISCHEADER_SIZE, - m_disc_header_nonpartition.data()); + m_nonpartition_contents.Add(NONPARTITION_DISCHEADER_ADDRESS, m_disc_header_nonpartition); } void DirectoryBlobReader::SetWiiRegionData(const std::string& game_partition_root) @@ -436,8 +448,7 @@ void DirectoryBlobReader::SetWiiRegionData(const std::string& game_partition_roo constexpr u64 WII_REGION_DATA_ADDRESS = 0x4E000; constexpr u64 WII_REGION_DATA_SIZE = 0x20; - m_nonpartition_contents.emplace(WII_REGION_DATA_ADDRESS, WII_REGION_DATA_SIZE, - m_wii_region_data.data()); + m_nonpartition_contents.Add(WII_REGION_DATA_ADDRESS, m_wii_region_data); } void DirectoryBlobReader::SetPartitions(std::vector&& partitions) @@ -501,8 +512,7 @@ void DirectoryBlobReader::SetPartitions(std::vector&& partiti } m_data_size = partition_address; - m_nonpartition_contents.emplace(PARTITION_TABLE_ADDRESS, m_partition_table.size(), - m_partition_table.data()); + m_nonpartition_contents.Add(PARTITION_TABLE_ADDRESS, m_partition_table); } // This function sets the header that's shortly before the start of the encrypted @@ -519,19 +529,19 @@ void DirectoryBlobReader::SetPartitionHeader(const DirectoryBlobPartition& parti const std::string& partition_root = partition.GetRootDirectory(); - AddFileToContents(&m_nonpartition_contents, partition_root + "ticket.bin", - partition_address + TICKET_OFFSET, TICKET_SIZE); + m_nonpartition_contents.CheckSizeAndAdd(partition_address + TICKET_OFFSET, TICKET_SIZE, + partition_root + "ticket.bin"); - const DiscContent& tmd = AddFileToContents(&m_nonpartition_contents, partition_root + "tmd.bin", - partition_address + TMD_OFFSET, MAX_TMD_SIZE); + const DiscContent& tmd = m_nonpartition_contents.CheckSizeAndAdd( + partition_address + TMD_OFFSET, MAX_TMD_SIZE, partition_root + "tmd.bin"); const u64 cert_offset = Common::AlignUp(TMD_OFFSET + tmd.GetSize(), 0x20ull); const u64 max_cert_size = H3_OFFSET - cert_offset; - const DiscContent& cert = AddFileToContents(&m_nonpartition_contents, partition_root + "cert.bin", - partition_address + cert_offset, max_cert_size); + const DiscContent& cert = m_nonpartition_contents.CheckSizeAndAdd( + partition_address + cert_offset, max_cert_size, partition_root + "cert.bin"); - AddFileToContents(&m_nonpartition_contents, partition_root + "h3.bin", - partition_address + H3_OFFSET, H3_SIZE); + m_nonpartition_contents.CheckSizeAndAdd(partition_address + H3_OFFSET, H3_SIZE, + partition_root + "h3.bin"); constexpr u32 PARTITION_HEADER_SIZE = 0x1c; constexpr u32 DATA_OFFSET = 0x20000; @@ -546,8 +556,7 @@ void DirectoryBlobReader::SetPartitionHeader(const DirectoryBlobPartition& parti Write32(DATA_OFFSET >> 2, 0x14, &partition_header); Write32(static_cast(data_size >> 2), 0x18, &partition_header); - m_nonpartition_contents.emplace(partition_address + TICKET_SIZE, PARTITION_HEADER_SIZE, - partition_header.data()); + m_nonpartition_contents.Add(partition_address + TICKET_SIZE, partition_header); } DirectoryBlobPartition::DirectoryBlobPartition(const std::string& root_directory, @@ -569,7 +578,7 @@ void DirectoryBlobPartition::SetDiscHeaderAndDiscType(std::optional is_wii if (ReadFileToVector(boot_bin_path, &m_disc_header) < 0x20) ERROR_LOG(DISCIO, "%s doesn't exist or is too small", boot_bin_path.c_str()); - m_contents.emplace(DISCHEADER_ADDRESS, DISCHEADER_SIZE, m_disc_header.data()); + m_contents.Add(DISCHEADER_ADDRESS, m_disc_header); if (is_wii.has_value()) { @@ -600,7 +609,7 @@ void DirectoryBlobPartition::SetBI2() if (!m_is_wii && bytes_read < 0x1C) ERROR_LOG(DISCIO, "Couldn't read region from %s", bi2_path.c_str()); - m_contents.emplace(BI2_ADDRESS, BI2_SIZE, m_bi2.data()); + m_contents.Add(BI2_ADDRESS, m_bi2); } u64 DirectoryBlobPartition::SetApploader() @@ -633,7 +642,7 @@ u64 DirectoryBlobPartition::SetApploader() constexpr u64 APPLOADER_ADDRESS = 0x2440; - m_contents.emplace(APPLOADER_ADDRESS, m_apploader.size(), m_apploader.data()); + m_contents.Add(APPLOADER_ADDRESS, m_apploader); // Return DOL address, 32 byte aligned (plus 32 byte padding) return Common::AlignUp(APPLOADER_ADDRESS + m_apploader.size() + 0x20, 0x20ull); @@ -642,7 +651,7 @@ u64 DirectoryBlobPartition::SetApploader() u64 DirectoryBlobPartition::SetDOL(u64 dol_address) { const DiscContent& dol = - AddFileToContents(&m_contents, m_root_directory + "sys/main.dol", dol_address); + m_contents.CheckSizeAndAdd(dol_address, m_root_directory + "sys/main.dol"); Write32(static_cast(dol_address >> m_address_shift), 0x0420, &m_disc_header); @@ -685,7 +694,7 @@ void DirectoryBlobPartition::BuildFST(u64 fst_address) 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); - m_contents.emplace(fst_address, m_fst_data.size(), m_fst_data.data()); + m_contents.Add(fst_address, m_fst_data); m_data_size = current_data_address; } @@ -747,8 +756,7 @@ void DirectoryBlobPartition::WriteDirectory(const File::FSTEntry& parent_entry, WriteEntryName(name_offset, entry.virtualName, name_table_offset); // write entry to virtual disc - auto result = m_contents.emplace(*data_offset, entry.size, entry.physicalName); - _dbg_assert_(DISCIO, result.second); // Check that this offset wasn't already occupied + auto result = m_contents.Add(*data_offset, entry.size, entry.physicalName); // 32 KiB aligned - many games are fine with less alignment, but not all *data_offset = Common::AlignUp(*data_offset + std::max(entry.size, 1ull), 0x8000ull); @@ -756,12 +764,6 @@ void DirectoryBlobPartition::WriteDirectory(const File::FSTEntry& parent_entry, } } -static const DiscContent& AddFileToContents(std::set* contents, - const std::string& path, u64 offset, u64 max_size) -{ - return *(contents->emplace(offset, std::min(File::GetSize(path), max_size), path).first); -} - static size_t ReadFileToVector(const std::string& path, std::vector* vector) { File::IOFile file(path, "rb"); -- cgit v1.2.3 From 1b1a75ee3ad52db3fca36158dca318376ebd0bb0 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 1 Aug 2017 19:04:33 +0200 Subject: DirectoryBlob: Lookup DiscContents by offset + size instead of offset This simplifies DiscContentContainer::Read. --- Source/Core/DiscIO/DirectoryBlob.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Source/Core/DiscIO/DirectoryBlob.cpp') diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index e017bfca78..320d3ed054 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -77,6 +77,11 @@ u64 DiscContent::GetOffset() const return m_offset; } +u64 DiscContent::GetEndOffset() const +{ + return m_offset + m_size; +} + u64 DiscContent::GetSize() const { return m_size; @@ -138,13 +143,8 @@ const DiscContent& DiscContentContainer::CheckSizeAndAdd(u64 offset, u64 max_siz bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer) const { - if (m_contents.empty()) - return true; - // Determine which DiscContent the offset refers to - std::set::const_iterator it = m_contents.lower_bound(DiscContent(offset)); - if (it->GetOffset() > offset && it != m_contents.begin()) - --it; + std::set::const_iterator it = m_contents.upper_bound(DiscContent(offset)); // zero fill to start of file data PadToAddress(it->GetOffset(), &offset, &length, &buffer); -- cgit v1.2.3 From 78fa98f5593ec61a505a56d89984e41885715313 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 1 Aug 2017 19:13:19 +0200 Subject: DirectoryBlob: Change the return type of Add/CheckSizeAndAdd Only return the information that isn't already known to the caller. --- Source/Core/DiscIO/DirectoryBlob.cpp | 38 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'Source/Core/DiscIO/DirectoryBlob.cpp') diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index 320d3ed054..bca7c66a9b 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -120,25 +120,28 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer) const return true; } -const DiscContent& DiscContentContainer::Add(u64 offset, u64 size, const std::string& path) +void DiscContentContainer::Add(u64 offset, u64 size, const std::string& path) { - return *(m_contents.emplace(offset, size, path).first); + m_contents.emplace(offset, size, path); } -const DiscContent& DiscContentContainer::Add(u64 offset, u64 size, const u8* data) +void DiscContentContainer::Add(u64 offset, u64 size, const u8* data) { - return *(m_contents.emplace(offset, size, data).first); + m_contents.emplace(offset, size, data); } -const DiscContent& DiscContentContainer::CheckSizeAndAdd(u64 offset, const std::string& path) +u64 DiscContentContainer::CheckSizeAndAdd(u64 offset, const std::string& path) { - return Add(offset, File::GetSize(path), path); + const u64 size = File::GetSize(path); + Add(offset, size, path); + return size; } -const DiscContent& DiscContentContainer::CheckSizeAndAdd(u64 offset, u64 max_size, - const std::string& path) +u64 DiscContentContainer::CheckSizeAndAdd(u64 offset, u64 max_size, const std::string& path) { - return Add(offset, std::min(File::GetSize(path), max_size), path); + const u64 size = std::min(File::GetSize(path), max_size); + Add(offset, size, path); + return size; } bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer) const @@ -532,12 +535,12 @@ void DirectoryBlobReader::SetPartitionHeader(const DirectoryBlobPartition& parti m_nonpartition_contents.CheckSizeAndAdd(partition_address + TICKET_OFFSET, TICKET_SIZE, partition_root + "ticket.bin"); - const DiscContent& tmd = m_nonpartition_contents.CheckSizeAndAdd( + const u64 tmd_size = m_nonpartition_contents.CheckSizeAndAdd( partition_address + TMD_OFFSET, MAX_TMD_SIZE, partition_root + "tmd.bin"); - const u64 cert_offset = Common::AlignUp(TMD_OFFSET + tmd.GetSize(), 0x20ull); + const u64 cert_offset = Common::AlignUp(TMD_OFFSET + tmd_size, 0x20ull); const u64 max_cert_size = H3_OFFSET - cert_offset; - const DiscContent& cert = m_nonpartition_contents.CheckSizeAndAdd( + const u64 cert_size = m_nonpartition_contents.CheckSizeAndAdd( partition_address + cert_offset, max_cert_size, partition_root + "cert.bin"); m_nonpartition_contents.CheckSizeAndAdd(partition_address + H3_OFFSET, H3_SIZE, @@ -548,9 +551,9 @@ void DirectoryBlobReader::SetPartitionHeader(const DirectoryBlobPartition& parti const u64 data_size = Common::AlignUp(partition.GetDataSize(), 0x7c00) / 0x7c00 * 0x8000; m_partition_headers.emplace_back(PARTITION_HEADER_SIZE); std::vector& partition_header = m_partition_headers.back(); - Write32(static_cast(tmd.GetSize()), 0x0, &partition_header); + Write32(static_cast(tmd_size), 0x0, &partition_header); Write32(TMD_OFFSET >> 2, 0x4, &partition_header); - Write32(static_cast(cert.GetSize()), 0x8, &partition_header); + Write32(static_cast(cert_size), 0x8, &partition_header); Write32(static_cast(cert_offset >> 2), 0x0C, &partition_header); Write32(H3_OFFSET >> 2, 0x10, &partition_header); Write32(DATA_OFFSET >> 2, 0x14, &partition_header); @@ -650,13 +653,12 @@ u64 DirectoryBlobPartition::SetApploader() u64 DirectoryBlobPartition::SetDOL(u64 dol_address) { - const DiscContent& dol = - m_contents.CheckSizeAndAdd(dol_address, m_root_directory + "sys/main.dol"); + const u64 dol_size = m_contents.CheckSizeAndAdd(dol_address, m_root_directory + "sys/main.dol"); Write32(static_cast(dol_address >> m_address_shift), 0x0420, &m_disc_header); // Return FST address, 32 byte aligned (plus 32 byte padding) - return Common::AlignUp(dol_address + dol.GetSize() + 0x20, 0x20ull); + return Common::AlignUp(dol_address + dol_size + 0x20, 0x20ull); } void DirectoryBlobPartition::BuildFST(u64 fst_address) @@ -756,7 +758,7 @@ void DirectoryBlobPartition::WriteDirectory(const File::FSTEntry& parent_entry, WriteEntryName(name_offset, entry.virtualName, name_table_offset); // write entry to virtual disc - auto result = m_contents.Add(*data_offset, entry.size, entry.physicalName); + m_contents.Add(*data_offset, entry.size, entry.physicalName); // 32 KiB aligned - many games are fine with less alignment, but not all *data_offset = Common::AlignUp(*data_offset + std::max(entry.size, 1ull), 0x8000ull); -- cgit v1.2.3 From 6b0a60d2ee24f3a7dde6eb97f22623696807651e Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 1 Aug 2017 19:21:38 +0200 Subject: DirectoryBlob: Don't add DiscContents with size 0 Having DiscContents with size 0 would mean that some DiscContents might not get added to the std::set because of them comparing identically to another DiscContent. This replaces an older piece of code in WriteDirectory that ensures that no two files have the same starting offset. (We now care about the ending offset, not the starting offset. The new solution both ensures that no two files have the same ending offset and that no two files have the same starting offset.) --- Source/Core/DiscIO/DirectoryBlob.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'Source/Core/DiscIO/DirectoryBlob.cpp') diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index bca7c66a9b..dfdc87ffb0 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -122,12 +122,14 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer) const void DiscContentContainer::Add(u64 offset, u64 size, const std::string& path) { - m_contents.emplace(offset, size, path); + if (size != 0) + m_contents.emplace(offset, size, path); } void DiscContentContainer::Add(u64 offset, u64 size, const u8* data) { - m_contents.emplace(offset, size, data); + if (size != 0) + m_contents.emplace(offset, size, data); } u64 DiscContentContainer::CheckSizeAndAdd(u64 offset, const std::string& path) @@ -761,7 +763,7 @@ void DirectoryBlobPartition::WriteDirectory(const File::FSTEntry& parent_entry, m_contents.Add(*data_offset, entry.size, entry.physicalName); // 32 KiB aligned - many games are fine with less alignment, but not all - *data_offset = Common::AlignUp(*data_offset + std::max(entry.size, 1ull), 0x8000ull); + *data_offset = Common::AlignUp(*data_offset + entry.size, 0x8000ull); } } } -- cgit v1.2.3 From 74ada98e84487a8173a2d9f53f9f66d1111086fc Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 1 Aug 2017 19:35:01 +0200 Subject: DirectoryBlob: Remove redundant assert DiscContent::Read contains an equivalent assertion. --- Source/Core/DiscIO/DirectoryBlob.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'Source/Core/DiscIO/DirectoryBlob.cpp') diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index dfdc87ffb0..d4dc3c872b 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -156,7 +156,6 @@ bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer) const while (it != m_contents.end() && length > 0) { - _dbg_assert_(DISCIO, it->GetOffset() <= offset); if (!it->Read(&offset, &length, &buffer)) return false; -- cgit v1.2.3 From b155c46aca55b18053bc9a8a83893b87d0dcb1fb Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 1 Aug 2017 19:33:49 +0200 Subject: DirectoryBlob: Fix reading beyond the end of the disc There were two problems with this: 1. If the starting offset was beyond the end of the disc, we would dereference an invalid iterator. 2. The data beyond the end of the disc was non-deterministic. --- Source/Core/DiscIO/DirectoryBlob.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'Source/Core/DiscIO/DirectoryBlob.cpp') diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index d4dc3c872b..696877b528 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -151,23 +151,21 @@ bool DiscContentContainer::Read(u64 offset, u64 length, u8* buffer) const // Determine which DiscContent the offset refers to std::set::const_iterator it = m_contents.upper_bound(DiscContent(offset)); - // zero fill to start of file data - PadToAddress(it->GetOffset(), &offset, &length, &buffer); - while (it != m_contents.end() && length > 0) { + // Zero fill to start of DiscContent data + PadToAddress(it->GetOffset(), &offset, &length, &buffer); + if (!it->Read(&offset, &length, &buffer)) return false; ++it; - - if (it != m_contents.end()) - { - _dbg_assert_(DISCIO, it->GetOffset() >= offset); - PadToAddress(it->GetOffset(), &offset, &length, &buffer); - } + _dbg_assert_(DISCIO, it == m_contents.end() || it->GetOffset() >= offset); } + // Zero fill if we went beyond the last DiscContent + std::fill_n(buffer, static_cast(length), 0); + return true; } -- cgit v1.2.3