Merge pull request #14613 from JosJuice/wad-tmd-checks

DiscIO: Add extra IsValid checks for VolumeWAD::m_tmd
This commit is contained in:
Admiral H. Curtiss
2026-05-11 22:59:40 +02:00
committed by GitHub
3 changed files with 73 additions and 36 deletions
+2 -2
View File
@@ -322,7 +322,7 @@ u16 TMDReader::GetNumContents() const
bool TMDReader::GetContent(u16 index, Content* content) const
{
if (index >= GetNumContents())
if (!IsValid() || index >= GetNumContents())
{
return false;
}
@@ -339,7 +339,7 @@ bool TMDReader::GetContent(u16 index, Content* content) const
std::vector<Content> TMDReader::GetContents() const
{
std::vector<Content> contents(GetNumContents());
std::vector<Content> contents(IsValid() ? GetNumContents() : 0);
for (size_t i = 0; i < contents.size(); ++i)
GetContent(static_cast<u16>(i), &contents[i]);
return contents;
+65 -34
View File
@@ -646,44 +646,65 @@ bool VolumeVerifier::CheckPartition(const Partition& partition)
if (type == PARTITION_UPDATE)
{
const IOS::ES::TMDReader& tmd = m_volume.GetTMD(m_volume.GetGamePartition());
// IOS9 is the only IOS which can be assumed to exist in a working state on any Wii
// regardless of what updates have been installed. At least Mario Party 8
// (RM8E01, revision 2) uses IOS9 without having it in its update partition.
const u64 ios_ver = tmd.GetIOSId() & 0xFF;
bool has_correct_ios = tmd.IsValid() && ios_ver == 9;
if (!has_correct_ios && tmd.IsValid())
if (tmd.IsValid())
{
std::unique_ptr<FileInfo> file_info = filesystem->FindFileInfo("_sys");
if (file_info)
const u64 ios_ver = tmd.GetIOSId() & 0xFF;
bool has_correct_ios = false;
if (ios_ver == 9)
{
const std::string ios_ver_str = std::to_string(ios_ver);
const std::string correct_ios =
IsDebugSigned() ? ("firmware.64." + ios_ver_str + ".") : ("ios" + ios_ver_str + "-");
for (const FileInfo& f : *file_info)
// IOS9 is the only IOS which can be assumed to exist in a working state on any Wii
// regardless of what updates have been installed. At least Mario Party 8
// (RM8E01, revision 2) uses IOS9 without having it in its update partition.
has_correct_ios = true;
}
else
{
std::unique_ptr<FileInfo> file_info = filesystem->FindFileInfo("_sys");
if (file_info)
{
std::string file_name = f.GetName();
Common::ToLower(&file_name);
if (file_name.starts_with(correct_ios))
const std::string ios_ver_str = std::to_string(ios_ver);
const std::string correct_ios =
IsDebugSigned() ? ("firmware.64." + ios_ver_str + ".") : ("ios" + ios_ver_str + "-");
for (const FileInfo& f : *file_info)
{
has_correct_ios = true;
break;
std::string file_name = f.GetName();
Common::ToLower(&file_name);
if (file_name.starts_with(correct_ios))
{
has_correct_ios = true;
break;
}
}
}
}
}
if (!has_correct_ios)
{
// This is reached for hacked dumps where the update partition has been replaced with
// a very old update partition so that no updates will be installed.
AddProblem(
Severity::Low,
Common::GetStringT("The update partition does not contain the IOS used by this title."));
if (!has_correct_ios)
{
// This is reached for hacked dumps where the update partition has been replaced with
// a very old update partition so that no updates will be installed.
AddProblem(Severity::Low,
Common::GetStringT(
"The update partition does not contain the IOS used by this title."));
}
}
}
const IOS::ES::TicketReader& ticket = m_volume.GetTicket(partition);
if (!ticket.IsValid())
{
AddProblem(severity,
// i18n: "Ticket" here is a kind of digital authorization to use a certain title
// (e.g. a game)
Common::FmtFormatT("The {0} partition does not have a valid ticket.", name));
}
const IOS::ES::TMDReader& tmd = m_volume.GetTMD(partition);
if (!tmd.IsValid())
{
AddProblem(severity, Common::FmtFormatT("The {0} partition does not have a valid TMD.", name));
}
return true;
}
@@ -981,18 +1002,28 @@ void VolumeVerifier::CheckMisc()
auto& es = ios.GetESCore();
const std::vector<u8>& cert_chain = m_volume.GetCertificateChain(PARTITION_NONE);
if (IOS::HLE::IPC_SUCCESS !=
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::Ticket,
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore, m_ticket,
cert_chain))
if (!m_ticket.IsValid())
{
// i18n: "Ticket" here is a kind of digital authorization to use a certain title (e.g. a game)
AddProblem(Severity::High, Common::GetStringT("The ticket is invalid."));
}
else if (IOS::HLE::IPC_SUCCESS !=
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::Ticket,
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore, m_ticket,
cert_chain))
{
// i18n: "Ticket" here is a kind of digital authorization to use a certain title (e.g. a game)
AddProblem(Severity::Low, Common::GetStringT("The ticket is not correctly signed."));
}
if (IOS::HLE::IPC_SUCCESS !=
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::TMD,
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore, tmd, cert_chain))
if (!tmd.IsValid())
{
AddProblem(Severity::High, Common::GetStringT("The TMD is invalid."));
}
else if (IOS::HLE::IPC_SUCCESS !=
es.VerifyContainer(IOS::HLE::ESCore::VerifyContainerType::TMD,
IOS::HLE::ESCore::VerifyMode::DoNotUpdateCertStore, tmd,
cert_chain))
{
AddProblem(
Severity::Medium,
+6
View File
@@ -230,11 +230,17 @@ IOS::ES::TicketReader VolumeWAD::GetTicketWithFixedCommonKey() const
std::string VolumeWAD::GetGameID(const Partition& partition) const
{
if (!m_tmd.IsValid())
return {};
return m_tmd.GetGameID();
}
std::string VolumeWAD::GetGameTDBID(const Partition& partition) const
{
if (!m_tmd.IsValid())
return {};
return m_tmd.GetGameTDBID();
}