mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Add Wii DVD integrity checking to Dolphin
This allows users to easily check whether their Wii dump is corrupted or not using the Dolphin properties window. Right click on a game, Properties, Filesystem tab, then right click on the game partition and select "Check partition integrity". This may have some false negatives due to the unused clusters heuristic (see the comment in VolumeWiiCrypted.cpp). False positives are unlikely.
This commit is contained in:
@ -17,6 +17,7 @@
|
||||
|
||||
#include "VolumeWiiCrypted.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Crypto/sha1.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
@ -232,4 +233,68 @@ u64 CVolumeWiiCrypted::GetSize() const
|
||||
}
|
||||
}
|
||||
|
||||
bool CVolumeWiiCrypted::CheckIntegrity() const
|
||||
{
|
||||
// Get partition data size
|
||||
u32 partSizeDiv4;
|
||||
RAWRead(m_VolumeOffset + 0x2BC, 4, (u8*)&partSizeDiv4);
|
||||
u64 partDataSize = (u64)Common::swap32(partSizeDiv4) * 4;
|
||||
|
||||
u32 nClusters = (u32)(partDataSize / 0x8000);
|
||||
for (u32 clusterID = 0; clusterID < nClusters; ++clusterID)
|
||||
{
|
||||
u64 clusterOff = m_VolumeOffset + dataOffset + (u64)clusterID * 0x8000;
|
||||
|
||||
// Read and decrypt the cluster metadata
|
||||
u8 clusterMDCrypted[0x400];
|
||||
u8 clusterMD[0x400];
|
||||
u8 IV[16] = { 0 };
|
||||
if (!m_pReader->Read(clusterOff, 0x400, clusterMDCrypted))
|
||||
{
|
||||
NOTICE_LOG(DISCIO, "Integrity Check: fail at cluster %d: could not read metadata", clusterID);
|
||||
return false;
|
||||
}
|
||||
AES_cbc_encrypt(clusterMDCrypted, clusterMD, 0x400, &m_AES_KEY, IV, AES_DECRYPT);
|
||||
|
||||
// Some clusters have invalid data and metadata because they aren't
|
||||
// meant to be read by the game (for example, holes between files). To
|
||||
// try to avoid reporting errors because of these clusters, we check
|
||||
// the 0x00 paddings in the metadata.
|
||||
//
|
||||
// This may cause some false negatives though: some bad clusters may be
|
||||
// skipped because they are *too* bad and are not even recognized as
|
||||
// valid clusters. To be improved.
|
||||
bool meaningless = false;
|
||||
for (u32 idx = 0x26C; idx < 0x280; ++idx)
|
||||
if (clusterMD[idx] != 0)
|
||||
meaningless = true;
|
||||
|
||||
if (meaningless)
|
||||
continue;
|
||||
|
||||
u8 clusterData[0x7C00];
|
||||
if (!Read((u64)clusterID * 0x7C00, 0x7C00, clusterData))
|
||||
{
|
||||
NOTICE_LOG(DISCIO, "Integrity Check: fail at cluster %d: could not read data", clusterID);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (u32 hashID = 0; hashID < 31; ++hashID)
|
||||
{
|
||||
u8 hash[20];
|
||||
|
||||
sha1(clusterData + hashID * 0x400, 0x400, hash);
|
||||
|
||||
// Note that we do not use strncmp here
|
||||
if (memcmp(hash, clusterMD + hashID * 20, 20))
|
||||
{
|
||||
NOTICE_LOG(DISCIO, "Integrity Check: fail at cluster %d: hash %d is invalid", clusterID, hashID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user