Separate trimming from retry pass fixes #172.

This commit is contained in:
2018-04-10 02:39:41 +01:00
parent 47e78ba0d4
commit 07f0dfe935
14 changed files with 281 additions and 80 deletions

View File

@@ -82,7 +82,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
uint skip,
bool nometadata)
bool nometadata, bool notrim)
{
bool aborted;
@@ -238,6 +238,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
bool newTrim = false;
start = DateTime.UtcNow;
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
@@ -282,7 +283,8 @@ namespace DiscImageChef.Core.Devices.Dumping
outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
i += skip - blocksToRead;
newTrim = true;
}
double newSpeed =
@@ -303,6 +305,41 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
totalDuration += duration;
if(error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(cmdBuf, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{

View File

@@ -91,7 +91,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip,
bool nometadata)
bool nometadata, bool notrim)
{
uint subSize;
DateTime start;
@@ -783,6 +783,7 @@ namespace DiscImageChef.Core.Devices.Dumping
double imageWriteDuration = 0;
if(skip < blocksToRead) skip = blocksToRead;
bool newTrim = false;
// Start reading
start = DateTime.UtcNow;
@@ -872,7 +873,8 @@ namespace DiscImageChef.Core.Devices.Dumping
ibgLog.Write(i, 0);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
i += skip - blocksToRead;
newTrim = true;
}
double newSpeed =
@@ -894,6 +896,60 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Compact Disc Error trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
if(readcd)
{
sense = true;
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)badSector, blockSize, 1,
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
true, MmcErrorField.None, supportedSubchannel, dev.Timeout,
out double cmdDuration);
totalDuration += cmdDuration;
}
if(sense || dev.Error) continue;
if(!sense && !dev.Error)
{
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
}
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[SECTOR_SIZE];
byte[] sub = new byte[subSize];
Array.Copy(readBuffer, 0, data, 0, SECTOR_SIZE);
Array.Copy(readBuffer, SECTOR_SIZE, sub, 0, subSize);
outputPlugin.WriteSectorLong(data, badSector);
outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
}
else outputPlugin.WriteSectorLong(readBuffer, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Compact Disc Error trimming
#region Compact Disc Error handling
// TODO: Pass 0 should be called differently, splitting, or something like that, because we are just
// separating skipped good sectors from really bad sectors and it's getting too chatty on log there...

View File

@@ -75,16 +75,16 @@ namespace DiscImageChef.Core.Devices.Dumping
/// <param name="outputPath">Path to output file</param>
/// <param name="formatOptions">Formats to pass to output file plugin</param>
/// <exception cref="NotImplementedException">If trying to dump GOD or WOD, or XGDs without a Kreon drive</exception>
internal static void Dump(Device dev, string devicePath, IWritableImage outputPlugin, ushort retryPasses,
bool force, bool dumpRaw, bool persistent, bool stopOnError,
ref MediaType dskType,
ref
Resume resume, ref DumpLog dumpLog, bool dumpLeadIn,
Encoding encoding,
string
outputPrefix, string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType
preSidecar, uint skip, bool nometadata)
internal static void Dump(Device dev, string devicePath,
IWritableImage outputPlugin, ushort retryPasses,
bool force, bool dumpRaw,
bool persistent, bool stopOnError, ref MediaType dskType,
ref Resume resume, ref DumpLog dumpLog,
bool dumpLeadIn, Encoding encoding,
string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip,
bool nometadata, bool notrim)
{
bool sense;
ulong blocks;
@@ -200,12 +200,12 @@ namespace DiscImageChef.Core.Devices.Dumping
{
CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
formatOptions, preSidecar, skip, nometadata);
formatOptions, preSidecar, skip, nometadata, notrim);
return;
}
Reader scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw);
blocks = scsiReader.GetDeviceBlocks();
blocks = scsiReader.GetDeviceBlocks();
dumpLog.WriteLine("Device reports disc has {0} blocks", blocks);
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>();
@@ -219,7 +219,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!sense)
{
PFI.PhysicalFormatInformation? nintendoPfi = PFI.Decode(cmdBuf);
if(nintendoPfi != null)
if(nintendoPfi != null)
if(nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo &&
nintendoPfi.Value.PartVersion == 15)
{
@@ -253,7 +253,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!sense)
if(PFI.Decode(cmdBuf).HasValue)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVD_PFI, tmpBuf);
@@ -352,7 +352,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(cmdBuf.Length == 2052)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVD_DMI, tmpBuf);
}
@@ -374,7 +374,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!sense)
if(CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVD_CMI, tmpBuf);
}
@@ -392,7 +392,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVD_BCA, tmpBuf);
}
@@ -409,7 +409,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!sense)
if(DDS.Decode(cmdBuf).HasValue)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVDRAM_DDS, tmpBuf);
}
@@ -421,7 +421,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!sense)
if(Spare.Decode(cmdBuf).HasValue)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVDRAM_SpareArea, tmpBuf);
}
@@ -437,7 +437,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVDR_PreRecordedInfo, tmpBuf);
}
@@ -457,7 +457,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.DvdrMediaIdentifier, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVDR_MediaIdentifier, tmpBuf);
}
@@ -468,7 +468,7 @@ namespace DiscImageChef.Core.Devices.Dumping
out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVDR_PFI, tmpBuf);
}
@@ -486,7 +486,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.Adip, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DVD_ADIP, tmpBuf);
}
@@ -496,7 +496,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.Dcb, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.DCB, tmpBuf);
}
@@ -512,7 +512,7 @@ namespace DiscImageChef.Core.Devices.Dumping
out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.HDDVD_CPI, tmpBuf);
}
@@ -532,7 +532,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!sense)
if(DI.Decode(cmdBuf).HasValue)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.BD_DI, tmpBuf);
}
@@ -561,7 +561,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.BdBurstCuttingArea, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.BD_BCA, tmpBuf);
}
@@ -579,7 +579,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.BdDds, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.BD_DDS, tmpBuf);
}
@@ -589,7 +589,7 @@ namespace DiscImageChef.Core.Devices.Dumping
MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, out _);
if(!sense)
{
tmpBuf = new byte[cmdBuf.Length - 4];
tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
mediaTags.Add(MediaTagType.BD_SpareArea, tmpBuf);
}
@@ -602,13 +602,13 @@ namespace DiscImageChef.Core.Devices.Dumping
{
Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
preSidecar, skip, nometadata);
preSidecar, skip, nometadata, notrim);
return;
}
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
preSidecar, skip, nometadata);
preSidecar, skip, nometadata, notrim);
}
internal static void AddMediaTagToSidecar(string outputPath,
@@ -729,8 +729,8 @@ namespace DiscImageChef.Core.Devices.Dumping
{
new XboxSecuritySectorsType
{
RequestNumber = 0,
RequestVersion = 1,
RequestNumber = 0,
RequestVersion = 1,
SecuritySectors = new DumpType
{
Image = outputPath,

View File

@@ -50,7 +50,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DumpLog dumpLog, Encoding encoding, string outputPrefix,
string outputPath,
Dictionary<string, string>
formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata)
formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata, bool notrim)
{
throw new NotImplementedException("NVMe devices not yet supported.");
}

View File

@@ -87,7 +87,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Encoding encoding, string outputPrefix,
string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip,
bool nometadata)
bool nometadata, bool notrim)
{
bool sense;
ulong blocks;
@@ -347,6 +347,7 @@ namespace DiscImageChef.Core.Devices.Dumping
throw new InvalidOperationException("Could not process resume file, not continuing...");
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
bool newTrim = false;
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
{
@@ -396,7 +397,8 @@ namespace DiscImageChef.Core.Devices.Dumping
ibgLog.Write(i, 0);
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
i += skip - blocksToRead;
newTrim = true;
}
double newSpeed =
@@ -417,6 +419,39 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration);
if(sense || dev.Error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(readBuffer, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{

View File

@@ -70,16 +70,15 @@ namespace DiscImageChef.Core.Devices.Dumping
/// <param name="outputPath">Path to output file</param>
/// <param name="formatOptions">Formats to pass to output file plugin</param>
/// <exception cref="ArgumentException">If you asked to dump long sectors from a SCSI Streaming device</exception>
public static void Dump(Device dev, string devicePath, IWritableImage outputPlugin, ushort retryPasses,
bool force, bool dumpRaw, bool persistent, bool stopOnError,
ref Resume resume,
ref
DumpLog dumpLog, bool dumpLeadIn, Encoding encoding,
string outputPrefix,
string
outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType
preSidecar, uint skip, bool nometadata)
public static void Dump(Device dev, string devicePath,
IWritableImage outputPlugin, ushort retryPasses,
bool force, bool dumpRaw,
bool persistent, bool stopOnError, ref Resume resume,
ref DumpLog dumpLog, bool dumpLeadIn,
Encoding encoding, string outputPrefix,
string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip, bool nometadata,
bool notrim)
{
MediaType dskType = MediaType.Unknown;
int resets = 0;
@@ -212,12 +211,12 @@ namespace DiscImageChef.Core.Devices.Dumping
case PeripheralDeviceTypes.MultiMediaDevice:
Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
formatOptions, preSidecar, skip, nometadata);
formatOptions, preSidecar, skip, nometadata, notrim);
return;
default:
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null,
ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath,
formatOptions, preSidecar, skip, nometadata);
formatOptions, preSidecar, skip, nometadata, notrim);
break;
}
}

