mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Implements verification on all currently supported disk
images. Implements DC42 CRC calculation. Calculates TeleDisk CRC for disk sectors. Resolves #2 and bumps version to 2.1.
This commit is contained in:
@@ -1251,70 +1251,68 @@ namespace DiscImageChef.ImagePlugins
|
||||
_imageInfo.diskBarcode = discimage.barcode;
|
||||
_imageInfo.diskType = discimage.disktype;
|
||||
|
||||
foreach(CDRWinTrack track in discimage.tracks)
|
||||
foreach (CDRWinTrack track in discimage.tracks)
|
||||
{
|
||||
switch(track.tracktype)
|
||||
switch (track.tracktype)
|
||||
{
|
||||
case CDRWinTrackTypeAudio:
|
||||
{
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags);
|
||||
break;
|
||||
}
|
||||
case CDRWinTrackTypeCDG:
|
||||
{
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDTrackFlags))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubchannel))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubchannel))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubchannel);
|
||||
break;
|
||||
}
|
||||
case CDRWinTrackTypeMode2Formless:
|
||||
case CDRWinTrackTypeCDI:
|
||||
{
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
|
||||
break;
|
||||
}
|
||||
case CDRWinTrackTypeMode2Raw:
|
||||
case CDRWinTrackTypeCDIRaw:
|
||||
{
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
|
||||
break;
|
||||
}
|
||||
case CDRWinTrackTypeMode1Raw:
|
||||
{
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_P))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_P))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_P);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_Q))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_Q))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_Q);
|
||||
if(!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
||||
if (!_imageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
||||
_imageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1928,6 +1926,8 @@ namespace DiscImageChef.ImagePlugins
|
||||
{
|
||||
List<Track> tracks = new List<Track>();
|
||||
|
||||
UInt64 previousStartSector = 0;
|
||||
|
||||
foreach (CDRWinTrack cdr_track in discimage.tracks)
|
||||
{
|
||||
Track _track = new Track();
|
||||
@@ -1936,6 +1936,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
_track.TrackDescription = cdr_track.title;
|
||||
if (!cdr_track.indexes.TryGetValue(0, out _track.TrackStartSector))
|
||||
cdr_track.indexes.TryGetValue(1, out _track.TrackStartSector);
|
||||
_track.TrackStartSector += previousStartSector;
|
||||
_track.TrackEndSector = _track.TrackStartSector + cdr_track.sectors - 1;
|
||||
_track.TrackPregap = cdr_track.pregap;
|
||||
_track.TrackSession = cdr_track.session;
|
||||
@@ -1943,6 +1944,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
_track.TrackType = CDRWinTrackTypeToTrackType(cdr_track.tracktype);
|
||||
|
||||
tracks.Add(_track);
|
||||
previousStartSector = _track.TrackEndSector + 1;
|
||||
}
|
||||
|
||||
return tracks;
|
||||
@@ -1989,6 +1991,85 @@ namespace DiscImageChef.ImagePlugins
|
||||
return discimage.sessions;
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress)
|
||||
{
|
||||
byte[] buffer = ReadSectorLong(sectorAddress);
|
||||
return Checksums.CDChecksums.CheckCDSector(buffer);
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
byte[] buffer = ReadSectorLong(sectorAddress, track);
|
||||
return Checksums.CDChecksums.CheckCDSector(buffer);
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
byte[] buffer = ReadSectorsLong(sectorAddress, length);
|
||||
int bps = (int)(buffer.Length / length);
|
||||
byte[] sector = new byte[bps];
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
Array.Copy(buffer, i * bps, sector, 0, bps);
|
||||
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
|
||||
|
||||
switch (sectorStatus)
|
||||
{
|
||||
case null:
|
||||
UnknownLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
case false:
|
||||
FailingLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (UnknownLBAs.Count > 0)
|
||||
return null;
|
||||
if (FailingLBAs.Count > 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
|
||||
int bps = (int)(buffer.Length / length);
|
||||
byte[] sector = new byte[bps];
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
Array.Copy(buffer, i * bps, sector, 0, bps);
|
||||
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
|
||||
|
||||
switch (sectorStatus)
|
||||
{
|
||||
case null:
|
||||
UnknownLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
case false:
|
||||
FailingLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (UnknownLBAs.Count > 0)
|
||||
return null;
|
||||
if (FailingLBAs.Count > 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool? VerifyDiskImage()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
@@ -2168,6 +2249,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
{
|
||||
return _imageInfo.imageCreator;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +373,83 @@ namespace DiscImageChef.ImagePlugins
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
|
||||
UnknownLBAs.Add(i);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
|
||||
UnknownLBAs.Add(i);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifyDiskImage()
|
||||
{
|
||||
byte[] data = new byte[header.dataSize];
|
||||
byte[] tags = new byte[header.tagSize];
|
||||
UInt32 dataChk;
|
||||
UInt32 tagsChk = 0;
|
||||
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Reading data");
|
||||
FileStream datastream = new FileStream(dc42ImagePath, FileMode.Open, FileAccess.Read);
|
||||
datastream.Seek((long)(dataOffset), SeekOrigin.Begin);
|
||||
datastream.Read(data, 0, (int)header.dataSize);
|
||||
datastream.Close();
|
||||
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Calculating data checksum");
|
||||
dataChk = DC42CheckSum(data);
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Calculated data checksum = 0x{0:X8}", dataChk);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Stored data checksum = 0x{0:X8}", header.dataChecksum);
|
||||
}
|
||||
|
||||
if (header.tagSize > 0)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Reading tags");
|
||||
FileStream tagstream = new FileStream(dc42ImagePath, FileMode.Open, FileAccess.Read);
|
||||
tagstream.Seek((long)(tagOffset), SeekOrigin.Begin);
|
||||
tagstream.Read(tags, 0, (int)header.tagSize);
|
||||
tagstream.Close();
|
||||
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Calculating data checksum");
|
||||
tagsChk = DC42CheckSum(data);
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Calculated data checksum = 0x{0:X8}", tagsChk);
|
||||
Console.WriteLine("DEBUG (DC42 plugin): Stored data checksum = 0x{0:X8}", header.tagChecksum);
|
||||
}
|
||||
}
|
||||
|
||||
return dataChk == header.dataChecksum && tagsChk == header.tagChecksum;
|
||||
}
|
||||
|
||||
public override bool ImageHasPartitions()
|
||||
{
|
||||
return _imageInfo.imageHasPartitions;
|
||||
@@ -640,6 +717,25 @@ namespace DiscImageChef.ImagePlugins
|
||||
}
|
||||
|
||||
#endregion Unsupported features
|
||||
|
||||
#region Private methods
|
||||
|
||||
private static UInt32 DC42CheckSum(byte[] buffer)
|
||||
{
|
||||
UInt32 dc42chk = 0;
|
||||
if ((buffer.Length & 0x01) == 0x01)
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
for (UInt32 i = 0; i < buffer.Length; i += 2)
|
||||
{
|
||||
dc42chk += (uint)(buffer[i] << 8);
|
||||
dc42chk += buffer[i + 1];
|
||||
dc42chk = (dc42chk >> 1) | (dc42chk << 31);
|
||||
}
|
||||
return dc42chk;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,6 @@ namespace DiscImageChef.ImagePlugins
|
||||
/// <param name="tag">Tag type to read.</param>
|
||||
public abstract byte[] ReadDiskTag(DiskTagType tag);
|
||||
|
||||
// Gets a disk tag
|
||||
/// <summary>
|
||||
/// Reads a sector's user data.
|
||||
/// </summary>
|
||||
@@ -370,7 +369,50 @@ namespace DiscImageChef.ImagePlugins
|
||||
/// </summary>
|
||||
/// <returns>The sessions.</returns>
|
||||
public abstract List<Session> GetSessions();
|
||||
// Returns disc sessions
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a sector.
|
||||
/// </summary>
|
||||
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
|
||||
/// <param name="sectorAddress">Sector address (LBA).</param>
|
||||
public abstract bool? VerifySector(UInt64 sectorAddress);
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a sector, relative to track.
|
||||
/// </summary>
|
||||
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
|
||||
/// <param name="sectorAddress">Sector address (relative LBA).</param>
|
||||
/// <param name="track">Track.</param>
|
||||
public abstract bool? VerifySector(UInt64 sectorAddress, UInt32 track);
|
||||
|
||||
/// <summary>
|
||||
/// Verifies several sectors.
|
||||
/// </summary>
|
||||
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
/// <param name="FailingLBAs">List of incorrect sectors</param>
|
||||
/// <param name="UnknownLBAs">List of uncheckable sectors</param>
|
||||
public abstract bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs);
|
||||
|
||||
/// <summary>
|
||||
/// Verifies several sectors, relative to track.
|
||||
/// </summary>
|
||||
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
|
||||
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
|
||||
/// <param name="length">How many sectors to read.</param>
|
||||
/// <param name="track">Track.</param>
|
||||
/// <param name="FailingLBAs">List of incorrect sectors</param>
|
||||
/// <param name="UnknownLBAs">List of uncheckable sectors</param>
|
||||
public abstract bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs);
|
||||
|
||||
/// <summary>
|
||||
/// Verifies disk image internal checksum.
|
||||
/// </summary>
|
||||
/// <returns>True if correct, false if incorrect, null if there is no internal checksum available</returns>
|
||||
public abstract bool? VerifyDiskImage();
|
||||
|
||||
|
||||
// CD flags bitmask
|
||||
|
||||
@@ -719,8 +761,9 @@ namespace DiscImageChef.ImagePlugins
|
||||
FDFORMAT_35_HD,
|
||||
|
||||
// Generic hard disks
|
||||
GENERIC_HDD
|
||||
};
|
||||
GENERIC_HDD}
|
||||
|
||||
;
|
||||
|
||||
/// <summary>
|
||||
/// Track (as partitioning element) types.
|
||||
@@ -738,8 +781,9 @@ namespace DiscImageChef.ImagePlugins
|
||||
/// <summary>Data track, compact disc mode 2, form 1</summary>
|
||||
CDMode2Form1,
|
||||
/// <summary>Data track, compact disc mode 2, form 2</summary>
|
||||
CDMode2Form2
|
||||
};
|
||||
CDMode2Form2}
|
||||
|
||||
;
|
||||
|
||||
/// <summary>
|
||||
/// Track defining structure.
|
||||
@@ -811,8 +855,9 @@ namespace DiscImageChef.ImagePlugins
|
||||
/// <summary>CD track flags, 1 byte</summary>
|
||||
CDTrackFlags,
|
||||
/// <summary>DVD sector copyright information</summary>
|
||||
DVD_CMI
|
||||
};
|
||||
DVD_CMI}
|
||||
|
||||
;
|
||||
|
||||
/// <summary>
|
||||
/// Metadata present for each disk.
|
||||
@@ -834,8 +879,9 @@ namespace DiscImageChef.ImagePlugins
|
||||
/// <summary>DVD Copyright Management Information</summary>
|
||||
DVD_CMI,
|
||||
/// <summary>DVD Disc Manufacturer Information</summary>
|
||||
DVD_DMI
|
||||
};
|
||||
DVD_DMI}
|
||||
|
||||
;
|
||||
|
||||
/// <summary>
|
||||
/// Feature is supported by image but not implemented yet.
|
||||
|
||||
@@ -2010,7 +2010,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TODO
|
||||
// TODO
|
||||
case DAOMode.DataM2RawSub:
|
||||
throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
|
||||
case DAOMode.DataRawSub:
|
||||
@@ -2291,6 +2291,85 @@ namespace DiscImageChef.ImagePlugins
|
||||
return imageSessions;
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress)
|
||||
{
|
||||
byte[] buffer = ReadSectorLong(sectorAddress);
|
||||
return Checksums.CDChecksums.CheckCDSector(buffer);
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
byte[] buffer = ReadSectorLong(sectorAddress, track);
|
||||
return Checksums.CDChecksums.CheckCDSector(buffer);
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
byte[] buffer = ReadSectorsLong(sectorAddress, length);
|
||||
int bps = (int)(buffer.Length / length);
|
||||
byte[] sector = new byte[bps];
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
Array.Copy(buffer, i * bps, sector, 0, bps);
|
||||
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
|
||||
|
||||
switch (sectorStatus)
|
||||
{
|
||||
case null:
|
||||
UnknownLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
case false:
|
||||
FailingLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (UnknownLBAs.Count > 0)
|
||||
return null;
|
||||
if (FailingLBAs.Count > 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
|
||||
int bps = (int)(buffer.Length / length);
|
||||
byte[] sector = new byte[bps];
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
Array.Copy(buffer, i * bps, sector, 0, bps);
|
||||
bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector);
|
||||
|
||||
switch (sectorStatus)
|
||||
{
|
||||
case null:
|
||||
UnknownLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
case false:
|
||||
FailingLBAs.Add((ulong)i + sectorAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (UnknownLBAs.Count > 0)
|
||||
return null;
|
||||
if (FailingLBAs.Count > 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool? VerifyDiskImage()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
class TeleDisk : ImagePlugin
|
||||
{
|
||||
#region Internal Structures
|
||||
|
||||
struct TD0Header
|
||||
{
|
||||
// "TD" or "td" depending on compression
|
||||
@@ -122,7 +123,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Internal Constants
|
||||
|
||||
// "TD" as little endian uint.
|
||||
@@ -186,13 +187,18 @@ namespace DiscImageChef.ImagePlugins
|
||||
const byte dataBlockRLE = 0x02;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Internal variables
|
||||
|
||||
TD0Header header;
|
||||
TDCommentBlockHeader commentHeader;
|
||||
byte[] commentBlock;
|
||||
Dictionary<UInt32, byte[]> sectorsData; // LBA, data
|
||||
Dictionary<UInt32, byte[]> sectorsData;
|
||||
// LBA, data
|
||||
UInt32 totalDiskSize;
|
||||
bool ADiskCRCHasFailed;
|
||||
List<UInt64> SectorsWhereCRCHasFailed;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accesible variables
|
||||
@@ -231,6 +237,8 @@ namespace DiscImageChef.ImagePlugins
|
||||
_imageInfo.driveManufacturer = null;
|
||||
_imageInfo.driveModel = null;
|
||||
_imageInfo.driveSerialNumber = null;
|
||||
ADiskCRCHasFailed = false;
|
||||
SectorsWhereCRCHasFailed = new List<UInt64>();
|
||||
}
|
||||
|
||||
public override bool IdentifyImage(string imagePath)
|
||||
@@ -295,7 +303,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public override bool OpenImage(string imagePath)
|
||||
{
|
||||
header = new TD0Header();
|
||||
@@ -346,8 +354,12 @@ namespace DiscImageChef.ImagePlugins
|
||||
// This may deny legal images
|
||||
|
||||
// That would be much of a coincidence
|
||||
if (header.crc != calculatedHeaderCRC && MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): Calculated CRC does not coincide with stored one.");
|
||||
if (header.crc != calculatedHeaderCRC)
|
||||
{
|
||||
ADiskCRCHasFailed = true;
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): Calculated CRC does not coincide with stored one.");
|
||||
}
|
||||
|
||||
if (header.sequence != 0x00)
|
||||
return false;
|
||||
@@ -390,7 +402,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
|
||||
UInt16 cmtcrc = TeleDiskCRC(0, commentBlockForCRC);
|
||||
|
||||
if(MainClass.isDebug)
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): Comment header");
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): \tcommentheader.crc = 0x{0:X4}", commentHeader.crc);
|
||||
@@ -404,23 +416,25 @@ namespace DiscImageChef.ImagePlugins
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): \tcommentheader.second = {0}", commentHeader.second);
|
||||
}
|
||||
|
||||
for(int i=0;i<commentBlock.Length;i++)
|
||||
ADiskCRCHasFailed |= cmtcrc != commentHeader.crc;
|
||||
|
||||
for (int i = 0; i < commentBlock.Length; i++)
|
||||
{
|
||||
// Replace NULLs, used by TeleDisk as newline markers, with UNIX newline marker
|
||||
if(commentBlock[i]==0x00)
|
||||
commentBlock[i]=0x0A;
|
||||
if (commentBlock[i] == 0x00)
|
||||
commentBlock[i] = 0x0A;
|
||||
}
|
||||
|
||||
_imageInfo.imageComments = System.Text.Encoding.ASCII.GetString(commentBlock);
|
||||
|
||||
if(MainClass.isDebug)
|
||||
if (MainClass.isDebug)
|
||||
{
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): Comment");
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): {0}", _imageInfo.imageComments);
|
||||
}
|
||||
|
||||
_imageInfo.imageCreationTime = new DateTime(commentHeader.year+1900, commentHeader.month+1, commentHeader.day,
|
||||
commentHeader.hour, commentHeader.minute, commentHeader.second, DateTimeKind.Unspecified);
|
||||
_imageInfo.imageCreationTime = new DateTime(commentHeader.year + 1900, commentHeader.month + 1, commentHeader.day,
|
||||
commentHeader.hour, commentHeader.minute, commentHeader.second, DateTimeKind.Unspecified);
|
||||
}
|
||||
|
||||
FileInfo fi = new FileInfo(imagePath);
|
||||
@@ -468,6 +482,8 @@ namespace DiscImageChef.ImagePlugins
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack header CRC: 0x{0:X2} (calculated 0x{1:X2})\t", TDTrack.crc, TDTrackCalculatedCRC);
|
||||
}
|
||||
|
||||
ADiskCRCHasFailed |= TDTrackCalculatedCRC != TDTrack.crc;
|
||||
|
||||
if (TDTrack.sectors == 0xFF) // End of disk image
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
@@ -529,6 +545,17 @@ namespace DiscImageChef.ImagePlugins
|
||||
}
|
||||
|
||||
decodedData = DecodeTeleDiskData(TDSector.sectorSize, TDData.dataEncoding, data);
|
||||
|
||||
byte TDSectorCalculatedCRC = (byte)(TeleDiskCRC(0, decodedData) & 0xFF);
|
||||
|
||||
if (TDSectorCalculatedCRC != TDSector.crc)
|
||||
{
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (TeleDisk plugin): Sector LBA {0} calculated CRC 0x{1:X2} differs from stored CRC 0x{2:X2}", LBA, TDSectorCalculatedCRC, TDSector.crc);
|
||||
if ((TDSector.flags & FlagsSectorNoID) != FlagsSectorNoID)
|
||||
if (!sectorsData.ContainsKey(LBA) && (TDSector.flags & FlagsSectorDuplicate) != FlagsSectorDuplicate)
|
||||
SectorsWhereCRCHasFailed.Add((UInt64)LBA);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -598,32 +625,32 @@ namespace DiscImageChef.ImagePlugins
|
||||
stream.Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public override bool ImageHasPartitions()
|
||||
{
|
||||
return _imageInfo.imageHasPartitions;
|
||||
}
|
||||
|
||||
|
||||
public override UInt64 GetImageSize()
|
||||
{
|
||||
return _imageInfo.imageSize;
|
||||
}
|
||||
|
||||
|
||||
public override UInt64 GetSectors()
|
||||
{
|
||||
return _imageInfo.sectors;
|
||||
}
|
||||
|
||||
|
||||
public override UInt32 GetSectorSize()
|
||||
{
|
||||
return _imageInfo.sectorSize;
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSector(UInt64 sectorAddress)
|
||||
{
|
||||
return ReadSectors(sectorAddress, 1);
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
|
||||
{
|
||||
if (sectorAddress > (ulong)sectorsData.Count - 1)
|
||||
@@ -643,7 +670,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
|
||||
byte[] sector;
|
||||
|
||||
if(!sectorsData.TryGetValue((uint)i, out sector))
|
||||
if (!sectorsData.TryGetValue((uint)i, out sector))
|
||||
throw new ImageNotSupportedException(String.Format("Error reading sector {0}", i));
|
||||
|
||||
if (first)
|
||||
@@ -662,58 +689,97 @@ namespace DiscImageChef.ImagePlugins
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectorLong(UInt64 sectorAddress)
|
||||
{
|
||||
return ReadSectors(sectorAddress, 1);
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length)
|
||||
{
|
||||
return ReadSectors(sectorAddress, length);
|
||||
}
|
||||
|
||||
|
||||
public override string GetImageFormat()
|
||||
{
|
||||
return "Sydex TeleDisk";
|
||||
}
|
||||
|
||||
|
||||
public override string GetImageVersion()
|
||||
{
|
||||
return _imageInfo.imageVersion;
|
||||
}
|
||||
|
||||
|
||||
public override string GetImageApplication()
|
||||
{
|
||||
return _imageInfo.imageApplication;
|
||||
}
|
||||
|
||||
|
||||
public override string GetImageApplicationVersion()
|
||||
{
|
||||
return _imageInfo.imageApplicationVersion;
|
||||
}
|
||||
|
||||
|
||||
public override DateTime GetImageCreationTime()
|
||||
{
|
||||
return _imageInfo.imageCreationTime;
|
||||
}
|
||||
|
||||
|
||||
public override DateTime GetImageLastModificationTime()
|
||||
{
|
||||
return _imageInfo.imageLastModificationTime;
|
||||
}
|
||||
|
||||
|
||||
public override string GetImageName()
|
||||
{
|
||||
return _imageInfo.imageName;
|
||||
}
|
||||
|
||||
|
||||
public override DiskType GetDiskType()
|
||||
{
|
||||
return _imageInfo.diskType;
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress)
|
||||
{
|
||||
return !SectorsWhereCRCHasFailed.Contains(sectorAddress);
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
|
||||
if (SectorsWhereCRCHasFailed.Contains(sectorAddress))
|
||||
FailingLBAs.Add(sectorAddress);
|
||||
|
||||
return FailingLBAs.Count <= 0;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
|
||||
UnknownLBAs.Add(i);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifyDiskImage()
|
||||
{
|
||||
return ADiskCRCHasFailed;
|
||||
}
|
||||
|
||||
#region Private methods
|
||||
|
||||
static UInt16 TeleDiskCRC(UInt16 crc, byte[] buffer)
|
||||
{
|
||||
int counter = 0;
|
||||
@@ -782,7 +848,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
|
||||
repeatNumber = BitConverter.ToUInt16(encodedData, ins);
|
||||
Array.Copy(encodedData, ins + 2, repeatValue, 0, 2);
|
||||
byte[] decodedPiece = new byte[repeatNumber*2];
|
||||
byte[] decodedPiece = new byte[repeatNumber * 2];
|
||||
ArrayHelpers.ArrayFill(decodedPiece, repeatValue);
|
||||
Array.Copy(decodedPiece, 0, decodedData, outs, decodedPiece.Length);
|
||||
ins += 4;
|
||||
@@ -845,7 +911,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
private DiskType DecodeTeleDiskDiskType()
|
||||
DiskType DecodeTeleDiskDiskType()
|
||||
{
|
||||
switch (header.driveType)
|
||||
{
|
||||
@@ -858,7 +924,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
case 163840:
|
||||
{
|
||||
// Acorn disk uses 256 bytes/sector
|
||||
if(_imageInfo.sectorSize == 256)
|
||||
if (_imageInfo.sectorSize == 256)
|
||||
return DiskType.ACORN_525_SS_DD_40;
|
||||
else // DOS disks use 512 bytes/sector
|
||||
return DiskType.DOS_525_SS_DD_8;
|
||||
@@ -866,7 +932,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
case 184320:
|
||||
{
|
||||
// Atari disk uses 256 bytes/sector
|
||||
if(_imageInfo.sectorSize == 256)
|
||||
if (_imageInfo.sectorSize == 256)
|
||||
return DiskType.ATARI_525_DD;
|
||||
else // DOS disks use 512 bytes/sector
|
||||
return DiskType.DOS_525_SS_DD_9;
|
||||
@@ -874,7 +940,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
case 327680:
|
||||
{
|
||||
// Acorn disk uses 256 bytes/sector
|
||||
if(_imageInfo.sectorSize == 256)
|
||||
if (_imageInfo.sectorSize == 256)
|
||||
return DiskType.ACORN_525_SS_DD_80;
|
||||
else // DOS disks use 512 bytes/sector
|
||||
return DiskType.DOS_525_DS_DD_8;
|
||||
@@ -994,7 +1060,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
case 512512:
|
||||
{
|
||||
// DEC disk uses 256 bytes/sector
|
||||
if(_imageInfo.sectorSize == 256)
|
||||
if (_imageInfo.sectorSize == 256)
|
||||
return DiskType.RX02;
|
||||
else // ECMA disks use 128 bytes/sector
|
||||
return DiskType.ECMA_59;
|
||||
@@ -1024,140 +1090,141 @@ namespace DiscImageChef.ImagePlugins
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unsupported features
|
||||
|
||||
|
||||
public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadDiskTag(DiskTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override string GetImageCreator()
|
||||
{
|
||||
return _imageInfo.imageCreator;
|
||||
}
|
||||
|
||||
|
||||
public override string GetImageComments()
|
||||
{
|
||||
return _imageInfo.imageComments;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDiskManufacturer()
|
||||
{
|
||||
return _imageInfo.diskManufacturer;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDiskModel()
|
||||
{
|
||||
return _imageInfo.diskModel;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDiskSerialNumber()
|
||||
{
|
||||
return _imageInfo.diskSerialNumber;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDiskBarcode()
|
||||
{
|
||||
return _imageInfo.diskBarcode;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDiskPartNumber()
|
||||
{
|
||||
return _imageInfo.diskPartNumber;
|
||||
}
|
||||
|
||||
|
||||
public override int GetDiskSequence()
|
||||
{
|
||||
return _imageInfo.diskSequence;
|
||||
}
|
||||
|
||||
|
||||
public override int GetLastDiskSequence()
|
||||
{
|
||||
return _imageInfo.lastDiskSequence;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDriveManufacturer()
|
||||
{
|
||||
return _imageInfo.driveManufacturer;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDriveModel()
|
||||
{
|
||||
return _imageInfo.driveModel;
|
||||
}
|
||||
|
||||
|
||||
public override string GetDriveSerialNumber()
|
||||
{
|
||||
return _imageInfo.driveSerialNumber;
|
||||
}
|
||||
|
||||
|
||||
public override List<PartPlugins.Partition> GetPartitions()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override List<Track> GetTracks()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override List<Track> GetSessionTracks(Session session)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override List<Track> GetSessionTracks(UInt16 session)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override List<Session> GetSessions()
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
||||
{
|
||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||
}
|
||||
|
||||
|
||||
#endregion Unsupported features
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,10 @@ namespace DiscImageChef.ImagePlugins
|
||||
class ZZZRawImage : ImagePlugin
|
||||
{
|
||||
#region Internal variables
|
||||
|
||||
string rawImagePath;
|
||||
bool differentTrackZeroSize;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accesible variables
|
||||
@@ -356,7 +358,45 @@ namespace DiscImageChef.ImagePlugins
|
||||
return _imageInfo.diskType;
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifySector(UInt64 sectorAddress, UInt32 track)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
|
||||
UnknownLBAs.Add(i);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
||||
{
|
||||
FailingLBAs = new List<UInt64>();
|
||||
UnknownLBAs = new List<UInt64>();
|
||||
|
||||
for (UInt64 i = sectorAddress; i < sectorAddress + length; i++)
|
||||
UnknownLBAs.Add(i);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool? VerifyDiskImage()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#region Private methods
|
||||
|
||||
private DiskType CalculateDiskType()
|
||||
{
|
||||
if (_imageInfo.sectorSize == 2048)
|
||||
@@ -492,6 +532,7 @@ namespace DiscImageChef.ImagePlugins
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unsupported features
|
||||
|
||||
Reference in New Issue
Block a user