@@ -30,9 +30,6 @@
<ClCompile Include="FileSystemGCWii.cpp">
<Filter>FileSystem</Filter>
</ClCompile>
<ClCompile Include="WiiWad.cpp">
<Filter>NAND</Filter>
</ClCompile>
<ClCompile Include="NANDImporter.cpp">
<Filter>NAND</Filter>
</ClCompile>
@@ -98,9 +95,6 @@
<ClInclude Include="FileSystemGCWii.h">
<Filter>FileSystem</Filter>
</ClInclude>
<ClInclude Include="WiiWad.h">
<Filter>NAND</Filter>
</ClInclude>
<ClInclude Include="NANDImporter.h">
<Filter>NAND</Filter>
</ClInclude>
@@ -223,7 +223,7 @@ bool FileInfoGCWii::IsValid(u64 fst_size, const FileInfoGCWii& parent_directory)
return true;
}

FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partition)
FileSystemGCWii::FileSystemGCWii(const VolumeDisc* volume, const Partition& partition)
: m_valid(false), m_root(nullptr, 0, 0, 0)
{
u8 offset_shift;
@@ -17,7 +17,7 @@

namespace DiscIO
{
class Volume;
class VolumeDisc;
struct Partition;

class FileInfoGCWii : public FileInfo
@@ -87,7 +87,7 @@ class FileInfoGCWii : public FileInfo
class FileSystemGCWii : public FileSystem
{
public:
FileSystemGCWii(const Volume* volume, const Partition& partition);
FileSystemGCWii(const VolumeDisc* volume, const Partition& partition);
~FileSystemGCWii() override;

bool IsValid() const override { return m_valid; }
@@ -43,30 +43,61 @@ std::map<Language, std::string> Volume::ReadWiiNames(const std::vector<char16_t>
return names;
}

std::unique_ptr<Volume> CreateVolumeFromFilename(const std::string& filename)
static std::unique_ptr<VolumeDisc> CreateDisc(std::unique_ptr<BlobReader>& reader)
{
std::unique_ptr<BlobReader> reader(CreateBlobReader(filename));
if (reader == nullptr)
return nullptr;

// Check for Wii
const std::optional<u32> wii_magic = reader->ReadSwapped<u32>(0x18);
if (wii_magic == u32(0x5D1C9EA3))
return std::make_unique<VolumeWii>(std::move(reader));

// Check for GC
const std::optional<u32> gc_magic = reader->ReadSwapped<u32>(0x1C);
if (gc_magic == u32(0xC2339F3D))
return std::make_unique<VolumeGC>(std::move(reader));

// No known magic words found
return nullptr;
}

std::unique_ptr<VolumeDisc> CreateDisc(const std::string& path)
{
std::unique_ptr<BlobReader> reader(CreateBlobReader(path));
return reader ? CreateDisc(reader) : nullptr;
}

static std::unique_ptr<VolumeWAD> CreateWAD(std::unique_ptr<BlobReader>& reader)
{
// Check for WAD
// 0x206962 for boot2 wads
const std::optional<u32> wad_magic = reader->ReadSwapped<u32>(0x02);
if (wad_magic == u32(0x00204973) || wad_magic == u32(0x00206962))
return std::make_unique<VolumeWAD>(std::move(reader));

// Check for GC
const std::optional<u32> gc_magic = reader->ReadSwapped<u32>(0x1C);
if (gc_magic == u32(0xC2339F3D))
return std::make_unique<VolumeGC>(std::move(reader));

// No known magic words found
return nullptr;
}

std::unique_ptr<VolumeWAD> CreateWAD(const std::string& path)
{
std::unique_ptr<BlobReader> reader(CreateBlobReader(path));
return reader ? CreateWAD(reader) : nullptr;
}

std::unique_ptr<Volume> CreateVolume(const std::string& path)
{
std::unique_ptr<BlobReader> reader(CreateBlobReader(path));
if (reader == nullptr)
return nullptr;

std::unique_ptr<VolumeDisc> disc = CreateDisc(reader);
if (disc)
return disc;

std::unique_ptr<VolumeWAD> wad = CreateWAD(reader);
if (wad)
return wad;

return nullptr;
}

} // namespace DiscIO
@@ -22,6 +22,7 @@ namespace DiscIO
{
enum class BlobType;
class FileSystem;
class VolumeWAD;

struct Partition final
{
@@ -73,6 +74,7 @@ class Volume
{
return INVALID_CERT_CHAIN;
}
virtual std::vector<u8> GetContent(u16 index) const { return {}; }
virtual std::vector<u64> GetContentOffsets() const { return {}; }
// Returns a non-owning pointer. Returns nullptr if the file system couldn't be read.
virtual const FileSystem* GetFileSystem(const Partition& partition) const = 0;
@@ -141,6 +143,12 @@ class Volume
static const std::vector<u8> INVALID_CERT_CHAIN;
};

std::unique_ptr<Volume> CreateVolumeFromFilename(const std::string& filename);
class VolumeDisc : public Volume
{
};

std::unique_ptr<VolumeDisc> CreateDisc(const std::string& path);
std::unique_ptr<VolumeWAD> CreateWAD(const std::string& path);
std::unique_ptr<Volume> CreateVolume(const std::string& path);

} // namespace DiscIO
@@ -25,7 +25,7 @@ enum class Language;
enum class Region;
enum class Platform;

class VolumeGC : public Volume
class VolumeGC : public VolumeDisc
{
public:
VolumeGC(std::unique_ptr<BlobReader> reader);
@@ -770,10 +770,7 @@ void VolumeVerifier::Process()

bool VolumeVerifier::CheckContentIntegrity(const IOS::ES::Content& content)
{
const u64 padded_size = Common::AlignUp(content.size, 0x40);
std::vector<u8> encrypted_data(padded_size);
m_volume.Read(m_content_offsets[m_content_index], padded_size, encrypted_data.data(),
PARTITION_NONE);
std::vector<u8> encrypted_data = m_volume.GetContent(content.index);

mbedtls_aes_context context;
const std::array<u8, 16> key = m_volume.GetTicket(PARTITION_NONE).GetTitleKey();
@@ -783,8 +780,8 @@ bool VolumeVerifier::CheckContentIntegrity(const IOS::ES::Content& content)
iv[0] = static_cast<u8>(content.index >> 8);
iv[1] = static_cast<u8>(content.index & 0xFF);

std::vector<u8> decrypted_data(padded_size);
mbedtls_aes_crypt_cbc(&context, MBEDTLS_AES_DECRYPT, padded_size, iv.data(),
std::vector<u8> decrypted_data(Common::AlignUp(content.size, 0x40));
mbedtls_aes_crypt_cbc(&context, MBEDTLS_AES_DECRYPT, decrypted_data.size(), iv.data(),
encrypted_data.data(), decrypted_data.data());

std::array<u8, 20> sha1;
@@ -61,10 +61,6 @@ VolumeWAD::VolumeWAD(std::unique_ptr<BlobReader> reader) : m_reader(std::move(re
Read(m_cert_chain_offset, m_cert_chain_size, m_cert_chain.data());
}

VolumeWAD::~VolumeWAD()
{
}

bool VolumeWAD::Read(u64 offset, u64 length, u8* buffer, const Partition& partition) const
{
if (partition != PARTITION_NONE)
@@ -118,6 +114,24 @@ const std::vector<u8>& VolumeWAD::GetCertificateChain(const Partition& partition
return m_cert_chain;
}

std::vector<u8> VolumeWAD::GetContent(u16 index) const
{
u64 offset = m_data_offset;
for (const IOS::ES::Content& content : m_tmd.GetContents())
{
const u64 aligned_size = Common::AlignUp(content.size, 0x40);
if (content.index == index)
{
std::vector<u8> data(aligned_size);
if (!m_reader->Read(offset, aligned_size, data.data()))
return {};
return data;
}
offset += aligned_size;
}
return {};
}

std::vector<u64> VolumeWAD::GetContentOffsets() const
{
const std::vector<IOS::ES::Content> contents = m_tmd.GetContents();
@@ -28,7 +28,6 @@ class VolumeWAD : public Volume
{
public:
VolumeWAD(std::unique_ptr<BlobReader> reader);
~VolumeWAD();
bool Read(u64 offset, u64 length, u8* buffer,
const Partition& partition = PARTITION_NONE) const override;
const FileSystem* GetFileSystem(const Partition& partition = PARTITION_NONE) const override;
@@ -38,6 +37,7 @@ class VolumeWAD : public Volume
const IOS::ES::TMDReader& GetTMD(const Partition& partition = PARTITION_NONE) const override;
const std::vector<u8>&
GetCertificateChain(const Partition& partition = PARTITION_NONE) const override;
std::vector<u8> GetContent(u16 index) const override;
std::vector<u64> GetContentOffsets() const override;
std::string GetGameID(const Partition& partition = PARTITION_NONE) const override;
std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const override;
@@ -27,7 +27,7 @@ enum class Language;
enum class Region;
enum class Platform;

class VolumeWii : public Volume
class VolumeWii : public VolumeDisc
{
public:
VolumeWii(std::unique_ptr<BlobReader> reader);

This file was deleted.

This file was deleted.

@@ -60,7 +60,7 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga

if (game.GetPlatform() != DiscIO::Platform::ELFOrDOL)
{
std::shared_ptr<DiscIO::Volume> volume = DiscIO::CreateVolumeFromFilename(game.GetFilePath());
std::shared_ptr<DiscIO::Volume> volume = DiscIO::CreateVolume(game.GetFilePath());
if (volume)
{
VerifyWidget* verify = new VerifyWidget(volume);
@@ -121,7 +121,7 @@ GameFile::GameFile(std::string path) : m_file_path(std::move(path))
SplitPath(m_file_path, nullptr, &name, &extension);
m_file_name = name + extension;

std::unique_ptr<DiscIO::Volume> volume(DiscIO::CreateVolumeFromFilename(m_file_path));
std::unique_ptr<DiscIO::Volume> volume(DiscIO::CreateVolume(m_file_path));
if (volume != nullptr)
{
m_platform = volume->GetVolumeType();