🐛Correct CD EDC calcuations.

This commit is contained in:
2018-04-10 05:07:53 +01:00
parent c93297a225
commit a4faba484a

View File

@@ -42,10 +42,9 @@ namespace DiscImageChef.Checksums
/// </summary> /// </summary>
public static class CdChecksums public static class CdChecksums
{ {
const uint CDCRC32_POLY = 0xD8018001;
const uint CDCRC32_SEED = 0x00000000;
static byte[] eccFTable; static byte[] eccFTable;
static byte[] eccBTable; static byte[] eccBTable;
static uint[] edcTable;
static readonly ushort[] CcittCrc16Table = static readonly ushort[] CcittCrc16Table =
{ {
@@ -109,12 +108,16 @@ namespace DiscImageChef.Checksums
{ {
eccFTable = new byte[256]; eccFTable = new byte[256];
eccBTable = new byte[256]; eccBTable = new byte[256];
edcTable = new uint[256];
for(uint i = 0; i < 256; i++) for(uint i = 0; i < 256; i++)
{ {
uint j = (uint)((i << 1) ^ ((i & 0x80) == 0x80 ? 0x11D : 0)); uint edc = i;
uint j = (uint)((i << 1) ^ ((i & 0x80) == 0x80 ? 0x11D : 0));
eccFTable[i] = (byte)j; eccFTable[i] = (byte)j;
eccBTable[i ^ j] = (byte)i; eccBTable[i ^ j] = (byte)i;
for(j = 0; j < 8; j++) edc = (edc >> 1) ^ ((edc & 1) > 0 ? 0xD8018001 : 0);
edcTable[i] = edc;
} }
} }
@@ -131,8 +134,7 @@ namespace DiscImageChef.Checksums
uint minor; uint minor;
for(minor = 0; minor < minorCount; minor++) for(minor = 0; minor < minorCount; minor++)
{ {
byte temp; byte temp = index < 4 ? address[index] : data[index - 4];
temp = index < 4 ? address[index] : data[index - 4];
index += minorInc; index += minorInc;
if(index >= size) index -= size; if(index >= size) index -= size;
eccA ^= temp; eccA ^= temp;
@@ -214,27 +216,23 @@ namespace DiscImageChef.Checksums
"Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check",
channel[0x00C], channel[0x00D], channel[0x00E]); channel[0x00C], channel[0x00D], channel[0x00E]);
return !failedEccP && !failedEccQ; uint storedEdc = BitConverter.ToUInt32(channel, 0x810);
uint calculatedEdc = ComputeEdc(0, channel, 0x810);
/* TODO: This is not working if(calculatedEdc == storedEdc) return !failedEccP && !failedEccQ;
byte[] SectorForCheck = new byte[0x810];
uint StoredEDC = BitConverter.ToUInt32(channel, 0x810);
byte[] CalculatedEDCBytes;
Array.Copy(channel, 0, SectorForCheck, 0, 0x810);
CRC32Context.Data(SectorForCheck, 0x810, out CalculatedEDCBytes, CDCRC32Poly, CDCRC32Seed);
uint CalculatedEDC = BitConverter.ToUInt32(CalculatedEDCBytes, 0);
if(CalculatedEDC != StoredEDC) DicConsole.DebugWriteLine("CD checksums",
{ "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}",
DicConsole.DebugWriteLine("CD checksums", "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", channel[0x00C], channel[0x00D], channel[0x00E], CalculatedEDC, StoredEDC); channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc);
return false; return false;
}*/
} }
if(channel[0x00F] == 0x02) // mode (1 byte) if(channel[0x00F] == 0x02) // mode (1 byte)
{ {
DicConsole.DebugWriteLine("CD checksums", "Mode 2 sector at address {0:X2}:{1:X2}:{2:X2}", //DicConsole.DebugWriteLine("CD checksums", "Mode 2 sector at address {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]); // channel[0x00C], channel[0x00D], channel[0x00E]);
byte[] mode2Sector = new byte[channel.Length - 0x10];
Array.Copy(channel, 0x10, mode2Sector, 0, mode2Sector.Length);
if((channel[0x012] & 0x20) == 0x20) // mode 2 form 2 if((channel[0x012] & 0x20) == 0x20) // mode 2 form 2
{ {
@@ -244,19 +242,18 @@ namespace DiscImageChef.Checksums
"Subheader copies differ in mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}", "Subheader copies differ in mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]); channel[0x00C], channel[0x00D], channel[0x00E]);
/* TODO: This is not working uint storedEdc = BitConverter.ToUInt32(mode2Sector, 0x91C);
byte[] SectorForCheck = new byte[0x91C]; // No CRC stored!
uint StoredEDC = BitConverter.ToUInt32(channel, 0x92C); if(storedEdc == 0x00000000) return true;
byte[] CalculatedEDCBytes;
Array.Copy(channel, 0x10, SectorForCheck, 0, 0x91C);
CRC32Context.Data(SectorForCheck, 0x91C, out CalculatedEDCBytes, CDCRC32Poly, CDCRC32Seed);
uint CalculatedEDC = BitConverter.ToUInt32(CalculatedEDCBytes, 0);
if(CalculatedEDC != StoredEDC && StoredEDC != 0x00000000) uint calculatedEdc = ComputeEdc(0, mode2Sector, 0x91C);
{
DicConsole.DebugWriteLine("CD checksums", "Mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", channel[0x00C], channel[0x00D], channel[0x00E], CalculatedEDC, StoredEDC); if(calculatedEdc == storedEdc || storedEdc == 0x00000000) return true;
return false;
}*/ DicConsole.DebugWriteLine("CD checksums",
"Mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}",
channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc);
return false;
} }
else else
{ {
@@ -291,23 +288,17 @@ namespace DiscImageChef.Checksums
if(failedEccQ) if(failedEccQ)
DicConsole.DebugWriteLine("CD checksums", DicConsole.DebugWriteLine("CD checksums",
"Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check",
channel[0x00F], channel[0x00C], channel[0x00D], channel[0x00E]); channel[0x00C], channel[0x00D], channel[0x00E]);
return !failedEccP && !failedEccQ; uint storedEdc = BitConverter.ToUInt32(mode2Sector, 0x808);
uint calculatedEdc = ComputeEdc(0, mode2Sector, 0x808);
/* TODO: This is not working if(calculatedEdc == storedEdc) return !failedEccP && !failedEccQ;
byte[] SectorForCheck = new byte[0x808];
uint StoredEDC = BitConverter.ToUInt32(channel, 0x818);
byte[] CalculatedEDCBytes;
Array.Copy(channel, 0x10, SectorForCheck, 0, 0x808);
CRC32Context.Data(SectorForCheck, 0x808, out CalculatedEDCBytes, CDCRC32Poly, CDCRC32Seed);
uint CalculatedEDC = BitConverter.ToUInt32(CalculatedEDCBytes, 0);
if(CalculatedEDC != StoredEDC) DicConsole.DebugWriteLine("CD checksums",
{ "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}",
DicConsole.DebugWriteLine("CD checksums", "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", channel[0x00C], channel[0x00D], channel[0x00E], CalculatedEDC, StoredEDC); channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc);
return false; return false;
}*/
} }
return true; return true;
@@ -318,6 +309,14 @@ namespace DiscImageChef.Checksums
return null; return null;
} }
static uint ComputeEdc(uint edc, byte[] src, int size)
{
int pos = 0;
for(; size > 0; size--) edc = (edc >> 8) ^ edcTable[(edc ^ src[pos++]) & 0xFF];
return edc;
}
static bool? CheckCdSectorSubChannel(byte[] subchannel) static bool? CheckCdSectorSubChannel(byte[] subchannel)
{ {
bool? status = true; bool? status = true;