diff options
Diffstat (limited to 'Source/Core/DiscIO/DiscScrubber.cpp')
| -rw-r--r-- | Source/Core/DiscIO/DiscScrubber.cpp | 159 |
1 files changed, 59 insertions, 100 deletions
diff --git a/Source/Core/DiscIO/DiscScrubber.cpp b/Source/Core/DiscIO/DiscScrubber.cpp index e00311e86f..ac3a39f4c6 100644 --- a/Source/Core/DiscIO/DiscScrubber.cpp +++ b/Source/Core/DiscIO/DiscScrubber.cpp @@ -123,15 +123,15 @@ void DiscScrubber::MarkAsUsedE(u64 partition_data_offset, u64 offset, u64 size) } // Helper functions for reading the BE volume -bool DiscScrubber::ReadFromVolume(u64 offset, u32& buffer, bool decrypt) +bool DiscScrubber::ReadFromVolume(u64 offset, u32& buffer, const Partition& partition) { - return m_disc->ReadSwapped(offset, &buffer, decrypt); + return m_disc->ReadSwapped(offset, &buffer, partition); } -bool DiscScrubber::ReadFromVolume(u64 offset, u64& buffer, bool decrypt) +bool DiscScrubber::ReadFromVolume(u64 offset, u64& buffer, const Partition& partition) { u32 temp_buffer; - if (!m_disc->ReadSwapped(offset, &temp_buffer, decrypt)) + if (!m_disc->ReadSwapped(offset, &temp_buffer, partition)) return false; buffer = static_cast<u64>(temp_buffer) << 2; return true; @@ -142,126 +142,85 @@ bool DiscScrubber::ParseDisc() // Mark the header as used - it's mostly 0s anyways MarkAsUsed(0, 0x50000); - for (u32 x = 0; x < 4; x++) + for (const DiscIO::Partition& partition : m_disc->GetPartitions()) { - if (!ReadFromVolume(0x40000 + (x * 8) + 0, m_partition_group[x].num_partitions, false) || - !ReadFromVolume(0x40000 + (x * 8) + 4, m_partition_group[x].partitions_offset, false)) + PartitionHeader header; + + if (!ReadFromVolume(partition.offset + 0x2a4, header.tmd_size, PARTITION_NONE) || + !ReadFromVolume(partition.offset + 0x2a8, header.tmd_offset, PARTITION_NONE) || + !ReadFromVolume(partition.offset + 0x2ac, header.cert_chain_size, PARTITION_NONE) || + !ReadFromVolume(partition.offset + 0x2b0, header.cert_chain_offset, PARTITION_NONE) || + !ReadFromVolume(partition.offset + 0x2b4, header.h3_offset, PARTITION_NONE) || + !ReadFromVolume(partition.offset + 0x2b8, header.data_offset, PARTITION_NONE) || + !ReadFromVolume(partition.offset + 0x2bc, header.data_size, PARTITION_NONE)) { return false; } - // Read all partitions - for (u32 i = 0; i < m_partition_group[x].num_partitions; i++) - { - Partition partition; - - partition.group_number = x; - partition.number = i; - - if (!ReadFromVolume(m_partition_group[x].partitions_offset + (i * 8) + 0, partition.offset, - false) || - !ReadFromVolume(m_partition_group[x].partitions_offset + (i * 8) + 4, partition.type, - false) || - !ReadFromVolume(partition.offset + 0x2a4, partition.header.tmd_size, false) || - !ReadFromVolume(partition.offset + 0x2a8, partition.header.tmd_offset, false) || - !ReadFromVolume(partition.offset + 0x2ac, partition.header.cert_chain_size, false) || - !ReadFromVolume(partition.offset + 0x2b0, partition.header.cert_chain_offset, false) || - !ReadFromVolume(partition.offset + 0x2b4, partition.header.h3_offset, false) || - !ReadFromVolume(partition.offset + 0x2b8, partition.header.data_offset, false) || - !ReadFromVolume(partition.offset + 0x2bc, partition.header.data_size, false)) - { - return false; - } - - m_partition_group[x].partitions.push_back(partition); - } - - for (auto& partition : m_partition_group[x].partitions) - { - const PartitionHeader& header = partition.header; - - MarkAsUsed(partition.offset, 0x2c0); + MarkAsUsed(partition.offset, 0x2c0); - MarkAsUsed(partition.offset + header.tmd_offset, header.tmd_size); - MarkAsUsed(partition.offset + header.cert_chain_offset, header.cert_chain_size); - MarkAsUsed(partition.offset + header.h3_offset, 0x18000); - // This would mark the whole (encrypted) data area - // we need to parse FST and other crap to find what's free within it! - // MarkAsUsed(partition.offset + header.data_offset, header.data_size); + MarkAsUsed(partition.offset + header.tmd_offset, header.tmd_size); + MarkAsUsed(partition.offset + header.cert_chain_offset, header.cert_chain_size); + MarkAsUsed(partition.offset + header.h3_offset, 0x18000); + // This would mark the whole (encrypted) data area + // we need to parse FST and other crap to find what's free within it! + // MarkAsUsed(partition.offset + header.data_offset, header.data_size); - // Parse Data! This is where the big gain is - if (!ParsePartitionData(partition)) - return false; - } + // Parse Data! This is where the big gain is + if (!ParsePartitionData(partition, &header)) + return false; } return true; } -// Operations dealing with encrypted space are done here - the volume is swapped to allow this -bool DiscScrubber::ParsePartitionData(Partition& partition) +// Operations dealing with encrypted space are done here +bool DiscScrubber::ParsePartitionData(const Partition& partition, PartitionHeader* header) { - bool parsed_ok = true; + std::unique_ptr<IFileSystem> filesystem(CreateFileSystem(m_disc.get(), partition)); + if (!filesystem) + { + ERROR_LOG(DISCIO, "Failed to read file system for the partition at 0x%" PRIx64, + partition.offset); + return false; + } - // Switch out the main volume temporarily - std::unique_ptr<IVolume> old_volume; - m_disc.swap(old_volume); + const u64 partition_data_offset = partition.offset + header->data_offset; - // Ready some stuff - m_disc = CreateVolumeFromFilename(m_filename, partition.group_number, partition.number); - if (m_disc == nullptr) + // Mark things as used which are not in the filesystem + // Header, Header Information, Apploader + if (!ReadFromVolume(0x2440 + 0x14, header->apploader_size, partition) || + !ReadFromVolume(0x2440 + 0x18, header->apploader_size, partition)) { - ERROR_LOG(DISCIO, "Failed to create volume from file %s", m_filename.c_str()); - m_disc.swap(old_volume); return false; } + MarkAsUsedE(partition_data_offset, 0, + 0x2440 + header->apploader_size + header->apploader_trailer_size); - std::unique_ptr<IFileSystem> filesystem(CreateFileSystem(m_disc.get())); - if (!filesystem) + // DOL + header->dol_offset = filesystem->GetBootDOLOffset(); + header->dol_size = filesystem->GetBootDOLSize(header->dol_offset); + if (header->dol_offset == 0 || header->dol_size == 0) + return false; + MarkAsUsedE(partition_data_offset, header->dol_offset, header->dol_size); + + // FST + if (!ReadFromVolume(0x424, header->fst_offset, partition) || + !ReadFromVolume(0x428, header->fst_size, partition)) { - ERROR_LOG(DISCIO, "Failed to create filesystem for group %u partition %u", - partition.group_number, partition.number); - parsed_ok = false; + return false; } - else + MarkAsUsedE(partition_data_offset, header->fst_offset, header->fst_size); + + // Go through the filesystem and mark entries as used + for (const SFileInfo& file : filesystem->GetFileList()) { - // Mark things as used which are not in the filesystem - // Header, Header Information, Apploader - parsed_ok = parsed_ok && ReadFromVolume(0x2440 + 0x14, partition.header.apploader_size, true); - parsed_ok = - parsed_ok && ReadFromVolume(0x2440 + 0x18, partition.header.apploader_trailer_size, true); - MarkAsUsedE(partition.offset + partition.header.data_offset, 0, - 0x2440 + partition.header.apploader_size + partition.header.apploader_trailer_size); - - // DOL - partition.header.dol_offset = filesystem->GetBootDOLOffset(); - partition.header.dol_size = filesystem->GetBootDOLSize(partition.header.dol_offset); - parsed_ok = parsed_ok && partition.header.dol_offset && partition.header.dol_size; - MarkAsUsedE(partition.offset + partition.header.data_offset, partition.header.dol_offset, - partition.header.dol_size); - - // FST - parsed_ok = parsed_ok && ReadFromVolume(0x424, partition.header.fst_offset, true); - parsed_ok = parsed_ok && ReadFromVolume(0x428, partition.header.fst_size, true); - MarkAsUsedE(partition.offset + partition.header.data_offset, partition.header.fst_offset, - partition.header.fst_size); - - // Go through the filesystem and mark entries as used - for (const SFileInfo& file : filesystem->GetFileList()) - { - DEBUG_LOG(DISCIO, "%s", file.m_FullPath.empty() ? "/" : file.m_FullPath.c_str()); - if ((file.m_NameOffset & 0x1000000) == 0) - { - MarkAsUsedE(partition.offset + partition.header.data_offset, file.m_Offset, - file.m_FileSize); - } - } + DEBUG_LOG(DISCIO, "%s", file.m_FullPath.empty() ? "/" : file.m_FullPath.c_str()); + if ((file.m_NameOffset & 0x1000000) == 0) + MarkAsUsedE(partition_data_offset, file.m_Offset, file.m_FileSize); } - // Swap back - m_disc.swap(old_volume); - - return parsed_ok; + return true; } } // namespace DiscIO |
