mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Refactor.
This commit is contained in:
@@ -53,9 +53,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
/// <summary>Dumps an ATA device</summary>
|
/// <summary>Dumps an ATA device</summary>
|
||||||
public void Ata()
|
public void Ata()
|
||||||
{
|
{
|
||||||
if(dumpRaw)
|
if(_dumpRaw)
|
||||||
{
|
{
|
||||||
if(force)
|
if(_force)
|
||||||
ErrorMessage?.Invoke("Raw dumping not yet supported in ATA devices, continuing...");
|
ErrorMessage?.Invoke("Raw dumping not yet supported in ATA devices, continuing...");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -70,8 +70,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
double imageWriteDuration = 0;
|
double imageWriteDuration = 0;
|
||||||
|
|
||||||
UpdateStatus?.Invoke("Requesting ATA IDENTIFY DEVICE.");
|
UpdateStatus?.Invoke("Requesting ATA IDENTIFY DEVICE.");
|
||||||
dumpLog.WriteLine("Requesting ATA IDENTIFY DEVICE.");
|
_dumpLog.WriteLine("Requesting ATA IDENTIFY DEVICE.");
|
||||||
bool sense = dev.AtaIdentify(out byte[] cmdBuf, out _);
|
bool sense = _dev.AtaIdentify(out byte[] cmdBuf, out _);
|
||||||
|
|
||||||
if(!sense &&
|
if(!sense &&
|
||||||
Identify.Decode(cmdBuf).HasValue)
|
Identify.Decode(cmdBuf).HasValue)
|
||||||
@@ -93,8 +93,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
// Initializate reader
|
// Initializate reader
|
||||||
UpdateStatus?.Invoke("Initializing reader.");
|
UpdateStatus?.Invoke("Initializing reader.");
|
||||||
dumpLog.WriteLine("Initializing reader.");
|
_dumpLog.WriteLine("Initializing reader.");
|
||||||
var ataReader = new Reader(dev, TIMEOUT, ataIdentify);
|
var ataReader = new Reader(_dev, TIMEOUT, ataIdentify);
|
||||||
|
|
||||||
// Fill reader blocks
|
// Fill reader blocks
|
||||||
ulong blocks = ataReader.GetDeviceBlocks();
|
ulong blocks = ataReader.GetDeviceBlocks();
|
||||||
@@ -102,7 +102,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
// Check block sizes
|
// Check block sizes
|
||||||
if(ataReader.GetBlockSize())
|
if(ataReader.GetBlockSize())
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("ERROR: Cannot get block size: {0}.", ataReader.ErrorMessage);
|
_dumpLog.WriteLine("ERROR: Cannot get block size: {0}.", ataReader.ErrorMessage);
|
||||||
ErrorMessage(ataReader.ErrorMessage);
|
ErrorMessage(ataReader.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -113,7 +113,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(ataReader.FindReadCommand())
|
if(ataReader.FindReadCommand())
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("ERROR: Cannot find correct read command: {0}.", ataReader.ErrorMessage);
|
_dumpLog.WriteLine("ERROR: Cannot find correct read command: {0}.", ataReader.ErrorMessage);
|
||||||
ErrorMessage(ataReader.ErrorMessage);
|
ErrorMessage(ataReader.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -122,7 +122,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
// Check how many blocks to read, if error show and return
|
// Check how many blocks to read, if error show and return
|
||||||
if(ataReader.GetBlocksToRead())
|
if(ataReader.GetBlocksToRead())
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read: {0}.", ataReader.ErrorMessage);
|
_dumpLog.WriteLine("ERROR: Cannot get blocks to read: {0}.", ataReader.ErrorMessage);
|
||||||
ErrorMessage(ataReader.ErrorMessage);
|
ErrorMessage(ataReader.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -141,23 +141,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");
|
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");
|
||||||
UpdateStatus?.Invoke($"Device reports {blockSize} bytes per logical block.");
|
UpdateStatus?.Invoke($"Device reports {blockSize} bytes per logical block.");
|
||||||
UpdateStatus?.Invoke($"Device reports {physicalsectorsize} bytes per physical block.");
|
UpdateStatus?.Invoke($"Device reports {physicalsectorsize} bytes per physical block.");
|
||||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
_dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||||
|
|
||||||
dumpLog.WriteLine("Device reports {0} cylinders {1} heads {2} sectors per track.", cylinders, heads,
|
_dumpLog.WriteLine("Device reports {0} cylinders {1} heads {2} sectors per track.", cylinders,
|
||||||
sectors);
|
heads, sectors);
|
||||||
|
|
||||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
_dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||||
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
|
_dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
|
||||||
dumpLog.WriteLine("Device reports {0} bytes per physical block.", physicalsectorsize);
|
_dumpLog.WriteLine("Device reports {0} bytes per physical block.", physicalsectorsize);
|
||||||
|
|
||||||
bool removable = !dev.IsCompactFlash &&
|
bool removable = !_dev.IsCompactFlash &&
|
||||||
ataId.GeneralConfiguration.HasFlag(Identify.GeneralConfigurationBit.Removable);
|
ataId.GeneralConfiguration.HasFlag(Identify.GeneralConfigurationBit.Removable);
|
||||||
|
|
||||||
DumpHardwareType currentTry = null;
|
DumpHardwareType currentTry = null;
|
||||||
ExtentsULong extents = null;
|
ExtentsULong extents = null;
|
||||||
|
|
||||||
ResumeSupport.Process(ataReader.IsLba, removable, blocks, dev.Manufacturer, dev.Model, dev.Serial,
|
ResumeSupport.Process(ataReader.IsLba, removable, blocks, _dev.Manufacturer, _dev.Model,
|
||||||
dev.PlatformId, ref resume, ref currentTry, ref extents);
|
_dev.Serial, _dev.PlatformId, ref _resume, ref currentTry, ref extents);
|
||||||
|
|
||||||
if(currentTry == null ||
|
if(currentTry == null ||
|
||||||
extents == null)
|
extents == null)
|
||||||
@@ -173,36 +173,36 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
if(dev.IsUsb &&
|
if(_dev.IsUsb &&
|
||||||
dev.UsbDescriptors != null &&
|
_dev.UsbDescriptors != null &&
|
||||||
!outputPlugin.SupportedMediaTags.Contains(MediaTagType.USB_Descriptors))
|
!_outputPlugin.SupportedMediaTags.Contains(MediaTagType.USB_Descriptors))
|
||||||
{
|
{
|
||||||
ret = false;
|
ret = false;
|
||||||
dumpLog.WriteLine("Output format does not support USB descriptors.");
|
_dumpLog.WriteLine("Output format does not support USB descriptors.");
|
||||||
ErrorMessage("Output format does not support USB descriptors.");
|
ErrorMessage("Output format does not support USB descriptors.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dev.IsPcmcia &&
|
if(_dev.IsPcmcia &&
|
||||||
dev.Cis != null &&
|
_dev.Cis != null &&
|
||||||
!outputPlugin.SupportedMediaTags.Contains(MediaTagType.PCMCIA_CIS))
|
!_outputPlugin.SupportedMediaTags.Contains(MediaTagType.PCMCIA_CIS))
|
||||||
{
|
{
|
||||||
ret = false;
|
ret = false;
|
||||||
dumpLog.WriteLine("Output format does not support PCMCIA CIS descriptors.");
|
_dumpLog.WriteLine("Output format does not support PCMCIA CIS descriptors.");
|
||||||
ErrorMessage("Output format does not support PCMCIA CIS descriptors.");
|
ErrorMessage("Output format does not support PCMCIA CIS descriptors.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!outputPlugin.SupportedMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
|
if(!_outputPlugin.SupportedMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
|
||||||
{
|
{
|
||||||
ret = false;
|
ret = false;
|
||||||
dumpLog.WriteLine("Output format does not support ATA IDENTIFY.");
|
_dumpLog.WriteLine("Output format does not support ATA IDENTIFY.");
|
||||||
ErrorMessage("Output format does not support ATA IDENTIFY.");
|
ErrorMessage("Output format does not support ATA IDENTIFY.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ret)
|
if(!ret)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Several media tags not supported, {0}continuing...", force ? "" : "not ");
|
_dumpLog.WriteLine("Several media tags not supported, {0}continuing...", _force ? "" : "not ");
|
||||||
|
|
||||||
if(force)
|
if(_force)
|
||||||
ErrorMessage("Several media tags not supported, continuing...");
|
ErrorMessage("Several media tags not supported, continuing...");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -212,40 +212,40 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = outputPlugin.Create(outputPath,
|
ret = _outputPlugin.Create(_outputPath,
|
||||||
dev.IsCompactFlash ? MediaType.CompactFlash : MediaType.GENERIC_HDD,
|
_dev.IsCompactFlash ? MediaType.CompactFlash : MediaType.GENERIC_HDD,
|
||||||
formatOptions, blocks, blockSize);
|
_formatOptions, blocks, blockSize);
|
||||||
|
|
||||||
// Cannot create image
|
// Cannot create image
|
||||||
if(!ret)
|
if(!ret)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Error creating output image, not continuing.");
|
_dumpLog.WriteLine("Error creating output image, not continuing.");
|
||||||
dumpLog.WriteLine(outputPlugin.ErrorMessage);
|
_dumpLog.WriteLine(_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Error creating output image, not continuing." +
|
StoppingErrorMessage?.Invoke("Error creating output image, not continuing." +
|
||||||
Environment.NewLine +
|
Environment.NewLine +
|
||||||
outputPlugin.ErrorMessage);
|
_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting geometry
|
// Setting geometry
|
||||||
outputPlugin.SetGeometry(cylinders, heads, sectors);
|
_outputPlugin.SetGeometry(cylinders, heads, sectors);
|
||||||
|
|
||||||
if(ataReader.IsLba)
|
if(ataReader.IsLba)
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time.");
|
UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time.");
|
||||||
|
|
||||||
if(skip < blocksToRead)
|
if(_skip < blocksToRead)
|
||||||
skip = blocksToRead;
|
_skip = blocksToRead;
|
||||||
|
|
||||||
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, blocksToRead);
|
||||||
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
|
ibgLog = new IbgLog(_outputPrefix + ".ibg", ATA_PROFILE);
|
||||||
|
|
||||||
if(resume.NextBlock > 0)
|
if(_resume.NextBlock > 0)
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke($"Resuming from block {resume.NextBlock}.");
|
UpdateStatus?.Invoke($"Resuming from block {_resume.NextBlock}.");
|
||||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
_dumpLog.WriteLine("Resuming from block {0}.", _resume.NextBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool newTrim = false;
|
bool newTrim = false;
|
||||||
@@ -255,13 +255,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
ulong sectorSpeedStart = 0;
|
ulong sectorSpeedStart = 0;
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
for(ulong i = _resume.NextBlock; i < blocks; i += blocksToRead)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -289,38 +289,38 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
mhddLog.Write(i, duration);
|
mhddLog.Write(i, duration);
|
||||||
ibgLog.Write(i, currentSpeed * 1024);
|
ibgLog.Write(i, currentSpeed * 1024);
|
||||||
DateTime writeStart = DateTime.Now;
|
DateTime writeStart = DateTime.Now;
|
||||||
outputPlugin.WriteSectors(cmdBuf, i, blocksToRead);
|
_outputPlugin.WriteSectors(cmdBuf, i, blocksToRead);
|
||||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||||
extents.Add(i, blocksToRead, true);
|
extents.Add(i, blocksToRead, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(i + skip > blocks)
|
if(i + _skip > blocks)
|
||||||
skip = (uint)(blocks - i);
|
_skip = (uint)(blocks - i);
|
||||||
|
|
||||||
for(ulong b = i; b < i + skip; b++)
|
for(ulong b = i; b < i + _skip; b++)
|
||||||
resume.BadBlocks.Add(b);
|
_resume.BadBlocks.Add(b);
|
||||||
|
|
||||||
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
||||||
|
|
||||||
ibgLog.Write(i, 0);
|
ibgLog.Write(i, 0);
|
||||||
DateTime writeStart = DateTime.Now;
|
DateTime writeStart = DateTime.Now;
|
||||||
outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip);
|
_outputPlugin.WriteSectors(new byte[blockSize * _skip], i, _skip);
|
||||||
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;
|
newTrim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sectorSpeedStart += blocksToRead;
|
sectorSpeedStart += blocksToRead;
|
||||||
resume.NextBlock = i + blocksToRead;
|
_resume.NextBlock = i + blocksToRead;
|
||||||
|
|
||||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||||
|
|
||||||
if(elapsed < 1)
|
if(elapsed < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||||
sectorSpeedStart = 0;
|
sectorSpeedStart = 0;
|
||||||
timeSpeedStart = DateTime.UtcNow;
|
timeSpeedStart = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -329,46 +329,46 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
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) / 1024 /
|
(blockSize * (double)(blocks + 1)) / 1024 /
|
||||||
(totalDuration / 1000), devicePath);
|
(totalDuration / 1000), _devicePath);
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
Invoke($"Average dump speed {((double)blockSize * (double)(blocks + 1)) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average write speed {(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
Invoke($"Average write speed {((double)blockSize * (double)(blocks + 1)) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||||
|
|
||||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
_dumpLog.WriteLine("Dump finished in {0} seconds.", (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 Trimming
|
#region Trimming
|
||||||
if(resume.BadBlocks.Count > 0 &&
|
if(_resume.BadBlocks.Count > 0 &&
|
||||||
!aborted &&
|
!_aborted &&
|
||||||
!notrim &&
|
!_notrim &&
|
||||||
newTrim)
|
newTrim)
|
||||||
{
|
{
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
UpdateStatus?.Invoke("Trimming bad sectors");
|
UpdateStatus?.Invoke("Trimming bad sectors");
|
||||||
dumpLog.WriteLine("Trimming bad sectors");
|
_dumpLog.WriteLine("Trimming bad sectors");
|
||||||
|
|
||||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
foreach(ulong badSector in tmpArray)
|
foreach(ulong badSector in tmpArray)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -382,44 +382,44 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(error)
|
if(error)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
resume.BadBlocks.Remove(badSector);
|
_resume.BadBlocks.Remove(badSector);
|
||||||
extents.Add(badSector);
|
extents.Add(badSector);
|
||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
_outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
UpdateStatus?.Invoke($"Trimmming finished in {(end - start).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Trimmming finished in {(end - start).TotalSeconds} seconds.");
|
||||||
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
|
_dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
|
||||||
}
|
}
|
||||||
#endregion Trimming
|
#endregion Trimming
|
||||||
|
|
||||||
#region Error handling
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 &&
|
if(_resume.BadBlocks.Count > 0 &&
|
||||||
!aborted &&
|
!_aborted &&
|
||||||
retryPasses > 0)
|
_retryPasses > 0)
|
||||||
{
|
{
|
||||||
int pass = 1;
|
int pass = 1;
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
repeatRetryLba:
|
repeatRetryLba:
|
||||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||||
|
|
||||||
foreach(ulong badSector in tmpArray)
|
foreach(ulong badSector in tmpArray)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PulseProgress?.Invoke(string.Format("Retrying sector {0}, pass {1}, {3}{2}", badSector,
|
PulseProgress?.Invoke(string.Format("Retrying sector {0}, pass {1}, {3}{2}", badSector,
|
||||||
pass, forward ? "forward" : "reverse",
|
pass, forward ? "forward" : "reverse",
|
||||||
persistent ? "recovering partial data, " : ""));
|
_persistent ? "recovering partial data, " : ""));
|
||||||
|
|
||||||
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
|
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
|
||||||
|
|
||||||
@@ -427,24 +427,24 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(!error)
|
if(!error)
|
||||||
{
|
{
|
||||||
resume.BadBlocks.Remove(badSector);
|
_resume.BadBlocks.Remove(badSector);
|
||||||
extents.Add(badSector);
|
extents.Add(badSector);
|
||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
_outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
||||||
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 &&
|
if(pass < _retryPasses &&
|
||||||
!aborted &&
|
!_aborted &&
|
||||||
resume.BadBlocks.Count > 0)
|
_resume.BadBlocks.Count > 0)
|
||||||
{
|
{
|
||||||
pass++;
|
pass++;
|
||||||
forward = !forward;
|
forward = !forward;
|
||||||
resume.BadBlocks.Sort();
|
_resume.BadBlocks.Sort();
|
||||||
resume.BadBlocks.Reverse();
|
_resume.BadBlocks.Reverse();
|
||||||
|
|
||||||
goto repeatRetryLba;
|
goto repeatRetryLba;
|
||||||
}
|
}
|
||||||
@@ -457,8 +457,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, blocksToRead);
|
||||||
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);
|
||||||
@@ -473,11 +473,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
for(byte sc = 1; sc < sectors; sc++)
|
for(byte sc = 1; sc < sectors; sc++)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -505,25 +505,25 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
||||||
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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resume.BadBlocks.Add(currentBlock);
|
_resume.BadBlocks.Add(currentBlock);
|
||||||
mhddLog.Write(currentBlock, duration < 500 ? 65535 : duration);
|
mhddLog.Write(currentBlock, duration < 500 ? 65535 : duration);
|
||||||
|
|
||||||
ibgLog.Write(currentBlock, 0);
|
ibgLog.Write(currentBlock, 0);
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -536,7 +536,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(elapsed < 1)
|
if(elapsed < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||||
sectorSpeedStart = 0;
|
sectorSpeedStart = 0;
|
||||||
timeSpeedStart = DateTime.UtcNow;
|
timeSpeedStart = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -547,47 +547,47 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
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) / 1024 /
|
(blockSize * (double)(blocks + 1)) / 1024 /
|
||||||
(totalDuration / 1000), devicePath);
|
(totalDuration / 1000), _devicePath);
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
Invoke($"Average dump speed {((double)blockSize * (double)(blocks + 1)) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average write speed {(double)blockSize * (double)(blocks + 1) / 1024 / (imageWriteDuration / 1000):F3} KiB/sec.");
|
Invoke($"Average write speed {((double)blockSize * (double)(blocks + 1)) / 1024 / (imageWriteDuration / 1000):F3} KiB/sec.");
|
||||||
|
|
||||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
_dumpLog.WriteLine("Dump finished in {0} seconds.", (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));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(ulong bad in resume.BadBlocks)
|
foreach(ulong bad in _resume.BadBlocks)
|
||||||
dumpLog.WriteLine("Sector {0} could not be read.", bad);
|
_dumpLog.WriteLine("Sector {0} could not be read.", bad);
|
||||||
|
|
||||||
outputPlugin.SetDumpHardware(resume.Tries);
|
_outputPlugin.SetDumpHardware(_resume.Tries);
|
||||||
|
|
||||||
if(preSidecar != null)
|
if(_preSidecar != null)
|
||||||
outputPlugin.SetCicmMetadata(preSidecar);
|
_outputPlugin.SetCicmMetadata(_preSidecar);
|
||||||
|
|
||||||
dumpLog.WriteLine("Closing output file.");
|
_dumpLog.WriteLine("Closing output file.");
|
||||||
UpdateStatus?.Invoke("Closing output file.");
|
UpdateStatus?.Invoke("Closing output file.");
|
||||||
DateTime closeStart = DateTime.Now;
|
DateTime closeStart = DateTime.Now;
|
||||||
outputPlugin.Close();
|
_outputPlugin.Close();
|
||||||
DateTime closeEnd = DateTime.Now;
|
DateTime closeEnd = DateTime.Now;
|
||||||
UpdateStatus?.Invoke($"Closed in {(closeEnd - closeStart).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Closed in {(closeEnd - closeStart).TotalSeconds} seconds.");
|
||||||
dumpLog.WriteLine("Closed in {0} seconds.", (closeEnd - closeStart).TotalSeconds);
|
_dumpLog.WriteLine("Closed in {0} seconds.", (closeEnd - closeStart).TotalSeconds);
|
||||||
|
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -595,12 +595,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
double totalChkDuration = 0;
|
double totalChkDuration = 0;
|
||||||
|
|
||||||
if(!nometadata)
|
if(!_nometadata)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
UpdateStatus?.Invoke("Creating sidecar.");
|
UpdateStatus?.Invoke("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
||||||
|
|
||||||
if(!inputPlugin.Open(filter))
|
if(!inputPlugin.Open(filter))
|
||||||
@@ -611,60 +611,64 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
|
|
||||||
DateTime chkStart = DateTime.UtcNow;
|
DateTime chkStart = DateTime.UtcNow;
|
||||||
sidecarClass = new Sidecar(inputPlugin, outputPath, filter.Id, encoding);
|
|
||||||
sidecarClass.InitProgressEvent += InitProgress;
|
|
||||||
sidecarClass.UpdateProgressEvent += UpdateProgress;
|
|
||||||
sidecarClass.EndProgressEvent += EndProgress;
|
|
||||||
sidecarClass.InitProgressEvent2 += InitProgress2;
|
|
||||||
sidecarClass.UpdateProgressEvent2 += UpdateProgress2;
|
|
||||||
sidecarClass.EndProgressEvent2 += EndProgress2;
|
|
||||||
sidecarClass.UpdateStatusEvent += UpdateStatus;
|
|
||||||
CICMMetadataType sidecar = sidecarClass.Create();
|
|
||||||
|
|
||||||
if(preSidecar != null)
|
_sidecarClass =
|
||||||
|
new Sidecar(inputPlugin, _outputPath, filter.Id, _encoding);
|
||||||
|
|
||||||
|
_sidecarClass.InitProgressEvent += InitProgress;
|
||||||
|
_sidecarClass.UpdateProgressEvent += UpdateProgress;
|
||||||
|
_sidecarClass.EndProgressEvent += EndProgress;
|
||||||
|
_sidecarClass.InitProgressEvent2 += InitProgress2;
|
||||||
|
_sidecarClass.UpdateProgressEvent2 += UpdateProgress2;
|
||||||
|
_sidecarClass.EndProgressEvent2 += EndProgress2;
|
||||||
|
_sidecarClass.UpdateStatusEvent += UpdateStatus;
|
||||||
|
CICMMetadataType sidecar = _sidecarClass.Create();
|
||||||
|
|
||||||
|
if(_preSidecar != null)
|
||||||
{
|
{
|
||||||
preSidecar.BlockMedia = sidecar.BlockMedia;
|
_preSidecar.BlockMedia = sidecar.BlockMedia;
|
||||||
sidecar = preSidecar;
|
sidecar = _preSidecar;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dev.IsUsb &&
|
if(_dev.IsUsb &&
|
||||||
dev.UsbDescriptors != null)
|
_dev.UsbDescriptors != null)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Reading USB descriptors.");
|
_dumpLog.WriteLine("Reading USB descriptors.");
|
||||||
UpdateStatus?.Invoke("Reading USB descriptors.");
|
UpdateStatus?.Invoke("Reading USB descriptors.");
|
||||||
ret = outputPlugin.WriteMediaTag(dev.UsbDescriptors, MediaTagType.USB_Descriptors);
|
ret = _outputPlugin.WriteMediaTag(_dev.UsbDescriptors, MediaTagType.USB_Descriptors);
|
||||||
|
|
||||||
if(ret)
|
if(ret)
|
||||||
sidecar.BlockMedia[0].USB = new USBType
|
sidecar.BlockMedia[0].USB = new USBType
|
||||||
{
|
{
|
||||||
ProductID = dev.UsbProductId, VendorID = dev.UsbVendorId, Descriptors = new DumpType
|
ProductID = _dev.UsbProductId, VendorID = _dev.UsbVendorId, Descriptors =
|
||||||
{
|
new DumpType
|
||||||
Image = outputPath, Size = (ulong)dev.UsbDescriptors.Length,
|
{
|
||||||
Checksums = Checksum.GetChecksums(dev.UsbDescriptors).ToArray()
|
Image = _outputPath, Size = (ulong)_dev.UsbDescriptors.Length,
|
||||||
}
|
Checksums = Checksum.GetChecksums(_dev.UsbDescriptors).ToArray()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dev.IsPcmcia &&
|
if(_dev.IsPcmcia &&
|
||||||
dev.Cis != null)
|
_dev.Cis != null)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Reading PCMCIA CIS.");
|
_dumpLog.WriteLine("Reading PCMCIA CIS.");
|
||||||
UpdateStatus?.Invoke("Reading PCMCIA CIS.");
|
UpdateStatus?.Invoke("Reading PCMCIA CIS.");
|
||||||
ret = outputPlugin.WriteMediaTag(dev.Cis, MediaTagType.PCMCIA_CIS);
|
ret = _outputPlugin.WriteMediaTag(_dev.Cis, MediaTagType.PCMCIA_CIS);
|
||||||
|
|
||||||
if(ret)
|
if(ret)
|
||||||
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
|
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
|
||||||
{
|
{
|
||||||
CIS = new DumpType
|
CIS = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath, Size = (ulong)dev.Cis.Length,
|
Image = _outputPath, Size = (ulong)_dev.Cis.Length,
|
||||||
Checksums = Checksum.GetChecksums(dev.Cis).ToArray()
|
Checksums = Checksum.GetChecksums(_dev.Cis).ToArray()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dumpLog.WriteLine("Decoding PCMCIA CIS.");
|
_dumpLog.WriteLine("Decoding PCMCIA CIS.");
|
||||||
UpdateStatus?.Invoke("Decoding PCMCIA CIS.");
|
UpdateStatus?.Invoke("Decoding PCMCIA CIS.");
|
||||||
Tuple[] tuples = CIS.GetTuples(dev.Cis);
|
Tuple[] tuples = CIS.GetTuples(_dev.Cis);
|
||||||
|
|
||||||
if(tuples != null)
|
if(tuples != null)
|
||||||
foreach(Tuple tuple in tuples)
|
foreach(Tuple tuple in tuples)
|
||||||
@@ -676,8 +680,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(manfid != null)
|
if(manfid != null)
|
||||||
{
|
{
|
||||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode =
|
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode = manfid.ManufacturerID;
|
||||||
manfid.ManufacturerID;
|
|
||||||
|
|
||||||
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
|
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
|
||||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
|
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
|
||||||
@@ -704,14 +707,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = outputPlugin.WriteMediaTag(ataIdentify, MediaTagType.ATA_IDENTIFY);
|
ret = _outputPlugin.WriteMediaTag(ataIdentify, MediaTagType.ATA_IDENTIFY);
|
||||||
|
|
||||||
if(ret)
|
if(ret)
|
||||||
sidecar.BlockMedia[0].ATA = new ATAType
|
sidecar.BlockMedia[0].ATA = new ATAType
|
||||||
{
|
{
|
||||||
Identify = new DumpType
|
Identify = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath, Size = (ulong)cmdBuf.Length,
|
Image = _outputPath, Size = (ulong)cmdBuf.Length,
|
||||||
Checksums = Checksum.GetChecksums(cmdBuf).ToArray()
|
Checksums = Checksum.GetChecksums(cmdBuf).ToArray()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -722,12 +725,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
UpdateStatus?.Invoke($"Sidecar created in {(chkEnd - chkStart).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Sidecar created in {(chkEnd - chkStart).TotalSeconds} seconds.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average checksum speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
Invoke($"Average checksum speed {((double)blockSize * (double)(blocks + 1)) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
List<(ulong start, string type)> filesystems = new List<(ulong start, string type)>();
|
List<(ulong start, string type)> filesystems = new List<(ulong start, string type)>();
|
||||||
|
|
||||||
@@ -746,15 +750,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Found filesystem {filesystem.type} at sector {filesystem.start}");
|
Invoke($"Found filesystem {filesystem.type} at sector {filesystem.start}");
|
||||||
|
|
||||||
dumpLog.WriteLine("Found filesystem {0} at sector {1}", filesystem.type,
|
_dumpLog.WriteLine("Found filesystem {0} at sector {1}", filesystem.type,
|
||||||
filesystem.start);
|
filesystem.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
(string type, string subType) xmlType;
|
(string type, string subType) xmlType;
|
||||||
|
|
||||||
if(dev.IsCompactFlash)
|
if(_dev.IsCompactFlash)
|
||||||
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.CompactFlash);
|
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.CompactFlash);
|
||||||
else if(dev.IsPcmcia)
|
else if(_dev.IsPcmcia)
|
||||||
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.PCCardTypeI);
|
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.PCCardTypeI);
|
||||||
else
|
else
|
||||||
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD);
|
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD);
|
||||||
@@ -765,9 +769,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
sidecar.BlockMedia[0].LogicalBlocks = blocks;
|
sidecar.BlockMedia[0].LogicalBlocks = blocks;
|
||||||
sidecar.BlockMedia[0].PhysicalBlockSize = physicalsectorsize;
|
sidecar.BlockMedia[0].PhysicalBlockSize = physicalsectorsize;
|
||||||
sidecar.BlockMedia[0].LogicalBlockSize = blockSize;
|
sidecar.BlockMedia[0].LogicalBlockSize = blockSize;
|
||||||
sidecar.BlockMedia[0].Manufacturer = dev.Manufacturer;
|
sidecar.BlockMedia[0].Manufacturer = _dev.Manufacturer;
|
||||||
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 = blocks * blockSize;
|
sidecar.BlockMedia[0].Size = blocks * blockSize;
|
||||||
|
|
||||||
if(cylinders > 0 &&
|
if(cylinders > 0 &&
|
||||||
@@ -784,7 +788,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
UpdateStatus?.Invoke("Writing metadata sidecar");
|
UpdateStatus?.Invoke("Writing metadata sidecar");
|
||||||
|
|
||||||
var xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
var xmlFs = new FileStream(_outputPrefix + ".cicm.xml", FileMode.Create);
|
||||||
|
|
||||||
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
||||||
xmlSer.Serialize(xmlFs, sidecar);
|
xmlSer.Serialize(xmlFs, sidecar);
|
||||||
@@ -797,21 +801,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average speed: {(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
Invoke($"Average speed: {((double)blockSize * (double)(blocks + 1)) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||||
UpdateStatus?.Invoke($"Slowest speed burst: {minSpeed:F3} MiB/sec.");
|
UpdateStatus?.Invoke($"Slowest speed burst: {minSpeed:F3} MiB/sec.");
|
||||||
UpdateStatus?.Invoke($"{resume.BadBlocks.Count} sectors could not be read.");
|
UpdateStatus?.Invoke($"{_resume.BadBlocks.Count} sectors could not be read.");
|
||||||
|
|
||||||
if(resume.BadBlocks.Count > 0)
|
if(_resume.BadBlocks.Count > 0)
|
||||||
resume.BadBlocks.Sort();
|
_resume.BadBlocks.Sort();
|
||||||
|
|
||||||
UpdateStatus?.Invoke("");
|
UpdateStatus?.Invoke("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dev.IsCompactFlash)
|
if(_dev.IsCompactFlash)
|
||||||
Statistics.AddMedia(MediaType.CompactFlash, true);
|
Statistics.AddMedia(MediaType.CompactFlash, true);
|
||||||
else if(dev.IsPcmcia)
|
else if(_dev.IsPcmcia)
|
||||||
Statistics.AddMedia(MediaType.PCCardTypeI, true);
|
Statistics.AddMedia(MediaType.PCCardTypeI, true);
|
||||||
else
|
else
|
||||||
Statistics.AddMedia(MediaType.GENERIC_HDD, true);
|
Statistics.AddMedia(MediaType.GENERIC_HDD, true);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,32 +14,30 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
public partial class Dump
|
public partial class Dump
|
||||||
{
|
{
|
||||||
readonly Device dev;
|
readonly Device _dev;
|
||||||
readonly string devicePath;
|
readonly string _devicePath;
|
||||||
readonly bool doResume;
|
readonly bool _doResume;
|
||||||
readonly DumpLog dumpLog;
|
readonly DumpLog _dumpLog;
|
||||||
readonly bool dumpRaw;
|
readonly bool _dumpRaw;
|
||||||
readonly Encoding encoding;
|
readonly Encoding _encoding;
|
||||||
readonly bool force;
|
readonly bool _force;
|
||||||
readonly Dictionary<string, string> formatOptions;
|
readonly Dictionary<string, string> _formatOptions;
|
||||||
readonly bool nometadata;
|
readonly bool _nometadata;
|
||||||
readonly bool notrim;
|
readonly bool _notrim;
|
||||||
readonly string outputPath;
|
readonly string _outputPath;
|
||||||
readonly IWritableImage outputPlugin;
|
readonly IWritableImage _outputPlugin;
|
||||||
readonly string outputPrefix;
|
readonly string _outputPrefix;
|
||||||
readonly bool persistent;
|
readonly bool _persistent;
|
||||||
readonly CICMMetadataType preSidecar;
|
readonly CICMMetadataType _preSidecar;
|
||||||
readonly ushort retryPasses;
|
readonly ushort _retryPasses;
|
||||||
readonly bool stopOnError;
|
readonly bool _stopOnError;
|
||||||
bool aborted;
|
bool _aborted;
|
||||||
bool dumpFirstTrackPregap;
|
bool _dumpFirstTrackPregap;
|
||||||
Resume resume;
|
Resume _resume;
|
||||||
Sidecar sidecarClass;
|
Sidecar _sidecarClass;
|
||||||
uint skip;
|
uint _skip;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Initializes dumpers</summary>
|
||||||
/// Initializes dumpers
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="doResume">Should resume?</param>
|
/// <param name="doResume">Should resume?</param>
|
||||||
/// <param name="dev">Device</param>
|
/// <param name="dev">Device</param>
|
||||||
/// <param name="devicePath">Path to the device</param>
|
/// <param name="devicePath">Path to the device</param>
|
||||||
@@ -60,130 +58,113 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
/// <param name="preSidecar">Sidecar to store in dumped image</param>
|
/// <param name="preSidecar">Sidecar to store in dumped image</param>
|
||||||
/// <param name="skip">How many sectors to skip reading on error</param>
|
/// <param name="skip">How many sectors to skip reading on error</param>
|
||||||
/// <param name="nometadata">Create metadata sidecar after dump?</param>
|
/// <param name="nometadata">Create metadata sidecar after dump?</param>
|
||||||
public Dump(bool doResume, Device dev, string devicePath,
|
public Dump(bool doResume, Device dev, string devicePath, IWritableImage outputPlugin, ushort retryPasses,
|
||||||
IWritableImage outputPlugin, ushort retryPasses,
|
bool force, bool dumpRaw, bool persistent, bool stopOnError, Resume resume, DumpLog dumpLog,
|
||||||
bool force, bool dumpRaw, bool persistent,
|
Encoding encoding, string outputPrefix, string outputPath, Dictionary<string, string> formatOptions,
|
||||||
bool stopOnError, Resume resume, DumpLog dumpLog,
|
CICMMetadataType preSidecar, uint skip, bool nometadata, bool notrim, bool dumpFirstTrackPregap)
|
||||||
Encoding encoding, string outputPrefix, string outputPath,
|
|
||||||
Dictionary<string, string> formatOptions,
|
|
||||||
CICMMetadataType preSidecar, uint skip, bool nometadata,
|
|
||||||
bool notrim, bool dumpFirstTrackPregap)
|
|
||||||
{
|
{
|
||||||
this.doResume = doResume;
|
_doResume = doResume;
|
||||||
this.dev = dev;
|
_dev = dev;
|
||||||
this.devicePath = devicePath;
|
_devicePath = devicePath;
|
||||||
this.outputPlugin = outputPlugin;
|
_outputPlugin = outputPlugin;
|
||||||
this.retryPasses = retryPasses;
|
_retryPasses = retryPasses;
|
||||||
this.force = force;
|
_force = force;
|
||||||
this.dumpRaw = dumpRaw;
|
_dumpRaw = dumpRaw;
|
||||||
this.persistent = persistent;
|
_persistent = persistent;
|
||||||
this.stopOnError = stopOnError;
|
_stopOnError = stopOnError;
|
||||||
this.resume = resume;
|
_resume = resume;
|
||||||
this.dumpLog = dumpLog;
|
_dumpLog = dumpLog;
|
||||||
this.encoding = encoding;
|
_encoding = encoding;
|
||||||
this.outputPrefix = outputPrefix;
|
_outputPrefix = outputPrefix;
|
||||||
this.outputPath = outputPath;
|
_outputPath = outputPath;
|
||||||
this.formatOptions = formatOptions;
|
_formatOptions = formatOptions;
|
||||||
this.preSidecar = preSidecar;
|
_preSidecar = preSidecar;
|
||||||
this.skip = skip;
|
_skip = skip;
|
||||||
this.nometadata = nometadata;
|
_nometadata = nometadata;
|
||||||
this.notrim = notrim;
|
_notrim = notrim;
|
||||||
this.dumpFirstTrackPregap = dumpFirstTrackPregap;
|
_dumpFirstTrackPregap = dumpFirstTrackPregap;
|
||||||
aborted = false;
|
_aborted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Starts dumping with the stablished fields and autodetecting the device type</summary>
|
||||||
/// Starts dumping with the stablished fields and autodetecting the device type
|
|
||||||
/// </summary>
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if(dev.IsUsb && dev.UsbVendorId == 0x054C &&
|
if(_dev.IsUsb &&
|
||||||
(dev.UsbProductId == 0x01C8 || dev.UsbProductId == 0x01C9 || dev.UsbProductId == 0x02D2))
|
_dev.UsbVendorId == 0x054C &&
|
||||||
|
(_dev.UsbProductId == 0x01C8 || _dev.UsbProductId == 0x01C9 || _dev.UsbProductId == 0x02D2))
|
||||||
PlayStationPortable();
|
PlayStationPortable();
|
||||||
else
|
else
|
||||||
switch(dev.Type)
|
switch(_dev.Type)
|
||||||
{
|
{
|
||||||
case DeviceType.ATA:
|
case DeviceType.ATA:
|
||||||
Ata();
|
Ata();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DeviceType.MMC:
|
case DeviceType.MMC:
|
||||||
case DeviceType.SecureDigital:
|
case DeviceType.SecureDigital:
|
||||||
SecureDigital();
|
SecureDigital();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DeviceType.NVMe:
|
case DeviceType.NVMe:
|
||||||
NVMe();
|
NVMe();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DeviceType.ATAPI:
|
case DeviceType.ATAPI:
|
||||||
case DeviceType.SCSI:
|
case DeviceType.SCSI:
|
||||||
Scsi();
|
Scsi();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dumpLog.WriteLine("Unknown device type.");
|
_dumpLog.WriteLine("Unknown device type.");
|
||||||
dumpLog.Close();
|
_dumpLog.Close();
|
||||||
StoppingErrorMessage?.Invoke("Unknown device type.");
|
StoppingErrorMessage?.Invoke("Unknown device type.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.Close();
|
_dumpLog.Close();
|
||||||
|
|
||||||
if(resume == null || !doResume) return;
|
if(_resume == null ||
|
||||||
|
!_doResume)
|
||||||
|
return;
|
||||||
|
|
||||||
resume.LastWriteDate = DateTime.UtcNow;
|
_resume.LastWriteDate = DateTime.UtcNow;
|
||||||
resume.BadBlocks.Sort();
|
_resume.BadBlocks.Sort();
|
||||||
|
|
||||||
if(File.Exists(outputPrefix + ".resume.xml")) File.Delete(outputPrefix + ".resume.xml");
|
if(File.Exists(_outputPrefix + ".resume.xml"))
|
||||||
|
File.Delete(_outputPrefix + ".resume.xml");
|
||||||
|
|
||||||
FileStream fs = new FileStream(outputPrefix + ".resume.xml", FileMode.Create, FileAccess.ReadWrite);
|
var fs = new FileStream(_outputPrefix + ".resume.xml", FileMode.Create, FileAccess.ReadWrite);
|
||||||
XmlSerializer xs = new XmlSerializer(resume.GetType());
|
var xs = new XmlSerializer(_resume.GetType());
|
||||||
xs.Serialize(fs, resume);
|
xs.Serialize(fs, _resume);
|
||||||
fs.Close();
|
fs.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Abort()
|
public void Abort()
|
||||||
{
|
{
|
||||||
aborted = true;
|
_aborted = true;
|
||||||
sidecarClass?.Abort();
|
_sidecarClass?.Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Event raised when the progress bar is not longer needed</summary>
|
||||||
/// Event raised when the progress bar is not longer needed
|
|
||||||
/// </summary>
|
|
||||||
public event EndProgressHandler EndProgress;
|
public event EndProgressHandler EndProgress;
|
||||||
/// <summary>
|
/// <summary>Event raised when a progress bar is needed</summary>
|
||||||
/// Event raised when a progress bar is needed
|
|
||||||
/// </summary>
|
|
||||||
public event InitProgressHandler InitProgress;
|
public event InitProgressHandler InitProgress;
|
||||||
/// <summary>
|
/// <summary>Event raised to report status updates</summary>
|
||||||
/// Event raised to report status updates
|
|
||||||
/// </summary>
|
|
||||||
public event UpdateStatusHandler UpdateStatus;
|
public event UpdateStatusHandler UpdateStatus;
|
||||||
/// <summary>
|
/// <summary>Event raised to report a non-fatal error</summary>
|
||||||
/// Event raised to report a non-fatal error
|
|
||||||
/// </summary>
|
|
||||||
public event ErrorMessageHandler ErrorMessage;
|
public event ErrorMessageHandler ErrorMessage;
|
||||||
/// <summary>
|
/// <summary>Event raised to report a fatal error that stops the dumping operation and should call user's attention</summary>
|
||||||
/// Event raised to report a fatal error that stops the dumping operation and should call user's attention
|
|
||||||
/// </summary>
|
|
||||||
public event ErrorMessageHandler StoppingErrorMessage;
|
public event ErrorMessageHandler StoppingErrorMessage;
|
||||||
/// <summary>
|
/// <summary>Event raised to update the values of a determinate progress bar</summary>
|
||||||
/// Event raised to update the values of a determinate progress bar
|
|
||||||
/// </summary>
|
|
||||||
public event UpdateProgressHandler UpdateProgress;
|
public event UpdateProgressHandler UpdateProgress;
|
||||||
/// <summary>
|
/// <summary>Event raised to update the status of an undeterminate progress bar</summary>
|
||||||
/// Event raised to update the status of an undeterminate progress bar
|
|
||||||
/// </summary>
|
|
||||||
public event PulseProgressHandler PulseProgress;
|
public event PulseProgressHandler PulseProgress;
|
||||||
/// <summary>
|
/// <summary>Event raised when the progress bar is not longer needed</summary>
|
||||||
/// Event raised when the progress bar is not longer needed
|
|
||||||
/// </summary>
|
|
||||||
public event EndProgressHandler2 EndProgress2;
|
public event EndProgressHandler2 EndProgress2;
|
||||||
/// <summary>
|
/// <summary>Event raised when a progress bar is needed</summary>
|
||||||
/// Event raised when a progress bar is needed
|
|
||||||
/// </summary>
|
|
||||||
public event InitProgressHandler2 InitProgress2;
|
public event InitProgressHandler2 InitProgress2;
|
||||||
/// <summary>
|
/// <summary>Event raised to update the values of a determinate progress bar</summary>
|
||||||
/// Event raised to update the values of a determinate progress bar
|
|
||||||
/// </summary>
|
|
||||||
public event UpdateProgressHandler2 UpdateProgress2;
|
public event UpdateProgressHandler2 UpdateProgress2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,13 +58,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
bool isXbox = false;
|
bool isXbox = false;
|
||||||
|
|
||||||
// TODO: Log not only what is it reading, but if it was read correctly or not.
|
// TODO: Log not only what is it reading, but if it was read correctly or not.
|
||||||
sense = dev.GetConfiguration(out byte[] cmdBuf, out _, 0, MmcGetConfigurationRt.Current, dev.Timeout,
|
sense = _dev.GetConfiguration(out byte[] cmdBuf, out _, 0, MmcGetConfigurationRt.Current, _dev.Timeout,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
Features.SeparatedFeatures ftr = Features.Separate(cmdBuf);
|
Features.SeparatedFeatures ftr = Features.Separate(cmdBuf);
|
||||||
dumpLog.WriteLine("Device reports current profile is 0x{0:X4}", ftr.CurrentProfile);
|
_dumpLog.WriteLine("Device reports current profile is 0x{0:X4}", ftr.CurrentProfile);
|
||||||
|
|
||||||
switch(ftr.CurrentProfile)
|
switch(ftr.CurrentProfile)
|
||||||
{
|
{
|
||||||
@@ -176,9 +176,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw);
|
var scsiReader = new Reader(_dev, _dev.Timeout, null, _dumpRaw);
|
||||||
ulong blocks = scsiReader.GetDeviceBlocks();
|
ulong blocks = scsiReader.GetDeviceBlocks();
|
||||||
dumpLog.WriteLine("Device reports disc has {0} blocks", blocks);
|
_dumpLog.WriteLine("Device reports disc has {0} blocks", blocks);
|
||||||
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>();
|
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>();
|
||||||
|
|
||||||
if(dskType == MediaType.PD650)
|
if(dskType == MediaType.PD650)
|
||||||
@@ -208,10 +208,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
switch(dskType)
|
switch(dskType)
|
||||||
{
|
{
|
||||||
case MediaType.Unknown when blocks > 0:
|
case MediaType.Unknown when blocks > 0:
|
||||||
dumpLog.WriteLine("Reading Physical Format Information");
|
_dumpLog.WriteLine("Reading Physical Format Information");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.PhysicalInformation, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -221,7 +221,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo &&
|
if(nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo &&
|
||||||
nintendoPfi.Value.PartVersion == 15)
|
nintendoPfi.Value.PartVersion == 15)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
_dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
||||||
|
|
||||||
StoppingErrorMessage?.
|
StoppingErrorMessage?.
|
||||||
Invoke("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
Invoke("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
||||||
@@ -248,10 +248,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case MediaType.HDDVDROM:
|
case MediaType.HDDVDROM:
|
||||||
case MediaType.HDDVDRW:
|
case MediaType.HDDVDRW:
|
||||||
case MediaType.HDDVDRWDL:
|
case MediaType.HDDVDRWDL:
|
||||||
dumpLog.WriteLine("Reading Physical Format Information");
|
_dumpLog.WriteLine("Reading Physical Format Information");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.PhysicalInformation, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
if(PFI.Decode(cmdBuf).HasValue)
|
if(PFI.Decode(cmdBuf).HasValue)
|
||||||
@@ -326,11 +326,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading Disc Manufacturing Information");
|
_dumpLog.WriteLine("Reading Disc Manufacturing Information");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout,
|
MmcDiscStructureFormat.DiscManufacturingInformation, 0, _dev.Timeout,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -352,13 +352,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
dskType = MediaType.XGD3;
|
dskType = MediaType.XGD3;
|
||||||
}
|
}
|
||||||
|
|
||||||
sense = dev.ScsiInquiry(out byte[] inqBuf, out _);
|
sense = _dev.ScsiInquiry(out byte[] inqBuf, out _);
|
||||||
|
|
||||||
if(sense ||
|
if(sense ||
|
||||||
!Inquiry.Decode(inqBuf).HasValue ||
|
!Inquiry.Decode(inqBuf).HasValue ||
|
||||||
(Inquiry.Decode(inqBuf).HasValue && !Inquiry.Decode(inqBuf).Value.KreonPresent))
|
(Inquiry.Decode(inqBuf).HasValue && !Inquiry.Decode(inqBuf).Value.KreonPresent))
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
_dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
||||||
|
|
||||||
StoppingErrorMessage?.
|
StoppingErrorMessage?.
|
||||||
Invoke("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
Invoke("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
||||||
@@ -366,7 +366,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dumpRaw && !force)
|
if(_dumpRaw && !_force)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.
|
StoppingErrorMessage?.
|
||||||
Invoke("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
|
Invoke("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
|
||||||
@@ -397,10 +397,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(dskType == MediaType.DVDDownload ||
|
if(dskType == MediaType.DVDDownload ||
|
||||||
dskType == MediaType.DVDROM)
|
dskType == MediaType.DVDROM)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
_dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.CopyrightInformation, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
if(CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue)
|
if(CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue)
|
||||||
@@ -418,10 +418,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case MediaType.DVDDownload:
|
case MediaType.DVDDownload:
|
||||||
case MediaType.DVDROM:
|
case MediaType.DVDROM:
|
||||||
case MediaType.HDDVDROM:
|
case MediaType.HDDVDROM:
|
||||||
dumpLog.WriteLine("Reading Burst Cutting Area.");
|
_dumpLog.WriteLine("Reading Burst Cutting Area.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.BurstCuttingArea, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -436,10 +436,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
#region DVD-RAM and HD DVD-RAM
|
#region DVD-RAM and HD DVD-RAM
|
||||||
case MediaType.DVDRAM:
|
case MediaType.DVDRAM:
|
||||||
case MediaType.HDDVDRAM:
|
case MediaType.HDDVDRAM:
|
||||||
dumpLog.WriteLine("Reading Disc Description Structure.");
|
_dumpLog.WriteLine("Reading Disc Description Structure.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.DvdramDds, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
if(DDS.Decode(cmdBuf).HasValue)
|
if(DDS.Decode(cmdBuf).HasValue)
|
||||||
@@ -449,11 +449,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
mediaTags.Add(MediaTagType.DVDRAM_DDS, tmpBuf);
|
mediaTags.Add(MediaTagType.DVDRAM_DDS, tmpBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading Spare Area Information.");
|
_dumpLog.WriteLine("Reading Spare Area Information.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout,
|
MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, _dev.Timeout,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
if(Spare.Decode(cmdBuf).HasValue)
|
if(Spare.Decode(cmdBuf).HasValue)
|
||||||
@@ -469,10 +469,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
#region DVD-R and DVD-RW
|
#region DVD-R and DVD-RW
|
||||||
case MediaType.DVDR:
|
case MediaType.DVDR:
|
||||||
case MediaType.DVDRW:
|
case MediaType.DVDRW:
|
||||||
dumpLog.WriteLine("Reading Pre-Recorded Information.");
|
_dumpLog.WriteLine("Reading Pre-Recorded Information.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.PreRecordedInfo, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -491,10 +491,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case MediaType.DVDR:
|
case MediaType.DVDR:
|
||||||
case MediaType.DVDRW:
|
case MediaType.DVDRW:
|
||||||
case MediaType.HDDVDR:
|
case MediaType.HDDVDR:
|
||||||
dumpLog.WriteLine("Reading Media Identifier.");
|
_dumpLog.WriteLine("Reading Media Identifier.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.DvdrMediaIdentifier, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.DvdrMediaIdentifier, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -503,11 +503,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
mediaTags.Add(MediaTagType.DVDR_MediaIdentifier, tmpBuf);
|
mediaTags.Add(MediaTagType.DVDR_MediaIdentifier, tmpBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading Recordable Physical Information.");
|
_dumpLog.WriteLine("Reading Recordable Physical Information.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.DvdrPhysicalInformation, 0, dev.Timeout,
|
MmcDiscStructureFormat.DvdrPhysicalInformation, 0, _dev.Timeout,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -524,10 +524,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case MediaType.DVDPRDL:
|
case MediaType.DVDPRDL:
|
||||||
case MediaType.DVDPRW:
|
case MediaType.DVDPRW:
|
||||||
case MediaType.DVDPRWDL:
|
case MediaType.DVDPRWDL:
|
||||||
dumpLog.WriteLine("Reading ADdress In Pregroove.");
|
_dumpLog.WriteLine("Reading ADdress In Pregroove.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.Adip, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.Adip, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -536,10 +536,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
mediaTags.Add(MediaTagType.DVD_ADIP, tmpBuf);
|
mediaTags.Add(MediaTagType.DVD_ADIP, tmpBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading Disc Control Blocks.");
|
_dumpLog.WriteLine("Reading Disc Control Blocks.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.Dcb, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.Dcb, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -553,11 +553,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
#region HD DVD-ROM
|
#region HD DVD-ROM
|
||||||
case MediaType.HDDVDROM:
|
case MediaType.HDDVDROM:
|
||||||
dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
_dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
|
||||||
MmcDiscStructureFormat.HddvdCopyrightInformation, 0, dev.Timeout,
|
MmcDiscStructureFormat.HddvdCopyrightInformation, 0, _dev.Timeout,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -575,10 +575,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case MediaType.BDROM:
|
case MediaType.BDROM:
|
||||||
case MediaType.BDRXL:
|
case MediaType.BDRXL:
|
||||||
case MediaType.BDREXL:
|
case MediaType.BDREXL:
|
||||||
dumpLog.WriteLine("Reading Disc Information.");
|
_dumpLog.WriteLine("Reading Disc Information.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
||||||
MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.DiscInformation, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
if(DI.Decode(cmdBuf).HasValue)
|
if(DI.Decode(cmdBuf).HasValue)
|
||||||
@@ -607,10 +607,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
#region BD-ROM only
|
#region BD-ROM only
|
||||||
case MediaType.BDROM:
|
case MediaType.BDROM:
|
||||||
dumpLog.WriteLine("Reading Burst Cutting Area.");
|
_dumpLog.WriteLine("Reading Burst Cutting Area.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
||||||
MmcDiscStructureFormat.BdBurstCuttingArea, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.BdBurstCuttingArea, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -627,10 +627,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case MediaType.BDRE:
|
case MediaType.BDRE:
|
||||||
case MediaType.BDRXL:
|
case MediaType.BDRXL:
|
||||||
case MediaType.BDREXL:
|
case MediaType.BDREXL:
|
||||||
dumpLog.WriteLine("Reading Disc Definition Structure.");
|
_dumpLog.WriteLine("Reading Disc Definition Structure.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
||||||
MmcDiscStructureFormat.BdDds, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.BdDds, 0, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -639,10 +639,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
mediaTags.Add(MediaTagType.BD_DDS, tmpBuf);
|
mediaTags.Add(MediaTagType.BD_DDS, tmpBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpLog.WriteLine("Reading Spare Area Information.");
|
_dumpLog.WriteLine("Reading Spare Area Information.");
|
||||||
|
|
||||||
sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0,
|
||||||
MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, out _);
|
MmcDiscStructureFormat.BdSpareAreaInformation, 0, _dev.Timeout,
|
||||||
|
out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -37,59 +37,66 @@ using DiscImageChef.Decoders.SCSI;
|
|||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Dumping
|
namespace DiscImageChef.Core.Devices.Dumping
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Implements dumping SCSI and ATAPI devices</summary>
|
||||||
/// Implements dumping SCSI and ATAPI devices
|
|
||||||
/// </summary>
|
|
||||||
public partial class Dump
|
public partial class Dump
|
||||||
{
|
{
|
||||||
// TODO: Get cartridge serial number from Certance vendor EVPD
|
// TODO: Get cartridge serial number from Certance vendor EVPD
|
||||||
/// <summary>
|
/// <summary>Dumps a SCSI Block Commands device or a Reduced Block Commands devices</summary>
|
||||||
/// Dumps a SCSI Block Commands device or a Reduced Block Commands devices
|
|
||||||
/// </summary>
|
|
||||||
public void Scsi()
|
public void Scsi()
|
||||||
{
|
{
|
||||||
MediaType dskType = MediaType.Unknown;
|
MediaType dskType = MediaType.Unknown;
|
||||||
int resets = 0;
|
int resets = 0;
|
||||||
|
|
||||||
if(dev.IsRemovable)
|
if(_dev.IsRemovable)
|
||||||
{
|
{
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
deviceGotReset:
|
deviceGotReset:
|
||||||
bool sense = dev.ScsiTestUnitReady(out byte[] senseBuf, dev.Timeout, out _);
|
bool sense = _dev.ScsiTestUnitReady(out byte[] senseBuf, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
FixedSense? decSense = Sense.DecodeFixed(senseBuf);
|
FixedSense? decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
{
|
{
|
||||||
ErrorMessage
|
ErrorMessage?.
|
||||||
?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||||
dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h",
|
|
||||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
_dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h",
|
||||||
|
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||||
|
|
||||||
// Just retry, for 5 times
|
// Just retry, for 5 times
|
||||||
if(decSense.Value.ASC == 0x29)
|
if(decSense.Value.ASC == 0x29)
|
||||||
{
|
{
|
||||||
resets++;
|
resets++;
|
||||||
if(resets < 5) goto deviceGotReset;
|
|
||||||
|
if(resets < 5)
|
||||||
|
goto deviceGotReset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(decSense.Value.ASC == 0x3A)
|
if(decSense.Value.ASC == 0x3A)
|
||||||
{
|
{
|
||||||
int leftRetries = 5;
|
int leftRetries = 5;
|
||||||
|
|
||||||
while(leftRetries > 0)
|
while(leftRetries > 0)
|
||||||
{
|
{
|
||||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||||
if(!sense) break;
|
|
||||||
|
if(!sense)
|
||||||
|
break;
|
||||||
|
|
||||||
decSense = Sense.DecodeFixed(senseBuf);
|
decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
{
|
{
|
||||||
ErrorMessage
|
ErrorMessage?.
|
||||||
?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||||
dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h",
|
|
||||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
_dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h",
|
||||||
|
decSense.Value.SenseKey, decSense.Value.ASC,
|
||||||
|
decSense.Value.ASCQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
leftRetries--;
|
leftRetries--;
|
||||||
@@ -98,26 +105,34 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Please insert media in drive");
|
StoppingErrorMessage?.Invoke("Please insert media in drive");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01)
|
else if(decSense.Value.ASC == 0x04 &&
|
||||||
|
decSense.Value.ASCQ == 0x01)
|
||||||
{
|
{
|
||||||
int leftRetries = 50;
|
int leftRetries = 50;
|
||||||
|
|
||||||
while(leftRetries > 0)
|
while(leftRetries > 0)
|
||||||
{
|
{
|
||||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||||
if(!sense) break;
|
|
||||||
|
if(!sense)
|
||||||
|
break;
|
||||||
|
|
||||||
decSense = Sense.DecodeFixed(senseBuf);
|
decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
{
|
{
|
||||||
ErrorMessage
|
ErrorMessage?.
|
||||||
?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
|
||||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
_dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||||
|
decSense.Value.SenseKey, decSense.Value.ASC,
|
||||||
|
decSense.Value.ASCQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
leftRetries--;
|
leftRetries--;
|
||||||
@@ -125,8 +140,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,20 +163,26 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
else if(decSense.Value.ASC == 0x28)
|
else if(decSense.Value.ASC == 0x28)
|
||||||
{
|
{
|
||||||
int leftRetries = 10;
|
int leftRetries = 10;
|
||||||
|
|
||||||
while(leftRetries > 0)
|
while(leftRetries > 0)
|
||||||
{
|
{
|
||||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||||
if(!sense) break;
|
|
||||||
|
if(!sense)
|
||||||
|
break;
|
||||||
|
|
||||||
decSense = Sense.DecodeFixed(senseBuf);
|
decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
{
|
{
|
||||||
ErrorMessage
|
ErrorMessage?.
|
||||||
?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
|
||||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
_dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||||
|
decSense.Value.SenseKey, decSense.Value.ASC,
|
||||||
|
decSense.Value.ASCQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
leftRetries--;
|
leftRetries--;
|
||||||
@@ -168,21 +190,24 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Unknown testing unit was ready.");
|
StoppingErrorMessage?.Invoke("Unknown testing unit was ready.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,28 +215,34 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev.ScsiType)
|
switch(_dev.ScsiType)
|
||||||
{
|
{
|
||||||
case PeripheralDeviceTypes.SequentialAccess:
|
case PeripheralDeviceTypes.SequentialAccess:
|
||||||
if(dumpRaw)
|
if(_dumpRaw)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Tapes cannot be dumped raw.");
|
StoppingErrorMessage?.Invoke("Tapes cannot be dumped raw.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(outputPlugin is IWritableTapeImage) Ssc();
|
if(_outputPlugin is IWritableTapeImage)
|
||||||
|
Ssc();
|
||||||
else
|
else
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke("The specified plugin does not support storing streaming tape images.");
|
Invoke("The specified plugin does not support storing streaming tape images.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case PeripheralDeviceTypes.MultiMediaDevice:
|
case PeripheralDeviceTypes.MultiMediaDevice:
|
||||||
if(outputPlugin is IWritableOpticalImage) Mmc(ref dskType);
|
if(_outputPlugin is IWritableOpticalImage)
|
||||||
|
Mmc(ref dskType);
|
||||||
else
|
else
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke("The specified plugin does not support storing optical disc images.");
|
Invoke("The specified plugin does not support storing optical disc images.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
Sbc(null, ref dskType, false);
|
Sbc(null, ref dskType, false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -53,9 +53,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
/// <summary>Dumps a MultiMediaCard or SecureDigital flash card</summary>
|
/// <summary>Dumps a MultiMediaCard or SecureDigital flash card</summary>
|
||||||
public void SecureDigital()
|
public void SecureDigital()
|
||||||
{
|
{
|
||||||
if(dumpRaw)
|
if(_dumpRaw)
|
||||||
{
|
{
|
||||||
if(force)
|
if(_force)
|
||||||
ErrorMessage?.
|
ErrorMessage?.
|
||||||
Invoke("Raw dumping is not supported in MultiMediaCard or SecureDigital devices. Continuing...");
|
Invoke("Raw dumping is not supported in MultiMediaCard or SecureDigital devices. Continuing...");
|
||||||
else
|
else
|
||||||
@@ -84,13 +84,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>();
|
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>();
|
||||||
|
|
||||||
switch(dev.Type)
|
switch(_dev.Type)
|
||||||
{
|
{
|
||||||
case DeviceType.MMC:
|
case DeviceType.MMC:
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke("Reading Extended CSD");
|
UpdateStatus?.Invoke("Reading Extended CSD");
|
||||||
dumpLog.WriteLine("Reading Extended CSD");
|
_dumpLog.WriteLine("Reading Extended CSD");
|
||||||
sense = dev.ReadExtendedCsd(out ecsd, out _, TIMEOUT, out duration);
|
sense = _dev.ReadExtendedCsd(out ecsd, out _, TIMEOUT, out duration);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -112,8 +112,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
ecsd = null;
|
ecsd = null;
|
||||||
|
|
||||||
UpdateStatus?.Invoke("Reading CSD");
|
UpdateStatus?.Invoke("Reading CSD");
|
||||||
dumpLog.WriteLine("Reading CSD");
|
_dumpLog.WriteLine("Reading CSD");
|
||||||
sense = dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
|
sense = _dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -130,8 +130,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
csd = null;
|
csd = null;
|
||||||
|
|
||||||
UpdateStatus?.Invoke("Reading OCR");
|
UpdateStatus?.Invoke("Reading OCR");
|
||||||
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)
|
if(sense)
|
||||||
ocr = null;
|
ocr = null;
|
||||||
@@ -144,8 +144,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
case DeviceType.SecureDigital:
|
case DeviceType.SecureDigital:
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke("Reading CSD");
|
UpdateStatus?.Invoke("Reading CSD");
|
||||||
dumpLog.WriteLine("Reading CSD");
|
_dumpLog.WriteLine("Reading CSD");
|
||||||
sense = dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
|
sense = _dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
@@ -165,8 +165,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
csd = null;
|
csd = null;
|
||||||
|
|
||||||
UpdateStatus?.Invoke("Reading OCR");
|
UpdateStatus?.Invoke("Reading OCR");
|
||||||
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)
|
if(sense)
|
||||||
ocr = null;
|
ocr = null;
|
||||||
@@ -174,8 +174,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
mediaTags.Add(MediaTagType.SD_OCR, null);
|
mediaTags.Add(MediaTagType.SD_OCR, null);
|
||||||
|
|
||||||
UpdateStatus?.Invoke("Reading SCR");
|
UpdateStatus?.Invoke("Reading SCR");
|
||||||
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)
|
if(sense)
|
||||||
scr = null;
|
scr = null;
|
||||||
@@ -187,13 +187,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateStatus?.Invoke("Reading CID");
|
UpdateStatus?.Invoke("Reading CID");
|
||||||
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)
|
if(sense)
|
||||||
cid = null;
|
cid = null;
|
||||||
else
|
else
|
||||||
mediaTags.Add(dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID : MediaTagType.MMC_CID, null);
|
mediaTags.Add(_dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID : MediaTagType.MMC_CID, null);
|
||||||
|
|
||||||
DateTime start;
|
DateTime start;
|
||||||
DateTime end;
|
DateTime end;
|
||||||
@@ -204,21 +204,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(blocks == 0)
|
if(blocks == 0)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Unable to get device size.");
|
_dumpLog.WriteLine("Unable to get device size.");
|
||||||
StoppingErrorMessage?.Invoke("Unable to get device size.");
|
StoppingErrorMessage?.Invoke("Unable to get device size.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Device reports {blocks} blocks.");
|
UpdateStatus?.Invoke($"Device reports {blocks} blocks.");
|
||||||
dumpLog.WriteLine("Device reports {0} blocks.", blocks);
|
_dumpLog.WriteLine("Device reports {0} blocks.", blocks);
|
||||||
|
|
||||||
byte[] cmdBuf;
|
byte[] cmdBuf;
|
||||||
bool error;
|
bool error;
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
error = dev.Read(out cmdBuf, out _, 0, blockSize, blocksToRead, byteAddressed, TIMEOUT, out duration);
|
error = _dev.Read(out cmdBuf, out _, 0, blockSize, blocksToRead, byteAddressed, TIMEOUT, out duration);
|
||||||
|
|
||||||
if(error)
|
if(error)
|
||||||
blocksToRead /= 2;
|
blocksToRead /= 2;
|
||||||
@@ -230,23 +230,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
if(error)
|
if(error)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read, device error {0}.", dev.LastError);
|
_dumpLog.WriteLine("ERROR: Cannot get blocks to read, device error {0}.", _dev.LastError);
|
||||||
StoppingErrorMessage?.Invoke($"Device error {dev.LastError} trying to guess ideal transfer length.");
|
StoppingErrorMessage?.Invoke($"Device error {_dev.LastError} trying to guess ideal transfer length.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");
|
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");
|
||||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
_dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||||
|
|
||||||
if(skip < blocksToRead)
|
if(_skip < blocksToRead)
|
||||||
skip = blocksToRead;
|
_skip = blocksToRead;
|
||||||
|
|
||||||
DumpHardwareType currentTry = null;
|
DumpHardwareType currentTry = null;
|
||||||
ExtentsULong extents = null;
|
ExtentsULong extents = null;
|
||||||
|
|
||||||
ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformId,
|
ResumeSupport.Process(true, false, blocks, _dev.Manufacturer, _dev.Model, _dev.Serial, _dev.PlatformId,
|
||||||
ref resume, ref currentTry, ref extents);
|
ref _resume, ref currentTry, ref extents);
|
||||||
|
|
||||||
if(currentTry == null ||
|
if(currentTry == null ||
|
||||||
extents == null)
|
extents == null)
|
||||||
@@ -260,53 +260,53 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
foreach(MediaTagType tag in mediaTags.Keys)
|
foreach(MediaTagType tag in mediaTags.Keys)
|
||||||
{
|
{
|
||||||
if(outputPlugin.SupportedMediaTags.Contains(tag))
|
if(_outputPlugin.SupportedMediaTags.Contains(tag))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = false;
|
ret = false;
|
||||||
dumpLog.WriteLine($"Output format does not support {tag}.");
|
_dumpLog.WriteLine($"Output format does not support {tag}.");
|
||||||
ErrorMessage?.Invoke($"Output format does not support {tag}.");
|
ErrorMessage?.Invoke($"Output format does not support {tag}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ret)
|
if(!ret)
|
||||||
{
|
{
|
||||||
if(force)
|
if(_force)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Several media tags not supported, continuing...");
|
_dumpLog.WriteLine("Several media tags not supported, continuing...");
|
||||||
ErrorMessage?.Invoke("Several media tags not supported, continuing...");
|
ErrorMessage?.Invoke("Several media tags not supported, continuing...");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Several media tags not supported, not continuing...");
|
_dumpLog.WriteLine("Several media tags not supported, not continuing...");
|
||||||
StoppingErrorMessage?.Invoke("Several media tags not supported, not continuing...");
|
StoppingErrorMessage?.Invoke("Several media tags not supported, not continuing...");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
var mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, blocksToRead);
|
||||||
var ibgLog = new IbgLog(outputPrefix + ".ibg", SD_PROFILE);
|
var ibgLog = new IbgLog(_outputPrefix + ".ibg", SD_PROFILE);
|
||||||
|
|
||||||
ret = outputPlugin.Create(outputPath,
|
ret = _outputPlugin.Create(_outputPath,
|
||||||
dev.Type == DeviceType.SecureDigital ? MediaType.SecureDigital : MediaType.MMC,
|
_dev.Type == DeviceType.SecureDigital ? MediaType.SecureDigital : MediaType.MMC,
|
||||||
formatOptions, blocks, blockSize);
|
_formatOptions, blocks, blockSize);
|
||||||
|
|
||||||
// Cannot create image
|
// Cannot create image
|
||||||
if(!ret)
|
if(!ret)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Error creating output image, not continuing.");
|
_dumpLog.WriteLine("Error creating output image, not continuing.");
|
||||||
dumpLog.WriteLine(outputPlugin.ErrorMessage);
|
_dumpLog.WriteLine(_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Error creating output image, not continuing." + Environment.NewLine +
|
StoppingErrorMessage?.Invoke("Error creating output image, not continuing." + Environment.NewLine +
|
||||||
outputPlugin.ErrorMessage);
|
_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resume.NextBlock > 0)
|
if(_resume.NextBlock > 0)
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke($"Resuming from block {resume.NextBlock}.");
|
UpdateStatus?.Invoke($"Resuming from block {_resume.NextBlock}.");
|
||||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
_dumpLog.WriteLine("Resuming from block {0}.", _resume.NextBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
@@ -317,13 +317,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
for(ulong i = _resume.NextBlock; i < blocks; i += blocksToRead)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -344,46 +344,46 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
|
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
|
||||||
(long)blocks);
|
(long)blocks);
|
||||||
|
|
||||||
error = dev.Read(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, byteAddressed, TIMEOUT,
|
error = _dev.Read(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, byteAddressed, TIMEOUT,
|
||||||
out duration);
|
out duration);
|
||||||
|
|
||||||
if(!error)
|
if(!error)
|
||||||
{
|
{
|
||||||
mhddLog.Write(i, duration);
|
mhddLog.Write(i, duration);
|
||||||
ibgLog.Write(i, currentSpeed * 1024);
|
ibgLog.Write(i, currentSpeed * 1024);
|
||||||
DateTime writeStart = DateTime.Now;
|
DateTime writeStart = DateTime.Now;
|
||||||
outputPlugin.WriteSectors(cmdBuf, i, blocksToRead);
|
_outputPlugin.WriteSectors(cmdBuf, i, blocksToRead);
|
||||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||||
extents.Add(i, blocksToRead, true);
|
extents.Add(i, blocksToRead, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(i + skip > blocks)
|
if(i + _skip > blocks)
|
||||||
skip = (uint)(blocks - i);
|
_skip = (uint)(blocks - i);
|
||||||
|
|
||||||
for(ulong b = i; b < i + skip; b++)
|
for(ulong b = i; b < i + _skip; b++)
|
||||||
resume.BadBlocks.Add(b);
|
_resume.BadBlocks.Add(b);
|
||||||
|
|
||||||
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
||||||
|
|
||||||
ibgLog.Write(i, 0);
|
ibgLog.Write(i, 0);
|
||||||
DateTime writeStart = DateTime.Now;
|
DateTime writeStart = DateTime.Now;
|
||||||
outputPlugin.WriteSectors(new byte[blockSize * skip], i, skip);
|
_outputPlugin.WriteSectors(new byte[blockSize * _skip], i, _skip);
|
||||||
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;
|
newTrim = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sectorSpeedStart += blocksToRead;
|
sectorSpeedStart += blocksToRead;
|
||||||
resume.NextBlock = i + blocksToRead;
|
_resume.NextBlock = i + blocksToRead;
|
||||||
|
|
||||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||||
|
|
||||||
if(elapsed < 1)
|
if(elapsed < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||||
sectorSpeedStart = 0;
|
sectorSpeedStart = 0;
|
||||||
timeSpeedStart = DateTime.UtcNow;
|
timeSpeedStart = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -392,76 +392,76 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
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) / 1024 / (totalDuration / 1000),
|
(blockSize * (double)(blocks + 1)) / 1024 / (totalDuration / 1000),
|
||||||
devicePath);
|
_devicePath);
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
Invoke($"Average dump speed {((double)blockSize * (double)(blocks + 1)) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average write speed {(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
Invoke($"Average write speed {((double)blockSize * (double)(blocks + 1)) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||||
|
|
||||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
_dumpLog.WriteLine("Dump finished in {0} seconds.", (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 Trimming
|
#region Trimming
|
||||||
if(resume.BadBlocks.Count > 0 &&
|
if(_resume.BadBlocks.Count > 0 &&
|
||||||
!aborted &&
|
!_aborted &&
|
||||||
!notrim &&
|
!_notrim &&
|
||||||
newTrim)
|
newTrim)
|
||||||
{
|
{
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
UpdateStatus?.Invoke("Trimming bad sectors");
|
UpdateStatus?.Invoke("Trimming bad sectors");
|
||||||
dumpLog.WriteLine("Trimming bad sectors");
|
_dumpLog.WriteLine("Trimming bad sectors");
|
||||||
|
|
||||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
foreach(ulong badSector in tmpArray)
|
foreach(ulong badSector in tmpArray)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PulseProgress?.Invoke($"Trimming sector {badSector}");
|
PulseProgress?.Invoke($"Trimming sector {badSector}");
|
||||||
|
|
||||||
error = dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
|
error = _dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
|
||||||
out duration);
|
out duration);
|
||||||
|
|
||||||
totalDuration += duration;
|
totalDuration += duration;
|
||||||
|
|
||||||
if(error)
|
if(error)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
resume.BadBlocks.Remove(badSector);
|
_resume.BadBlocks.Remove(badSector);
|
||||||
extents.Add(badSector);
|
extents.Add(badSector);
|
||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
_outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
UpdateStatus?.Invoke($"Trimmming finished in {(end - start).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Trimmming finished in {(end - start).TotalSeconds} seconds.");
|
||||||
dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
|
_dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds);
|
||||||
}
|
}
|
||||||
#endregion Trimming
|
#endregion Trimming
|
||||||
|
|
||||||
#region Error handling
|
#region Error handling
|
||||||
if(resume.BadBlocks.Count > 0 &&
|
if(_resume.BadBlocks.Count > 0 &&
|
||||||
!aborted &&
|
!_aborted &&
|
||||||
retryPasses > 0)
|
_retryPasses > 0)
|
||||||
{
|
{
|
||||||
int pass = 1;
|
int pass = 1;
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
@@ -469,15 +469,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
repeatRetryLba:
|
repeatRetryLba:
|
||||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||||
|
|
||||||
foreach(ulong badSector in tmpArray)
|
foreach(ulong badSector in tmpArray)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -486,31 +486,31 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
forward ? "forward" : "reverse",
|
forward ? "forward" : "reverse",
|
||||||
runningPersistent ? "recovering partial data, " : ""));
|
runningPersistent ? "recovering partial data, " : ""));
|
||||||
|
|
||||||
error = dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
|
error = _dev.Read(out cmdBuf, out _, (uint)badSector, blockSize, 1, byteAddressed, TIMEOUT,
|
||||||
out duration);
|
out duration);
|
||||||
|
|
||||||
totalDuration += duration;
|
totalDuration += duration;
|
||||||
|
|
||||||
if(!error)
|
if(!error)
|
||||||
{
|
{
|
||||||
resume.BadBlocks.Remove(badSector);
|
_resume.BadBlocks.Remove(badSector);
|
||||||
extents.Add(badSector);
|
extents.Add(badSector);
|
||||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
_outputPlugin.WriteSector(cmdBuf, badSector);
|
||||||
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
||||||
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 &&
|
if(pass < _retryPasses &&
|
||||||
!aborted &&
|
!_aborted &&
|
||||||
resume.BadBlocks.Count > 0)
|
_resume.BadBlocks.Count > 0)
|
||||||
{
|
{
|
||||||
pass++;
|
pass++;
|
||||||
forward = !forward;
|
forward = !forward;
|
||||||
resume.BadBlocks.Sort();
|
_resume.BadBlocks.Sort();
|
||||||
resume.BadBlocks.Reverse();
|
_resume.BadBlocks.Reverse();
|
||||||
|
|
||||||
goto repeatRetryLba;
|
goto repeatRetryLba;
|
||||||
}
|
}
|
||||||
@@ -521,58 +521,58 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
|
|
||||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
|
|
||||||
outputPlugin.SetDumpHardware(resume.Tries);
|
_outputPlugin.SetDumpHardware(_resume.Tries);
|
||||||
|
|
||||||
if(preSidecar != null)
|
if(_preSidecar != null)
|
||||||
outputPlugin.SetCicmMetadata(preSidecar);
|
_outputPlugin.SetCicmMetadata(_preSidecar);
|
||||||
|
|
||||||
dumpLog.WriteLine("Closing output file.");
|
_dumpLog.WriteLine("Closing output file.");
|
||||||
UpdateStatus?.Invoke("Closing output file.");
|
UpdateStatus?.Invoke("Closing output file.");
|
||||||
DateTime closeStart = DateTime.Now;
|
DateTime closeStart = DateTime.Now;
|
||||||
outputPlugin.Close();
|
_outputPlugin.Close();
|
||||||
DateTime closeEnd = DateTime.Now;
|
DateTime closeEnd = DateTime.Now;
|
||||||
UpdateStatus?.Invoke($"Closed in {(closeEnd - closeStart).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Closed in {(closeEnd - closeStart).TotalSeconds} seconds.");
|
||||||
dumpLog.WriteLine("Closed in {0} seconds.", (closeEnd - closeStart).TotalSeconds);
|
_dumpLog.WriteLine("Closed in {0} seconds.", (closeEnd - closeStart).TotalSeconds);
|
||||||
|
|
||||||
if(aborted)
|
if(_aborted)
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke("Aborted!");
|
UpdateStatus?.Invoke("Aborted!");
|
||||||
dumpLog.WriteLine("Aborted!");
|
_dumpLog.WriteLine("Aborted!");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double totalChkDuration = 0;
|
double totalChkDuration = 0;
|
||||||
|
|
||||||
if(!nometadata)
|
if(!_nometadata)
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke("Creating sidecar.");
|
UpdateStatus?.Invoke("Creating sidecar.");
|
||||||
dumpLog.WriteLine("Creating sidecar.");
|
_dumpLog.WriteLine("Creating sidecar.");
|
||||||
var filters = new FiltersList();
|
var filters = new FiltersList();
|
||||||
IFilter filter = filters.GetFilter(outputPath);
|
IFilter filter = filters.GetFilter(_outputPath);
|
||||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
||||||
|
|
||||||
if(!inputPlugin.Open(filter))
|
if(!inputPlugin.Open(filter))
|
||||||
StoppingErrorMessage?.Invoke("Could not open created image.");
|
StoppingErrorMessage?.Invoke("Could not open created image.");
|
||||||
|
|
||||||
DateTime chkStart = DateTime.UtcNow;
|
DateTime chkStart = DateTime.UtcNow;
|
||||||
sidecarClass = new Sidecar(inputPlugin, outputPath, filter.Id, encoding);
|
_sidecarClass = new Sidecar(inputPlugin, _outputPath, filter.Id, _encoding);
|
||||||
sidecarClass.InitProgressEvent += InitProgress;
|
_sidecarClass.InitProgressEvent += InitProgress;
|
||||||
sidecarClass.UpdateProgressEvent += UpdateProgress;
|
_sidecarClass.UpdateProgressEvent += UpdateProgress;
|
||||||
sidecarClass.EndProgressEvent += EndProgress;
|
_sidecarClass.EndProgressEvent += EndProgress;
|
||||||
sidecarClass.InitProgressEvent2 += InitProgress2;
|
_sidecarClass.InitProgressEvent2 += InitProgress2;
|
||||||
sidecarClass.UpdateProgressEvent2 += UpdateProgress2;
|
_sidecarClass.UpdateProgressEvent2 += UpdateProgress2;
|
||||||
sidecarClass.EndProgressEvent2 += EndProgress2;
|
_sidecarClass.EndProgressEvent2 += EndProgress2;
|
||||||
sidecarClass.UpdateStatusEvent += UpdateStatus;
|
_sidecarClass.UpdateStatusEvent += UpdateStatus;
|
||||||
CICMMetadataType sidecar = sidecarClass.Create();
|
CICMMetadataType sidecar = _sidecarClass.Create();
|
||||||
|
|
||||||
if(preSidecar != null)
|
if(_preSidecar != null)
|
||||||
{
|
{
|
||||||
preSidecar.BlockMedia = sidecar.BlockMedia;
|
_preSidecar.BlockMedia = sidecar.BlockMedia;
|
||||||
sidecar = preSidecar;
|
sidecar = _preSidecar;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev.Type)
|
switch(_dev.Type)
|
||||||
{
|
{
|
||||||
case DeviceType.MMC:
|
case DeviceType.MMC:
|
||||||
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
||||||
@@ -592,22 +592,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
cidDump = new DumpType
|
cidDump = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath, Size = (ulong)cid.Length, Checksums = Checksum.GetChecksums(cid).ToArray()
|
Image = _outputPath, Size = (ulong)cid.Length, Checksums = Checksum.GetChecksums(cid).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
outputPlugin.WriteMediaTag(cid,
|
_outputPlugin.WriteMediaTag(cid,
|
||||||
dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID
|
_dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID
|
||||||
: MediaTagType.MMC_CID);
|
: MediaTagType.MMC_CID);
|
||||||
|
|
||||||
// Cannot write CID to image
|
// Cannot write CID to image
|
||||||
if(!ret &&
|
if(!ret &&
|
||||||
!force)
|
!_force)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Cannot write CID to output image.");
|
_dumpLog.WriteLine("Cannot write CID to output image.");
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Cannot write CID to output image." + Environment.NewLine +
|
StoppingErrorMessage?.Invoke("Cannot write CID to output image." + Environment.NewLine +
|
||||||
outputPlugin.ErrorMessage);
|
_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -617,22 +617,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
csdDump = new DumpType
|
csdDump = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath, Size = (ulong)csd.Length, Checksums = Checksum.GetChecksums(csd).ToArray()
|
Image = _outputPath, Size = (ulong)csd.Length, Checksums = Checksum.GetChecksums(csd).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
outputPlugin.WriteMediaTag(csd,
|
_outputPlugin.WriteMediaTag(csd,
|
||||||
dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CSD
|
_dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CSD
|
||||||
: MediaTagType.MMC_CSD);
|
: MediaTagType.MMC_CSD);
|
||||||
|
|
||||||
// Cannot write CSD to image
|
// Cannot write CSD to image
|
||||||
if(!ret &&
|
if(!ret &&
|
||||||
!force)
|
!_force)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Cannot write CSD to output image.");
|
_dumpLog.WriteLine("Cannot write CSD to output image.");
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Cannot write CSD to output image." + Environment.NewLine +
|
StoppingErrorMessage?.Invoke("Cannot write CSD to output image." + Environment.NewLine +
|
||||||
outputPlugin.ErrorMessage);
|
_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -642,20 +642,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
|
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath, Size = (ulong)ecsd.Length, Checksums = Checksum.GetChecksums(ecsd).ToArray()
|
Image = _outputPath, Size = (ulong)ecsd.Length,
|
||||||
|
Checksums = Checksum.GetChecksums(ecsd).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
ret = outputPlugin.WriteMediaTag(ecsd, MediaTagType.MMC_ExtendedCSD);
|
ret = _outputPlugin.WriteMediaTag(ecsd, MediaTagType.MMC_ExtendedCSD);
|
||||||
|
|
||||||
// Cannot write Extended CSD to image
|
// Cannot write Extended CSD to image
|
||||||
if(!ret &&
|
if(!ret &&
|
||||||
!force)
|
!_force)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Cannot write Extended CSD to output image.");
|
_dumpLog.WriteLine("Cannot write Extended CSD to output image.");
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Cannot write Extended CSD to output image." +
|
StoppingErrorMessage?.Invoke("Cannot write Extended CSD to output image." +
|
||||||
Environment.NewLine +
|
Environment.NewLine +
|
||||||
outputPlugin.ErrorMessage);
|
_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -665,22 +666,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
ocrDump = new DumpType
|
ocrDump = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath, Size = (ulong)ocr.Length, Checksums = Checksum.GetChecksums(ocr).ToArray()
|
Image = _outputPath, Size = (ulong)ocr.Length, Checksums = Checksum.GetChecksums(ocr).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
outputPlugin.WriteMediaTag(ocr,
|
_outputPlugin.WriteMediaTag(ocr,
|
||||||
dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_OCR
|
_dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_OCR
|
||||||
: MediaTagType.MMC_OCR);
|
: MediaTagType.MMC_OCR);
|
||||||
|
|
||||||
// Cannot write OCR to image
|
// Cannot write OCR to image
|
||||||
if(!ret &&
|
if(!ret &&
|
||||||
!force)
|
!_force)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Cannot write OCR to output image.");
|
_dumpLog.WriteLine("Cannot write OCR to output image.");
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Cannot write OCR to output image." + Environment.NewLine +
|
StoppingErrorMessage?.Invoke("Cannot write OCR to output image." + Environment.NewLine +
|
||||||
outputPlugin.ErrorMessage);
|
_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -690,25 +691,25 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
{
|
{
|
||||||
sidecar.BlockMedia[0].SecureDigital.SCR = new DumpType
|
sidecar.BlockMedia[0].SecureDigital.SCR = new DumpType
|
||||||
{
|
{
|
||||||
Image = outputPath, Size = (ulong)scr.Length, Checksums = Checksum.GetChecksums(scr).ToArray()
|
Image = _outputPath, Size = (ulong)scr.Length, Checksums = Checksum.GetChecksums(scr).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
ret = outputPlugin.WriteMediaTag(scr, MediaTagType.SD_SCR);
|
ret = _outputPlugin.WriteMediaTag(scr, MediaTagType.SD_SCR);
|
||||||
|
|
||||||
// Cannot write SCR to image
|
// Cannot write SCR to image
|
||||||
if(!ret &&
|
if(!ret &&
|
||||||
!force)
|
!_force)
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Cannot write SCR to output image.");
|
_dumpLog.WriteLine("Cannot write SCR to output image.");
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Cannot write SCR to output image." + Environment.NewLine +
|
StoppingErrorMessage?.Invoke("Cannot write SCR to output image." + Environment.NewLine +
|
||||||
outputPlugin.ErrorMessage);
|
_outputPlugin.ErrorMessage);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev.Type)
|
switch(_dev.Type)
|
||||||
{
|
{
|
||||||
case DeviceType.MMC:
|
case DeviceType.MMC:
|
||||||
sidecar.BlockMedia[0].MultiMediaCard.CID = cidDump;
|
sidecar.BlockMedia[0].MultiMediaCard.CID = cidDump;
|
||||||
@@ -730,20 +731,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average checksum speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
Invoke($"Average checksum speed {((double)blockSize * (double)(blocks + 1)) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
(string type, string subType) xmlType = (null, null);
|
(string type, string subType) xmlType = (null, null);
|
||||||
|
|
||||||
switch(dev.Type)
|
switch(_dev.Type)
|
||||||
{
|
{
|
||||||
case DeviceType.MMC:
|
case DeviceType.MMC:
|
||||||
xmlType =
|
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.MMC);
|
||||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.MMC);
|
|
||||||
|
|
||||||
sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(MediaType.MMC);
|
sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(MediaType.MMC);
|
||||||
|
|
||||||
@@ -762,14 +762,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
sidecar.BlockMedia[0].LogicalBlocks = blocks;
|
sidecar.BlockMedia[0].LogicalBlocks = blocks;
|
||||||
sidecar.BlockMedia[0].PhysicalBlockSize = physicalBlockSize > 0 ? physicalBlockSize : blockSize;
|
sidecar.BlockMedia[0].PhysicalBlockSize = physicalBlockSize > 0 ? physicalBlockSize : blockSize;
|
||||||
sidecar.BlockMedia[0].LogicalBlockSize = blockSize;
|
sidecar.BlockMedia[0].LogicalBlockSize = blockSize;
|
||||||
sidecar.BlockMedia[0].Manufacturer = dev.Manufacturer;
|
sidecar.BlockMedia[0].Manufacturer = _dev.Manufacturer;
|
||||||
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 = blocks * blockSize;
|
sidecar.BlockMedia[0].Size = blocks * blockSize;
|
||||||
|
|
||||||
UpdateStatus?.Invoke("Writing metadata sidecar");
|
UpdateStatus?.Invoke("Writing metadata sidecar");
|
||||||
|
|
||||||
var xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
var xmlFs = new FileStream(_outputPrefix + ".cicm.xml", FileMode.Create);
|
||||||
|
|
||||||
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
||||||
xmlSer.Serialize(xmlFs, sidecar);
|
xmlSer.Serialize(xmlFs, sidecar);
|
||||||
@@ -782,17 +782,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||||
|
|
||||||
UpdateStatus?.
|
UpdateStatus?.
|
||||||
Invoke($"Average speed: {(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
Invoke($"Average speed: {((double)blockSize * (double)(blocks + 1)) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||||
UpdateStatus?.Invoke($"Slowest speed burst: {minSpeed:F3} MiB/sec.");
|
UpdateStatus?.Invoke($"Slowest speed burst: {minSpeed:F3} MiB/sec.");
|
||||||
UpdateStatus?.Invoke($"{resume.BadBlocks.Count} sectors could not be read.");
|
UpdateStatus?.Invoke($"{_resume.BadBlocks.Count} sectors could not be read.");
|
||||||
UpdateStatus?.Invoke("");
|
UpdateStatus?.Invoke("");
|
||||||
|
|
||||||
if(resume.BadBlocks.Count > 0)
|
if(_resume.BadBlocks.Count > 0)
|
||||||
resume.BadBlocks.Sort();
|
_resume.BadBlocks.Sort();
|
||||||
|
|
||||||
switch(dev.Type)
|
switch(_dev.Type)
|
||||||
{
|
{
|
||||||
case DeviceType.MMC:
|
case DeviceType.MMC:
|
||||||
Statistics.AddMedia(MediaType.MMC, true);
|
Statistics.AddMedia(MediaType.MMC, true);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -54,16 +54,18 @@ using Schemas;
|
|||||||
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
|
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
|
||||||
using MediaType = DiscImageChef.CommonTypes.MediaType;
|
using MediaType = DiscImageChef.CommonTypes.MediaType;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Local
|
||||||
|
|
||||||
namespace DiscImageChef.Gui.Forms
|
namespace DiscImageChef.Gui.Forms
|
||||||
{
|
{
|
||||||
public class frmDump : Form
|
public class frmDump : Form
|
||||||
{
|
{
|
||||||
readonly string devicePath;
|
readonly string _devicePath;
|
||||||
Device dev;
|
Device _dev;
|
||||||
Dump dumper;
|
Dump _dumper;
|
||||||
string outputPrefix;
|
string _outputPrefix;
|
||||||
Resume resume;
|
Resume _resume;
|
||||||
CICMMetadataType sidecar;
|
CICMMetadataType _sidecar;
|
||||||
|
|
||||||
public frmDump(string devicePath, DeviceInfo deviceInfo, ScsiInfo scsiInfo = null)
|
public frmDump(string devicePath, DeviceInfo deviceInfo, ScsiInfo scsiInfo = null)
|
||||||
{
|
{
|
||||||
@@ -189,7 +191,7 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.devicePath = devicePath;
|
_devicePath = devicePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnCmbFormatSelectedIndexChanged(object sender, EventArgs e)
|
void OnCmbFormatSelectedIndexChanged(object sender, EventArgs e)
|
||||||
@@ -318,7 +320,7 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
if(result != DialogResult.Ok)
|
if(result != DialogResult.Ok)
|
||||||
{
|
{
|
||||||
txtDestination.Text = "";
|
txtDestination.Text = "";
|
||||||
outputPrefix = null;
|
_outputPrefix = null;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -328,8 +330,8 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
|
|
||||||
txtDestination.Text = dlgDestination.FileName;
|
txtDestination.Text = dlgDestination.FileName;
|
||||||
|
|
||||||
outputPrefix = Path.Combine(Path.GetDirectoryName(dlgDestination.FileName),
|
_outputPrefix = Path.Combine(Path.GetDirectoryName(dlgDestination.FileName),
|
||||||
Path.GetFileNameWithoutExtension(dlgDestination.FileName));
|
Path.GetFileNameWithoutExtension(dlgDestination.FileName));
|
||||||
|
|
||||||
chkResume.Checked = true;
|
chkResume.Checked = true;
|
||||||
}
|
}
|
||||||
@@ -344,7 +346,7 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
{
|
{
|
||||||
if(chkExistingMetadata.Checked == false)
|
if(chkExistingMetadata.Checked == false)
|
||||||
{
|
{
|
||||||
sidecar = null;
|
_sidecar = null;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -370,7 +372,7 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sr = new StreamReader(dlgMetadata.FileName);
|
var sr = new StreamReader(dlgMetadata.FileName);
|
||||||
sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
|
_sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
|
||||||
sr.Close();
|
sr.Close();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -385,19 +387,19 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
if(chkResume.Checked == false)
|
if(chkResume.Checked == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(outputPrefix != null)
|
if(_outputPrefix != null)
|
||||||
CheckResumeFile();
|
CheckResumeFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckResumeFile()
|
void CheckResumeFile()
|
||||||
{
|
{
|
||||||
resume = null;
|
_resume = null;
|
||||||
var xs = new XmlSerializer(typeof(Resume));
|
var xs = new XmlSerializer(typeof(Resume));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sr = new StreamReader(outputPrefix + ".resume.xml");
|
var sr = new StreamReader(_outputPrefix + ".resume.xml");
|
||||||
resume = (Resume)xs.Deserialize(sr);
|
_resume = (Resume)xs.Deserialize(sr);
|
||||||
sr.Close();
|
sr.Close();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -408,9 +410,9 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resume == null ||
|
if(_resume == null ||
|
||||||
resume.NextBlock <= resume.LastBlock ||
|
_resume.NextBlock <= _resume.LastBlock ||
|
||||||
(resume.BadBlocks.Count != 0 && !resume.Tape))
|
(_resume.BadBlocks.Count != 0 && !_resume.Tape))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MessageBox.Show("Media already dumped correctly, please choose another destination...",
|
MessageBox.Show("Media already dumped correctly, please choose another destination...",
|
||||||
@@ -424,7 +426,7 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
void OnBtnStopClick(object sender, EventArgs e)
|
void OnBtnStopClick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
btnStop.Enabled = false;
|
btnStop.Enabled = false;
|
||||||
dumper.Abort();
|
_dumper.Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnBtnDumpClick(object sender, EventArgs e)
|
void OnBtnDumpClick(object sender, EventArgs e)
|
||||||
@@ -442,15 +444,15 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dev = new Device(devicePath);
|
_dev = new Device(_devicePath);
|
||||||
|
|
||||||
if(dev.IsRemote)
|
if(_dev.IsRemote)
|
||||||
Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
|
Statistics.AddRemote(_dev.RemoteApplication, _dev.RemoteVersion, _dev.RemoteOperatingSystem,
|
||||||
dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
|
_dev.RemoteOperatingSystemVersion, _dev.RemoteArchitecture);
|
||||||
|
|
||||||
if(dev.Error)
|
if(_dev.Error)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage($"Error {dev.LastError} opening device.");
|
StoppingErrorMessage($"Error {_dev.LastError} opening device.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -462,7 +464,7 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Statistics.AddDevice(dev);
|
Statistics.AddDevice(_dev);
|
||||||
Statistics.AddCommand("dump-media");
|
Statistics.AddCommand("dump-media");
|
||||||
|
|
||||||
if(!(cmbFormat.SelectedValue is IWritableImage outputFormat))
|
if(!(cmbFormat.SelectedValue is IWritableImage outputFormat))
|
||||||
@@ -515,36 +517,37 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
parsedOptions.Add(key, value);
|
parsedOptions.Add(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dumpLog = new DumpLog(outputPrefix + ".log", dev);
|
var dumpLog = new DumpLog(_outputPrefix + ".log", _dev);
|
||||||
|
|
||||||
dumpLog.WriteLine("Output image format: {0}.", outputFormat.Name);
|
dumpLog.WriteLine("Output image format: {0}.", outputFormat.Name);
|
||||||
|
|
||||||
dumper = new Dump(chkResume.Checked == true, dev, devicePath, outputFormat, (ushort)stpRetries.Value,
|
_dumper = new Dump(chkResume.Checked == true, _dev, _devicePath, outputFormat,
|
||||||
chkForce.Checked == true, false, chkPersistent.Checked == true,
|
(ushort)stpRetries.Value,
|
||||||
chkStopOnError.Checked == true, resume, dumpLog, encoding, outputPrefix,
|
chkForce.Checked == true, false, chkPersistent.Checked == true,
|
||||||
txtDestination.Text, parsedOptions, sidecar, (uint)stpSkipped.Value,
|
chkStopOnError.Checked == true, _resume, dumpLog, encoding, _outputPrefix,
|
||||||
chkExistingMetadata.Checked == false, chkTrim.Checked == false,
|
txtDestination.Text, parsedOptions, _sidecar, (uint)stpSkipped.Value,
|
||||||
chkTrack1Pregap.Checked == true);
|
chkExistingMetadata.Checked == false, chkTrim.Checked == false,
|
||||||
|
chkTrack1Pregap.Checked == true);
|
||||||
|
|
||||||
new Thread(DoWork).Start();
|
new Thread(DoWork).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoWork()
|
void DoWork()
|
||||||
{
|
{
|
||||||
dumper.UpdateStatus += UpdateStatus;
|
_dumper.UpdateStatus += UpdateStatus;
|
||||||
dumper.ErrorMessage += ErrorMessage;
|
_dumper.ErrorMessage += ErrorMessage;
|
||||||
dumper.StoppingErrorMessage += StoppingErrorMessage;
|
_dumper.StoppingErrorMessage += StoppingErrorMessage;
|
||||||
dumper.PulseProgress += PulseProgress;
|
_dumper.PulseProgress += PulseProgress;
|
||||||
dumper.InitProgress += InitProgress;
|
_dumper.InitProgress += InitProgress;
|
||||||
dumper.UpdateProgress += UpdateProgress;
|
_dumper.UpdateProgress += UpdateProgress;
|
||||||
dumper.EndProgress += EndProgress;
|
_dumper.EndProgress += EndProgress;
|
||||||
dumper.InitProgress2 += InitProgress2;
|
_dumper.InitProgress2 += InitProgress2;
|
||||||
dumper.UpdateProgress2 += UpdateProgress2;
|
_dumper.UpdateProgress2 += UpdateProgress2;
|
||||||
dumper.EndProgress2 += EndProgress2;
|
_dumper.EndProgress2 += EndProgress2;
|
||||||
|
|
||||||
dumper.Start();
|
_dumper.Start();
|
||||||
|
|
||||||
dev.Close();
|
_dev.Close();
|
||||||
|
|
||||||
WorkFinished();
|
WorkFinished();
|
||||||
}
|
}
|
||||||
@@ -643,6 +646,7 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region XAML IDs
|
#region XAML IDs
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
ComboBox cmbFormat;
|
ComboBox cmbFormat;
|
||||||
TextBox txtDestination;
|
TextBox txtDestination;
|
||||||
Button btnDestination;
|
Button btnDestination;
|
||||||
@@ -673,6 +677,8 @@ namespace DiscImageChef.Gui.Forms
|
|||||||
Label lblProgress2;
|
Label lblProgress2;
|
||||||
ProgressBar prgProgress2;
|
ProgressBar prgProgress2;
|
||||||
StackLayout stkOptions;
|
StackLayout stkOptions;
|
||||||
|
|
||||||
|
// ReSharper restore InconsistentNaming
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,6 +190,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=certance/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=certance/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=checksumming/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=checksumming/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=checksums/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=checksums/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=cicm/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Claunia/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Claunia/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=DDCD/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=DDCD/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Drive_0027s/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Drive_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@@ -52,81 +52,77 @@ using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
|
|||||||
|
|
||||||
namespace DiscImageChef.Commands
|
namespace DiscImageChef.Commands
|
||||||
{
|
{
|
||||||
|
// TODO: Add raw dumping
|
||||||
internal class DumpMediaCommand : Command
|
internal class DumpMediaCommand : Command
|
||||||
{
|
{
|
||||||
string cicmXml;
|
string _cicmXml;
|
||||||
string devicePath;
|
string _devicePath;
|
||||||
bool doResume = true;
|
bool _doResume = true;
|
||||||
string encodingName;
|
string _encodingName;
|
||||||
bool firstTrackPregap;
|
bool _firstTrackPregap;
|
||||||
bool force;
|
bool _force;
|
||||||
bool noMetadata;
|
bool _noMetadata;
|
||||||
bool noTrim;
|
bool _noTrim;
|
||||||
string outputFile;
|
string _outputFile;
|
||||||
string outputOptions;
|
string _outputOptions;
|
||||||
|
bool _persistent;
|
||||||
bool persistent;
|
ushort _retryPasses = 5;
|
||||||
|
bool _showHelp;
|
||||||
// TODO: Add raw dumping
|
int _skip = 512;
|
||||||
ushort retryPasses = 5;
|
bool _stopOnError;
|
||||||
bool showHelp;
|
string _wantedOutputFormat;
|
||||||
int skip = 512;
|
|
||||||
bool stopOnError;
|
|
||||||
string wantedOutputFormat;
|
|
||||||
|
|
||||||
public DumpMediaCommand() : base("dump-media", "Dumps the media inserted on a device to a media image.")
|
public DumpMediaCommand() : base("dump-media", "Dumps the media inserted on a device to a media image.")
|
||||||
{
|
{
|
||||||
Options = new OptionSet
|
Options = new OptionSet
|
||||||
{
|
{
|
||||||
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
|
$"{MainClass.AssemblyTitle} {MainClass.AssemblyVersion?.InformationalVersion}",
|
||||||
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] devicepath outputimage",
|
$"{MainClass.AssemblyCopyright}", "", $"usage: DiscImageChef {Name} [OPTIONS] device_path output_image",
|
||||||
"", Help,
|
"", Help,
|
||||||
{
|
{
|
||||||
"cicm-xml|x=", "Take metadata from existing CICM XML sidecar.", s => cicmXml = s
|
"cicm-xml|x=", "Take metadata from existing CICM XML sidecar.", s => _cicmXml = s
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"encoding|e=", "Name of character encoding to use.", s => encodingName = s
|
"encoding|e=", "Name of character encoding to use.", s => _encodingName = s
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(DetectOS.GetRealPlatformID() != PlatformID.FreeBSD)
|
if(DetectOS.GetRealPlatformID() != PlatformID.FreeBSD)
|
||||||
Options.Add("first-pregap", "Try to read first track pregap. Only applicable to CD/DDCD/GD.",
|
Options.Add("first-pregap", "Try to read first track pregap. Only applicable to CD/DDCD/GD.",
|
||||||
b => firstTrackPregap = b != null);
|
b => _firstTrackPregap = b != null);
|
||||||
|
|
||||||
Options.Add("force|f", "Continue dump whatever happens.", b => force = b != null);
|
Options.Add("force|f", "Continue dump whatever happens.", b => _force = b != null);
|
||||||
|
|
||||||
Options.Add("format|t=",
|
Options.Add("format|t=",
|
||||||
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.",
|
"Format of the output image, as plugin name or plugin id. If not present, will try to detect it from output image extension.",
|
||||||
s => wantedOutputFormat = s);
|
s => _wantedOutputFormat = s);
|
||||||
|
|
||||||
Options.Add("no-metadata", "Disables creating CICM XML sidecar.", b => noMetadata = b != null);
|
Options.Add("no-metadata", "Disables creating CICM XML sidecar.", b => _noMetadata = b != null);
|
||||||
Options.Add("no-trim", "Disables trimming errored from skipped sectors.", b => noTrim = b != null);
|
Options.Add("no-trim", "Disables trimming errored from skipped sectors.", b => _noTrim = b != null);
|
||||||
|
|
||||||
Options.Add("options|O=", "Comma separated name=value pairs of options to pass to output image plugin.",
|
Options.Add("options|O=", "Comma separated name=value pairs of options to pass to output image plugin.",
|
||||||
s => outputOptions = s);
|
s => _outputOptions = s);
|
||||||
|
|
||||||
Options.Add("persistent", "Try to recover partial or incorrect data.", b => persistent = b != null);
|
Options.Add("persistent", "Try to recover partial or incorrect data.", b => _persistent = b != null);
|
||||||
|
|
||||||
|
Options.Add("resume|r", "Create/use resume mapfile.", b => _doResume = b != null);
|
||||||
|
|
||||||
|
Options.Add("retry-passes|p=", "How many retry passes to do.", (ushort us) => _retryPasses = us);
|
||||||
|
Options.Add("skip|k=", "When an unreadable sector is found skip this many sectors.", (int i) => _skip = i);
|
||||||
|
|
||||||
|
Options.Add("stop-on-error|s", "Stop media dump on first error.", b => _stopOnError = b != null);
|
||||||
|
|
||||||
|
Options.Add("help|h|?", "Show this message and exit.", v => _showHelp = v != null);
|
||||||
|
|
||||||
/* TODO: Disabled temporarily
|
/* TODO: Disabled temporarily
|
||||||
Options.Add("raw|r", "Dump sectors with tags included. For optical media, dump scrambled sectors.", (b) => raw = b != null);*/
|
Options.Add("raw|r", "Dump sectors with tags included. For optical media, dump scrambled sectors.", (b) => raw = b != null);*/
|
||||||
Options.Add("resume|r", "Create/use resume mapfile.",
|
|
||||||
b => doResume = b != null);
|
|
||||||
|
|
||||||
Options.Add("retry-passes|p=", "How many retry passes to do.", (ushort us) => retryPasses = us);
|
|
||||||
Options.Add("skip|k=", "When an unreadable sector is found skip this many sectors.", (int i) => skip = i);
|
|
||||||
|
|
||||||
Options.Add("stop-on-error|s", "Stop media dump on first error.",
|
|
||||||
b => stopOnError = b != null);
|
|
||||||
|
|
||||||
Options.Add("help|h|?", "Show this message and exit.",
|
|
||||||
v => showHelp = v != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int Invoke(IEnumerable<string> arguments)
|
public override int Invoke(IEnumerable<string> arguments)
|
||||||
{
|
{
|
||||||
List<string> extra = Options.Parse(arguments);
|
List<string> extra = Options.Parse(arguments);
|
||||||
|
|
||||||
if(showHelp)
|
if(_showHelp)
|
||||||
{
|
{
|
||||||
Options.WriteOptionDescriptions(CommandSet.Out);
|
Options.WriteOptionDescriptions(CommandSet.Out);
|
||||||
|
|
||||||
@@ -157,31 +153,31 @@ namespace DiscImageChef.Commands
|
|||||||
return(int)ErrorNumber.MissingArgument;
|
return(int)ErrorNumber.MissingArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
devicePath = extra[0];
|
_devicePath = extra[0];
|
||||||
outputFile = extra[1];
|
_outputFile = extra[1];
|
||||||
|
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", cicmXml);
|
DicConsole.DebugWriteLine("Dump-Media command", "--cicm-xml={0}", _cicmXml);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", MainClass.Debug);
|
DicConsole.DebugWriteLine("Dump-Media command", "--debug={0}", MainClass.Debug);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", devicePath);
|
DicConsole.DebugWriteLine("Dump-Media command", "--device={0}", _devicePath);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", encodingName);
|
DicConsole.DebugWriteLine("Dump-Media command", "--encoding={0}", _encodingName);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", firstTrackPregap);
|
DicConsole.DebugWriteLine("Dump-Media command", "--first-pregap={0}", _firstTrackPregap);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force);
|
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", _force);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", force);
|
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", _force);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", wantedOutputFormat);
|
DicConsole.DebugWriteLine("Dump-Media command", "--format={0}", _wantedOutputFormat);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--no-metadata={0}", noMetadata);
|
DicConsole.DebugWriteLine("Dump-Media command", "--no-metadata={0}", _noMetadata);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", Options);
|
DicConsole.DebugWriteLine("Dump-Media command", "--options={0}", Options);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", outputFile);
|
DicConsole.DebugWriteLine("Dump-Media command", "--output={0}", _outputFile);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", persistent);
|
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", _persistent);
|
||||||
|
DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", _doResume);
|
||||||
|
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", _retryPasses);
|
||||||
|
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", _skip);
|
||||||
|
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", _stopOnError);
|
||||||
|
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose);
|
||||||
|
|
||||||
// TODO: Disabled temporarily
|
// TODO: Disabled temporarily
|
||||||
//DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw);
|
//DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--resume={0}", doResume);
|
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", retryPasses);
|
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", skip);
|
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", stopOnError);
|
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose);
|
|
||||||
|
|
||||||
Dictionary<string, string> parsedOptions = Core.Options.Parse(outputOptions);
|
Dictionary<string, string> parsedOptions = Core.Options.Parse(_outputOptions);
|
||||||
DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:");
|
DicConsole.DebugWriteLine("Dump-Media command", "Parsed options:");
|
||||||
|
|
||||||
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
foreach(KeyValuePair<string, string> parsedOption in parsedOptions)
|
||||||
@@ -189,10 +185,10 @@ namespace DiscImageChef.Commands
|
|||||||
|
|
||||||
Encoding encoding = null;
|
Encoding encoding = null;
|
||||||
|
|
||||||
if(encodingName != null)
|
if(_encodingName != null)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName);
|
encoding = Claunia.Encoding.Encoding.GetEncoding(_encodingName);
|
||||||
|
|
||||||
if(MainClass.Verbose)
|
if(MainClass.Verbose)
|
||||||
DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
|
DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
|
||||||
@@ -204,17 +200,17 @@ namespace DiscImageChef.Commands
|
|||||||
return(int)ErrorNumber.EncodingUnknown;
|
return(int)ErrorNumber.EncodingUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(devicePath.Length == 2 &&
|
if(_devicePath.Length == 2 &&
|
||||||
devicePath[1] == ':' &&
|
_devicePath[1] == ':' &&
|
||||||
devicePath[0] != '/' &&
|
_devicePath[0] != '/' &&
|
||||||
char.IsLetter(devicePath[0]))
|
char.IsLetter(_devicePath[0]))
|
||||||
devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
|
_devicePath = "\\\\.\\" + char.ToUpper(_devicePath[0]) + ':';
|
||||||
|
|
||||||
Device dev;
|
Device dev;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dev = new Device(devicePath);
|
dev = new Device(_devicePath);
|
||||||
|
|
||||||
if(dev.IsRemote)
|
if(dev.IsRemote)
|
||||||
Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
|
Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
|
||||||
@@ -236,13 +232,13 @@ namespace DiscImageChef.Commands
|
|||||||
|
|
||||||
Statistics.AddDevice(dev);
|
Statistics.AddDevice(dev);
|
||||||
|
|
||||||
string outputPrefix = Path.Combine(Path.GetDirectoryName(outputFile),
|
string outputPrefix = Path.Combine(Path.GetDirectoryName(_outputFile),
|
||||||
Path.GetFileNameWithoutExtension(outputFile));
|
Path.GetFileNameWithoutExtension(_outputFile));
|
||||||
|
|
||||||
Resume resume = null;
|
Resume resume = null;
|
||||||
var xs = new XmlSerializer(typeof(Resume));
|
var xs = new XmlSerializer(typeof(Resume));
|
||||||
|
|
||||||
if(File.Exists(outputPrefix + ".resume.xml") && doResume)
|
if(File.Exists(outputPrefix + ".resume.xml") && _doResume)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sr = new StreamReader(outputPrefix + ".resume.xml");
|
var sr = new StreamReader(outputPrefix + ".resume.xml");
|
||||||
@@ -269,12 +265,12 @@ namespace DiscImageChef.Commands
|
|||||||
CICMMetadataType sidecar = null;
|
CICMMetadataType sidecar = null;
|
||||||
var sidecarXs = new XmlSerializer(typeof(CICMMetadataType));
|
var sidecarXs = new XmlSerializer(typeof(CICMMetadataType));
|
||||||
|
|
||||||
if(cicmXml != null)
|
if(_cicmXml != null)
|
||||||
if(File.Exists(cicmXml))
|
if(File.Exists(_cicmXml))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sr = new StreamReader(cicmXml);
|
var sr = new StreamReader(_cicmXml);
|
||||||
sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
|
sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
|
||||||
sr.Close();
|
sr.Close();
|
||||||
}
|
}
|
||||||
@@ -296,18 +292,19 @@ namespace DiscImageChef.Commands
|
|||||||
List<IWritableImage> candidates = new List<IWritableImage>();
|
List<IWritableImage> candidates = new List<IWritableImage>();
|
||||||
|
|
||||||
// Try extension
|
// Try extension
|
||||||
if(string.IsNullOrEmpty(wantedOutputFormat))
|
if(string.IsNullOrEmpty(_wantedOutputFormat))
|
||||||
candidates.AddRange(plugins.WritableImages.Values.Where(t =>
|
candidates.AddRange(plugins.WritableImages.Values.Where(t =>
|
||||||
t.KnownExtensions.
|
t.KnownExtensions.
|
||||||
Contains(Path.GetExtension(outputFile))));
|
Contains(Path.
|
||||||
|
GetExtension(_outputFile))));
|
||||||
|
|
||||||
// Try Id
|
// Try Id
|
||||||
else if(Guid.TryParse(wantedOutputFormat, out Guid outId))
|
else if(Guid.TryParse(_wantedOutputFormat, out Guid outId))
|
||||||
candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId)));
|
candidates.AddRange(plugins.WritableImages.Values.Where(t => t.Id.Equals(outId)));
|
||||||
|
|
||||||
// Try name
|
// Try name
|
||||||
else
|
else
|
||||||
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, wantedOutputFormat,
|
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, _wantedOutputFormat,
|
||||||
StringComparison.
|
StringComparison.
|
||||||
InvariantCultureIgnoreCase)));
|
InvariantCultureIgnoreCase)));
|
||||||
|
|
||||||
@@ -340,9 +337,9 @@ namespace DiscImageChef.Commands
|
|||||||
DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
|
DicConsole.WriteLine("Output image format: {0}.", outputFormat.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dumper = new Dump(doResume, dev, devicePath, outputFormat, retryPasses, force, false, persistent,
|
var dumper = new Dump(_doResume, dev, _devicePath, outputFormat, _retryPasses, _force, false, _persistent,
|
||||||
stopOnError, resume, dumpLog, encoding, outputPrefix, outputFile, parsedOptions,
|
_stopOnError, resume, dumpLog, encoding, outputPrefix, _outputFile, parsedOptions,
|
||||||
sidecar, (uint)skip, noMetadata, noTrim, firstTrackPregap);
|
sidecar, (uint)_skip, _noMetadata, _noTrim, _firstTrackPregap);
|
||||||
|
|
||||||
dumper.UpdateStatus += Progress.UpdateStatus;
|
dumper.UpdateStatus += Progress.UpdateStatus;
|
||||||
dumper.ErrorMessage += Progress.ErrorMessage;
|
dumper.ErrorMessage += Progress.ErrorMessage;
|
||||||
|
|||||||
Reference in New Issue
Block a user