diff options
| author | JosJuice <josjuice@gmail.com> | 2017-05-16 23:06:32 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-16 23:06:32 +0200 |
| commit | fa06d10f4a09ec5f16c0653f6e3e2cbbc043e925 (patch) | |
| tree | 56ee1ce35f3a7128467289ff180cd6fd56af2f50 /Source/Core/DiscIO | |
| parent | f4e8a01d166378bda874fdfd7063b2fcce1ac89e (diff) | |
| parent | 2bcad57225b9b0a4635d62eeabbbb138d71386bf (diff) | |
Merge pull request #2353 from JosJuice/wii-partition-cleanup
VolumeWiiCrypted: Replace ChangePartition with a partition parameter
Diffstat (limited to 'Source/Core/DiscIO')
| -rw-r--r-- | Source/Core/DiscIO/DiscScrubber.cpp | 159 | ||||
| -rw-r--r-- | Source/Core/DiscIO/DiscScrubber.h | 25 | ||||
| -rw-r--r-- | Source/Core/DiscIO/FileSystemGCWii.cpp | 64 | ||||
| -rw-r--r-- | Source/Core/DiscIO/FileSystemGCWii.h | 6 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Filesystem.cpp | 8 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Filesystem.h | 11 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Volume.h | 63 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeCreator.cpp | 125 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeCreator.h | 7 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeDirectory.cpp | 30 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeDirectory.h | 18 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeGC.cpp | 46 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeGC.h | 19 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeWad.cpp | 34 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeWad.h | 27 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeWiiCrypted.cpp | 236 | ||||
| -rw-r--r-- | Source/Core/DiscIO/VolumeWiiCrypted.h | 45 |
17 files changed, 439 insertions, 484 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 diff --git a/Source/Core/DiscIO/DiscScrubber.h b/Source/Core/DiscIO/DiscScrubber.h index 152e16f123..959d22fd4a 100644 --- a/Source/Core/DiscIO/DiscScrubber.h +++ b/Source/Core/DiscIO/DiscScrubber.h @@ -26,6 +26,7 @@ class IOFile; namespace DiscIO { class IVolume; +struct Partition; class DiscScrubber final { @@ -57,34 +58,16 @@ private: u32 apploader_trailer_size; }; - struct Partition final - { - u32 group_number; - u32 number; - u64 offset; - u32 type; - PartitionHeader header; - }; - - struct PartitionGroup final - { - u32 num_partitions; - u64 partitions_offset; - std::vector<Partition> partitions; - }; - void MarkAsUsed(u64 offset, u64 size); void MarkAsUsedE(u64 partition_data_offset, u64 offset, u64 size); - bool ReadFromVolume(u64 offset, u32& buffer, bool decrypt); - bool ReadFromVolume(u64 offset, u64& buffer, bool decrypt); + bool ReadFromVolume(u64 offset, u32& buffer, const Partition& partition); + bool ReadFromVolume(u64 offset, u64& buffer, const Partition& partition); bool ParseDisc(); - bool ParsePartitionData(Partition& partition); + bool ParsePartitionData(const Partition& partition, PartitionHeader* header); std::string m_filename; std::unique_ptr<IVolume> m_disc; - std::array<PartitionGroup, 4> m_partition_group{}; - std::vector<u8> m_free_table; u64 m_file_size = 0; u64 m_block_count = 0; diff --git a/Source/Core/DiscIO/FileSystemGCWii.cpp b/Source/Core/DiscIO/FileSystemGCWii.cpp index b19fd7cf95..c3b9df3119 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/FileSystemGCWii.cpp @@ -20,8 +20,8 @@ namespace DiscIO { -CFileSystemGCWii::CFileSystemGCWii(const IVolume* _rVolume) - : IFileSystem(_rVolume), m_Initialized(false), m_Valid(false), m_Wii(false) +CFileSystemGCWii::CFileSystemGCWii(const IVolume* _rVolume, const Partition& partition) + : IFileSystem(_rVolume, partition), m_Initialized(false), m_Valid(false), m_offset_shift(0) { m_Valid = DetectFileSystem(); } @@ -80,7 +80,7 @@ u64 CFileSystemGCWii::ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 read_length, _OffsetInFile, _rFullPath.c_str(), pFileInfo->m_Offset, pFileInfo->m_FileSize); - m_rVolume->Read(pFileInfo->m_Offset + _OffsetInFile, read_length, _pBuffer, m_Wii); + m_rVolume->Read(pFileInfo->m_Offset + _OffsetInFile, read_length, _pBuffer, m_partition); return read_length; } @@ -111,7 +111,7 @@ bool CFileSystemGCWii::ExportFile(const std::string& _rFullPath, std::vector<u8> buffer(readSize); - result = m_rVolume->Read(fileOffset, readSize, &buffer[0], m_Wii); + result = m_rVolume->Read(fileOffset, readSize, &buffer[0], m_partition); if (!result) break; @@ -130,14 +130,14 @@ bool CFileSystemGCWii::ExportApploader(const std::string& _rExportFolder) const u32 apploader_size; u32 trailer_size; const u32 header_size = 0x20; - if (!m_rVolume->ReadSwapped(0x2440 + 0x14, &apploader_size, m_Wii) || - !m_rVolume->ReadSwapped(0x2440 + 0x18, &trailer_size, m_Wii)) + if (!m_rVolume->ReadSwapped(0x2440 + 0x14, &apploader_size, m_partition) || + !m_rVolume->ReadSwapped(0x2440 + 0x18, &trailer_size, m_partition)) return false; apploader_size += trailer_size + header_size; DEBUG_LOG(DISCIO, "Apploader size -> %x", apploader_size); std::vector<u8> buffer(apploader_size); - if (m_rVolume->Read(0x2440, apploader_size, buffer.data(), m_Wii)) + if (m_rVolume->Read(0x2440, apploader_size, buffer.data(), m_partition)) { std::string exportName(_rExportFolder + "/apploader.img"); @@ -155,8 +155,8 @@ bool CFileSystemGCWii::ExportApploader(const std::string& _rExportFolder) const u64 CFileSystemGCWii::GetBootDOLOffset() const { u32 offset = 0; - m_rVolume->ReadSwapped(0x420, &offset, m_Wii); - return static_cast<u64>(offset) << GetOffsetShift(); + m_rVolume->ReadSwapped(0x420, &offset, m_partition); + return static_cast<u64>(offset) << m_offset_shift; } u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const @@ -173,8 +173,8 @@ u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const // Iterate through the 7 code segments for (u8 i = 0; i < 7; i++) { - if (!m_rVolume->ReadSwapped(dol_offset + 0x00 + i * 4, &offset, m_Wii) || - !m_rVolume->ReadSwapped(dol_offset + 0x90 + i * 4, &size, m_Wii)) + if (!m_rVolume->ReadSwapped(dol_offset + 0x00 + i * 4, &offset, m_partition) || + !m_rVolume->ReadSwapped(dol_offset + 0x90 + i * 4, &size, m_partition)) return 0; dol_size = std::max(offset + size, dol_size); } @@ -182,8 +182,8 @@ u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const // Iterate through the 11 data segments for (u8 i = 0; i < 11; i++) { - if (!m_rVolume->ReadSwapped(dol_offset + 0x1c + i * 4, &offset, m_Wii) || - !m_rVolume->ReadSwapped(dol_offset + 0xac + i * 4, &size, m_Wii)) + if (!m_rVolume->ReadSwapped(dol_offset + 0x1c + i * 4, &offset, m_partition) || + !m_rVolume->ReadSwapped(dol_offset + 0xac + i * 4, &size, m_partition)) return 0; dol_size = std::max(offset + size, dol_size); } @@ -200,7 +200,7 @@ bool CFileSystemGCWii::ExportDOL(const std::string& _rExportFolder) const return false; std::vector<u8> buffer(DolSize); - if (m_rVolume->Read(DolOffset, DolSize, &buffer[0], m_Wii)) + if (m_rVolume->Read(DolOffset, DolSize, &buffer[0], m_partition)) { std::string exportName(_rExportFolder + "/boot.dol"); @@ -218,7 +218,7 @@ bool CFileSystemGCWii::ExportDOL(const std::string& _rExportFolder) const std::string CFileSystemGCWii::GetStringFromOffset(u64 _Offset) const { std::string data(255, 0x00); - m_rVolume->Read(_Offset, data.size(), (u8*)&data[0], m_Wii); + m_rVolume->Read(_Offset, data.size(), (u8*)&data[0], m_partition); data.erase(std::find(data.begin(), data.end(), 0x00), data.end()); // TODO: Should we really always use SHIFT-JIS? @@ -251,14 +251,14 @@ const SFileInfo* CFileSystemGCWii::FindFileInfo(const std::string& _rFullPath) bool CFileSystemGCWii::DetectFileSystem() { u32 magic_bytes; - if (m_rVolume->ReadSwapped(0x18, &magic_bytes, false) && magic_bytes == 0x5D1C9EA3) + if (m_rVolume->ReadSwapped(0x18, &magic_bytes, m_partition) && magic_bytes == 0x5D1C9EA3) { - m_Wii = true; + m_offset_shift = 2; // Wii file system return true; } - else if (m_rVolume->ReadSwapped(0x1c, &magic_bytes, false) && magic_bytes == 0xC2339F3D) + else if (m_rVolume->ReadSwapped(0x1c, &magic_bytes, m_partition) && magic_bytes == 0xC2339F3D) { - m_Wii = false; + m_offset_shift = 0; // GameCube file system return true; } @@ -268,21 +268,20 @@ bool CFileSystemGCWii::DetectFileSystem() void CFileSystemGCWii::InitFileSystem() { m_Initialized = true; - u32 const shift = GetOffsetShift(); // read the whole FST u32 fst_offset_unshifted; - if (!m_rVolume->ReadSwapped(0x424, &fst_offset_unshifted, m_Wii)) + if (!m_rVolume->ReadSwapped(0x424, &fst_offset_unshifted, m_partition)) return; - u64 FSTOffset = static_cast<u64>(fst_offset_unshifted) << shift; + u64 FSTOffset = static_cast<u64>(fst_offset_unshifted) << m_offset_shift; // read all fileinfos u32 name_offset, offset, size; - if (!m_rVolume->ReadSwapped(FSTOffset + 0x0, &name_offset, m_Wii) || - !m_rVolume->ReadSwapped(FSTOffset + 0x4, &offset, m_Wii) || - !m_rVolume->ReadSwapped(FSTOffset + 0x8, &size, m_Wii)) + if (!m_rVolume->ReadSwapped(FSTOffset + 0x0, &name_offset, m_partition) || + !m_rVolume->ReadSwapped(FSTOffset + 0x4, &offset, m_partition) || + !m_rVolume->ReadSwapped(FSTOffset + 0x8, &size, m_partition)) return; - SFileInfo root = {name_offset, static_cast<u64>(offset) << shift, size}; + SFileInfo root = {name_offset, static_cast<u64>(offset) << m_offset_shift, size}; if (!root.IsDirectory()) return; @@ -308,12 +307,12 @@ void CFileSystemGCWii::InitFileSystem() { const u64 read_offset = FSTOffset + (i * 0xC); name_offset = 0; - m_rVolume->ReadSwapped(read_offset + 0x0, &name_offset, m_Wii); + m_rVolume->ReadSwapped(read_offset + 0x0, &name_offset, m_partition); offset = 0; - m_rVolume->ReadSwapped(read_offset + 0x4, &offset, m_Wii); + m_rVolume->ReadSwapped(read_offset + 0x4, &offset, m_partition); size = 0; - m_rVolume->ReadSwapped(read_offset + 0x8, &size, m_Wii); - m_FileInfoVector.emplace_back(name_offset, static_cast<u64>(offset) << shift, size); + m_rVolume->ReadSwapped(read_offset + 0x8, &size, m_partition); + m_FileInfoVector.emplace_back(name_offset, static_cast<u64>(offset) << m_offset_shift, size); NameTableOffset += 0xC; } @@ -351,9 +350,4 @@ size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _ return CurrentIndex; } -u32 CFileSystemGCWii::GetOffsetShift() const -{ - return m_Wii ? 2 : 0; -} - } // namespace diff --git a/Source/Core/DiscIO/FileSystemGCWii.h b/Source/Core/DiscIO/FileSystemGCWii.h index ac75f1acf0..c40e87e8c4 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.h +++ b/Source/Core/DiscIO/FileSystemGCWii.h @@ -14,11 +14,12 @@ namespace DiscIO { class IVolume; +struct Partition; class CFileSystemGCWii : public IFileSystem { public: - CFileSystemGCWii(const IVolume* _rVolume); + CFileSystemGCWii(const IVolume* _rVolume, const Partition& partition); virtual ~CFileSystemGCWii(); bool IsValid() const override { return m_Valid; } @@ -36,7 +37,7 @@ public: private: bool m_Initialized; bool m_Valid; - bool m_Wii; + u32 m_offset_shift; std::vector<SFileInfo> m_FileInfoVector; std::string GetStringFromOffset(u64 _Offset) const; @@ -45,7 +46,6 @@ private: void InitFileSystem(); size_t BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const std::string& _szDirectory, u64 _NameTableOffset); - u32 GetOffsetShift() const; }; } // namespace diff --git a/Source/Core/DiscIO/Filesystem.cpp b/Source/Core/DiscIO/Filesystem.cpp index 48c9a33b6f..9670ecda43 100644 --- a/Source/Core/DiscIO/Filesystem.cpp +++ b/Source/Core/DiscIO/Filesystem.cpp @@ -5,10 +5,12 @@ #include "DiscIO/Filesystem.h" #include <memory> #include "DiscIO/FileSystemGCWii.h" +#include "DiscIO/Volume.h" namespace DiscIO { -IFileSystem::IFileSystem(const IVolume* _rVolume) : m_rVolume(_rVolume) +IFileSystem::IFileSystem(const IVolume* _rVolume, const Partition& partition) + : m_rVolume(_rVolume), m_partition(partition) { } @@ -16,12 +18,12 @@ IFileSystem::~IFileSystem() { } -std::unique_ptr<IFileSystem> CreateFileSystem(const IVolume* volume) +std::unique_ptr<IFileSystem> CreateFileSystem(const IVolume* volume, const Partition& partition) { if (!volume) return nullptr; - std::unique_ptr<IFileSystem> filesystem = std::make_unique<CFileSystemGCWii>(volume); + std::unique_ptr<IFileSystem> filesystem = std::make_unique<CFileSystemGCWii>(volume, partition); if (!filesystem) return nullptr; diff --git a/Source/Core/DiscIO/Filesystem.h b/Source/Core/DiscIO/Filesystem.h index 25a414d980..71b19e6005 100644 --- a/Source/Core/DiscIO/Filesystem.h +++ b/Source/Core/DiscIO/Filesystem.h @@ -9,11 +9,10 @@ #include <vector> #include "Common/CommonTypes.h" +#include "DiscIO/Volume.h" namespace DiscIO { -class IVolume; - // file info of an FST entry struct SFileInfo { @@ -35,7 +34,7 @@ struct SFileInfo class IFileSystem { public: - IFileSystem(const IVolume* _rVolume); + IFileSystem(const IVolume* _rVolume, const Partition& partition); virtual ~IFileSystem(); virtual bool IsValid() const = 0; @@ -50,10 +49,12 @@ public: virtual u64 GetBootDOLOffset() const = 0; virtual u32 GetBootDOLSize(u64 dol_offset) const = 0; + virtual const Partition GetPartition() const { return m_partition; } protected: - const IVolume* m_rVolume; + const IVolume* const m_rVolume; + const Partition m_partition; }; -std::unique_ptr<IFileSystem> CreateFileSystem(const IVolume* volume); +std::unique_ptr<IFileSystem> CreateFileSystem(const IVolume* volume, const Partition& partition); } // namespace diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index cd48249ccb..d03e168709 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -5,6 +5,7 @@ #pragma once #include <cstring> +#include <limits> #include <map> #include <string> #include <vector> @@ -19,49 +20,71 @@ namespace DiscIO { enum class BlobType; +struct Partition final +{ + Partition() : offset(std::numeric_limits<u64>::max()) {} + explicit Partition(u64 offset_) : offset(offset_) {} + bool operator==(const Partition& other) const { return offset == other.offset; } + bool operator!=(const Partition& other) const { return !(*this == other); } + bool operator<(const Partition& other) const { return offset < other.offset; } + bool operator>(const Partition& other) const { return other < *this; } + bool operator<=(const Partition& other) const { return !(*this < other); } + bool operator>=(const Partition& other) const { return !(*this > other); } + u64 offset; +}; + +const Partition PARTITION_NONE(std::numeric_limits<u64>::max() - 1); + class IVolume { public: IVolume() {} virtual ~IVolume() {} - // decrypt parameter must be false if not reading a Wii disc - virtual bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const = 0; + virtual bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, const Partition& partition) const = 0; template <typename T> - bool ReadSwapped(u64 offset, T* buffer, bool decrypt) const + bool ReadSwapped(u64 offset, T* buffer, const Partition& partition) const { T temp; - if (!Read(offset, sizeof(T), reinterpret_cast<u8*>(&temp), decrypt)) + if (!Read(offset, sizeof(T), reinterpret_cast<u8*>(&temp), partition)) return false; *buffer = Common::FromBigEndian(temp); return true; } - - virtual bool GetTitleID(u64*) const { return false; } - virtual IOS::ES::TicketReader GetTicket() const { return {}; } - virtual IOS::ES::TMDReader GetTMD() const { return {}; } - virtual u64 PartitionOffsetToRawOffset(u64 offset) const { return offset; } - virtual std::string GetGameID() const = 0; - virtual std::string GetMakerID() const = 0; - virtual u16 GetRevision() const = 0; - virtual std::string GetInternalName() const = 0; + virtual std::vector<Partition> GetPartitions() const { return {{}}; } + virtual Partition GetGamePartition() const { return PARTITION_NONE; } + bool GetTitleID(u64* buffer) const { return GetTitleID(buffer, GetGamePartition()); } + virtual bool GetTitleID(u64* buffer, const Partition& partition) const { return false; } + virtual IOS::ES::TicketReader GetTicket(const Partition& partition) const { return {}; } + virtual IOS::ES::TMDReader GetTMD(const Partition& partition) const { return {}; } + std::string GetGameID() const { return GetGameID(GetGamePartition()); } + virtual std::string GetGameID(const Partition& partition) const = 0; + std::string GetMakerID() const { return GetMakerID(GetGamePartition()); } + virtual std::string GetMakerID(const Partition& partition) const = 0; + u16 GetRevision() const { return GetRevision(GetGamePartition()); } + virtual u16 GetRevision(const Partition& partition) const = 0; + std::string GetInternalName() const { return GetInternalName(GetGamePartition()); } + virtual std::string GetInternalName(const Partition& partition) const = 0; virtual std::map<Language, std::string> GetShortNames() const { return {{}}; } virtual std::map<Language, std::string> GetLongNames() const { return {{}}; } virtual std::map<Language, std::string> GetShortMakers() const { return {{}}; } virtual std::map<Language, std::string> GetLongMakers() const { return {{}}; } virtual std::map<Language, std::string> GetDescriptions() const { return {{}}; } virtual std::vector<u32> GetBanner(int* width, int* height) const = 0; - virtual u64 GetFSTSize() const = 0; - virtual std::string GetApploaderDate() const = 0; + u64 GetFSTSize() const { return GetFSTSize(GetGamePartition()); } + virtual u64 GetFSTSize(const Partition& partition) const = 0; + std::string GetApploaderDate() const { return GetApploaderDate(GetGamePartition()); } + virtual std::string GetApploaderDate(const Partition& partition) const = 0; // 0 is the first disc, 1 is the second disc - virtual u8 GetDiscNumber() const { return 0; } + u8 GetDiscNumber() const { return GetDiscNumber(GetGamePartition()); } + virtual u8 GetDiscNumber(const Partition& partition) const { return 0; } virtual Platform GetVolumeType() const = 0; virtual bool SupportsIntegrityCheck() const { return false; } - virtual bool CheckIntegrity() const { return false; } - virtual bool ChangePartition(u64 offset) { return false; } + virtual bool CheckIntegrity(const Partition& partition) const { return false; } virtual Region GetRegion() const = 0; - virtual Country GetCountry() const = 0; + Country GetCountry() const { return GetCountry(GetGamePartition()); } + virtual Country GetCountry(const Partition& partition) const = 0; virtual BlobType GetBlobType() const = 0; - // Size of virtual disc (not always accurate) + // Size of virtual disc (may be inaccurate depending on the blob type) virtual u64 GetSize() const = 0; // Size on disc (compressed size) virtual u64 GetRawSize() const = 0; diff --git a/Source/Core/DiscIO/VolumeCreator.cpp b/Source/Core/DiscIO/VolumeCreator.cpp index 21988d8b91..4b2c23aea9 100644 --- a/Source/Core/DiscIO/VolumeCreator.cpp +++ b/Source/Core/DiscIO/VolumeCreator.cpp @@ -9,8 +9,6 @@ #include <utility> #include <vector> -#include <mbedtls/aes.h> - #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" @@ -33,24 +31,9 @@ enum EDiscType DISC_TYPE_WAD }; -static const unsigned char s_master_key[16] = {0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4, - 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7}; - -static const unsigned char s_master_key_korean[16] = { - 0x63, 0xb8, 0x2b, 0xb4, 0xf4, 0x61, 0x4e, 0x2e, 0x13, 0xf2, 0xfe, 0xfb, 0xba, 0x4c, 0x9b, 0x7e}; - -static const unsigned char s_master_key_rvt[16] = {0xa1, 0x60, 0x4a, 0x6a, 0x71, 0x23, 0xb5, 0x29, - 0xae, 0x8b, 0xec, 0x32, 0xc8, 0x16, 0xfc, 0xaa}; - -static const char s_issuer_rvt[] = "Root-CA00000002-XS00000006"; - -static std::unique_ptr<IVolume> CreateVolumeFromCryptedWiiImage(std::unique_ptr<IBlobReader> reader, - u32 partition_group, - u32 volume_type, u32 volume_number); EDiscType GetDiscType(IBlobReader& _rReader); -std::unique_ptr<IVolume> CreateVolumeFromFilename(const std::string& filename, u32 partition_group, - u32 volume_number) +std::unique_ptr<IVolume> CreateVolumeFromFilename(const std::string& filename) { std::unique_ptr<IBlobReader> reader(CreateBlobReader(filename)); if (reader == nullptr) @@ -66,7 +49,7 @@ std::unique_ptr<IVolume> CreateVolumeFromFilename(const std::string& filename, u return std::make_unique<CVolumeWAD>(std::move(reader)); case DISC_TYPE_WII_CONTAINER: - return CreateVolumeFromCryptedWiiImage(std::move(reader), partition_group, 0, volume_number); + return std::make_unique<CVolumeWiiCrypted>(std::move(reader)); case DISC_TYPE_UNK: return nullptr; @@ -85,110 +68,6 @@ std::unique_ptr<IVolume> CreateVolumeFromDirectory(const std::string& directory, return nullptr; } -void VolumeKeyForPartition(IBlobReader& _rReader, u64 offset, u8* VolumeKey) -{ - u8 SubKey[16]; - _rReader.Read(offset + 0x1bf, 16, SubKey); - - u8 IV[16]; - memset(IV, 0, 16); - _rReader.Read(offset + 0x44c, 8, IV); - - mbedtls_aes_context AES_ctx; - - u8 issuer[sizeof(s_issuer_rvt)]; - _rReader.Read(offset + 0x140, sizeof(issuer), issuer); - if (!memcmp(issuer, s_issuer_rvt, sizeof(s_issuer_rvt))) - { - // RVT issuer. Use the RVT (debug) master key. - mbedtls_aes_setkey_dec(&AES_ctx, s_master_key_rvt, 128); - } - else - { - // Issue: 6813 - // Magic value is at partition's offset + 0x1f1 (1byte) - // If encrypted with the Korean key, the magic value would be 1 - // Otherwise it is zero - u8 using_korean_key = 0; - _rReader.Read(offset + 0x1f1, sizeof(u8), &using_korean_key); - u8 region = 0; - _rReader.Read(0x3, sizeof(u8), ®ion); - - mbedtls_aes_setkey_dec( - &AES_ctx, (using_korean_key == 1 && region == 'K' ? s_master_key_korean : s_master_key), - 128); - } - - mbedtls_aes_crypt_cbc(&AES_ctx, MBEDTLS_AES_DECRYPT, 16, IV, SubKey, VolumeKey); -} - -static std::unique_ptr<IVolume> CreateVolumeFromCryptedWiiImage(std::unique_ptr<IBlobReader> reader, - u32 partition_group, - u32 volume_type, u32 volume_number) -{ - CBlobBigEndianReader big_endian_reader(*reader); - - u32 num_partitions; - if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8), &num_partitions)) - return nullptr; - - // Check if we're looking for a valid partition - if ((int)volume_number != -1 && volume_number > num_partitions) - return nullptr; - - u32 partitions_offset_unshifted; - if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8) + 4, - &partitions_offset_unshifted)) - return nullptr; - u64 partitions_offset = (u64)partitions_offset_unshifted << 2; - - struct SPartition - { - SPartition(u64 offset_, u32 type_) : offset(offset_), type(type_) {} - u64 offset; - u32 type; - }; - - struct SPartitionGroup - { - u32 num_partitions; - u64 partitions_offset; - std::vector<SPartition> partitions; - }; - SPartitionGroup partition_groups[4]; - - // Read all partitions - for (SPartitionGroup& group : partition_groups) - { - for (u32 i = 0; i < num_partitions; i++) - { - u32 partition_offset, partition_type; - if (big_endian_reader.ReadSwapped(partitions_offset + (i * 8) + 0, &partition_offset) && - big_endian_reader.ReadSwapped(partitions_offset + (i * 8) + 4, &partition_type)) - { - group.partitions.emplace_back((u64)partition_offset << 2, partition_type); - } - } - } - - // Return the partition type specified or number - // types: 0 = game, 1 = firmware update, 2 = channel installer - // some partitions on SSBB use the ASCII title id of the demo VC game they hold... - for (size_t i = 0; i < partition_groups[partition_group].partitions.size(); i++) - { - const SPartition& partition = partition_groups[partition_group].partitions.at(i); - - if ((partition.type == volume_type && (int)volume_number == -1) || i == volume_number) - { - u8 volume_key[16]; - VolumeKeyForPartition(*reader, partition.offset, volume_key); - return std::make_unique<CVolumeWiiCrypted>(std::move(reader), partition.offset, volume_key); - } - } - - return nullptr; -} - EDiscType GetDiscType(IBlobReader& _rReader) { CBlobBigEndianReader Reader(_rReader); diff --git a/Source/Core/DiscIO/VolumeCreator.h b/Source/Core/DiscIO/VolumeCreator.h index 6b185b4b81..79c08cf1db 100644 --- a/Source/Core/DiscIO/VolumeCreator.h +++ b/Source/Core/DiscIO/VolumeCreator.h @@ -7,18 +7,13 @@ #include <memory> #include <string> -#include "Common/CommonTypes.h" - namespace DiscIO { class IVolume; -class IBlobReader; -std::unique_ptr<IVolume> CreateVolumeFromFilename(const std::string& filename, - u32 partition_group = 0, u32 volume_number = -1); +std::unique_ptr<IVolume> CreateVolumeFromFilename(const std::string& filename); std::unique_ptr<IVolume> CreateVolumeFromDirectory(const std::string& directory, bool is_wii, const std::string& apploader = "", const std::string& dol = ""); -void VolumeKeyForPartition(IBlobReader& _rReader, u64 offset, u8* VolumeKey); } // namespace diff --git a/Source/Core/DiscIO/VolumeDirectory.cpp b/Source/Core/DiscIO/VolumeDirectory.cpp index 249c6f520d..397f0fc831 100644 --- a/Source/Core/DiscIO/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/VolumeDirectory.cpp @@ -64,8 +64,10 @@ bool CVolumeDirectory::IsValidDirectory(const std::string& directory) return File::IsDirectory(ExtractDirectoryName(directory)); } -bool CVolumeDirectory::Read(u64 offset, u64 length, u8* buffer, bool decrypt) const +bool CVolumeDirectory::Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const { + bool decrypt = partition != PARTITION_NONE; + if (!decrypt && (offset + length >= 0x400) && m_is_wii) { // Fully supporting this would require re-encrypting every file that's read. @@ -77,7 +79,7 @@ bool CVolumeDirectory::Read(u64 offset, u64 length, u8* buffer, bool decrypt) co } if (decrypt && !m_is_wii) - PanicAlertT("Tried to decrypt data from a non-Wii volume"); + return false; // header if (offset < DISKHEADERINFO_ADDRESS) @@ -157,7 +159,17 @@ bool CVolumeDirectory::Read(u64 offset, u64 length, u8* buffer, bool decrypt) co return true; } -std::string CVolumeDirectory::GetGameID() const +std::vector<Partition> CVolumeDirectory::GetPartitions() const +{ + return m_is_wii ? std::vector<Partition>{GetGamePartition()} : std::vector<Partition>(); +} + +Partition CVolumeDirectory::GetGamePartition() const +{ + return m_is_wii ? Partition(0x50000) : PARTITION_NONE; +} + +std::string CVolumeDirectory::GetGameID(const Partition& partition) const { return std::string(m_disk_header.begin(), m_disk_header.begin() + MAX_ID_LENGTH); } @@ -175,21 +187,21 @@ Region CVolumeDirectory::GetRegion() const return RegionSwitchGC(m_disk_header[3]); } -Country CVolumeDirectory::GetCountry() const +Country CVolumeDirectory::GetCountry(const Partition& partition) const { return CountrySwitch(m_disk_header[3]); } -std::string CVolumeDirectory::GetMakerID() const +std::string CVolumeDirectory::GetMakerID(const Partition& partition) const { // Not implemented return "00"; } -std::string CVolumeDirectory::GetInternalName() const +std::string CVolumeDirectory::GetInternalName(const Partition& partition) const { char name[0x60]; - if (Read(0x20, 0x60, (u8*)name, false)) + if (Read(0x20, 0x60, (u8*)name, partition)) return DecodeString(name); else return ""; @@ -218,13 +230,13 @@ void CVolumeDirectory::SetName(const std::string& name) m_disk_header[length + 0x20] = 0; } -u64 CVolumeDirectory::GetFSTSize() const +u64 CVolumeDirectory::GetFSTSize(const Partition& partition) const { // Not implemented return 0; } -std::string CVolumeDirectory::GetApploaderDate() const +std::string CVolumeDirectory::GetApploaderDate(const Partition& partition) const { // Not implemented return "VOID"; diff --git a/Source/Core/DiscIO/VolumeDirectory.h b/Source/Core/DiscIO/VolumeDirectory.h index 155459285c..83530c223c 100644 --- a/Source/Core/DiscIO/VolumeDirectory.h +++ b/Source/Core/DiscIO/VolumeDirectory.h @@ -39,26 +39,28 @@ public: static bool IsValidDirectory(const std::string& directory); - bool Read(u64 offset, u64 length, u8* buffer, bool decrypt) const override; + bool Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const override; + std::vector<Partition> GetPartitions() const override; + Partition GetGamePartition() const override; - std::string GetGameID() const override; + std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; void SetGameID(const std::string& id); - std::string GetMakerID() const override; + std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override; - u16 GetRevision() const override { return 0; } - std::string GetInternalName() const override; + u16 GetRevision(const Partition& partition = PARTITION_NONE) const override { return 0; } + std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override; std::map<Language, std::string> GetLongNames() const override; std::vector<u32> GetBanner(int* width, int* height) const override; void SetName(const std::string&); - u64 GetFSTSize() const override; + u64 GetFSTSize(const Partition& partition = PARTITION_NONE) const override; - std::string GetApploaderDate() const override; + std::string GetApploaderDate(const Partition& partition = PARTITION_NONE) const override; Platform GetVolumeType() const override; Region GetRegion() const override; - Country GetCountry() const override; + Country GetCountry(const Partition& partition = PARTITION_NONE) const override; BlobType GetBlobType() const override; u64 GetSize() const override; diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index adc20f5569..d6abd08263 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -32,21 +32,21 @@ CVolumeGC::~CVolumeGC() { } -bool CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const +bool CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer, const Partition& partition) const { - if (decrypt) - PanicAlertT("Tried to decrypt data from a non-Wii volume"); + if (partition != PARTITION_NONE) + return false; return m_pReader->Read(_Offset, _Length, _pBuffer); } -std::string CVolumeGC::GetGameID() const +std::string CVolumeGC::GetGameID(const Partition& partition) const { static const std::string NO_UID("NO_UID"); char ID[6]; - if (!Read(0, sizeof(ID), reinterpret_cast<u8*>(ID))) + if (!Read(0, sizeof(ID), reinterpret_cast<u8*>(ID), partition)) { PanicAlertT("Failed to read unique ID from disc image"); return NO_UID; @@ -58,43 +58,43 @@ std::string CVolumeGC::GetGameID() const Region CVolumeGC::GetRegion() const { u8 country_code; - if (!ReadSwapped(3, &country_code, false)) + if (!ReadSwapped(3, &country_code, PARTITION_NONE)) return Region::UNKNOWN_REGION; return RegionSwitchGC(country_code); } -Country CVolumeGC::GetCountry() const +Country CVolumeGC::GetCountry(const Partition& partition) const { u8 country_code; - if (!ReadSwapped(3, &country_code, false)) + if (!ReadSwapped(3, &country_code, partition)) return Country::COUNTRY_UNKNOWN; return CountrySwitch(country_code); } -std::string CVolumeGC::GetMakerID() const +std::string CVolumeGC::GetMakerID(const Partition& partition) const { char makerID[2]; - if (!Read(0x4, 0x2, (u8*)&makerID)) + if (!Read(0x4, 0x2, (u8*)&makerID, partition)) return std::string(); return DecodeString(makerID); } -u16 CVolumeGC::GetRevision() const +u16 CVolumeGC::GetRevision(const Partition& partition) const { u8 revision; - if (!ReadSwapped(7, &revision, false)) + if (!ReadSwapped(7, &revision, partition)) return 0; return revision; } -std::string CVolumeGC::GetInternalName() const +std::string CVolumeGC::GetInternalName(const Partition& partition) const { char name[0x60]; - if (Read(0x20, 0x60, (u8*)name)) + if (Read(0x20, 0x60, (u8*)name, partition)) return DecodeString(name); return ""; @@ -138,19 +138,19 @@ std::vector<u32> CVolumeGC::GetBanner(int* width, int* height) const return m_image_buffer; } -u64 CVolumeGC::GetFSTSize() const +u64 CVolumeGC::GetFSTSize(const Partition& partition) const { u32 size; - if (!Read(0x428, 0x4, (u8*)&size)) + if (!Read(0x428, 0x4, (u8*)&size, partition)) return 0; return Common::swap32(size); } -std::string CVolumeGC::GetApploaderDate() const +std::string CVolumeGC::GetApploaderDate(const Partition& partition) const { char date[16]; - if (!Read(0x2440, 0x10, (u8*)&date)) + if (!Read(0x2440, 0x10, (u8*)&date, partition)) return std::string(); return DecodeString(date); @@ -171,10 +171,10 @@ u64 CVolumeGC::GetRawSize() const return m_pReader->GetRawSize(); } -u8 CVolumeGC::GetDiscNumber() const +u8 CVolumeGC::GetDiscNumber(const Partition& partition) const { u8 disc_number = 0; - ReadSwapped(6, &disc_number, false); + ReadSwapped(6, &disc_number, partition); return disc_number; } @@ -192,9 +192,11 @@ void CVolumeGC::LoadBannerFile() const m_banner_loaded = true; GCBanner banner_file; - std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this)); - size_t file_size = (size_t)file_system->GetFileSize("opening.bnr"); + std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this, PARTITION_NONE)); + if (!file_system) + return; + size_t file_size = static_cast<size_t>(file_system->GetFileSize("opening.bnr")); constexpr int BNR1_MAGIC = 0x31524e42; constexpr int BNR2_MAGIC = 0x32524e42; if (file_size != BNR1_SIZE && file_size != BNR2_SIZE) diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index 10e5bf9df7..9ae149ed94 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -28,24 +28,25 @@ class CVolumeGC : public IVolume public: CVolumeGC(std::unique_ptr<IBlobReader> reader); ~CVolumeGC(); - bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt = false) const override; - std::string GetGameID() const override; - std::string GetMakerID() const override; - u16 GetRevision() const override; - std::string GetInternalName() const override; + bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, + const Partition& partition = PARTITION_NONE) const override; + std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; + std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override; + u16 GetRevision(const Partition& partition = PARTITION_NONE) const override; + std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override; std::map<Language, std::string> GetShortNames() const override; std::map<Language, std::string> GetLongNames() const override; std::map<Language, std::string> GetShortMakers() const override; std::map<Language, std::string> GetLongMakers() const override; std::map<Language, std::string> GetDescriptions() const override; std::vector<u32> GetBanner(int* width, int* height) const override; - u64 GetFSTSize() const override; - std::string GetApploaderDate() const override; - u8 GetDiscNumber() const override; + u64 GetFSTSize(const Partition& partition = PARTITION_NONE) const override; + std::string GetApploaderDate(const Partition& partition = PARTITION_NONE) const override; + u8 GetDiscNumber(const Partition& partition = PARTITION_NONE) const override; Platform GetVolumeType() const override; Region GetRegion() const override; - Country GetCountry() const override; + Country GetCountry(const Partition& partition = PARTITION_NONE) const override; BlobType GetBlobType() const override; u64 GetSize() const override; u64 GetRawSize() const override; diff --git a/Source/Core/DiscIO/VolumeWad.cpp b/Source/Core/DiscIO/VolumeWad.cpp index 4e8185f4f6..a8316c9e04 100644 --- a/Source/Core/DiscIO/VolumeWad.cpp +++ b/Source/Core/DiscIO/VolumeWad.cpp @@ -29,11 +29,11 @@ CVolumeWAD::CVolumeWAD(std::unique_ptr<IBlobReader> reader) : m_reader(std::move _assert_(m_reader); // Source: http://wiibrew.org/wiki/WAD_files - ReadSwapped(0x00, &m_hdr_size, false); - ReadSwapped(0x08, &m_cert_size, false); - ReadSwapped(0x10, &m_tick_size, false); - ReadSwapped(0x14, &m_tmd_size, false); - ReadSwapped(0x18, &m_data_size, false); + ReadSwapped(0x00, &m_hdr_size, PARTITION_NONE); + ReadSwapped(0x08, &m_cert_size, PARTITION_NONE); + ReadSwapped(0x10, &m_tick_size, PARTITION_NONE); + ReadSwapped(0x14, &m_tmd_size, PARTITION_NONE); + ReadSwapped(0x18, &m_data_size, PARTITION_NONE); m_offset = Common::AlignUp(m_hdr_size, 0x40) + Common::AlignUp(m_cert_size, 0x40); m_tmd_offset = Common::AlignUp(m_hdr_size, 0x40) + Common::AlignUp(m_cert_size, 0x40) + @@ -48,7 +48,7 @@ CVolumeWAD::CVolumeWAD(std::unique_ptr<IBlobReader> reader) : m_reader(std::move } std::vector<u8> tmd_buffer(m_tmd_size); - Read(m_tmd_offset, m_tmd_size, tmd_buffer.data(), false); + Read(m_tmd_offset, m_tmd_size, tmd_buffer.data()); m_tmd.SetBytes(std::move(tmd_buffer)); } @@ -56,10 +56,10 @@ CVolumeWAD::~CVolumeWAD() { } -bool CVolumeWAD::Read(u64 offset, u64 length, u8* buffer, bool decrypt) const +bool CVolumeWAD::Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const { - if (decrypt) - PanicAlertT("Tried to decrypt data from a non-Wii volume"); + if (partition != PARTITION_NONE) + return false; return m_reader->Read(offset, length, buffer); } @@ -71,7 +71,7 @@ Region CVolumeWAD::GetRegion() const return m_tmd.GetRegion(); } -Country CVolumeWAD::GetCountry() const +Country CVolumeWAD::GetCountry(const Partition& partition) const { if (!m_tmd.IsValid()) return Country::COUNTRY_UNKNOWN; @@ -83,20 +83,20 @@ Country CVolumeWAD::GetCountry() const return CountrySwitch(country_code); } -IOS::ES::TMDReader CVolumeWAD::GetTMD() const +IOS::ES::TMDReader CVolumeWAD::GetTMD(const Partition& partition) const { return m_tmd; } -std::string CVolumeWAD::GetGameID() const +std::string CVolumeWAD::GetGameID(const Partition& partition) const { return m_tmd.GetGameID(); } -std::string CVolumeWAD::GetMakerID() const +std::string CVolumeWAD::GetMakerID(const Partition& partition) const { char temp[2]; - if (!Read(0x198 + m_tmd_offset, 2, (u8*)temp)) + if (!Read(0x198 + m_tmd_offset, 2, (u8*)temp, partition)) return "00"; // Some weird channels use 0x0000 in place of the MakerID, so we need a check here @@ -107,12 +107,12 @@ std::string CVolumeWAD::GetMakerID() const return DecodeString(temp); } -bool CVolumeWAD::GetTitleID(u64* buffer) const +bool CVolumeWAD::GetTitleID(u64* buffer, const Partition& partition) const { - return ReadSwapped(m_offset + 0x01DC, buffer, false); + return ReadSwapped(m_offset + 0x01DC, buffer, partition); } -u16 CVolumeWAD::GetRevision() const +u16 CVolumeWAD::GetRevision(const Partition& partition) const { if (!m_tmd.IsValid()) return 0; diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h index f84af08796..ecaef672fe 100644 --- a/Source/Core/DiscIO/VolumeWad.h +++ b/Source/Core/DiscIO/VolumeWad.h @@ -31,20 +31,27 @@ class CVolumeWAD : public IVolume public: CVolumeWAD(std::unique_ptr<IBlobReader> reader); ~CVolumeWAD(); - bool Read(u64 offset, u64 length, u8* buffer, bool decrypt = false) const override; - bool GetTitleID(u64* buffer) const override; - IOS::ES::TMDReader GetTMD() const override; - std::string GetGameID() const override; - std::string GetMakerID() const override; - u16 GetRevision() const override; - std::string GetInternalName() const override { return ""; } + bool Read(u64 offset, u64 length, u8* buffer, + const Partition& partition = PARTITION_NONE) const override; + bool GetTitleID(u64* buffer, const Partition& partition = PARTITION_NONE) const override; + IOS::ES::TMDReader GetTMD(const Partition& partition = PARTITION_NONE) const override; + std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; + std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override; + u16 GetRevision(const Partition& partition = PARTITION_NONE) const override; + std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override + { + return ""; + } std::map<Language, std::string> GetLongNames() const override; std::vector<u32> GetBanner(int* width, int* height) const override; - u64 GetFSTSize() const override { return 0; } - std::string GetApploaderDate() const override { return ""; } + u64 GetFSTSize(const Partition& partition = PARTITION_NONE) const override { return 0; } + std::string GetApploaderDate(const Partition& partition = PARTITION_NONE) const override + { + return ""; + } Platform GetVolumeType() const override; Region GetRegion() const override; - Country GetCountry() const override; + Country GetCountry(const Partition& partition = PARTITION_NONE) const override; BlobType GetBlobType() const override; u64 GetSize() const override; diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/VolumeWiiCrypted.cpp index e1e0657114..05d34aa126 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -4,6 +4,7 @@ #include "DiscIO/VolumeWiiCrypted.h" +#include <algorithm> #include <cstddef> #include <cstring> #include <map> @@ -28,58 +29,129 @@ namespace DiscIO { -CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader, u64 _VolumeOffset, - const unsigned char* _pVolumeKey) - : m_pReader(std::move(reader)), m_AES_ctx(std::make_unique<mbedtls_aes_context>()), - m_VolumeOffset(_VolumeOffset), m_dataOffset(0x20000), m_LastDecryptedBlockOffset(-1) +constexpr u64 PARTITION_DATA_OFFSET = 0x20000; + +CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader) + : m_pReader(std::move(reader)), m_game_partition(PARTITION_NONE), m_last_decrypted_block(-1) { _assert_(m_pReader); - mbedtls_aes_setkey_dec(m_AES_ctx.get(), _pVolumeKey, 128); -} + // Get decryption keys for all partitions + CBlobBigEndianReader big_endian_reader(*m_pReader.get()); + for (u32 partition_group = 0; partition_group < 4; ++partition_group) + { + u32 number_of_partitions; + if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8), &number_of_partitions)) + continue; -bool CVolumeWiiCrypted::ChangePartition(u64 offset) -{ - m_VolumeOffset = offset; - m_LastDecryptedBlockOffset = -1; + u32 read_buffer; + if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8) + 4, &read_buffer)) + continue; + const u64 partition_table_offset = (u64)read_buffer << 2; - u8 volume_key[16]; - DiscIO::VolumeKeyForPartition(*m_pReader, offset, volume_key); - mbedtls_aes_setkey_dec(m_AES_ctx.get(), volume_key, 128); - return true; + for (u32 i = 0; i < number_of_partitions; i++) + { + if (!big_endian_reader.ReadSwapped(partition_table_offset + (i * 8), &read_buffer)) + continue; + const u64 partition_offset = (u64)read_buffer << 2; + + if (m_game_partition == PARTITION_NONE) + { + u32 partition_type; + if (!big_endian_reader.ReadSwapped(partition_table_offset + (i * 8) + 4, &partition_type)) + continue; + + if (partition_type == 0) + m_game_partition = Partition(partition_offset); + } + + u8 sub_key[16]; + if (!m_pReader->Read(partition_offset + 0x1bf, 16, sub_key)) + continue; + + u8 iv[16]; + memset(iv, 0, 16); + if (!m_pReader->Read(partition_offset + 0x44c, 8, iv)) + continue; + + static const u8 common_key_standard[16] = {0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4, + 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7}; + static const u8 common_key_korean[16] = {0x63, 0xb8, 0x2b, 0xb4, 0xf4, 0x61, 0x4e, 0x2e, + 0x13, 0xf2, 0xfe, 0xfb, 0xba, 0x4c, 0x9b, 0x7e}; + static const u8 common_key_rvt[16] = {0xa1, 0x60, 0x4a, 0x6a, 0x71, 0x23, 0xb5, 0x29, + 0xae, 0x8b, 0xec, 0x32, 0xc8, 0x16, 0xfc, 0xaa}; + static const char issuer_rvt[] = "Root-CA00000002-XS00000006"; + + const u8* common_key; + + u8 issuer[sizeof(issuer_rvt)]; + if (!m_pReader->Read(partition_offset + 0x140, sizeof(issuer), issuer)) + continue; + + if (!memcmp(issuer, issuer_rvt, sizeof(issuer_rvt))) + { + // RVT issuer. Use the RVT (debug) master key. + common_key = common_key_rvt; + } + else + { + u8 key_number = 0; + if (!big_endian_reader.ReadSwapped(partition_offset + 0x1f1, &key_number)) + continue; + common_key = (key_number == 1) ? common_key_korean : common_key_standard; + } + + mbedtls_aes_context aes_context; + mbedtls_aes_setkey_dec(&aes_context, common_key, 128); + + u8 volume_key[16]; + mbedtls_aes_crypt_cbc(&aes_context, MBEDTLS_AES_DECRYPT, 16, iv, sub_key, volume_key); + + std::unique_ptr<mbedtls_aes_context> partition_AES_context = + std::make_unique<mbedtls_aes_context>(); + mbedtls_aes_setkey_dec(partition_AES_context.get(), volume_key, 128); + m_partitions[Partition(partition_offset)] = std::move(partition_AES_context); + } + } } CVolumeWiiCrypted::~CVolumeWiiCrypted() { } -bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool decrypt) const +bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, + const Partition& partition) const { - if (!decrypt) + if (partition == PARTITION_NONE) return m_pReader->Read(_ReadOffset, _Length, _pBuffer); + // Get the decryption key for the partition + auto it = m_partitions.find(partition); + if (it == m_partitions.end()) + return false; + mbedtls_aes_context* aes_context = it->second.get(); + std::vector<u8> read_buffer(BLOCK_TOTAL_SIZE); while (_Length > 0) { - // Calculate block offset - u64 Block = _ReadOffset / BLOCK_DATA_SIZE; - u64 Offset = _ReadOffset % BLOCK_DATA_SIZE; + // Calculate offsets + u64 block_offset_on_disc = + partition.offset + PARTITION_DATA_OFFSET + _ReadOffset / BLOCK_DATA_SIZE * BLOCK_TOTAL_SIZE; + u64 data_offset_in_block = _ReadOffset % BLOCK_DATA_SIZE; - if (m_LastDecryptedBlockOffset != Block) + if (m_last_decrypted_block != block_offset_on_disc) { // Read the current block - if (!m_pReader->Read(m_VolumeOffset + m_dataOffset + Block * BLOCK_TOTAL_SIZE, - BLOCK_TOTAL_SIZE, read_buffer.data())) + if (!m_pReader->Read(block_offset_on_disc, BLOCK_TOTAL_SIZE, read_buffer.data())) return false; // Decrypt the block's data. - // 0x3D0 - 0x3DF in m_pBuffer will be overwritten, + // 0x3D0 - 0x3DF in read_buffer will be overwritten, // but that won't affect anything, because we won't - // use the content of m_pBuffer anymore after this - mbedtls_aes_crypt_cbc(m_AES_ctx.get(), MBEDTLS_AES_DECRYPT, BLOCK_DATA_SIZE, - &read_buffer[0x3D0], &read_buffer[BLOCK_HEADER_SIZE], - m_LastDecryptedBlock); - m_LastDecryptedBlockOffset = Block; + // use the content of read_buffer anymore after this + mbedtls_aes_crypt_cbc(aes_context, MBEDTLS_AES_DECRYPT, BLOCK_DATA_SIZE, &read_buffer[0x3D0], + &read_buffer[BLOCK_HEADER_SIZE], m_last_decrypted_block_data); + m_last_decrypted_block = block_offset_on_disc; // The only thing we currently use from the 0x000 - 0x3FF part // of the block is the IV (at 0x3D0), but it also contains SHA-1 @@ -88,39 +160,52 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool de } // Copy the decrypted data - u64 MaxSizeToCopy = BLOCK_DATA_SIZE - Offset; - u64 CopySize = (_Length > MaxSizeToCopy) ? MaxSizeToCopy : _Length; - memcpy(_pBuffer, &m_LastDecryptedBlock[Offset], (size_t)CopySize); + u64 copy_size = std::min(_Length, BLOCK_DATA_SIZE - data_offset_in_block); + memcpy(_pBuffer, &m_last_decrypted_block_data[data_offset_in_block], + static_cast<size_t>(copy_size)); // Update offsets - _Length -= CopySize; - _pBuffer += CopySize; - _ReadOffset += CopySize; + _Length -= copy_size; + _pBuffer += copy_size; + _ReadOffset += copy_size; } return true; } -bool CVolumeWiiCrypted::GetTitleID(u64* buffer) const +std::vector<Partition> CVolumeWiiCrypted::GetPartitions() const { - return ReadSwapped(m_VolumeOffset + 0x1DC, buffer, false); + std::vector<Partition> partitions; + for (const auto& pair : m_partitions) + partitions.push_back(pair.first); + return partitions; } -IOS::ES::TicketReader CVolumeWiiCrypted::GetTicket() const +Partition CVolumeWiiCrypted::GetGamePartition() const +{ + return m_game_partition; +} + +bool CVolumeWiiCrypted::GetTitleID(u64* buffer, const Partition& partition) const +{ + return ReadSwapped(partition.offset + 0x1DC, buffer, PARTITION_NONE); +} + +IOS::ES::TicketReader CVolumeWiiCrypted::GetTicket(const Partition& partition) const { std::vector<u8> buffer(0x2a4); - Read(m_VolumeOffset, buffer.size(), buffer.data(), false); + Read(partition.offset, buffer.size(), buffer.data(), PARTITION_NONE); return IOS::ES::TicketReader{std::move(buffer)}; } -IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD() const +IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD(const Partition& partition) const { u32 tmd_size = 0; u32 tmd_address = 0; - if (!ReadSwapped(m_VolumeOffset + 0x2a4, &tmd_size, false)) + if (!ReadSwapped(partition.offset + 0x2a4, &tmd_size, PARTITION_NONE)) return {}; - if (!ReadSwapped(m_VolumeOffset + 0x2a8, &tmd_address, false)) + if (!ReadSwapped(partition.offset + 0x2a8, &tmd_address, PARTITION_NONE)) return {}; tmd_address <<= 2; @@ -135,23 +220,26 @@ IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD() const } std::vector<u8> buffer(tmd_size); - if (!Read(m_VolumeOffset + tmd_address, tmd_size, buffer.data(), false)) + if (!Read(partition.offset + tmd_address, tmd_size, buffer.data(), PARTITION_NONE)) return {}; return IOS::ES::TMDReader{std::move(buffer)}; } -u64 CVolumeWiiCrypted::PartitionOffsetToRawOffset(u64 offset) const +u64 CVolumeWiiCrypted::PartitionOffsetToRawOffset(u64 offset, const Partition& partition) { - return m_VolumeOffset + m_dataOffset + (offset / BLOCK_DATA_SIZE * BLOCK_TOTAL_SIZE) + + if (partition == PARTITION_NONE) + return offset; + + return partition.offset + PARTITION_DATA_OFFSET + (offset / BLOCK_DATA_SIZE * BLOCK_TOTAL_SIZE) + (offset % BLOCK_DATA_SIZE); } -std::string CVolumeWiiCrypted::GetGameID() const +std::string CVolumeWiiCrypted::GetGameID(const Partition& partition) const { char ID[6]; - if (!Read(0, 6, (u8*)ID, true)) + if (!Read(0, 6, (u8*)ID, partition)) return std::string(); return DecodeString(ID); @@ -160,16 +248,16 @@ std::string CVolumeWiiCrypted::GetGameID() const Region CVolumeWiiCrypted::GetRegion() const { u32 region_code; - if (!ReadSwapped(0x4E000, ®ion_code, false)) + if (!ReadSwapped(0x4E000, ®ion_code, PARTITION_NONE)) return Region::UNKNOWN_REGION; return static_cast<Region>(region_code); } -Country CVolumeWiiCrypted::GetCountry() const +Country CVolumeWiiCrypted::GetCountry(const Partition& partition) const { u8 country_byte; - if (!ReadSwapped(3, &country_byte, true)) + if (!ReadSwapped(3, &country_byte, partition)) return Country::COUNTRY_UNKNOWN; const Region region = GetRegion(); @@ -180,29 +268,29 @@ Country CVolumeWiiCrypted::GetCountry() const return CountrySwitch(country_byte); } -std::string CVolumeWiiCrypted::GetMakerID() const +std::string CVolumeWiiCrypted::GetMakerID(const Partition& partition) const { char makerID[2]; - if (!Read(0x4, 0x2, (u8*)&makerID, true)) + if (!Read(0x4, 0x2, (u8*)&makerID, partition)) return std::string(); return DecodeString(makerID); } -u16 CVolumeWiiCrypted::GetRevision() const +u16 CVolumeWiiCrypted::GetRevision(const Partition& partition) const { u8 revision; - if (!ReadSwapped(7, &revision, true)) + if (!ReadSwapped(7, &revision, partition)) return 0; return revision; } -std::string CVolumeWiiCrypted::GetInternalName() const +std::string CVolumeWiiCrypted::GetInternalName(const Partition& partition) const { char name_buffer[0x60]; - if (Read(0x20, 0x60, (u8*)&name_buffer, true)) + if (Read(0x20, 0x60, (u8*)&name_buffer, partition)) return DecodeString(name_buffer); return ""; @@ -210,7 +298,10 @@ std::string CVolumeWiiCrypted::GetInternalName() const std::map<Language, std::string> CVolumeWiiCrypted::GetLongNames() const { - std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this)); + std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this, GetGamePartition())); + if (!file_system) + return {{}}; + std::vector<u8> opening_bnr(NAMES_TOTAL_BYTES); size_t size = file_system->ReadFile("opening.bnr", opening_bnr.data(), opening_bnr.size(), 0x5C); opening_bnr.resize(size); @@ -223,27 +314,27 @@ std::vector<u32> CVolumeWiiCrypted::GetBanner(int* width, int* height) const *height = 0; u64 title_id; - if (!GetTitleID(&title_id)) + if (!GetTitleID(&title_id, GetGamePartition())) return std::vector<u32>(); return GetWiiBanner(width, height, title_id); } -u64 CVolumeWiiCrypted::GetFSTSize() const +u64 CVolumeWiiCrypted::GetFSTSize(const Partition& partition) const { u32 size; - if (!Read(0x428, 0x4, (u8*)&size, true)) + if (!Read(0x428, 0x4, (u8*)&size, partition)) return 0; return (u64)Common::swap32(size) << 2; } -std::string CVolumeWiiCrypted::GetApploaderDate() const +std::string CVolumeWiiCrypted::GetApploaderDate(const Partition& partition) const { char date[16]; - if (!Read(0x2440, 0x10, (u8*)&date, true)) + if (!Read(0x2440, 0x10, (u8*)&date, partition)) return std::string(); return DecodeString(date); @@ -254,10 +345,10 @@ Platform CVolumeWiiCrypted::GetVolumeType() const return Platform::WII_DISC; } -u8 CVolumeWiiCrypted::GetDiscNumber() const +u8 CVolumeWiiCrypted::GetDiscNumber(const Partition& partition) const { u8 disc_number = 0; - ReadSwapped(6, &disc_number, true); + ReadSwapped(6, &disc_number, partition); return disc_number; } @@ -276,29 +367,34 @@ u64 CVolumeWiiCrypted::GetRawSize() const return m_pReader->GetRawSize(); } -bool CVolumeWiiCrypted::CheckIntegrity() const +bool CVolumeWiiCrypted::CheckIntegrity(const Partition& partition) const { + // Get the decryption key for the partition + auto it = m_partitions.find(partition); + if (it == m_partitions.end()) + return false; + mbedtls_aes_context* aes_context = it->second.get(); + // Get partition data size u32 partSizeDiv4; - Read(m_VolumeOffset + 0x2BC, 4, (u8*)&partSizeDiv4, false); + Read(partition.offset + 0x2BC, 4, (u8*)&partSizeDiv4, PARTITION_NONE); u64 partDataSize = (u64)Common::swap32(partSizeDiv4) * 4; u32 nClusters = (u32)(partDataSize / 0x8000); for (u32 clusterID = 0; clusterID < nClusters; ++clusterID) { - u64 clusterOff = m_VolumeOffset + m_dataOffset + (u64)clusterID * 0x8000; + u64 clusterOff = partition.offset + PARTITION_DATA_OFFSET + (u64)clusterID * 0x8000; // Read and decrypt the cluster metadata u8 clusterMDCrypted[0x400]; u8 clusterMD[0x400]; u8 IV[16] = {0}; - if (!Read(clusterOff, 0x400, clusterMDCrypted, false)) + if (!Read(clusterOff, 0x400, clusterMDCrypted, PARTITION_NONE)) { WARN_LOG(DISCIO, "Integrity Check: fail at cluster %d: could not read metadata", clusterID); return false; } - mbedtls_aes_crypt_cbc(m_AES_ctx.get(), MBEDTLS_AES_DECRYPT, 0x400, IV, clusterMDCrypted, - clusterMD); + mbedtls_aes_crypt_cbc(aes_context, MBEDTLS_AES_DECRYPT, 0x400, IV, clusterMDCrypted, clusterMD); // Some clusters have invalid data and metadata because they aren't // meant to be read by the game (for example, holes between files). To @@ -317,7 +413,7 @@ bool CVolumeWiiCrypted::CheckIntegrity() const continue; u8 clusterData[0x7C00]; - if (!Read((u64)clusterID * 0x7C00, 0x7C00, clusterData, true)) + if (!Read((u64)clusterID * 0x7C00, 0x7C00, clusterData, partition)) { WARN_LOG(DISCIO, "Integrity Check: fail at cluster %d: could not read data", clusterID); return false; diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h index d7e7c4bddb..88befabcb6 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -28,48 +28,47 @@ enum class Platform; class CVolumeWiiCrypted : public IVolume { public: - CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader, u64 _VolumeOffset, - const unsigned char* _pVolumeKey); + CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader); ~CVolumeWiiCrypted(); - bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const override; - bool GetTitleID(u64* buffer) const override; - IOS::ES::TicketReader GetTicket() const override; - IOS::ES::TMDReader GetTMD() const override; - u64 PartitionOffsetToRawOffset(u64 offset) const override; - std::string GetGameID() const override; - std::string GetMakerID() const override; - u16 GetRevision() const override; - std::string GetInternalName() const override; + bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, const Partition& partition) const override; + std::vector<Partition> GetPartitions() const override; + Partition GetGamePartition() const override; + bool GetTitleID(u64* buffer, const Partition& partition) const override; + IOS::ES::TicketReader GetTicket(const Partition& partition) const override; + IOS::ES::TMDReader GetTMD(const Partition& partition) const override; + std::string GetGameID(const Partition& partition) const override; + std::string GetMakerID(const Partition& partition) const override; + u16 GetRevision(const Partition& partition) const override; + std::string GetInternalName(const Partition& partition) const override; std::map<Language, std::string> GetLongNames() const override; std::vector<u32> GetBanner(int* width, int* height) const override; - u64 GetFSTSize() const override; - std::string GetApploaderDate() const override; - u8 GetDiscNumber() const override; + u64 GetFSTSize(const Partition& partition) const override; + std::string GetApploaderDate(const Partition& partition) const override; + u8 GetDiscNumber(const Partition& partition) const override; Platform GetVolumeType() const override; bool SupportsIntegrityCheck() const override { return true; } - bool CheckIntegrity() const override; - bool ChangePartition(u64 offset) override; + bool CheckIntegrity(const Partition& partition) const override; Region GetRegion() const override; - Country GetCountry() const override; + Country GetCountry(const Partition& partition) const override; BlobType GetBlobType() const override; u64 GetSize() const override; u64 GetRawSize() const override; + static u64 PartitionOffsetToRawOffset(u64 offset, const Partition& partition); + static constexpr unsigned int BLOCK_HEADER_SIZE = 0x0400; static constexpr unsigned int BLOCK_DATA_SIZE = 0x7C00; static constexpr unsigned int BLOCK_TOTAL_SIZE = BLOCK_HEADER_SIZE + BLOCK_DATA_SIZE; private: std::unique_ptr<IBlobReader> m_pReader; - std::unique_ptr<mbedtls_aes_context> m_AES_ctx; - - u64 m_VolumeOffset; - u64 m_dataOffset; + std::map<Partition, std::unique_ptr<mbedtls_aes_context>> m_partitions; + Partition m_game_partition; - mutable u64 m_LastDecryptedBlockOffset; - mutable unsigned char m_LastDecryptedBlock[BLOCK_DATA_SIZE]; + mutable u64 m_last_decrypted_block; + mutable u8 m_last_decrypted_block_data[BLOCK_DATA_SIZE]; }; } // namespace |
