Do not read audio and data sectors in the same command, as this gives a false error in almost all drives.

This commit is contained in:
2019-12-25 21:03:21 +00:00
parent 956fb20d80
commit 8d7cf1bd7c

View File

@@ -73,9 +73,10 @@ namespace DiscImageChef.Core.Devices.Dumping
/// <param name="dskType">Disc type as detected in MMC layer</param> /// <param name="dskType">Disc type as detected in MMC layer</param>
void CompactDisc(out MediaType dskType) void CompactDisc(out MediaType dskType)
{ {
ExtentsULong audioExtents; // Extents with audio sectors
ulong blocks; // Total number of positive sectors ulong blocks; // Total number of positive sectors
uint blockSize; // Size of the read sector in bytes uint blockSize; // Size of the read sector in bytes
uint blocksToRead = 64; // How many sectors to read at once uint blocksToRead = 0; // How many sectors to read at once
CdOffset cdOffset; // Read offset from database CdOffset cdOffset; // Read offset from database
byte[] cmdBuf; // Data buffer byte[] cmdBuf; // Data buffer
double cmdDuration = 0; // Command execution time double cmdDuration = 0; // Command execution time
@@ -119,6 +120,9 @@ namespace DiscImageChef.Core.Devices.Dumping
Track[] tracks; // Tracks in disc as array Track[] tracks; // Tracks in disc as array
int offsetBytes; // Read offset int offsetBytes; // Read offset
bool
nextData; // Next cluster of sectors is all data;
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>(); // Media tags Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>(); // Media tags
int firstTrackLastSession = 0; // Number of first track in last session int firstTrackLastSession = 0; // Number of first track in last session
@@ -127,6 +131,8 @@ namespace DiscImageChef.Core.Devices.Dumping
DateTime timeSpeedStart; // Time of start for speed calculation DateTime timeSpeedStart; // Time of start for speed calculation
uint maximumReadable = 64; // Maximum number of sectors drive can read at once
dskType = MediaType.CD; dskType = MediaType.CD;
if(_dumpRaw) if(_dumpRaw)
@@ -157,7 +163,7 @@ namespace DiscImageChef.Core.Devices.Dumping
UpdateStatus?.Invoke($"Device in database since {dbDev.LastSynchronized}."); UpdateStatus?.Invoke($"Device in database since {dbDev.LastSynchronized}.");
if(dbDev.OptimalMultipleSectorsRead > 0) if(dbDev.OptimalMultipleSectorsRead > 0)
blocksToRead = (uint)dbDev.OptimalMultipleSectorsRead; maximumReadable = (uint)dbDev.OptimalMultipleSectorsRead;
} }
// Search for read offset in master database // Search for read offset in master database
@@ -1092,47 +1098,48 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
if(readcd) if(readcd)
{ {
sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, blockSize, blocksToRead, MmcSectorTypes.AllTypes, sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, blockSize, maximumReadable,
false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
supportedSubchannel, _dev.Timeout, out _); true, MmcErrorField.None, supportedSubchannel, _dev.Timeout, out _);
if(_dev.Error || sense) if(_dev.Error || sense)
blocksToRead /= 2; maximumReadable /= 2;
} }
else if(read16) else if(read16)
{ {
sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, 0, blockSize, 0, blocksToRead, sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, 0, blockSize, 0,
false, _dev.Timeout, out _); maximumReadable, false, _dev.Timeout, out _);
if(_dev.Error || sense) if(_dev.Error || sense)
blocksToRead /= 2; maximumReadable /= 2;
} }
else if(read12) else if(read12)
{ {
sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, blockSize, 0,
blocksToRead, false, _dev.Timeout, out _); maximumReadable, false, _dev.Timeout, out _);
if(_dev.Error || sense) if(_dev.Error || sense)
blocksToRead /= 2; maximumReadable /= 2;
} }
else if(read10) else if(read10)
{ {
sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, blockSize, 0,
(ushort)blocksToRead, _dev.Timeout, out _); (ushort)maximumReadable, _dev.Timeout, out _);
if(_dev.Error || sense) if(_dev.Error || sense)
blocksToRead /= 2; maximumReadable /= 2;
} }
else if(read6) else if(read6)
{ {
sense = _dev.Read6(out cmdBuf, out senseBuf, 0, blockSize, (byte)blocksToRead, _dev.Timeout, out _); sense = _dev.Read6(out cmdBuf, out senseBuf, 0, blockSize, (byte)maximumReadable, _dev.Timeout,
out _);
if(_dev.Error || sense) if(_dev.Error || sense)
blocksToRead /= 2; maximumReadable /= 2;
} }
if(!_dev.Error || if(!_dev.Error ||
blocksToRead == 1) maximumReadable == 1)
break; break;
} }
@@ -1142,16 +1149,16 @@ namespace DiscImageChef.Core.Devices.Dumping
StoppingErrorMessage?.Invoke($"Device error {_dev.LastError} trying to guess ideal transfer length."); StoppingErrorMessage?.Invoke($"Device error {_dev.LastError} trying to guess ideal transfer length.");
} }
_dumpLog.WriteLine("Reading {0} sectors at a time.", blocksToRead); _dumpLog.WriteLine("Reading {0} sectors at a time.", maximumReadable);
_dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize); _dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
_dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead); _dumpLog.WriteLine("Device can read {0} blocks at a time.", maximumReadable);
_dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize); _dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
_dumpLog.WriteLine("SCSI device type: {0}.", _dev.ScsiType); _dumpLog.WriteLine("SCSI device type: {0}.", _dev.ScsiType);
_dumpLog.WriteLine("Media identified as {0}.", dskType); _dumpLog.WriteLine("Media identified as {0}.", dskType);
UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time."); UpdateStatus?.Invoke($"Reading {maximumReadable} sectors at a time.");
UpdateStatus?.Invoke($"Device reports {blocks} blocks ({blocks * blockSize} bytes)."); UpdateStatus?.Invoke($"Device reports {blocks} blocks ({blocks * blockSize} bytes).");
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time."); UpdateStatus?.Invoke($"Device can read {maximumReadable} blocks at a time.");
UpdateStatus?.Invoke($"Device reports {blockSize} bytes per logical block."); UpdateStatus?.Invoke($"Device reports {blockSize} bytes per logical block.");
UpdateStatus?.Invoke($"SCSI device type: {_dev.ScsiType}."); UpdateStatus?.Invoke($"SCSI device type: {_dev.ScsiType}.");
UpdateStatus?.Invoke($"Media identified as {dskType}."); UpdateStatus?.Invoke($"Media identified as {dskType}.");
@@ -1295,8 +1302,8 @@ namespace DiscImageChef.Core.Devices.Dumping
_dumpLog.WriteLine("Resuming from block {0}.", _resume.NextBlock); _dumpLog.WriteLine("Resuming from block {0}.", _resume.NextBlock);
} }
if(_skip < blocksToRead) if(_skip < maximumReadable)
_skip = blocksToRead; _skip = maximumReadable;
#if DEBUG #if DEBUG
foreach(Track trk in tracks) foreach(Track trk in tracks)
@@ -1366,9 +1373,17 @@ namespace DiscImageChef.Core.Devices.Dumping
UpdateStatus?.Invoke("There are audio tracks and offset fixing is disabled, dump may not be correct."); UpdateStatus?.Invoke("There are audio tracks and offset fixing is disabled, dump may not be correct.");
} }
mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, blocksToRead); mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, maximumReadable);
ibgLog = new IbgLog(_outputPrefix + ".ibg", 0x0008); ibgLog = new IbgLog(_outputPrefix + ".ibg", 0x0008);
audioExtents = new ExtentsULong();
nextData = firstTrackType != TrackType.Audio;
foreach(Track audioTrack in tracks.Where(t => t.TrackType == TrackType.Audio))
{
audioExtents.Add(audioTrack.TrackStartSector, audioTrack.TrackEndSector);
}
// Start reading // Start reading
start = DateTime.UtcNow; start = DateTime.UtcNow;
currentSpeed = 0; currentSpeed = 0;
@@ -1390,8 +1405,37 @@ namespace DiscImageChef.Core.Devices.Dumping
uint firstSectorToRead = (uint)i; uint firstSectorToRead = (uint)i;
if((lastSector + 1) - (long)i < blocksToRead) if((lastSector + 1) - (long)i < maximumReadable)
blocksToRead = (uint)((lastSector + 1) - (long)i); maximumReadable = (uint)((lastSector + 1) - (long)i);
blocksToRead = 0;
bool inData = nextData;
for(ulong j = i; j < i + maximumReadable; j++)
{
if(nextData)
{
if(audioExtents.Contains(j))
{
nextData = false;
break;
}
blocksToRead++;
}
else
{
if(!audioExtents.Contains(j))
{
nextData = true;
break;
}
blocksToRead++;
}
}
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
@@ -1716,15 +1760,15 @@ namespace DiscImageChef.Core.Devices.Dumping
out cmdDuration); out cmdDuration);
else if(read16) else if(read16)
sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, badSector, blockSize, 0, sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, badSector, blockSize, 0,
blocksToRead, false, _dev.Timeout, out cmdDuration); 1, false, _dev.Timeout, out cmdDuration);
else if(read12) else if(read12)
sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)badSector, sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)badSector,
blockSize, 0, blocksToRead, false, _dev.Timeout, out cmdDuration); blockSize, 0, 1, false, _dev.Timeout, out cmdDuration);
else if(read10) else if(read10)
sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)badSector, sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)badSector,
blockSize, 0, (ushort)blocksToRead, _dev.Timeout, out cmdDuration); blockSize, 0, 1, _dev.Timeout, out cmdDuration);
else if(read6) else if(read6)
sense = _dev.Read6(out cmdBuf, out senseBuf, (uint)badSector, blockSize, (byte)blocksToRead, sense = _dev.Read6(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1,
_dev.Timeout, out cmdDuration); _dev.Timeout, out cmdDuration);
totalDuration += cmdDuration; totalDuration += cmdDuration;
@@ -1759,8 +1803,6 @@ namespace DiscImageChef.Core.Devices.Dumping
if(cmdBuf.Length % 2352 == 0) if(cmdBuf.Length % 2352 == 0)
{ {
byte[] data = new byte[2048]; byte[] data = new byte[2048];
for(int b = 0; b < blocksToRead; b++)
Array.Copy(cmdBuf, 16, data, 0, 2048); Array.Copy(cmdBuf, 16, data, 0, 2048);
_outputPlugin.WriteSector(data, badSector); _outputPlugin.WriteSector(data, badSector);