View File

@@ -80,7 +80,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
uint skip,
bool nometadata)
bool nometadata, bool notrim)
{
bool aborted;
@@ -280,6 +280,7 @@ namespace DiscImageChef.Core.Devices.Dumping
start = DateTime.UtcNow;
double imageWriteDuration = 0;
bool newTrim = false;
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
{
@@ -324,7 +325,8 @@ namespace DiscImageChef.Core.Devices.Dumping
outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip);
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
i += skip - blocksToRead;
i += skip - blocksToRead;
newTrim = true;
}
double newSpeed =
@@ -345,6 +347,42 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
error = dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
out duration);
totalDuration += duration;
if(error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(cmdBuf, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{

View File

@@ -90,7 +90,7 @@ namespace DiscImageChef.Core.Devices.Dumping
string outputPrefix, string outputPath,
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
uint skip,
bool nometadata)
bool nometadata, bool notrim)
{
bool sense;
ulong blocks;
@@ -377,6 +377,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ulong currentSector = resume.NextBlock;
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
bool newTrim = false;
dumpLog.WriteLine("Reading game partition.");
for(int e = 0; e <= 16; e++)
@@ -473,6 +474,7 @@ namespace DiscImageChef.Core.Devices.Dumping
StringSplitOptions
.RemoveEmptyEntries);
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
newTrim = true;
}
double newSpeed =
@@ -649,6 +651,41 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
(double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / imageWriteDuration);
#region Trimming
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
{
start = DateTime.UtcNow;
dumpLog.WriteLine("Trimming bad sectors");
ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray)
{
if(aborted)
{
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
dumpLog.WriteLine("Aborted!");
break;
}
DicConsole.Write("\rTrimming sector {0}", badSector);
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)badSector,
BLOCK_SIZE, 0, 1, false, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration;
if(sense || dev.Error) continue;
resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputPlugin.WriteSector(readBuffer, badSector);
}
DicConsole.WriteLine();
end = DateTime.UtcNow;
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
}
#endregion Trimming
#region Error handling
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
{