mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Separate trimming from retry pass fixes #172.
This commit is contained in:
@@ -82,7 +82,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
string outputPrefix, string outputPath,
|
string outputPrefix, string outputPath,
|
||||||
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
||||||
uint skip,
|
uint skip,
|
||||||
bool nometadata)
|
bool nometadata, bool notrim)
|
||||||
{
|
{
|
||||||
bool aborted;
|
bool aborted;
|
||||||
|
|
||||||
@@ -238,6 +238,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
|
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
|
||||||
|
|
||||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||||
|
bool newTrim = false;
|
||||||
|
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||||
@@ -283,6 +284,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||||
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
||||||
i += skip - blocksToRead;
|
i += skip - blocksToRead;
|
||||||
|
newTrim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double newSpeed =
|
double newSpeed =
|
||||||
@@ -303,6 +305,41 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
(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
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
string outputPrefix, string outputPath,
|
string outputPrefix, string outputPath,
|
||||||
Dictionary<string, string> formatOptions,
|
Dictionary<string, string> formatOptions,
|
||||||
CICMMetadataType preSidecar, uint skip,
|
CICMMetadataType preSidecar, uint skip,
|
||||||
bool nometadata)
|
bool nometadata, bool notrim)
|
||||||
{
|
{
|
||||||
uint subSize;
|
uint subSize;
|
||||||
DateTime start;
|
DateTime start;
|
||||||
@@ -783,6 +783,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
double imageWriteDuration = 0;
|
double imageWriteDuration = 0;
|
||||||
|
|
||||||
if(skip < blocksToRead) skip = blocksToRead;
|
if(skip < blocksToRead) skip = blocksToRead;
|
||||||
|
bool newTrim = false;
|
||||||
|
|
||||||
// Start reading
|
// Start reading
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
@@ -873,6 +874,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
ibgLog.Write(i, 0);
|
ibgLog.Write(i, 0);
|
||||||
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
||||||
i += skip - blocksToRead;
|
i += skip - blocksToRead;
|
||||||
|
newTrim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double newSpeed =
|
double newSpeed =
|
||||||
@@ -894,6 +896,60 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
(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
|
#region Compact Disc Error handling
|
||||||
// TODO: Pass 0 should be called differently, splitting, or something like that, because we are just
|
// 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...
|
// separating skipped good sectors from really bad sectors and it's getting too chatty on log there...
|
||||||
|
|||||||
@@ -75,16 +75,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
/// <param name="outputPath">Path to output file</param>
|
/// <param name="outputPath">Path to output file</param>
|
||||||
/// <param name="formatOptions">Formats to pass to output file plugin</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>
|
/// <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,
|
internal static void Dump(Device dev, string devicePath,
|
||||||
bool force, bool dumpRaw, bool persistent, bool stopOnError,
|
IWritableImage outputPlugin, ushort retryPasses,
|
||||||
ref MediaType dskType,
|
bool force, bool dumpRaw,
|
||||||
ref
|
bool persistent, bool stopOnError, ref MediaType dskType,
|
||||||
Resume resume, ref DumpLog dumpLog, bool dumpLeadIn,
|
ref Resume resume, ref DumpLog dumpLog,
|
||||||
Encoding encoding,
|
bool dumpLeadIn, Encoding encoding,
|
||||||
string
|
string outputPrefix, string outputPath,
|
||||||
outputPrefix, string outputPath, Dictionary<string, string> formatOptions,
|
Dictionary<string, string> formatOptions,
|
||||||
CICMMetadataType
|
CICMMetadataType preSidecar, uint skip,
|
||||||
preSidecar, uint skip, bool nometadata)
|
bool nometadata, bool notrim)
|
||||||
{
|
{
|
||||||
bool sense;
|
bool sense;
|
||||||
ulong blocks;
|
ulong blocks;
|
||||||
@@ -200,7 +200,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
|
CompactDisc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
|
||||||
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
|
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
|
||||||
formatOptions, preSidecar, skip, nometadata);
|
formatOptions, preSidecar, skip, nometadata, notrim);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,13 +602,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
|
Xgd.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
|
||||||
ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
|
ref dskType, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
|
||||||
preSidecar, skip, nometadata);
|
preSidecar, skip, nometadata, notrim);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
|
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, mediaTags,
|
||||||
ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
|
ref dskType, true, ref resume, ref dumpLog, encoding, outputPrefix, outputPath, formatOptions,
|
||||||
preSidecar, skip, nometadata);
|
preSidecar, skip, nometadata, notrim);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void AddMediaTagToSidecar(string outputPath,
|
internal static void AddMediaTagToSidecar(string outputPath,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
DumpLog dumpLog, Encoding encoding, string outputPrefix,
|
DumpLog dumpLog, Encoding encoding, string outputPrefix,
|
||||||
string outputPath,
|
string outputPath,
|
||||||
Dictionary<string, string>
|
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.");
|
throw new NotImplementedException("NVMe devices not yet supported.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
Encoding encoding, string outputPrefix,
|
Encoding encoding, string outputPrefix,
|
||||||
string outputPath, Dictionary<string, string> formatOptions,
|
string outputPath, Dictionary<string, string> formatOptions,
|
||||||
CICMMetadataType preSidecar, uint skip,
|
CICMMetadataType preSidecar, uint skip,
|
||||||
bool nometadata)
|
bool nometadata, bool notrim)
|
||||||
{
|
{
|
||||||
bool sense;
|
bool sense;
|
||||||
ulong blocks;
|
ulong blocks;
|
||||||
@@ -347,6 +347,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
throw new InvalidOperationException("Could not process resume file, not continuing...");
|
throw new InvalidOperationException("Could not process resume file, not continuing...");
|
||||||
|
|
||||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||||
|
bool newTrim = false;
|
||||||
|
|
||||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||||
{
|
{
|
||||||
@@ -397,6 +398,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
ibgLog.Write(i, 0);
|
ibgLog.Write(i, 0);
|
||||||
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
||||||
i += skip - blocksToRead;
|
i += skip - blocksToRead;
|
||||||
|
newTrim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double newSpeed =
|
double newSpeed =
|
||||||
@@ -417,6 +419,39 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
(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
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,16 +70,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
/// <param name="outputPath">Path to output file</param>
|
/// <param name="outputPath">Path to output file</param>
|
||||||
/// <param name="formatOptions">Formats to pass to output file plugin</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>
|
/// <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,
|
public static void Dump(Device dev, string devicePath,
|
||||||
bool force, bool dumpRaw, bool persistent, bool stopOnError,
|
IWritableImage outputPlugin, ushort retryPasses,
|
||||||
ref Resume resume,
|
bool force, bool dumpRaw,
|
||||||
ref
|
bool persistent, bool stopOnError, ref Resume resume,
|
||||||
DumpLog dumpLog, bool dumpLeadIn, Encoding encoding,
|
ref DumpLog dumpLog, bool dumpLeadIn,
|
||||||
string outputPrefix,
|
Encoding encoding, string outputPrefix,
|
||||||
string
|
string outputPath, Dictionary<string, string> formatOptions,
|
||||||
outputPath, Dictionary<string, string> formatOptions,
|
CICMMetadataType preSidecar, uint skip, bool nometadata,
|
||||||
CICMMetadataType
|
bool notrim)
|
||||||
preSidecar, uint skip, bool nometadata)
|
|
||||||
{
|
{
|
||||||
MediaType dskType = MediaType.Unknown;
|
MediaType dskType = MediaType.Unknown;
|
||||||
int resets = 0;
|
int resets = 0;
|
||||||
@@ -212,12 +211,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case PeripheralDeviceTypes.MultiMediaDevice:
|
case PeripheralDeviceTypes.MultiMediaDevice:
|
||||||
Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
|
Mmc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError,
|
||||||
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
|
ref dskType, ref resume, ref dumpLog, dumpLeadIn, encoding, outputPrefix, outputPath,
|
||||||
formatOptions, preSidecar, skip, nometadata);
|
formatOptions, preSidecar, skip, nometadata, notrim);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null,
|
Sbc.Dump(dev, devicePath, outputPlugin, retryPasses, force, dumpRaw, persistent, stopOnError, null,
|
||||||
ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath,
|
ref dskType, false, ref resume, ref dumpLog, encoding, outputPrefix, outputPath,
|
||||||
formatOptions, preSidecar, skip, nometadata);
|
formatOptions, preSidecar, skip, nometadata, notrim);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
string outputPrefix, string outputPath,
|
string outputPrefix, string outputPath,
|
||||||
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
||||||
uint skip,
|
uint skip,
|
||||||
bool nometadata)
|
bool nometadata, bool notrim)
|
||||||
{
|
{
|
||||||
bool aborted;
|
bool aborted;
|
||||||
|
|
||||||
@@ -280,6 +280,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
double imageWriteDuration = 0;
|
double imageWriteDuration = 0;
|
||||||
|
bool newTrim = false;
|
||||||
|
|
||||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||||
{
|
{
|
||||||
@@ -325,6 +326,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||||
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, i);
|
||||||
i += skip - blocksToRead;
|
i += skip - blocksToRead;
|
||||||
|
newTrim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double newSpeed =
|
double newSpeed =
|
||||||
@@ -345,6 +347,42 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
(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
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
string outputPrefix, string outputPath,
|
string outputPrefix, string outputPath,
|
||||||
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
||||||
uint skip,
|
uint skip,
|
||||||
bool nometadata)
|
bool nometadata, bool notrim)
|
||||||
{
|
{
|
||||||
bool sense;
|
bool sense;
|
||||||
ulong blocks;
|
ulong blocks;
|
||||||
@@ -377,6 +377,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
ulong currentSector = resume.NextBlock;
|
ulong currentSector = resume.NextBlock;
|
||||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||||
|
bool newTrim = false;
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading game partition.");
|
dumpLog.WriteLine("Reading game partition.");
|
||||||
for(int e = 0; e <= 16; e++)
|
for(int e = 0; e <= 16; e++)
|
||||||
@@ -473,6 +474,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
StringSplitOptions
|
StringSplitOptions
|
||||||
.RemoveEmptyEntries);
|
.RemoveEmptyEntries);
|
||||||
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
|
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
|
||||||
|
newTrim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double newSpeed =
|
double newSpeed =
|
||||||
@@ -649,6 +651,41 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||||
(double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
(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
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../../Changelog.md
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../DONATING.md
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../README.md
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../TODO.md
|
|
||||||
@@ -207,26 +207,28 @@ namespace DiscImageChef.Commands
|
|||||||
case DeviceType.ATA:
|
case DeviceType.ATA:
|
||||||
Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
|
Ata.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
|
||||||
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
|
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
|
||||||
options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata);
|
options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata,
|
||||||
|
options.NoTrim);
|
||||||
break;
|
break;
|
||||||
case DeviceType.MMC:
|
case DeviceType.MMC:
|
||||||
case DeviceType.SecureDigital:
|
case DeviceType.SecureDigital:
|
||||||
SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
|
SecureDigital.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force,
|
||||||
options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog,
|
options.Raw, options.Persistent, options.StopOnError, ref resume, ref dumpLog,
|
||||||
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
|
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar,
|
||||||
options.NoMetadata);
|
(uint)options.Skip, options.NoMetadata, options.NoTrim);
|
||||||
break;
|
break;
|
||||||
case DeviceType.NVMe:
|
case DeviceType.NVMe:
|
||||||
NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
|
NvMe.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
|
||||||
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
|
options.Persistent, options.StopOnError, ref resume, ref dumpLog, encoding, outputPrefix,
|
||||||
options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata);
|
options.OutputFile, parsedOptions, sidecar, (uint)options.Skip, options.NoMetadata,
|
||||||
|
options.NoTrim);
|
||||||
break;
|
break;
|
||||||
case DeviceType.ATAPI:
|
case DeviceType.ATAPI:
|
||||||
case DeviceType.SCSI:
|
case DeviceType.SCSI:
|
||||||
Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
|
Scsi.Dump(dev, options.DevicePath, outputFormat, options.RetryPasses, options.Force, options.Raw,
|
||||||
options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.LeadIn,
|
options.Persistent, options.StopOnError, ref resume, ref dumpLog, options.LeadIn,
|
||||||
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
|
encoding, outputPrefix, options.OutputFile, parsedOptions, sidecar, (uint)options.Skip,
|
||||||
options.NoMetadata);
|
options.NoMetadata, options.NoTrim);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dumpLog.WriteLine("Unknown device type.");
|
dumpLog.WriteLine("Unknown device type.");
|
||||||
|
|||||||
@@ -93,12 +93,10 @@ namespace DiscImageChef
|
|||||||
[Option("crc64", Default = false, HelpText = "Calculates CRC64 (ECMA).")]
|
[Option("crc64", Default = false, HelpText = "Calculates CRC64 (ECMA).")]
|
||||||
public bool DoCrc64 { get; set; }
|
public bool DoCrc64 { get; set; }
|
||||||
|
|
||||||
[Option("fletcher16", Default = false,
|
[Option("fletcher16", Default = false, HelpText = "Calculates Fletcher-16.")]
|
||||||
HelpText = "Calculates Fletcher-16.")]
|
|
||||||
public bool DoFletcher16 { get; set; }
|
public bool DoFletcher16 { get; set; }
|
||||||
|
|
||||||
[Option("fletcher32", Default = false,
|
[Option("fletcher32", Default = false, HelpText = "Calculates Fletcher-32.")]
|
||||||
HelpText = "Calculates Fletcher-32.")]
|
|
||||||
public bool DoFletcher32 { get; set; }
|
public bool DoFletcher32 { get; set; }
|
||||||
|
|
||||||
[Option('m', "md5", Default = true, HelpText = "Calculates MD5.")]
|
[Option('m', "md5", Default = true, HelpText = "Calculates MD5.")]
|
||||||
@@ -314,6 +312,9 @@ namespace DiscImageChef
|
|||||||
|
|
||||||
[Option("no-metadata", Default = false, HelpText = "Disables creating CICM XML sidecar.")]
|
[Option("no-metadata", Default = false, HelpText = "Disables creating CICM XML sidecar.")]
|
||||||
public bool NoMetadata { get; set; }
|
public bool NoMetadata { get; set; }
|
||||||
|
|
||||||
|
[Option("no-trim", Default = false, HelpText = "Disables trimming errored from skipped sectors.")]
|
||||||
|
public bool NoTrim { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")]
|
[Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")]
|
||||||
|
|||||||
Reference in New Issue
Block a user