In dicformat deconstruct MODE 2 sectors so if they have correct ECC, correct/empty EDC, those fields are not stored in the image.

This commit is contained in:
2018-08-02 23:25:20 +01:00
parent 076297bbbd
commit 04c1b358aa
3 changed files with 84 additions and 24 deletions

View File

@@ -41,9 +41,12 @@ namespace DiscImageChef.DiscImages
byte[] eccBTable; byte[] eccBTable;
byte[] eccFTable; byte[] eccFTable;
uint[] edcTable; uint[] edcTable;
bool initedEdc;
void EccInit() void EccInit()
{ {
if(initedEdc) return;
eccFTable = new byte[256]; eccFTable = new byte[256];
eccBTable = new byte[256]; eccBTable = new byte[256];
edcTable = new uint[256]; edcTable = new uint[256];
@@ -57,30 +60,22 @@ namespace DiscImageChef.DiscImages
for(j = 0; j < 8; j++) edc = (edc >> 1) ^ ((edc & 1) > 0 ? 0xD8018001 : 0); for(j = 0; j < 8; j++) edc = (edc >> 1) ^ ((edc & 1) > 0 ? 0xD8018001 : 0);
edcTable[i] = edc; edcTable[i] = edc;
} }
initedEdc = true;
} }
bool SuffixIsCorrect(byte[] sector) bool SuffixIsCorrect(byte[] sector)
{ {
if(!initedEdc) EccInit();
if(sector[0x814] != 0x00 || // reserved (8 bytes) if(sector[0x814] != 0x00 || // reserved (8 bytes)
sector[0x815] != 0x00 || sector[0x816] != 0x00 || sector[0x817] != 0x00 || sector[0x818] != 0x00 || sector[0x815] != 0x00 || sector[0x816] != 0x00 || sector[0x817] != 0x00 || sector[0x818] != 0x00 ||
sector[0x819] != 0x00 || sector[0x81A] != 0x00 || sector[0x81B] != 0x00) return false; sector[0x819] != 0x00 || sector[0x81A] != 0x00 || sector[0x81B] != 0x00) return false;
byte[] address = new byte[4]; bool correctEccP = CheckEcc(sector, sector, 86, 24, 2, 86, sector, 0xC, 0x10, 0x81C);
byte[] data = new byte[2060];
byte[] data2 = new byte[2232];
byte[] eccP = new byte[172];
byte[] eccQ = new byte[104];
Array.Copy(sector, 0x0C, address, 0, 4);
Array.Copy(sector, 0x10, data, 0, 2060);
Array.Copy(sector, 0x10, data2, 0, 2232);
Array.Copy(sector, 0x81C, eccP, 0, 172);
Array.Copy(sector, 0x8C8, eccQ, 0, 104);
bool correctEccP = CheckEcc(ref address, ref data, 86, 24, 2, 86, ref eccP);
if(!correctEccP) return false; if(!correctEccP) return false;
bool correctEccQ = CheckEcc(ref address, ref data2, 52, 43, 86, 88, ref eccQ); bool correctEccQ = CheckEcc(sector, sector, 52, 43, 86, 88, sector, 0xC, 0x10, 0x81C + 0xAC);
if(!correctEccQ) return false; if(!correctEccQ) return false;
uint storedEdc = BitConverter.ToUInt32(sector, 0x810); uint storedEdc = BitConverter.ToUInt32(sector, 0x810);
@@ -93,8 +88,31 @@ namespace DiscImageChef.DiscImages
return calculatedEdc == storedEdc; return calculatedEdc == storedEdc;
} }
bool CheckEcc(ref byte[] address, ref byte[] data, uint majorCount, uint minorCount, uint majorMult, bool SuffixIsCorrectMode2(byte[] sector)
uint minorInc, ref byte[] ecc) {
if(!initedEdc) EccInit();
byte[] zeroaddress = new byte[4];
bool correctEccP = CheckEcc(zeroaddress, sector, 86, 24, 2, 86, sector, 0, 0x10, 0x81C);
if(!correctEccP) return false;
bool correctEccQ = CheckEcc(zeroaddress, sector, 52, 43, 86, 88, sector, 0, 0x10, 0x81C + 0xAC);
if(!correctEccQ) return false;
uint storedEdc = BitConverter.ToUInt32(sector, 0x818);
uint edc = 0;
int size = 0x808;
int pos = 0x10;
for(; size > 0; size--) edc = (edc >> 8) ^ edcTable[(edc ^ sector[pos++]) & 0xFF];
uint calculatedEdc = edc;
return calculatedEdc == storedEdc;
}
bool CheckEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult,
uint minorInc,
byte[] ecc, int addressOffset, int dataOffset, int eccOffset)
{ {
uint size = majorCount * minorCount; uint size = majorCount * minorCount;
uint major; uint major;
@@ -106,7 +124,7 @@ namespace DiscImageChef.DiscImages
uint minor; uint minor;
for(minor = 0; minor < minorCount; minor++) for(minor = 0; minor < minorCount; minor++)
{ {
byte temp = idx < 4 ? address[idx] : data[idx - 4]; byte temp = idx < 4 ? address[idx + addressOffset] : data[idx + dataOffset - 4];
idx += minorInc; idx += minorInc;
if(idx >= size) idx -= size; if(idx >= size) idx -= size;
eccA ^= temp; eccA ^= temp;
@@ -115,7 +133,7 @@ namespace DiscImageChef.DiscImages
} }
eccA = eccBTable[eccFTable[eccA] ^ eccB]; eccA = eccBTable[eccFTable[eccA] ^ eccB];
if(ecc[major] != eccA || ecc[major + majorCount] != (eccA ^ eccB)) return false; if(ecc[major + eccOffset] != eccA || ecc[major + majorCount + eccOffset] != (eccA ^ eccB)) return false;
} }
return true; return true;
@@ -217,6 +235,7 @@ namespace DiscImageChef.DiscImages
TrackType type) TrackType type)
{ {
byte[] computedEdc; byte[] computedEdc;
if(!initedEdc) EccInit();
switch(type) switch(type)
{ {
@@ -281,6 +300,7 @@ namespace DiscImageChef.DiscImages
uint ComputeEdc(uint edc, byte[] src, int size, int srcOffset = 0) uint ComputeEdc(uint edc, byte[] src, int size, int srcOffset = 0)
{ {
if(!initedEdc) EccInit();
int pos = srcOffset; int pos = srcOffset;
for(; size > 0; size--) edc = (edc >> 8) ^ edcTable[(edc ^ src[pos++]) & 0xFF]; for(; size > 0; size--) edc = (edc >> 8) ^ edcTable[(edc ^ src[pos++]) & 0xFF];

View File

@@ -252,8 +252,11 @@ namespace DiscImageChef.DiscImages
enum CdFixFlags : uint enum CdFixFlags : uint
{ {
NotDumped = 0x10000000, NotDumped = 0x10000000,
Correct = 0x20000000 Correct = 0x20000000,
Mode2Form1Ok = 0x30000000,
Mode2Form2Ok = 0x40000000,
Mode2Form2NoCrc = 0x50000000
} }
} }
} }

View File

@@ -1249,8 +1249,46 @@ namespace DiscImageChef.DiscImages
if(mode2Subheaders == null) mode2Subheaders = new byte[imageInfo.Sectors * 8]; if(mode2Subheaders == null) mode2Subheaders = new byte[imageInfo.Sectors * 8];
bool correctEcc = SuffixIsCorrectMode2(data);
bool correctEdc = false;
if(correctEcc)
{
uint computedEdc = ComputeEdc(0, data, 0x808, 0x10);
uint edc = BitConverter.ToUInt32(data, 0x818);
correctEdc = computedEdc == edc;
}
else
{
uint computedEdc = ComputeEdc(0, data, 0x91C, 0x10);
uint edc = BitConverter.ToUInt32(data, 0x92C);
correctEdc = computedEdc == edc;
}
if(correctEcc && correctEdc)
{
sector = new byte[2048];
if(sectorSuffixDdt == null) sectorSuffixDdt = new uint[imageInfo.Sectors];
sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form1Ok;
Array.Copy(data, 24, sector, 0, 2048);
}
else if(correctEdc)
{
sector = new byte[2324];
if(sectorSuffixDdt == null) sectorSuffixDdt = new uint[imageInfo.Sectors];
sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2Ok;
Array.Copy(data, 24, sector, 0, 2324);
}
else if(BitConverter.ToUInt32(data, 0x92C) == 0)
{
sector = new byte[2324];
if(sectorSuffixDdt == null) sectorSuffixDdt = new uint[imageInfo.Sectors];
sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2NoCrc;
Array.Copy(data, 24, sector, 0, 2324);
}
else Array.Copy(data, 24, sector, 0, 2328);
Array.Copy(data, 16, mode2Subheaders, (int)sectorAddress * 8, 8); Array.Copy(data, 16, mode2Subheaders, (int)sectorAddress * 8, 8);
Array.Copy(data, 24, sector, 0, 2328);
return WriteSector(sector, sectorAddress); return WriteSector(sector, sectorAddress);
} }
@@ -2411,7 +2449,7 @@ namespace DiscImageChef.DiscImages
subheaderBlock.compression = CompressionType.None; subheaderBlock.compression = CompressionType.None;
subheaderBlock.cmpCrc64 = subheaderBlock.crc64; subheaderBlock.cmpCrc64 = subheaderBlock.crc64;
subheaderBlock.cmpLength = subheaderBlock.length; subheaderBlock.cmpLength = subheaderBlock.length;
blockStream = new MemoryStream(mode2Subheaders); blockStream = new MemoryStream(mode2Subheaders);
} }
else else
{ {
@@ -2425,7 +2463,7 @@ namespace DiscImageChef.DiscImages
Crc64Context cmpCrc = new Crc64Context(); Crc64Context cmpCrc = new Crc64Context();
cmpCrc.Update(lzmaProperties); cmpCrc.Update(lzmaProperties);
cmpCrc.Update(blockStream.ToArray()); cmpCrc.Update(blockStream.ToArray());
blockCrc = cmpCrc.Final(); blockCrc = cmpCrc.Final();
subheaderBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH; subheaderBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
subheaderBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); subheaderBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
subheaderBlock.compression = CompressionType.Lzma; subheaderBlock.compression = CompressionType.Lzma;
@@ -2454,7 +2492,6 @@ namespace DiscImageChef.DiscImages
blockStream = null; blockStream = null;
} }
if(sectorSubchannel != null) if(sectorSubchannel != null)
{ {
idxEntry = new IndexEntry idxEntry = new IndexEntry