static IVolume* CreateVolumeFromCryptedWiiImage(std::unique_ptr<IBlobReader> reader, u32 _PartitionGroup, u32 _VolumeType, u32 _VolumeNum) { CBlobBigEndianReader big_endian_reader(*reader); u32 numPartitions = big_endian_reader.Read32(0x40000 + (_PartitionGroup * 8)); u64 PartitionsOffset = (u64)big_endian_reader.Read32(0x40000 + (_PartitionGroup * 8) + 4) << 2; // Check if we're looking for a valid partition if ((int)_VolumeNum != -1 && _VolumeNum > numPartitions) return nullptr; struct SPartition { u64 Offset; u32 Type; }; struct SPartitionGroup { u32 numPartitions; u64 PartitionsOffset; std::vector<SPartition> PartitionsVec; }; SPartitionGroup PartitionGroup[4]; // Read all partitions for (SPartitionGroup& group : PartitionGroup) { for (u32 i = 0; i < numPartitions; i++) { SPartition Partition; Partition.Offset = ((u64)big_endian_reader.Read32(PartitionsOffset + (i * 8) + 0)) << 2; Partition.Type = big_endian_reader.Read32(PartitionsOffset + (i * 8) + 4); group.PartitionsVec.push_back(Partition); } } // 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 < PartitionGroup[_PartitionGroup].PartitionsVec.size(); i++) { const SPartition& rPartition = PartitionGroup[_PartitionGroup].PartitionsVec.at(i); if ((rPartition.Type == _VolumeType && (int)_VolumeNum == -1) || i == _VolumeNum) { u8 VolumeKey[16]; VolumeKeyForPartition(*reader, rPartition.Offset, VolumeKey); return new CVolumeWiiCrypted(std::move(reader), rPartition.Offset, VolumeKey); } } return nullptr; }
bool WiiWAD::ParseWAD(IBlobReader& reader) { CBlobBigEndianReader big_endian_reader(reader); if (!IsWiiWAD(big_endian_reader)) return false; u32 certificate_chain_size; u32 reserved; u32 ticket_size; u32 tmd_size; u32 data_app_size; u32 footer_size; if (!big_endian_reader.ReadSwapped(0x08, &certificate_chain_size) || !big_endian_reader.ReadSwapped(0x0C, &reserved) || !big_endian_reader.ReadSwapped(0x10, &ticket_size) || !big_endian_reader.ReadSwapped(0x14, &tmd_size) || !big_endian_reader.ReadSwapped(0x18, &data_app_size) || !big_endian_reader.ReadSwapped(0x1C, &footer_size)) return false; if (MAX_LOGLEVEL >= LogTypes::LOG_LEVELS::LDEBUG) _dbg_assert_msg_(BOOT, reserved == 0x00, "WiiWAD: Reserved must be 0x00"); u32 offset = 0x40; m_certificate_chain = CreateWADEntry(reader, certificate_chain_size, offset); offset += ROUND_UP(certificate_chain_size, 0x40); m_ticket = CreateWADEntry(reader, ticket_size, offset); offset += ROUND_UP(ticket_size, 0x40); m_tmd = CreateWADEntry(reader, tmd_size, offset); offset += ROUND_UP(tmd_size, 0x40); m_data_app = CreateWADEntry(reader, data_app_size, offset); offset += ROUND_UP(data_app_size, 0x40); m_footer = CreateWADEntry(reader, footer_size, offset); offset += ROUND_UP(footer_size, 0x40); return true; }
bool WiiWAD::IsWiiWAD(const std::string& name) { std::unique_ptr<IBlobReader> blob_reader(DiscIO::CreateBlobReader(name)); if (blob_reader == nullptr) return false; CBlobBigEndianReader big_endian_reader(*blob_reader); bool result = false; // check for Wii wad if (big_endian_reader.Read32(0x00) == 0x20) { u32 wad_type = big_endian_reader.Read32(0x04); switch (wad_type) { case 0x49730000: case 0x69620000: result = true; } } return result; }