mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
🐛No retry passes means do not retry errors, act so.
This commit is contained in:
@@ -74,16 +74,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="InvalidOperationException">If the resume file is invalid</exception>
|
/// <exception cref="InvalidOperationException">If the resume file is invalid</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, Encoding encoding, string outputPrefix,
|
ref DumpLog dumpLog, Encoding encoding,
|
||||||
string outputPath,
|
string outputPrefix, string outputPath,
|
||||||
Dictionary<string, string>
|
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
||||||
formatOptions, CICMMetadataType preSidecar, uint skip,
|
uint skip,
|
||||||
bool
|
bool nometadata)
|
||||||
nometadata)
|
|
||||||
{
|
{
|
||||||
bool aborted;
|
bool aborted;
|
||||||
|
|
||||||
@@ -113,7 +112,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
Identify.IdentifyDevice ataId = ataIdNullable.Value;
|
Identify.IdentifyDevice ataId = ataIdNullable.Value;
|
||||||
byte[] ataIdentify = cmdBuf;
|
byte[] ataIdentify = cmdBuf;
|
||||||
cmdBuf = new byte[0];
|
cmdBuf = new byte[0];
|
||||||
|
|
||||||
DateTime start;
|
DateTime start;
|
||||||
DateTime end;
|
DateTime end;
|
||||||
@@ -273,7 +272,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(i + skip > blocks) skip = (uint)(blocks - i);
|
if(i + skip > blocks) skip = (uint)(blocks - i);
|
||||||
|
|
||||||
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
|
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
|
||||||
|
|
||||||
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
||||||
@@ -289,24 +288,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
double newSpeed =
|
double newSpeed =
|
||||||
(double)blockSize * blocksToRead / 1048576 / (duration / 1000);
|
(double)blockSize * blocksToRead / 1048576 / (duration / 1000);
|
||||||
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
||||||
resume.NextBlock = i + blocksToRead;
|
resume.NextBlock = i + blocksToRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
end = DateTime.Now;
|
end = DateTime.Now;
|
||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
blockSize *
|
blockSize * (double)(blocks + 1) / 1024 /
|
||||||
(double)(blocks + 1) / 1024 / (totalDuration / 1000), devicePath);
|
(totalDuration / 1000), devicePath);
|
||||||
dumpLog.WriteLine("Dump finished in {0} seconds.",
|
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||||
(end - start).TotalSeconds);
|
|
||||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||||
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 Error handling
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
@@ -337,8 +335,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||||
}
|
}
|
||||||
else if(persistent)
|
else if(persistent) outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||||
@@ -362,8 +359,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
|
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
|
||||||
|
|
||||||
ulong currentBlock = 0;
|
ulong currentBlock = 0;
|
||||||
blocks = (ulong)(cylinders * heads * sectors);
|
blocks = (ulong)(cylinders * heads * sectors);
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
for(ushort cy = 0; cy < cylinders; cy++)
|
for(ushort cy = 0; cy < cylinders; cy++)
|
||||||
{
|
{
|
||||||
for(byte hd = 0; hd < heads; hd++)
|
for(byte hd = 0; hd < heads; hd++)
|
||||||
@@ -396,7 +393,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
DateTime writeStart = DateTime.Now;
|
DateTime writeStart = DateTime.Now;
|
||||||
outputPlugin.WriteSector(cmdBuf,
|
outputPlugin.WriteSector(cmdBuf,
|
||||||
(ulong)((cy * heads + hd) * sectors + (sc - 1)));
|
(ulong)((cy * heads + hd) * sectors + (sc - 1)));
|
||||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||||
extents.Add(currentBlock);
|
extents.Add(currentBlock);
|
||||||
dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", cy, hd,
|
dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", cy, hd,
|
||||||
sc);
|
sc);
|
||||||
@@ -410,7 +407,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
DateTime writeStart = DateTime.Now;
|
DateTime writeStart = DateTime.Now;
|
||||||
outputPlugin.WriteSector(new byte[blockSize],
|
outputPlugin.WriteSector(new byte[blockSize],
|
||||||
(ulong)((cy * heads + hd) * sectors + (sc - 1)));
|
(ulong)((cy * heads + hd) * sectors + (sc - 1)));
|
||||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
double newSpeed =
|
double newSpeed =
|
||||||
@@ -426,14 +423,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
blockSize *
|
blockSize * (double)(blocks + 1) / 1024 /
|
||||||
(double)(blocks + 1) / 1024 / (totalDuration / 1000), devicePath);
|
(totalDuration / 1000), devicePath);
|
||||||
dumpLog.WriteLine("Dump finished in {0} seconds.",
|
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||||
(end - start).TotalSeconds);
|
|
||||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 /
|
(double)blockSize * (double)(blocks + 1) / 1024 /
|
||||||
(imageWriteDuration / 1000));
|
(imageWriteDuration / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,8 +474,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(ret)
|
if(ret)
|
||||||
sidecar.BlockMedia[0].USB = new USBType
|
sidecar.BlockMedia[0].USB = new USBType
|
||||||
{
|
{
|
||||||
ProductID = dev.UsbProductId,
|
ProductID = dev.UsbProductId,
|
||||||
VendorID = dev.UsbVendorId,
|
VendorID = dev.UsbVendorId,
|
||||||
Descriptors = new DumpType
|
Descriptors = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath,
|
Image = outputPath,
|
||||||
@@ -532,7 +528,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
|
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
|
||||||
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
|
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
|
||||||
sidecar.BlockMedia[0].PCMCIA.Compliance =
|
sidecar.BlockMedia[0].PCMCIA.Compliance =
|
||||||
$"{vers.MajorVersion}.{vers.MinorVersion}";
|
$"{vers.MajorVersion}.{vers.MinorVersion}";
|
||||||
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation =
|
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation =
|
||||||
vers.AdditionalInformation;
|
vers.AdditionalInformation;
|
||||||
@@ -557,7 +553,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
DateTime chkEnd = DateTime.UtcNow;
|
DateTime chkEnd = DateTime.UtcNow;
|
||||||
|
|
||||||
totalChkDuration = (chkEnd - chkStart).TotalMilliseconds;
|
totalChkDuration = (chkEnd - chkStart).TotalMilliseconds;
|
||||||
dumpLog.WriteLine("Sidecar created in {0} seconds.", (chkEnd - chkStart).TotalSeconds);
|
dumpLog.WriteLine("Sidecar created in {0} seconds.", (chkEnd - chkStart).TotalSeconds);
|
||||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
||||||
@@ -630,10 +626,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(dev.IsCompactFlash) Statistics.AddMedia(MediaType.CompactFlash, true);
|
if(dev.IsCompactFlash) Statistics.AddMedia(MediaType.CompactFlash, true);
|
||||||
else if(dev.IsPcmcia)
|
else if(dev.IsPcmcia) Statistics.AddMedia(MediaType.PCCardTypeI, true);
|
||||||
Statistics.AddMedia(MediaType.PCCardTypeI, true);
|
else Statistics.AddMedia(MediaType.GENERIC_HDD, true);
|
||||||
else
|
|
||||||
Statistics.AddMedia(MediaType.GENERIC_HDD, true);
|
|
||||||
}
|
}
|
||||||
else DicConsole.ErrorWriteLine("Unable to communicate with ATA device.");
|
else DicConsole.ErrorWriteLine("Unable to communicate with ATA device.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -897,7 +897,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
#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...
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
||||||
|
|
||||||
#region Error handling
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
|
|||||||
@@ -72,14 +72,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, Encoding encoding, string outputPrefix,
|
ref DumpLog dumpLog, Encoding encoding,
|
||||||
string outputPath,
|
string outputPrefix, string outputPath,
|
||||||
Dictionary<string, string>
|
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
||||||
formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata)
|
uint skip,
|
||||||
|
bool nometadata)
|
||||||
{
|
{
|
||||||
bool aborted;
|
bool aborted;
|
||||||
|
|
||||||
@@ -121,12 +122,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
ExtendedCSD ecsdDecoded = Decoders.MMC.Decoders.DecodeExtendedCSD(ecsd);
|
ExtendedCSD ecsdDecoded = Decoders.MMC.Decoders.DecodeExtendedCSD(ecsd);
|
||||||
blocksToRead = ecsdDecoded.OptimalReadSize;
|
blocksToRead = ecsdDecoded.OptimalReadSize;
|
||||||
blocks = ecsdDecoded.SectorCount;
|
blocks = ecsdDecoded.SectorCount;
|
||||||
blockSize = (uint)(ecsdDecoded.SectorSize == 1 ? 4096 : 512);
|
blockSize = (uint)(ecsdDecoded.SectorSize == 1 ? 4096 : 512);
|
||||||
if(ecsdDecoded.NativeSectorSize == 0) physicalBlockSize = 512;
|
if(ecsdDecoded.NativeSectorSize == 0) physicalBlockSize = 512;
|
||||||
else if(ecsdDecoded.NativeSectorSize == 1)
|
else if(ecsdDecoded.NativeSectorSize == 1) physicalBlockSize = 4096;
|
||||||
physicalBlockSize = 4096;
|
|
||||||
// Supposing it's high-capacity MMC if it has Extended CSD...
|
// Supposing it's high-capacity MMC if it has Extended CSD...
|
||||||
byteAddressed = false;
|
byteAddressed = false;
|
||||||
mediaTags.Add(MediaTagType.MMC_ExtendedCSD, null);
|
mediaTags.Add(MediaTagType.MMC_ExtendedCSD, null);
|
||||||
@@ -140,9 +140,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(blocks == 0)
|
if(blocks == 0)
|
||||||
{
|
{
|
||||||
CSD csdDecoded = Decoders.MMC.Decoders.DecodeCSD(csd);
|
CSD csdDecoded = Decoders.MMC.Decoders.DecodeCSD(csd);
|
||||||
blocks =
|
blocks = (ulong)((csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2));
|
||||||
(ulong)((csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2));
|
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
|
||||||
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaTags.Add(MediaTagType.MMC_CSD, null);
|
mediaTags.Add(MediaTagType.MMC_CSD, null);
|
||||||
@@ -150,7 +149,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
else csd = null;
|
else csd = null;
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading OCR");
|
dumpLog.WriteLine("Reading OCR");
|
||||||
sense = dev.ReadOcr(out ocr, out _, TIMEOUT, out duration);
|
sense = dev.ReadOcr(out ocr, out _, TIMEOUT, out duration);
|
||||||
if(sense) ocr = null;
|
if(sense) ocr = null;
|
||||||
else mediaTags.Add(MediaTagType.MMC_OCR, null);
|
else mediaTags.Add(MediaTagType.MMC_OCR, null);
|
||||||
|
|
||||||
@@ -163,10 +162,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
Decoders.SecureDigital.CSD csdDecoded = Decoders.SecureDigital.Decoders.DecodeCSD(csd);
|
Decoders.SecureDigital.CSD csdDecoded = Decoders.SecureDigital.Decoders.DecodeCSD(csd);
|
||||||
blocks = (ulong)(csdDecoded.Structure == 0
|
blocks = (ulong)(csdDecoded.Structure == 0
|
||||||
? (csdDecoded.Size + 1) *
|
? (csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2)
|
||||||
Math.Pow(2, csdDecoded.SizeMultiplier + 2)
|
: (csdDecoded.Size + 1) * 1024);
|
||||||
: (csdDecoded.Size + 1) * 1024);
|
|
||||||
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
|
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
|
||||||
// Structure >=1 for SDHC/SDXC, so that's block addressed
|
// Structure >=1 for SDHC/SDXC, so that's block addressed
|
||||||
byteAddressed = csdDecoded.Structure == 0;
|
byteAddressed = csdDecoded.Structure == 0;
|
||||||
@@ -175,12 +173,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
else csd = null;
|
else csd = null;
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading OCR");
|
dumpLog.WriteLine("Reading OCR");
|
||||||
sense = dev.ReadSdocr(out ocr, out _, TIMEOUT, out duration);
|
sense = dev.ReadSdocr(out ocr, out _, TIMEOUT, out duration);
|
||||||
if(sense) ocr = null;
|
if(sense) ocr = null;
|
||||||
else mediaTags.Add(MediaTagType.SD_OCR, null);
|
else mediaTags.Add(MediaTagType.SD_OCR, null);
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading SCR");
|
dumpLog.WriteLine("Reading SCR");
|
||||||
sense = dev.ReadScr(out scr, out _, TIMEOUT, out duration);
|
sense = dev.ReadScr(out scr, out _, TIMEOUT, out duration);
|
||||||
if(sense) scr = null;
|
if(sense) scr = null;
|
||||||
else mediaTags.Add(MediaTagType.SD_SCR, null);
|
else mediaTags.Add(MediaTagType.SD_SCR, null);
|
||||||
|
|
||||||
@@ -189,16 +187,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading CID");
|
dumpLog.WriteLine("Reading CID");
|
||||||
sense = dev.ReadCid(out byte[] cid, out _, TIMEOUT, out duration);
|
sense = dev.ReadCid(out byte[] cid, out _, TIMEOUT, out duration);
|
||||||
if(sense) cid = null;
|
if(sense) cid = null;
|
||||||
else mediaTags.Add(dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID : MediaTagType.MMC_CID, null);
|
else mediaTags.Add(dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID : MediaTagType.MMC_CID, null);
|
||||||
|
|
||||||
DateTime start;
|
DateTime start;
|
||||||
DateTime end;
|
DateTime end;
|
||||||
double totalDuration = 0;
|
double totalDuration = 0;
|
||||||
double currentSpeed = 0;
|
double currentSpeed = 0;
|
||||||
double maxSpeed = double.MinValue;
|
double maxSpeed = double.MinValue;
|
||||||
double minSpeed = double.MaxValue;
|
double minSpeed = double.MaxValue;
|
||||||
|
|
||||||
aborted = false;
|
aborted = false;
|
||||||
System.Console.CancelKeyPress += (sender, e) => e.Cancel = aborted = true;
|
System.Console.CancelKeyPress += (sender, e) => e.Cancel = aborted = true;
|
||||||
@@ -264,11 +262,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
MhddLog mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
MhddLog mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||||
IbgLog ibgLog = new IbgLog(outputPrefix + ".ibg", SD_PROFILE);
|
IbgLog ibgLog = new IbgLog(outputPrefix + ".ibg", SD_PROFILE);
|
||||||
ret = outputPlugin.Create(outputPath,
|
ret = outputPlugin.Create(outputPath,
|
||||||
dev.Type == DeviceType.SecureDigital
|
dev.Type == DeviceType.SecureDigital ? MediaType.SecureDigital : MediaType.MMC,
|
||||||
? MediaType.SecureDigital
|
formatOptions, blocks, blockSize);
|
||||||
: MediaType.MMC,
|
|
||||||
formatOptions, blocks, blockSize);
|
|
||||||
|
|
||||||
// Cannot create image
|
// Cannot create image
|
||||||
if(!ret)
|
if(!ret)
|
||||||
@@ -282,7 +278,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||||
|
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
double imageWriteDuration = 0;
|
double imageWriteDuration = 0;
|
||||||
|
|
||||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||||
@@ -318,7 +314,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(i + skip > blocks) skip = (uint)(blocks - i);
|
if(i + skip > blocks) skip = (uint)(blocks - i);
|
||||||
|
|
||||||
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
|
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
|
||||||
|
|
||||||
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
||||||
@@ -334,24 +330,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
double newSpeed =
|
double newSpeed =
|
||||||
(double)blockSize * blocksToRead / 1048576 / (duration / 1000);
|
(double)blockSize * blocksToRead / 1048576 / (duration / 1000);
|
||||||
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
||||||
resume.NextBlock = i + blocksToRead;
|
resume.NextBlock = i + blocksToRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
end = DateTime.Now;
|
end = DateTime.Now;
|
||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
blockSize * (double)(blocks + 1) /
|
blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000),
|
||||||
1024 / (totalDuration / 1000), devicePath);
|
devicePath);
|
||||||
dumpLog.WriteLine("Dump finished in {0} seconds.",
|
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||||
(end - start).TotalSeconds);
|
|
||||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||||
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 Error handling
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
@@ -384,8 +379,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||||
}
|
}
|
||||||
else if(runningPersistent)
|
else if(runningPersistent) outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||||
@@ -573,7 +567,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
|
|
||||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||||
dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
||||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
||||||
@@ -601,7 +595,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
sidecar.BlockMedia[0].Model = dev.Model;
|
sidecar.BlockMedia[0].Model = dev.Model;
|
||||||
sidecar.BlockMedia[0].Serial = dev.Serial;
|
sidecar.BlockMedia[0].Serial = dev.Serial;
|
||||||
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
|
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
|
||||||
|
|
||||||
DicConsole.WriteLine("Writing metadata sidecar");
|
DicConsole.WriteLine("Writing metadata sidecar");
|
||||||
|
|
||||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||||
|
|||||||
@@ -80,16 +80,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
/// If the provided resume does not correspond with the current in progress
|
/// If the provided resume does not correspond with the current in progress
|
||||||
/// dump
|
/// dump
|
||||||
/// </exception>
|
/// </exception>
|
||||||
internal static void Dump(Device dev, string devicePath,
|
internal static void Dump(Device dev, string devicePath,
|
||||||
IWritableImage outputPlugin, ushort retryPasses,
|
IWritableImage outputPlugin, ushort retryPasses,
|
||||||
bool force, bool dumpRaw,
|
bool force, bool dumpRaw,
|
||||||
bool persistent, bool stopOnError,
|
bool persistent, bool stopOnError,
|
||||||
Dictionary<MediaTagType, byte[]> mediaTags, ref MediaType dskType,
|
Dictionary<MediaTagType, byte[]> mediaTags, ref MediaType dskType,
|
||||||
ref Resume resume,
|
ref Resume resume,
|
||||||
ref DumpLog dumpLog,
|
ref DumpLog dumpLog, Encoding encoding,
|
||||||
Encoding encoding, string outputPrefix, string outputPath,
|
string outputPrefix, string outputPath,
|
||||||
Dictionary<string, string> formatOptions,
|
Dictionary<string, string> formatOptions, CICMMetadataType preSidecar,
|
||||||
CICMMetadataType preSidecar, uint skip, bool nometadata)
|
uint skip,
|
||||||
|
bool nometadata)
|
||||||
{
|
{
|
||||||
bool sense;
|
bool sense;
|
||||||
ulong blocks;
|
ulong blocks;
|
||||||
@@ -97,11 +98,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
uint blocksToRead = 64;
|
uint blocksToRead = 64;
|
||||||
DateTime start;
|
DateTime start;
|
||||||
DateTime end;
|
DateTime end;
|
||||||
double totalDuration = 0;
|
double totalDuration = 0;
|
||||||
double currentSpeed = 0;
|
double currentSpeed = 0;
|
||||||
double maxSpeed = double.MinValue;
|
double maxSpeed = double.MinValue;
|
||||||
double minSpeed = double.MaxValue;
|
double minSpeed = double.MaxValue;
|
||||||
bool aborted = false;
|
bool aborted = false;
|
||||||
System.Console.CancelKeyPress += (sender, e) => e.Cancel = aborted = true;
|
System.Console.CancelKeyPress += (sender, e) => e.Cancel = aborted = true;
|
||||||
|
|
||||||
if(mediaTags.ContainsKey(MediaTagType.DVD_PFI)) mediaTags.Remove(MediaTagType.DVD_PFI);
|
if(mediaTags.ContainsKey(MediaTagType.DVD_PFI)) mediaTags.Remove(MediaTagType.DVD_PFI);
|
||||||
@@ -125,7 +126,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] tmpBuf = new byte[ssBuf.Length - 4];
|
byte[] tmpBuf = new byte[ssBuf.Length - 4];
|
||||||
Array.Copy(ssBuf, 4, tmpBuf, 0, ssBuf.Length - 4);
|
Array.Copy(ssBuf, 4, tmpBuf, 0, ssBuf.Length - 4);
|
||||||
mediaTags.Add(MediaTagType.Xbox_SecuritySector, tmpBuf);
|
mediaTags.Add(MediaTagType.Xbox_SecuritySector, tmpBuf);
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpBuf = new byte[readBuffer.Length - 4];
|
tmpBuf = new byte[readBuffer.Length - 4];
|
||||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||||
mediaTags.Add(MediaTagType.DVD_PFI, tmpBuf);
|
mediaTags.Add(MediaTagType.DVD_PFI, tmpBuf);
|
||||||
DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", totalSize);
|
DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", totalSize);
|
||||||
@@ -178,7 +179,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpBuf = new byte[readBuffer.Length - 4];
|
tmpBuf = new byte[readBuffer.Length - 4];
|
||||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||||
mediaTags.Add(MediaTagType.DVD_DMI, tmpBuf);
|
mediaTags.Add(MediaTagType.DVD_DMI, tmpBuf);
|
||||||
|
|
||||||
@@ -238,13 +239,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
|
|
||||||
DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors", totalSize);
|
DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors", totalSize);
|
||||||
blocks = totalSize + 1;
|
blocks = totalSize + 1;
|
||||||
middleZone =
|
middleZone =
|
||||||
totalSize - (PFI.Decode(readBuffer).Value.Layer0EndPSN -
|
totalSize - (PFI.Decode(readBuffer).Value.Layer0EndPSN -
|
||||||
PFI.Decode(readBuffer).Value.DataAreaStartPSN +
|
PFI.Decode(readBuffer).Value.DataAreaStartPSN +
|
||||||
1) - gameSize + 1;
|
1) - gameSize + 1;
|
||||||
|
|
||||||
tmpBuf = new byte[readBuffer.Length - 4];
|
tmpBuf = new byte[readBuffer.Length - 4];
|
||||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||||
mediaTags.Add(MediaTagType.Xbox_PFI, tmpBuf);
|
mediaTags.Add(MediaTagType.Xbox_PFI, tmpBuf);
|
||||||
|
|
||||||
@@ -258,12 +259,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpBuf = new byte[readBuffer.Length - 4];
|
tmpBuf = new byte[readBuffer.Length - 4];
|
||||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||||
mediaTags.Add(MediaTagType.Xbox_DMI, tmpBuf);
|
mediaTags.Add(MediaTagType.Xbox_DMI, tmpBuf);
|
||||||
|
|
||||||
totalSize = l0Video + l1Video + middleZone * 2 + gameSize;
|
totalSize = l0Video + l1Video + middleZone * 2 + gameSize;
|
||||||
layerBreak = l0Video + middleZone + gameSize / 2;
|
layerBreak = l0Video + middleZone + gameSize / 2;
|
||||||
|
|
||||||
DicConsole.WriteLine("Video layer 0 size: {0} sectors", l0Video);
|
DicConsole.WriteLine("Video layer 0 size: {0} sectors", l0Video);
|
||||||
DicConsole.WriteLine("Video layer 1 size: {0} sectors", l1Video);
|
DicConsole.WriteLine("Video layer 1 size: {0} sectors", l1Video);
|
||||||
@@ -336,7 +337,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
MhddLog mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, BLOCK_SIZE, blocksToRead);
|
MhddLog mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, BLOCK_SIZE, blocksToRead);
|
||||||
IbgLog ibgLog = new IbgLog(outputPrefix + ".ibg", 0x0010);
|
IbgLog ibgLog = new IbgLog(outputPrefix + ".ibg", 0x0010);
|
||||||
ret = outputPlugin.Create(outputPath, dskType, formatOptions, blocks, BLOCK_SIZE);
|
ret = outputPlugin.Create(outputPath, dskType, formatOptions, blocks, BLOCK_SIZE);
|
||||||
|
|
||||||
// Cannot create image
|
// Cannot create image
|
||||||
if(!ret)
|
if(!ret)
|
||||||
@@ -348,7 +349,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
double imageWriteDuration = 0;
|
double imageWriteDuration = 0;
|
||||||
|
|
||||||
double cmdDuration = 0;
|
double cmdDuration = 0;
|
||||||
@@ -373,7 +374,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
TrackType = TrackType.Data
|
TrackType = TrackType.Data
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -397,13 +398,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(xboxSs.Value.Extents[e].StartPSN <= xboxSs.Value.Layer0EndPSN)
|
if(xboxSs.Value.Extents[e].StartPSN <= xboxSs.Value.Layer0EndPSN)
|
||||||
extentStart = xboxSs.Value.Extents[e].StartPSN - 0x30000;
|
extentStart = xboxSs.Value.Extents[e].StartPSN - 0x30000;
|
||||||
else
|
else
|
||||||
extentStart = (xboxSs.Value.Layer0EndPSN + 1) * 2 -
|
extentStart = (xboxSs.Value.Layer0EndPSN + 1) * 2 -
|
||||||
((xboxSs.Value.Extents[e].StartPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
((xboxSs.Value.Extents[e].StartPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
||||||
if(xboxSs.Value.Extents[e].EndPSN <= xboxSs.Value.Layer0EndPSN)
|
if(xboxSs.Value.Extents[e].EndPSN <= xboxSs.Value.Layer0EndPSN)
|
||||||
extentEnd = xboxSs.Value.Extents[e].EndPSN - 0x30000;
|
extentEnd = xboxSs.Value.Extents[e].EndPSN - 0x30000;
|
||||||
else
|
else
|
||||||
extentEnd = (xboxSs.Value.Layer0EndPSN + 1) * 2 -
|
extentEnd = (xboxSs.Value.Layer0EndPSN + 1) * 2 -
|
||||||
((xboxSs.Value.Extents[e].EndPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
((xboxSs.Value.Extents[e].EndPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
||||||
}
|
}
|
||||||
// After last extent
|
// After last extent
|
||||||
else
|
else
|
||||||
@@ -453,7 +454,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(stopOnError) return; // TODO: Return more cleanly
|
if(stopOnError) return; // TODO: Return more cleanly
|
||||||
|
|
||||||
if(i + skip > blocks) skip = (uint)(blocks - i);
|
if(i + skip > blocks) skip = (uint)(blocks - i);
|
||||||
|
|
||||||
// Write empty data
|
// Write empty data
|
||||||
DateTime writeStart = DateTime.Now;
|
DateTime writeStart = DateTime.Now;
|
||||||
outputPlugin.WriteSectors(new byte[BLOCK_SIZE * skip], i, skip);
|
outputPlugin.WriteSectors(new byte[BLOCK_SIZE * skip], i, skip);
|
||||||
@@ -467,7 +468,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;
|
||||||
string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
|
string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
|
||||||
StringSplitOptions
|
StringSplitOptions
|
||||||
.RemoveEmptyEntries);
|
.RemoveEmptyEntries);
|
||||||
@@ -477,9 +478,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
double newSpeed =
|
double newSpeed =
|
||||||
(double)BLOCK_SIZE * blocksToRead / 1048576 / (cmdDuration / 1000);
|
(double)BLOCK_SIZE * blocksToRead / 1048576 / (cmdDuration / 1000);
|
||||||
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
||||||
blocksToRead = saveBlocksToRead;
|
blocksToRead = saveBlocksToRead;
|
||||||
currentSector = i + 1;
|
currentSector = i + 1;
|
||||||
resume.NextBlock = currentSector;
|
resume.NextBlock = currentSector;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(ulong i = extentStart; i <= extentEnd; i += blocksToRead)
|
for(ulong i = extentStart; i <= extentEnd; i += blocksToRead)
|
||||||
@@ -607,7 +608,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
ibgLog.Write(l1, 0);
|
ibgLog.Write(l1, 0);
|
||||||
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, l1);
|
dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", skip, l1);
|
||||||
l1 += skip - blocksToRead;
|
l1 += skip - blocksToRead;
|
||||||
string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
|
string[] senseLines = Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
|
||||||
StringSplitOptions.RemoveEmptyEntries);
|
StringSplitOptions.RemoveEmptyEntries);
|
||||||
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
|
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
|
||||||
@@ -615,9 +616,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
double newSpeed =
|
double newSpeed =
|
||||||
(double)BLOCK_SIZE * blocksToRead / 1048576 / (cmdDuration / 1000);
|
(double)BLOCK_SIZE * blocksToRead / 1048576 / (cmdDuration / 1000);
|
||||||
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed;
|
||||||
currentSector += blocksToRead;
|
currentSector += blocksToRead;
|
||||||
resume.NextBlock = currentSector;
|
resume.NextBlock = currentSector;
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Unlocking drive (Wxripper).");
|
dumpLog.WriteLine("Unlocking drive (Wxripper).");
|
||||||
@@ -640,17 +641,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
ibgLog.Close(dev, blocks, BLOCK_SIZE, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, blocks, BLOCK_SIZE, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
BLOCK_SIZE * (double)(blocks + 1) /
|
BLOCK_SIZE * (double)(blocks + 1) / 1024 / (totalDuration / 1000),
|
||||||
1024 / (totalDuration / 1000), devicePath);
|
devicePath);
|
||||||
dumpLog.WriteLine("Dump finished in {0} seconds.",
|
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||||
(end - start).TotalSeconds);
|
|
||||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||||
(double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
(double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||||
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 Error handling
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||||
{
|
{
|
||||||
List<ulong> tmpList = new List<ulong>();
|
List<ulong> tmpList = new List<ulong>();
|
||||||
|
|
||||||
@@ -692,8 +692,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
outputPlugin.WriteSector(readBuffer, badSector);
|
outputPlugin.WriteSector(readBuffer, badSector);
|
||||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||||
}
|
}
|
||||||
else if(runningPersistent)
|
else if(runningPersistent) outputPlugin.WriteSector(readBuffer, badSector);
|
||||||
outputPlugin.WriteSector(readBuffer, badSector);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||||
@@ -713,12 +712,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
if(dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice)
|
if(dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice)
|
||||||
{
|
{
|
||||||
Modes.ModePage_01_MMC pgMmc =
|
Modes.ModePage_01_MMC pgMmc =
|
||||||
new Modes.ModePage_01_MMC {PS = false, ReadRetryCount = 255, Parameter = 0x20};
|
new Modes.ModePage_01_MMC {PS = false, ReadRetryCount = 255, Parameter = 0x20};
|
||||||
Modes.DecodedMode md = new Modes.DecodedMode
|
Modes.DecodedMode md = new Modes.DecodedMode
|
||||||
{
|
{
|
||||||
Header = new Modes.ModeHeader(),
|
Header = new Modes.ModeHeader(),
|
||||||
Pages = new[]
|
Pages = new[]
|
||||||
{
|
{
|
||||||
new Modes.ModePage
|
new Modes.ModePage
|
||||||
{
|
{
|
||||||
@@ -749,7 +748,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
Modes.DecodedMode md = new Modes.DecodedMode
|
Modes.DecodedMode md = new Modes.DecodedMode
|
||||||
{
|
{
|
||||||
Header = new Modes.ModeHeader(),
|
Header = new Modes.ModeHeader(),
|
||||||
Pages = new[]
|
Pages = new[]
|
||||||
{
|
{
|
||||||
new Modes.ModePage
|
new Modes.ModePage
|
||||||
{
|
{
|
||||||
@@ -764,7 +763,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out _);
|
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out _);
|
||||||
if(sense) sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out _);
|
if(sense) sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out _);
|
||||||
|
|
||||||
runningPersistent = true;
|
runningPersistent = true;
|
||||||
@@ -836,7 +835,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
DateTime chkStart = DateTime.UtcNow;
|
DateTime chkStart = DateTime.UtcNow;
|
||||||
CICMMetadataType sidecar = Sidecar.Create(inputPlugin, outputPath, filter.Id, encoding);
|
CICMMetadataType sidecar = Sidecar.Create(inputPlugin, outputPath, filter.Id, encoding);
|
||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
|
|
||||||
if(preSidecar != null)
|
if(preSidecar != null)
|
||||||
{
|
{
|
||||||
@@ -844,7 +843,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
sidecar = preSidecar;
|
sidecar = preSidecar;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||||
dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
||||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||||
(double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
(double)BLOCK_SIZE * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
||||||
|
|||||||
Reference in New Issue
Block a user