mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Use tuples to convert MediaType to type and subtype.
This commit is contained in:
1
.idea/.idea.DiscImageChef/.idea/contentModel.xml
generated
1
.idea/.idea.DiscImageChef/.idea/contentModel.xml
generated
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ContentModelStore">
|
||||
<e p="$APPLICATION_PLUGINS_DIR$/puppet/lib/stubs" t="IncludeRecursive" />
|
||||
<e p="$USER_HOME$/.Rider2019.3/system/extResources" t="IncludeRecursive" />
|
||||
<e p="$USER_HOME$/.Rider2019.3/system/resharper-host/local/Transient/ReSharperHost/v193/SolutionCaches/_DiscImageChef.-1491758497.00" t="ExcludeRecursive" />
|
||||
<e p="$USER_HOME$/.nuget/packages/sqlitepclraw.lib.e_sqlite3.linux/1.1.12/runtimes/linux-x64/native/libe_sqlite3.so" t="Include" />
|
||||
|
||||
Submodule DiscImageChef.CommonTypes updated: 681fd8e8b9...374c145562
@@ -47,22 +47,20 @@ using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
|
||||
|
||||
namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements dumping ATA devices
|
||||
/// </summary>
|
||||
/// <summary>Implements dumping ATA devices</summary>
|
||||
public partial class Dump
|
||||
{
|
||||
/// <summary>
|
||||
/// Dumps an ATA device
|
||||
/// </summary>
|
||||
/// <summary>Dumps an ATA device</summary>
|
||||
public void Ata()
|
||||
{
|
||||
if(dumpRaw)
|
||||
{
|
||||
if(force) ErrorMessage?.Invoke("Raw dumping not yet supported in ATA devices, continuing...");
|
||||
if(force)
|
||||
ErrorMessage?.Invoke("Raw dumping not yet supported in ATA devices, continuing...");
|
||||
else
|
||||
{
|
||||
StoppingErrorMessage?.Invoke("Raw dumping not yet supported in ATA devices, aborting...");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -74,9 +72,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke("Requesting ATA IDENTIFY DEVICE.");
|
||||
dumpLog.WriteLine("Requesting ATA IDENTIFY DEVICE.");
|
||||
bool sense = dev.AtaIdentify(out byte[] cmdBuf, out _);
|
||||
if(!sense && Identify.Decode(cmdBuf).HasValue)
|
||||
|
||||
if(!sense &&
|
||||
Identify.Decode(cmdBuf).HasValue)
|
||||
{
|
||||
Identify.IdentifyDevice? ataIdNullable = Identify.Decode(cmdBuf);
|
||||
|
||||
if(ataIdNullable != null)
|
||||
{
|
||||
Identify.IdentifyDevice ataId = ataIdNullable.Value;
|
||||
@@ -93,23 +94,28 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
// Initializate reader
|
||||
UpdateStatus?.Invoke("Initializing reader.");
|
||||
dumpLog.WriteLine("Initializing reader.");
|
||||
Reader ataReader = new Reader(dev, TIMEOUT, ataIdentify);
|
||||
var ataReader = new Reader(dev, TIMEOUT, ataIdentify);
|
||||
|
||||
// Fill reader blocks
|
||||
ulong blocks = ataReader.GetDeviceBlocks();
|
||||
|
||||
// Check block sizes
|
||||
if(ataReader.GetBlockSize())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get block size: {0}.", ataReader.ErrorMessage);
|
||||
ErrorMessage(ataReader.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint blockSize = ataReader.LogicalBlockSize;
|
||||
uint physicalsectorsize = ataReader.PhysicalBlockSize;
|
||||
|
||||
if(ataReader.FindReadCommand())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot find correct read command: {0}.", ataReader.ErrorMessage);
|
||||
ErrorMessage(ataReader.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,6 +124,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read: {0}.", ataReader.ErrorMessage);
|
||||
ErrorMessage(ataReader.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,27 +134,36 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
byte sectors = ataReader.Sectors;
|
||||
|
||||
UpdateStatus?.Invoke($"Device reports {blocks} blocks ({blocks * blockSize} bytes).");
|
||||
UpdateStatus
|
||||
?.Invoke($"Device reports {cylinders} cylinders {heads} heads {sectors} sectors per track.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Device reports {cylinders} cylinders {heads} heads {sectors} sectors per track.");
|
||||
|
||||
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");
|
||||
UpdateStatus?.Invoke($"Device reports {blockSize} bytes per logical 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} cylinders {1} heads {2} sectors per track.", cylinders, heads,
|
||||
sectors);
|
||||
|
||||
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 physical block.", physicalsectorsize);
|
||||
|
||||
bool removable = !dev.IsCompactFlash &&
|
||||
ataId.GeneralConfiguration.HasFlag(Identify.GeneralConfigurationBit.Removable);
|
||||
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
|
||||
ResumeSupport.Process(ataReader.IsLba, removable, blocks, dev.Manufacturer, dev.Model, dev.Serial,
|
||||
dev.PlatformId, ref resume, ref currentTry, ref extents);
|
||||
if(currentTry == null || extents == null)
|
||||
|
||||
if(currentTry == null ||
|
||||
extents == null)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke("Could not process resume file, not continuing...");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -157,7 +173,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
bool ret = true;
|
||||
|
||||
if(dev.IsUsb && dev.UsbDescriptors != null &&
|
||||
if(dev.IsUsb &&
|
||||
dev.UsbDescriptors != null &&
|
||||
!outputPlugin.SupportedMediaTags.Contains(MediaTagType.USB_Descriptors))
|
||||
{
|
||||
ret = false;
|
||||
@@ -165,7 +182,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ErrorMessage("Output format does not support USB descriptors.");
|
||||
}
|
||||
|
||||
if(dev.IsPcmcia && dev.Cis != null &&
|
||||
if(dev.IsPcmcia &&
|
||||
dev.Cis != null &&
|
||||
!outputPlugin.SupportedMediaTags.Contains(MediaTagType.PCMCIA_CIS))
|
||||
{
|
||||
ret = false;
|
||||
@@ -183,10 +201,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(!ret)
|
||||
{
|
||||
dumpLog.WriteLine("Several media tags not supported, {0}continuing...", force ? "" : "not ");
|
||||
if(force) ErrorMessage("Several media tags not supported, continuing...");
|
||||
|
||||
if(force)
|
||||
ErrorMessage("Several media tags not supported, continuing...");
|
||||
else
|
||||
{
|
||||
StoppingErrorMessage?.Invoke("Several media tags not supported, not continuing...");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -200,9 +221,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
dumpLog.WriteLine("Error creating output image, not continuing.");
|
||||
dumpLog.WriteLine(outputPlugin.ErrorMessage);
|
||||
|
||||
StoppingErrorMessage?.Invoke("Error creating output image, not continuing." +
|
||||
Environment.NewLine +
|
||||
outputPlugin.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,7 +235,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(ataReader.IsLba)
|
||||
{
|
||||
UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time.");
|
||||
if(skip < blocksToRead) skip = blocksToRead;
|
||||
|
||||
if(skip < blocksToRead)
|
||||
skip = blocksToRead;
|
||||
|
||||
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IbgLog(outputPrefix + ".ibg", ATA_PROFILE);
|
||||
@@ -229,6 +254,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DateTime timeSpeedStart = DateTime.UtcNow;
|
||||
ulong sectorSpeedStart = 0;
|
||||
InitProgress?.Invoke();
|
||||
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
@@ -236,14 +262,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks - i < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
if(blocks - i < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
||||
if(currentSpeed > maxSpeed &&
|
||||
currentSpeed != 0)
|
||||
maxSpeed = currentSpeed;
|
||||
|
||||
if(currentSpeed < minSpeed &&
|
||||
currentSpeed != 0)
|
||||
minSpeed = currentSpeed;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)",
|
||||
@@ -262,9 +295,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i + skip > blocks) skip = (uint)(blocks - i);
|
||||
if(i + skip > blocks)
|
||||
skip = (uint)(blocks - i);
|
||||
|
||||
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
|
||||
for(ulong b = i; b < i + skip; b++)
|
||||
resume.BadBlocks.Add(b);
|
||||
|
||||
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
||||
|
||||
@@ -281,7 +316,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.NextBlock = i + blocksToRead;
|
||||
|
||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||
if(elapsed < 1) continue;
|
||||
|
||||
if(elapsed < 1)
|
||||
continue;
|
||||
|
||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
||||
sectorSpeedStart = 0;
|
||||
@@ -291,23 +328,32 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
end = DateTime.Now;
|
||||
EndProgress?.Invoke();
|
||||
mhddLog.Close();
|
||||
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
blockSize * (double)(blocks + 1) / 1024 /
|
||||
(totalDuration / 1000), devicePath);
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average write speed {(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
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("Average dump speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||
|
||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
||||
|
||||
#region Trimming
|
||||
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
|
||||
if(resume.BadBlocks.Count > 0 &&
|
||||
!aborted &&
|
||||
!notrim &&
|
||||
newTrim)
|
||||
{
|
||||
start = DateTime.UtcNow;
|
||||
UpdateStatus?.Invoke("Trimming bad sectors");
|
||||
@@ -315,6 +361,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
InitProgress?.Invoke();
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(aborted)
|
||||
@@ -322,6 +369,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -331,7 +379,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
totalDuration += duration;
|
||||
|
||||
if(error) continue;
|
||||
if(error)
|
||||
continue;
|
||||
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
@@ -346,7 +395,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#endregion Trimming
|
||||
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||
if(resume.BadBlocks.Count > 0 &&
|
||||
!aborted &&
|
||||
retryPasses > 0)
|
||||
{
|
||||
int pass = 1;
|
||||
bool forward = true;
|
||||
@@ -354,6 +405,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
InitProgress?.Invoke();
|
||||
repeatRetryLba:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(aborted)
|
||||
@@ -361,6 +413,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -380,15 +433,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(persistent) outputPlugin.WriteSector(cmdBuf, badSector);
|
||||
else if(persistent)
|
||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
if(pass < retryPasses &&
|
||||
!aborted &&
|
||||
resume.BadBlocks.Count > 0)
|
||||
{
|
||||
pass++;
|
||||
forward = !forward;
|
||||
resume.BadBlocks.Sort();
|
||||
resume.BadBlocks.Reverse();
|
||||
|
||||
goto repeatRetryLba;
|
||||
}
|
||||
|
||||
@@ -409,6 +466,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DateTime timeSpeedStart = DateTime.UtcNow;
|
||||
ulong sectorSpeedStart = 0;
|
||||
InitProgress?.Invoke();
|
||||
|
||||
for(ushort cy = 0; cy < cylinders; cy++)
|
||||
{
|
||||
for(byte hd = 0; hd < heads; hd++)
|
||||
@@ -420,16 +478,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
||||
if(currentSpeed > maxSpeed &&
|
||||
currentSpeed != 0)
|
||||
maxSpeed = currentSpeed;
|
||||
|
||||
if(currentSpeed < minSpeed &&
|
||||
currentSpeed != 0)
|
||||
minSpeed = currentSpeed;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
PulseProgress
|
||||
?.Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
|
||||
PulseProgress?.
|
||||
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
|
||||
|
||||
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
|
||||
|
||||
@@ -440,10 +504,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
mhddLog.Write(currentBlock, duration);
|
||||
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
||||
DateTime writeStart = DateTime.Now;
|
||||
|
||||
outputPlugin.WriteSector(cmdBuf,
|
||||
(ulong)((cy * heads + hd) * sectors + (sc - 1)));
|
||||
|
||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||
extents.Add(currentBlock);
|
||||
|
||||
dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", cy, hd,
|
||||
sc);
|
||||
}
|
||||
@@ -454,8 +521,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
ibgLog.Write(currentBlock, 0);
|
||||
DateTime writeStart = DateTime.Now;
|
||||
|
||||
outputPlugin.WriteSector(new byte[blockSize],
|
||||
(ulong)((cy * heads + hd) * sectors + (sc - 1)));
|
||||
|
||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||
}
|
||||
|
||||
@@ -463,7 +532,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentBlock++;
|
||||
|
||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||
if(elapsed < 1) continue;
|
||||
|
||||
if(elapsed < 1)
|
||||
continue;
|
||||
|
||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
||||
sectorSpeedStart = 0;
|
||||
@@ -475,25 +546,37 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
end = DateTime.Now;
|
||||
EndProgress?.Invoke();
|
||||
mhddLog.Close();
|
||||
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
blockSize * (double)(blocks + 1) / 1024 /
|
||||
(totalDuration / 1000), devicePath);
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average write speed {(double)blockSize * (double)(blocks + 1) / 1024 / (imageWriteDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
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("Average dump speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||
|
||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 /
|
||||
(imageWriteDuration / 1000));
|
||||
}
|
||||
|
||||
foreach(ulong bad in resume.BadBlocks) dumpLog.WriteLine("Sector {0} could not be read.", bad);
|
||||
foreach(ulong bad in resume.BadBlocks)
|
||||
dumpLog.WriteLine("Sector {0} could not be read.", bad);
|
||||
|
||||
outputPlugin.SetDumpHardware(resume.Tries);
|
||||
if(preSidecar != null) outputPlugin.SetCicmMetadata(preSidecar);
|
||||
|
||||
if(preSidecar != null)
|
||||
outputPlugin.SetCicmMetadata(preSidecar);
|
||||
|
||||
dumpLog.WriteLine("Closing output file.");
|
||||
UpdateStatus?.Invoke("Closing output file.");
|
||||
DateTime closeStart = DateTime.Now;
|
||||
@@ -506,20 +589,24 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
double totalChkDuration = 0;
|
||||
|
||||
if(!nometadata)
|
||||
{
|
||||
dumpLog.WriteLine("Creating sidecar.");
|
||||
UpdateStatus?.Invoke("Creating sidecar.");
|
||||
FiltersList filters = new FiltersList();
|
||||
var filters = new FiltersList();
|
||||
IFilter filter = filters.GetFilter(outputPath);
|
||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
||||
|
||||
if(!inputPlugin.Open(filter))
|
||||
{
|
||||
StoppingErrorMessage?.Invoke("Could not open created image.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -533,13 +620,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecarClass.EndProgressEvent2 += EndProgress2;
|
||||
sidecarClass.UpdateStatusEvent += UpdateStatus;
|
||||
CICMMetadataType sidecar = sidecarClass.Create();
|
||||
|
||||
if(preSidecar != null)
|
||||
{
|
||||
preSidecar.BlockMedia = sidecar.BlockMedia;
|
||||
sidecar = preSidecar;
|
||||
}
|
||||
|
||||
if(dev.IsUsb && dev.UsbDescriptors != null)
|
||||
if(dev.IsUsb &&
|
||||
dev.UsbDescriptors != null)
|
||||
{
|
||||
dumpLog.WriteLine("Reading USB descriptors.");
|
||||
UpdateStatus?.Invoke("Reading USB descriptors.");
|
||||
@@ -548,18 +637,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(ret)
|
||||
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,
|
||||
Image = outputPath, Size = (ulong)dev.UsbDescriptors.Length,
|
||||
Checksums = Checksum.GetChecksums(dev.UsbDescriptors).ToArray()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if(dev.IsPcmcia && dev.Cis != null)
|
||||
if(dev.IsPcmcia &&
|
||||
dev.Cis != null)
|
||||
{
|
||||
dumpLog.WriteLine("Reading PCMCIA CIS.");
|
||||
UpdateStatus?.Invoke("Reading PCMCIA CIS.");
|
||||
@@ -570,8 +657,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
CIS = new DumpType
|
||||
{
|
||||
Image = outputPath,
|
||||
Size = (ulong)dev.Cis.Length,
|
||||
Image = outputPath, Size = (ulong)dev.Cis.Length,
|
||||
Checksums = Checksum.GetChecksums(dev.Cis).ToArray()
|
||||
}
|
||||
};
|
||||
@@ -579,6 +665,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpLog.WriteLine("Decoding PCMCIA CIS.");
|
||||
UpdateStatus?.Invoke("Decoding PCMCIA CIS.");
|
||||
Tuple[] tuples = CIS.GetTuples(dev.Cis);
|
||||
|
||||
if(tuples != null)
|
||||
foreach(Tuple tuple in tuples)
|
||||
switch(tuple.Code)
|
||||
@@ -591,6 +678,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode =
|
||||
manfid.ManufacturerID;
|
||||
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true;
|
||||
@@ -604,8 +692,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
|
||||
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
|
||||
|
||||
sidecar.BlockMedia[0].PCMCIA.Compliance =
|
||||
$"{vers.MajorVersion}.{vers.MinorVersion}";
|
||||
|
||||
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation =
|
||||
vers.AdditionalInformation;
|
||||
}
|
||||
@@ -621,8 +711,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
Identify = new DumpType
|
||||
{
|
||||
Image = outputPath,
|
||||
Size = (ulong)cmdBuf.Length,
|
||||
Image = outputPath, Size = (ulong)cmdBuf.Length,
|
||||
Checksums = Checksum.GetChecksums(cmdBuf).ToArray()
|
||||
}
|
||||
};
|
||||
@@ -631,13 +720,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
totalChkDuration = (chkEnd - chkStart).TotalMilliseconds;
|
||||
UpdateStatus?.Invoke($"Sidecar created in {(chkEnd - chkStart).TotalSeconds} seconds.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average checksum speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
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("Average checksum speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
||||
|
||||
List<(ulong start, string type)> filesystems = new List<(ulong start, string type)>();
|
||||
|
||||
if(sidecar.BlockMedia[0].FileSystemInformation != null)
|
||||
filesystems.AddRange(from partition in sidecar.BlockMedia[0].FileSystemInformation
|
||||
where partition.FileSystems != null
|
||||
@@ -645,26 +738,29 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
select (partition.StartSector, fileSystem.Type));
|
||||
|
||||
if(filesystems.Count > 0)
|
||||
foreach(var filesystem in filesystems.Select(o => new {o.start, o.type}).Distinct())
|
||||
foreach(var filesystem in filesystems.Select(o => new
|
||||
{
|
||||
UpdateStatus
|
||||
?.Invoke($"Found filesystem {filesystem.type} at sector {filesystem.start}");
|
||||
o.start, o.type
|
||||
}).Distinct())
|
||||
{
|
||||
UpdateStatus?.
|
||||
Invoke($"Found filesystem {filesystem.type} at sector {filesystem.start}");
|
||||
|
||||
dumpLog.WriteLine("Found filesystem {0} at sector {1}", filesystem.type,
|
||||
filesystem.start);
|
||||
}
|
||||
|
||||
string xmlDskTyp, xmlDskSubTyp;
|
||||
(string type, string subType) xmlType;
|
||||
|
||||
if(dev.IsCompactFlash)
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.CompactFlash, out xmlDskTyp,
|
||||
out xmlDskSubTyp);
|
||||
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.CompactFlash);
|
||||
else if(dev.IsPcmcia)
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.PCCardTypeI, out xmlDskTyp,
|
||||
out xmlDskSubTyp);
|
||||
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.PCCardTypeI);
|
||||
else
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD, out xmlDskTyp,
|
||||
out xmlDskSubTyp);
|
||||
sidecar.BlockMedia[0].DiskType = xmlDskTyp;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp;
|
||||
xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD);
|
||||
|
||||
sidecar.BlockMedia[0].DiskType = xmlType.type;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlType.subType;
|
||||
sidecar.BlockMedia[0].Interface = "ATA";
|
||||
sidecar.BlockMedia[0].LogicalBlocks = blocks;
|
||||
sidecar.BlockMedia[0].PhysicalBlockSize = physicalsectorsize;
|
||||
@@ -673,7 +769,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.BlockMedia[0].Model = dev.Model;
|
||||
sidecar.BlockMedia[0].Serial = dev.Serial;
|
||||
sidecar.BlockMedia[0].Size = blocks * blockSize;
|
||||
if(cylinders > 0 && heads > 0 && sectors > 0)
|
||||
|
||||
if(cylinders > 0 &&
|
||||
heads > 0 &&
|
||||
sectors > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].Cylinders = cylinders;
|
||||
sidecar.BlockMedia[0].CylindersSpecified = true;
|
||||
@@ -685,30 +784,40 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
UpdateStatus?.Invoke("Writing metadata sidecar");
|
||||
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
var xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
||||
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
UpdateStatus
|
||||
?.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
|
||||
?.Invoke($"Average speed: {(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
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?.
|
||||
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($"Slowest speed burst: {minSpeed:F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"{resume.BadBlocks.Count} sectors could not be read.");
|
||||
if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
|
||||
|
||||
if(resume.BadBlocks.Count > 0)
|
||||
resume.BadBlocks.Sort();
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
}
|
||||
|
||||
if(dev.IsCompactFlash) Statistics.AddMedia(MediaType.CompactFlash, true);
|
||||
else if(dev.IsPcmcia) Statistics.AddMedia(MediaType.PCCardTypeI, true);
|
||||
else Statistics.AddMedia(MediaType.GENERIC_HDD, true);
|
||||
if(dev.IsCompactFlash)
|
||||
Statistics.AddMedia(MediaType.CompactFlash, true);
|
||||
else if(dev.IsPcmcia)
|
||||
Statistics.AddMedia(MediaType.PCCardTypeI, true);
|
||||
else
|
||||
Statistics.AddMedia(MediaType.GENERIC_HDD, true);
|
||||
}
|
||||
else StoppingErrorMessage?.Invoke("Unable to communicate with ATA device.");
|
||||
else
|
||||
StoppingErrorMessage?.Invoke("Unable to communicate with ATA device.");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -400,8 +400,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke($"Blocksize changed to {blockSize} bytes at block {currentBlock}");
|
||||
dumpLog.WriteLine("Blocksize changed to {0} bytes at block {1}", blockSize, currentBlock);
|
||||
|
||||
sense = dev.Space(out senseBuf, SscSpaceCodes.LogicalBlock, -1, dev.Timeout,
|
||||
out duration);
|
||||
sense = dev.Space(out senseBuf, SscSpaceCodes.LogicalBlock, -1, dev.Timeout, out duration);
|
||||
|
||||
totalDuration += duration;
|
||||
|
||||
@@ -891,8 +890,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke($"Blocksize changed to {blockSize} bytes at block {currentBlock}");
|
||||
dumpLog.WriteLine("Blocksize changed to {0} bytes at block {1}", blockSize, currentBlock);
|
||||
|
||||
sense = dev.Space(out senseBuf, SscSpaceCodes.LogicalBlock, -1, dev.Timeout,
|
||||
out duration);
|
||||
sense = dev.Space(out senseBuf, SscSpaceCodes.LogicalBlock, -1, dev.Timeout, out duration);
|
||||
|
||||
totalDuration += duration;
|
||||
|
||||
@@ -1314,11 +1312,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(dskType);
|
||||
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp,
|
||||
out string xmlDskSubTyp);
|
||||
(string type, string subType) xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(dskType);
|
||||
|
||||
sidecar.BlockMedia[0].DiskType = xmlDskTyp;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp;
|
||||
sidecar.BlockMedia[0].DiskType = xmlType.type;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlType.subType;
|
||||
|
||||
// TODO: Implement device firmware revision
|
||||
if(!dev.IsRemovable ||
|
||||
|
||||
@@ -47,25 +47,22 @@ using MediaType = DiscImageChef.CommonTypes.MediaType;
|
||||
|
||||
namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements dumping a MultiMediaCard or SecureDigital flash card
|
||||
/// </summary>
|
||||
/// <summary>Implements dumping a MultiMediaCard or SecureDigital flash card</summary>
|
||||
public partial class Dump
|
||||
{
|
||||
/// <summary>
|
||||
/// Dumps a MultiMediaCard or SecureDigital flash card
|
||||
/// </summary>
|
||||
/// <summary>Dumps a MultiMediaCard or SecureDigital flash card</summary>
|
||||
public void SecureDigital()
|
||||
{
|
||||
if(dumpRaw)
|
||||
{
|
||||
if(force)
|
||||
ErrorMessage
|
||||
?.Invoke("Raw dumping is not supported in MultiMediaCard or SecureDigital devices. Continuing...");
|
||||
ErrorMessage?.
|
||||
Invoke("Raw dumping is not supported in MultiMediaCard or SecureDigital devices. Continuing...");
|
||||
else
|
||||
{
|
||||
StoppingErrorMessage
|
||||
?.Invoke("Raw dumping is not supported in MultiMediaCard or SecureDigital devices. Aborting...");
|
||||
StoppingErrorMessage?.
|
||||
Invoke("Raw dumping is not supported in MultiMediaCard or SecureDigital devices. Aborting...");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -94,23 +91,30 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke("Reading Extended CSD");
|
||||
dumpLog.WriteLine("Reading Extended CSD");
|
||||
sense = dev.ReadExtendedCsd(out ecsd, out _, TIMEOUT, out duration);
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
ExtendedCSD ecsdDecoded = Decoders.MMC.Decoders.DecodeExtendedCSD(ecsd);
|
||||
blocksToRead = ecsdDecoded.OptimalReadSize;
|
||||
blocks = ecsdDecoded.SectorCount;
|
||||
blockSize = (uint)(ecsdDecoded.SectorSize == 1 ? 4096 : 512);
|
||||
if(ecsdDecoded.NativeSectorSize == 0) physicalBlockSize = 512;
|
||||
else if(ecsdDecoded.NativeSectorSize == 1) physicalBlockSize = 4096;
|
||||
|
||||
if(ecsdDecoded.NativeSectorSize == 0)
|
||||
physicalBlockSize = 512;
|
||||
else if(ecsdDecoded.NativeSectorSize == 1)
|
||||
physicalBlockSize = 4096;
|
||||
|
||||
// Supposing it's high-capacity MMC if it has Extended CSD...
|
||||
byteAddressed = false;
|
||||
mediaTags.Add(MediaTagType.MMC_ExtendedCSD, null);
|
||||
}
|
||||
else ecsd = null;
|
||||
else
|
||||
ecsd = null;
|
||||
|
||||
UpdateStatus?.Invoke("Reading CSD");
|
||||
dumpLog.WriteLine("Reading CSD");
|
||||
sense = dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
if(blocks == 0)
|
||||
@@ -122,13 +126,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
mediaTags.Add(MediaTagType.MMC_CSD, null);
|
||||
}
|
||||
else csd = null;
|
||||
else
|
||||
csd = null;
|
||||
|
||||
UpdateStatus?.Invoke("Reading OCR");
|
||||
dumpLog.WriteLine("Reading OCR");
|
||||
sense = dev.ReadOcr(out ocr, out _, TIMEOUT, out duration);
|
||||
if(sense) ocr = null;
|
||||
else mediaTags.Add(MediaTagType.MMC_OCR, null);
|
||||
|
||||
if(sense)
|
||||
ocr = null;
|
||||
else
|
||||
mediaTags.Add(MediaTagType.MMC_OCR, null);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -138,30 +146,41 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke("Reading CSD");
|
||||
dumpLog.WriteLine("Reading CSD");
|
||||
sense = dev.ReadCsd(out csd, out _, TIMEOUT, out duration);
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SecureDigital.CSD csdDecoded = Decoders.SecureDigital.Decoders.DecodeCSD(csd);
|
||||
|
||||
blocks = (ulong)(csdDecoded.Structure == 0
|
||||
? (csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2)
|
||||
: (csdDecoded.Size + 1) * 1024);
|
||||
|
||||
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
|
||||
|
||||
// Structure >=1 for SDHC/SDXC, so that's block addressed
|
||||
byteAddressed = csdDecoded.Structure == 0;
|
||||
mediaTags.Add(MediaTagType.SD_CSD, null);
|
||||
}
|
||||
else csd = null;
|
||||
else
|
||||
csd = null;
|
||||
|
||||
UpdateStatus?.Invoke("Reading OCR");
|
||||
dumpLog.WriteLine("Reading OCR");
|
||||
sense = dev.ReadSdocr(out ocr, out _, TIMEOUT, out duration);
|
||||
if(sense) ocr = null;
|
||||
else mediaTags.Add(MediaTagType.SD_OCR, null);
|
||||
|
||||
if(sense)
|
||||
ocr = null;
|
||||
else
|
||||
mediaTags.Add(MediaTagType.SD_OCR, null);
|
||||
|
||||
UpdateStatus?.Invoke("Reading SCR");
|
||||
dumpLog.WriteLine("Reading SCR");
|
||||
sense = dev.ReadScr(out scr, out _, TIMEOUT, out duration);
|
||||
if(sense) scr = null;
|
||||
else mediaTags.Add(MediaTagType.SD_SCR, null);
|
||||
|
||||
if(sense)
|
||||
scr = null;
|
||||
else
|
||||
mediaTags.Add(MediaTagType.SD_SCR, null);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -170,8 +189,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke("Reading CID");
|
||||
dumpLog.WriteLine("Reading CID");
|
||||
sense = dev.ReadCid(out byte[] cid, out _, TIMEOUT, out duration);
|
||||
if(sense) cid = null;
|
||||
else mediaTags.Add(dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID : MediaTagType.MMC_CID, null);
|
||||
|
||||
if(sense)
|
||||
cid = null;
|
||||
else
|
||||
mediaTags.Add(dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID : MediaTagType.MMC_CID, null);
|
||||
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
@@ -184,6 +206,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
dumpLog.WriteLine("Unable to get device size.");
|
||||
StoppingErrorMessage?.Invoke("Unable to get device size.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,30 +220,39 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
error = dev.Read(out cmdBuf, out _, 0, blockSize, blocksToRead, byteAddressed, TIMEOUT, out duration);
|
||||
|
||||
if(error) blocksToRead /= 2;
|
||||
if(error)
|
||||
blocksToRead /= 2;
|
||||
|
||||
if(!error || blocksToRead == 1) break;
|
||||
if(!error ||
|
||||
blocksToRead == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if(error)
|
||||
{
|
||||
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.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");
|
||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||
|
||||
if(skip < blocksToRead) skip = blocksToRead;
|
||||
if(skip < blocksToRead)
|
||||
skip = blocksToRead;
|
||||
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
|
||||
ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformId,
|
||||
ref resume, ref currentTry, ref extents);
|
||||
if(currentTry == null || extents == null)
|
||||
|
||||
if(currentTry == null ||
|
||||
extents == null)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke("Could not process resume file, not continuing...");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -228,7 +260,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
foreach(MediaTagType tag in mediaTags.Keys)
|
||||
{
|
||||
if(outputPlugin.SupportedMediaTags.Contains(tag)) continue;
|
||||
if(outputPlugin.SupportedMediaTags.Contains(tag))
|
||||
continue;
|
||||
|
||||
ret = false;
|
||||
dumpLog.WriteLine($"Output format does not support {tag}.");
|
||||
@@ -246,12 +279,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
dumpLog.WriteLine("Several media tags not supported, not continuing...");
|
||||
StoppingErrorMessage?.Invoke("Several media tags not supported, not continuing...");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MhddLog mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
IbgLog ibgLog = new IbgLog(outputPrefix + ".ibg", SD_PROFILE);
|
||||
var mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
var ibgLog = new IbgLog(outputPrefix + ".ibg", SD_PROFILE);
|
||||
|
||||
ret = outputPlugin.Create(outputPath,
|
||||
dev.Type == DeviceType.SecureDigital ? MediaType.SecureDigital : MediaType.MMC,
|
||||
formatOptions, blocks, blockSize);
|
||||
@@ -261,8 +296,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
dumpLog.WriteLine("Error creating output image, not continuing.");
|
||||
dumpLog.WriteLine(outputPlugin.ErrorMessage);
|
||||
|
||||
StoppingErrorMessage?.Invoke("Error creating output image, not continuing." + Environment.NewLine +
|
||||
outputPlugin.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -279,6 +316,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ulong sectorSpeedStart = 0;
|
||||
|
||||
InitProgress?.Invoke();
|
||||
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
@@ -286,14 +324,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks - i < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
if(blocks - i < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
||||
if(currentSpeed > maxSpeed &&
|
||||
currentSpeed != 0)
|
||||
maxSpeed = currentSpeed;
|
||||
|
||||
if(currentSpeed < minSpeed &&
|
||||
currentSpeed != 0)
|
||||
minSpeed = currentSpeed;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
|
||||
@@ -313,9 +358,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i + skip > blocks) skip = (uint)(blocks - i);
|
||||
if(i + skip > blocks)
|
||||
skip = (uint)(blocks - i);
|
||||
|
||||
for(ulong b = i; b < i + skip; b++) resume.BadBlocks.Add(b);
|
||||
for(ulong b = i; b < i + skip; b++)
|
||||
resume.BadBlocks.Add(b);
|
||||
|
||||
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
||||
|
||||
@@ -332,7 +379,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.NextBlock = i + blocksToRead;
|
||||
|
||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||
if(elapsed < 1) continue;
|
||||
|
||||
if(elapsed < 1)
|
||||
continue;
|
||||
|
||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
||||
sectorSpeedStart = 0;
|
||||
@@ -342,22 +391,32 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
end = DateTime.Now;
|
||||
EndProgress?.Invoke();
|
||||
mhddLog.Close();
|
||||
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000),
|
||||
devicePath);
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average write speed {(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
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("Average dump speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||
|
||||
dumpLog.WriteLine("Average write speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration);
|
||||
|
||||
#region Trimming
|
||||
if(resume.BadBlocks.Count > 0 && !aborted && !notrim && newTrim)
|
||||
if(resume.BadBlocks.Count > 0 &&
|
||||
!aborted &&
|
||||
!notrim &&
|
||||
newTrim)
|
||||
{
|
||||
start = DateTime.UtcNow;
|
||||
UpdateStatus?.Invoke("Trimming bad sectors");
|
||||
@@ -365,6 +424,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
InitProgress?.Invoke();
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(aborted)
|
||||
@@ -372,6 +432,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -382,7 +443,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
totalDuration += duration;
|
||||
|
||||
if(error) continue;
|
||||
if(error)
|
||||
continue;
|
||||
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
@@ -397,7 +459,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#endregion Trimming
|
||||
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted && retryPasses > 0)
|
||||
if(resume.BadBlocks.Count > 0 &&
|
||||
!aborted &&
|
||||
retryPasses > 0)
|
||||
{
|
||||
int pass = 1;
|
||||
bool forward = true;
|
||||
@@ -406,6 +470,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
InitProgress?.Invoke();
|
||||
repeatRetryLba:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(aborted)
|
||||
@@ -413,6 +478,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -433,15 +499,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent) outputPlugin.WriteSector(cmdBuf, badSector);
|
||||
else if(runningPersistent)
|
||||
outputPlugin.WriteSector(cmdBuf, badSector);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
if(pass < retryPasses &&
|
||||
!aborted &&
|
||||
resume.BadBlocks.Count > 0)
|
||||
{
|
||||
pass++;
|
||||
forward = !forward;
|
||||
resume.BadBlocks.Sort();
|
||||
resume.BadBlocks.Reverse();
|
||||
|
||||
goto repeatRetryLba;
|
||||
}
|
||||
|
||||
@@ -452,7 +522,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
|
||||
outputPlugin.SetDumpHardware(resume.Tries);
|
||||
if(preSidecar != null) outputPlugin.SetCicmMetadata(preSidecar);
|
||||
|
||||
if(preSidecar != null)
|
||||
outputPlugin.SetCicmMetadata(preSidecar);
|
||||
|
||||
dumpLog.WriteLine("Closing output file.");
|
||||
UpdateStatus?.Invoke("Closing output file.");
|
||||
DateTime closeStart = DateTime.Now;
|
||||
@@ -465,18 +538,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
double totalChkDuration = 0;
|
||||
|
||||
if(!nometadata)
|
||||
{
|
||||
UpdateStatus?.Invoke("Creating sidecar.");
|
||||
dumpLog.WriteLine("Creating sidecar.");
|
||||
FiltersList filters = new FiltersList();
|
||||
var filters = new FiltersList();
|
||||
IFilter filter = filters.GetFilter(outputPath);
|
||||
IMediaImage inputPlugin = ImageFormat.Detect(filter);
|
||||
if(!inputPlugin.Open(filter)) StoppingErrorMessage?.Invoke("Could not open created image.");
|
||||
|
||||
if(!inputPlugin.Open(filter))
|
||||
StoppingErrorMessage?.Invoke("Could not open created image.");
|
||||
|
||||
DateTime chkStart = DateTime.UtcNow;
|
||||
sidecarClass = new Sidecar(inputPlugin, outputPath, filter.Id, encoding);
|
||||
@@ -499,9 +576,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
case DeviceType.MMC:
|
||||
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
||||
|
||||
break;
|
||||
case DeviceType.SecureDigital:
|
||||
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -513,23 +592,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
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 =
|
||||
outputPlugin.WriteMediaTag(cid,
|
||||
dev.Type == DeviceType.SecureDigital
|
||||
? MediaTagType.SD_CID
|
||||
dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CID
|
||||
: MediaTagType.MMC_CID);
|
||||
|
||||
// Cannot write CID to image
|
||||
if(!ret && !force)
|
||||
if(!ret &&
|
||||
!force)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot write CID to output image.");
|
||||
|
||||
StoppingErrorMessage?.Invoke("Cannot write CID to output image." + Environment.NewLine +
|
||||
outputPlugin.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -538,23 +617,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
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 =
|
||||
outputPlugin.WriteMediaTag(csd,
|
||||
dev.Type == DeviceType.SecureDigital
|
||||
? MediaTagType.SD_CSD
|
||||
dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_CSD
|
||||
: MediaTagType.MMC_CSD);
|
||||
|
||||
// Cannot write CSD to image
|
||||
if(!ret && !force)
|
||||
if(!ret &&
|
||||
!force)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot write CSD to output image.");
|
||||
|
||||
StoppingErrorMessage?.Invoke("Cannot write CSD to output image." + Environment.NewLine +
|
||||
outputPlugin.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -563,20 +642,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
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);
|
||||
|
||||
// Cannot write Extended CSD to image
|
||||
if(!ret && !force)
|
||||
if(!ret &&
|
||||
!force)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot write Extended CSD to output image.");
|
||||
|
||||
StoppingErrorMessage?.Invoke("Cannot write Extended CSD to output image." +
|
||||
Environment.NewLine +
|
||||
outputPlugin.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -585,23 +665,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
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 =
|
||||
outputPlugin.WriteMediaTag(ocr,
|
||||
dev.Type == DeviceType.SecureDigital
|
||||
? MediaTagType.SD_OCR
|
||||
dev.Type == DeviceType.SecureDigital ? MediaTagType.SD_OCR
|
||||
: MediaTagType.MMC_OCR);
|
||||
|
||||
// Cannot write OCR to image
|
||||
if(!ret && !force)
|
||||
if(!ret &&
|
||||
!force)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot write OCR to output image.");
|
||||
|
||||
StoppingErrorMessage?.Invoke("Cannot write OCR to output image." + Environment.NewLine +
|
||||
outputPlugin.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -610,19 +690,20 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
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);
|
||||
|
||||
// Cannot write SCR to image
|
||||
if(!ret && !force)
|
||||
if(!ret &&
|
||||
!force)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot write SCR to output image.");
|
||||
|
||||
StoppingErrorMessage?.Invoke("Cannot write SCR to output image." + Environment.NewLine +
|
||||
outputPlugin.ErrorMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -633,11 +714,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.BlockMedia[0].MultiMediaCard.CID = cidDump;
|
||||
sidecar.BlockMedia[0].MultiMediaCard.CSD = csdDump;
|
||||
sidecar.BlockMedia[0].MultiMediaCard.OCR = ocrDump;
|
||||
|
||||
break;
|
||||
case DeviceType.SecureDigital:
|
||||
sidecar.BlockMedia[0].SecureDigital.CID = cidDump;
|
||||
sidecar.BlockMedia[0].SecureDigital.CSD = csdDump;
|
||||
sidecar.BlockMedia[0].SecureDigital.OCR = ocrDump;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -645,29 +728,36 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
||||
UpdateStatus
|
||||
?.Invoke($"Average checksum speed {(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
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("Average checksum speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
||||
|
||||
string xmlDskTyp = null, xmlDskSubTyp = null;
|
||||
(string type, string subType) xmlType = (null, null);
|
||||
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.MMC:
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.MMC, out xmlDskTyp,
|
||||
out xmlDskSubTyp);
|
||||
xmlType =
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.MMC);
|
||||
|
||||
sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(MediaType.MMC);
|
||||
|
||||
break;
|
||||
case DeviceType.SecureDigital:
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.SecureDigital, out xmlDskTyp,
|
||||
out xmlDskSubTyp);
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(MediaType.SecureDigital);
|
||||
sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(MediaType.SecureDigital);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sidecar.BlockMedia[0].DiskType = xmlDskTyp;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp;
|
||||
sidecar.BlockMedia[0].DiskType = xmlType.type;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlType.subType;
|
||||
|
||||
// TODO: Implement device firmware revision
|
||||
sidecar.BlockMedia[0].LogicalBlocks = blocks;
|
||||
sidecar.BlockMedia[0].PhysicalBlockSize = physicalBlockSize > 0 ? physicalBlockSize : blockSize;
|
||||
@@ -679,31 +769,38 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
UpdateStatus?.Invoke("Writing metadata sidecar");
|
||||
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
var xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
XmlSerializer xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
||||
var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
UpdateStatus
|
||||
?.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
|
||||
?.Invoke($"Average speed: {(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
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?.
|
||||
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($"Slowest speed burst: {minSpeed:F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"{resume.BadBlocks.Count} sectors could not be read.");
|
||||
UpdateStatus?.Invoke("");
|
||||
if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
|
||||
|
||||
if(resume.BadBlocks.Count > 0)
|
||||
resume.BadBlocks.Sort();
|
||||
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.MMC:
|
||||
Statistics.AddMedia(MediaType.MMC, true);
|
||||
|
||||
break;
|
||||
case DeviceType.SecureDigital:
|
||||
Statistics.AddMedia(MediaType.SecureDigital, true);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,11 +81,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.
|
||||
ErrorWriteLine("Because of the commands sent to a device, dumping XGD must be done with administrative privileges. Cannot continue.");
|
||||
|
||||
dumpLog.WriteLine("Cannot dump XGD without administrative privileges.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(mediaTags.ContainsKey(MediaTagType.DVD_PFI))
|
||||
mediaTags.Remove(MediaTagType.DVD_PFI);
|
||||
|
||||
@@ -1232,10 +1234,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.OpticalDisc[0].Sessions = 1;
|
||||
sidecar.OpticalDisc[0].Dimensions = Dimensions.DimensionsFromMediaType(dskType);
|
||||
|
||||
var xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(dskType);
|
||||
(string type, string subType) xmlType = CommonTypes.Metadata.MediaType.MediaTypeToString(dskType);
|
||||
|
||||
sidecar.OpticalDisc[0].DiscType = xmlDskTyp;
|
||||
sidecar.OpticalDisc[0].DiscSubType = xmlDskSubTyp;
|
||||
sidecar.OpticalDisc[0].DiscType = xmlType.type;
|
||||
sidecar.OpticalDisc[0].DiscSubType = xmlType.subType;
|
||||
|
||||
foreach(KeyValuePair<MediaTagType, byte[]> tag in mediaTags)
|
||||
if(outputPlugin.SupportedMediaTags.Contains(tag.Key))
|
||||
|
||||
@@ -53,9 +53,7 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
public partial class Sidecar
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a metadata sidecar for a block media (e.g. floppy, hard disk, flash card, usb stick)
|
||||
/// </summary>
|
||||
/// <summary>Creates a metadata sidecar for a block media (e.g. floppy, hard disk, flash card, usb stick)</summary>
|
||||
/// <param name="image">Image</param>
|
||||
/// <param name="filterId">Filter uuid</param>
|
||||
/// <param name="imagePath">Image path</param>
|
||||
@@ -63,30 +61,29 @@ namespace DiscImageChef.Core
|
||||
/// <param name="plugins">Image plugins</param>
|
||||
/// <param name="imgChecksums">List of image checksums</param>
|
||||
/// <param name="sidecar">Metadata sidecar</param>
|
||||
void BlockMedia(IMediaImage image, Guid filterId, string imagePath, FileInfo fi,
|
||||
PluginBase plugins,
|
||||
void BlockMedia(IMediaImage image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins,
|
||||
List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar, Encoding encoding)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
sidecar.BlockMedia = new[]
|
||||
{
|
||||
new BlockMediaType
|
||||
{
|
||||
Checksums = imgChecksums.ToArray(),
|
||||
Image = new ImageType
|
||||
Checksums = imgChecksums.ToArray(), Image = new ImageType
|
||||
{
|
||||
format = image.Format,
|
||||
offset = 0,
|
||||
offsetSpecified = true,
|
||||
Value = Path.GetFileName(imagePath)
|
||||
format = image.Format, offset = 0, offsetSpecified = true, Value = Path.GetFileName(imagePath)
|
||||
},
|
||||
Size = (ulong)fi.Length,
|
||||
Sequence = new SequenceType {MediaTitle = image.Info.MediaTitle}
|
||||
Size = (ulong)fi.Length, Sequence = new SequenceType
|
||||
{
|
||||
MediaTitle = image.Info.MediaTitle
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(image.Info.MediaSequence != 0 && image.Info.LastMediaSequence != 0)
|
||||
if(image.Info.MediaSequence != 0 &&
|
||||
image.Info.LastMediaSequence != 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].Sequence.MediaSequence = (uint)image.Info.MediaSequence;
|
||||
sidecar.BlockMedia[0].Sequence.TotalMedia = (uint)image.Info.LastMediaSequence;
|
||||
@@ -98,9 +95,11 @@ namespace DiscImageChef.Core
|
||||
}
|
||||
|
||||
UpdateStatus("Hashing media tags...");
|
||||
|
||||
foreach(MediaTagType tagType in image.Info.ReadableMediaTags)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
switch(tagType)
|
||||
{
|
||||
@@ -109,27 +108,28 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
Identify = new DumpType
|
||||
{
|
||||
Checksums =
|
||||
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY))
|
||||
.ToArray(),
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY)).
|
||||
ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY).Length
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.ATA_IDENTIFY:
|
||||
sidecar.BlockMedia[0].ATA = new ATAType
|
||||
{
|
||||
Identify = new DumpType
|
||||
{
|
||||
Checksums = Checksum
|
||||
.GetChecksums(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY))
|
||||
.ToArray(),
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)).
|
||||
ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.ATA_IDENTIFY).Length
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.PCMCIA_CIS:
|
||||
byte[] cis = image.ReadDiskTag(MediaTagType.PCMCIA_CIS);
|
||||
|
||||
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
|
||||
{
|
||||
CIS = new DumpType
|
||||
@@ -137,7 +137,9 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(cis).ToArray(), Size = (ulong)cis.Length
|
||||
}
|
||||
};
|
||||
|
||||
Tuple[] tuples = CIS.GetTuples(cis);
|
||||
|
||||
if(tuples != null)
|
||||
foreach(Tuple tuple in tuples)
|
||||
switch(tuple.Code)
|
||||
@@ -150,6 +152,7 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode =
|
||||
manfid.ManufacturerID;
|
||||
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true;
|
||||
@@ -163,8 +166,10 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
|
||||
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
|
||||
|
||||
sidecar.BlockMedia[0].PCMCIA.Compliance =
|
||||
$"{vers.MajorVersion}.{vers.MinorVersion}";
|
||||
|
||||
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation =
|
||||
vers.AdditionalInformation;
|
||||
}
|
||||
@@ -178,112 +183,137 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
Inquiry = new DumpType
|
||||
{
|
||||
Checksums = Checksum
|
||||
.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_INQUIRY))
|
||||
.ToArray(),
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_INQUIRY)).
|
||||
ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SCSI_INQUIRY).Length
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.SD_CID:
|
||||
if(sidecar.BlockMedia[0].SecureDigital == null)
|
||||
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
|
||||
|
||||
sidecar.BlockMedia[0].SecureDigital.CID = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CID)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SD_CID).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.SD_CSD:
|
||||
if(sidecar.BlockMedia[0].SecureDigital == null)
|
||||
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
|
||||
|
||||
sidecar.BlockMedia[0].SecureDigital.CSD = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CSD)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SD_CSD).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.SD_SCR:
|
||||
if(sidecar.BlockMedia[0].SecureDigital == null)
|
||||
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
|
||||
|
||||
sidecar.BlockMedia[0].SecureDigital.SCR = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_SCR)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SD_SCR).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.SD_OCR:
|
||||
if(sidecar.BlockMedia[0].SecureDigital == null)
|
||||
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
|
||||
|
||||
sidecar.BlockMedia[0].SecureDigital.OCR = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_OCR)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SD_OCR).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.MMC_CID:
|
||||
if(sidecar.BlockMedia[0].MultiMediaCard == null)
|
||||
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
||||
|
||||
sidecar.BlockMedia[0].MultiMediaCard.CID = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CID)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SD_CID).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.MMC_CSD:
|
||||
if(sidecar.BlockMedia[0].MultiMediaCard == null)
|
||||
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
||||
|
||||
sidecar.BlockMedia[0].MultiMediaCard.CSD = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CSD)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SD_CSD).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.MMC_OCR:
|
||||
if(sidecar.BlockMedia[0].MultiMediaCard == null)
|
||||
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
||||
|
||||
sidecar.BlockMedia[0].MultiMediaCard.OCR = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_OCR)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SD_OCR).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.MMC_ExtendedCSD:
|
||||
if(sidecar.BlockMedia[0].MultiMediaCard == null)
|
||||
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
||||
|
||||
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD))
|
||||
.ToArray(),
|
||||
Checksums =
|
||||
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.USB_Descriptors:
|
||||
if(sidecar.BlockMedia[0].USB == null) sidecar.BlockMedia[0].USB = new USBType();
|
||||
if(sidecar.BlockMedia[0].USB == null)
|
||||
sidecar.BlockMedia[0].USB = new USBType();
|
||||
|
||||
sidecar.BlockMedia[0].USB.Descriptors = new DumpType
|
||||
{
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.USB_Descriptors))
|
||||
.ToArray(),
|
||||
Checksums =
|
||||
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.USB_Descriptors)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.USB_Descriptors).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.SCSI_MODESENSE_6:
|
||||
if(sidecar.BlockMedia[0].SCSI == null) sidecar.BlockMedia[0].SCSI = new SCSIType();
|
||||
if(sidecar.BlockMedia[0].SCSI == null)
|
||||
sidecar.BlockMedia[0].SCSI = new SCSIType();
|
||||
|
||||
sidecar.BlockMedia[0].SCSI.ModeSense = new DumpType
|
||||
{
|
||||
Checksums =
|
||||
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6)).ToArray(),
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6)).
|
||||
ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.SCSI_MODESENSE_10:
|
||||
if(sidecar.BlockMedia[0].SCSI == null) sidecar.BlockMedia[0].SCSI = new SCSIType();
|
||||
if(sidecar.BlockMedia[0].SCSI == null)
|
||||
sidecar.BlockMedia[0].SCSI = new SCSIType();
|
||||
|
||||
sidecar.BlockMedia[0].SCSI.ModeSense10 = new DumpType
|
||||
{
|
||||
Checksums =
|
||||
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10)).ToArray(),
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10)).
|
||||
ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10).Length
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +326,7 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
UpdateStatus("Hashing sectors...");
|
||||
|
||||
Checksum contentChkWorker = new Checksum();
|
||||
var contentChkWorker = new Checksum();
|
||||
|
||||
// For fast debugging, skip checksum
|
||||
//goto skipImageChecksum;
|
||||
@@ -306,11 +336,13 @@ namespace DiscImageChef.Core
|
||||
ulong doneSectors = 0;
|
||||
|
||||
InitProgress2();
|
||||
|
||||
while(doneSectors < sectors)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress2();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -342,29 +374,30 @@ namespace DiscImageChef.Core
|
||||
EndProgress2();
|
||||
}
|
||||
|
||||
MediaType.MediaTypeToString(image.Info.MediaType, out string dskType, out string dskSubType);
|
||||
sidecar.BlockMedia[0].DiskType = dskType;
|
||||
sidecar.BlockMedia[0].DiskSubType = dskSubType;
|
||||
(string type, string subType) diskType = MediaType.MediaTypeToString(image.Info.MediaType);
|
||||
sidecar.BlockMedia[0].DiskType = diskType.type;
|
||||
sidecar.BlockMedia[0].DiskSubType = diskType.subType;
|
||||
Statistics.AddMedia(image.Info.MediaType, false);
|
||||
|
||||
sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(image.Info.MediaType);
|
||||
|
||||
sidecar.BlockMedia[0].LogicalBlocks = image.Info.Sectors;
|
||||
sidecar.BlockMedia[0].LogicalBlockSize = image.Info.SectorSize;
|
||||
|
||||
// TODO: Detect it
|
||||
sidecar.BlockMedia[0].PhysicalBlockSize = image.Info.SectorSize;
|
||||
|
||||
if(image is ITapeImage tapeImage && tapeImage.IsTape)
|
||||
if(image is ITapeImage tapeImage &&
|
||||
tapeImage.IsTape)
|
||||
{
|
||||
List<TapePartitionType> tapePartitions = new List<TapePartitionType>();
|
||||
|
||||
foreach(TapePartition tapePartition in tapeImage.TapePartitions)
|
||||
{
|
||||
TapePartitionType thisPartition = new TapePartitionType
|
||||
var thisPartition = new TapePartitionType
|
||||
{
|
||||
Image = sidecar.BlockMedia[0].Image,
|
||||
Sequence = tapePartition.Number,
|
||||
StartBlock = tapePartition.FirstBlock,
|
||||
EndBlock = tapePartition.LastBlock
|
||||
Image = sidecar.BlockMedia[0].Image, Sequence = tapePartition.Number,
|
||||
StartBlock = tapePartition.FirstBlock, EndBlock = tapePartition.LastBlock
|
||||
};
|
||||
|
||||
if(tapeImage.TapePartitions.Count == 1)
|
||||
@@ -373,9 +406,10 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
UpdateStatus($"Hashing partition {tapePartition.Number}...");
|
||||
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
Checksum tapePartitionChk = new Checksum();
|
||||
var tapePartitionChk = new Checksum();
|
||||
|
||||
// For fast debugging, skip checksum
|
||||
//goto skipImageChecksum;
|
||||
@@ -385,11 +419,13 @@ namespace DiscImageChef.Core
|
||||
ulong doneSectors = 0;
|
||||
|
||||
InitProgress2();
|
||||
|
||||
while(doneSectors < sectors)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress2();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -405,6 +441,7 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
sector = image.ReadSectors(tapePartition.FirstBlock + doneSectors,
|
||||
(uint)(sectors - doneSectors));
|
||||
|
||||
UpdateProgress2("Hashing blocks {0} of {1}", (long)doneSectors, (long)sectors);
|
||||
doneSectors += sectors - doneSectors;
|
||||
}
|
||||
@@ -428,14 +465,11 @@ namespace DiscImageChef.Core
|
||||
|
||||
foreach(TapeFile tapeFile in tapeImage.Files.Where(f => f.Partition == tapePartition.Number))
|
||||
{
|
||||
TapeFileType thisFile = new TapeFileType
|
||||
var thisFile = new TapeFileType
|
||||
{
|
||||
Sequence = tapeFile.File,
|
||||
StartBlock = tapeFile.FirstBlock,
|
||||
Sequence = tapeFile.File, StartBlock = tapeFile.FirstBlock,
|
||||
EndBlock = tapeFile.LastBlock,
|
||||
Image = sidecar.BlockMedia[0].Image,
|
||||
Size = 0,
|
||||
BlockSize = 0
|
||||
Image = sidecar.BlockMedia[0].Image, Size = 0, BlockSize = 0
|
||||
};
|
||||
|
||||
if(tapeImage.Files.Count(f => f.Partition == tapePartition.Number) == 1)
|
||||
@@ -447,9 +481,10 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
UpdateStatus($"Hashing file {tapeFile.File}...");
|
||||
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
Checksum tapeFileChk = new Checksum();
|
||||
var tapeFileChk = new Checksum();
|
||||
|
||||
// For fast debugging, skip checksum
|
||||
//goto skipImageChecksum;
|
||||
@@ -459,11 +494,13 @@ namespace DiscImageChef.Core
|
||||
ulong doneSectors = 0;
|
||||
|
||||
InitProgress2();
|
||||
|
||||
while(doneSectors < sectors)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress2();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -479,6 +516,7 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
sector = image.ReadSectors(tapeFile.FirstBlock + doneSectors,
|
||||
(uint)(sectors - doneSectors));
|
||||
|
||||
UpdateProgress2("Hashing blocks {0} of {1}", (long)doneSectors, (long)sectors);
|
||||
doneSectors += sectors - doneSectors;
|
||||
}
|
||||
@@ -513,36 +551,40 @@ namespace DiscImageChef.Core
|
||||
|
||||
UpdateStatus("Checking filesystems...");
|
||||
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
List<Partition> partitions = Partitions.GetAll(image);
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
|
||||
sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[1];
|
||||
|
||||
if(partitions.Count > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[partitions.Count];
|
||||
|
||||
for(int i = 0; i < partitions.Count; i++)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
sidecar.BlockMedia[0].FileSystemInformation[i] = new PartitionType
|
||||
{
|
||||
Description = partitions[i].Description,
|
||||
EndSector = partitions[i].End,
|
||||
Name = partitions[i].Name,
|
||||
Sequence = (uint)partitions[i].Sequence,
|
||||
StartSector = partitions[i].Start,
|
||||
Type = partitions[i].Type
|
||||
Description = partitions[i].Description, EndSector = partitions[i].End,
|
||||
Name = partitions[i].Name, Sequence = (uint)partitions[i].Sequence,
|
||||
StartSector = partitions[i].Start, Type = partitions[i].Type
|
||||
};
|
||||
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
|
||||
foreach(IFilesystem plugin in plugins.PluginsList.Values)
|
||||
try
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
if(!plugin.Identify(image, partitions[i])) continue;
|
||||
if(!plugin.Identify(image, partitions[i]))
|
||||
continue;
|
||||
|
||||
if(plugin is IReadOnlyFilesystem fsPlugin &&
|
||||
fsPlugin.Mount(image, partitions[i], encoding, null, null) == Errno.NoError)
|
||||
@@ -553,7 +595,8 @@ namespace DiscImageChef.Core
|
||||
|
||||
fsPlugin.Unmount();
|
||||
}
|
||||
else plugin.GetInformation(image, partitions[i], out _, encoding);
|
||||
else
|
||||
plugin.GetInformation(image, partitions[i], out _, encoding);
|
||||
|
||||
lstFs.Add(plugin.XmlFsType);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
@@ -565,20 +608,23 @@ namespace DiscImageChef.Core
|
||||
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[i].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0)
|
||||
sidecar.BlockMedia[0].FileSystemInformation[i].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
sidecar.BlockMedia[0].FileSystemInformation[0] =
|
||||
new PartitionType {StartSector = 0, EndSector = image.Info.Sectors - 1};
|
||||
|
||||
Partition wholePart = new Partition
|
||||
sidecar.BlockMedia[0].FileSystemInformation[0] = new PartitionType
|
||||
{
|
||||
Name = "Whole device",
|
||||
Length = image.Info.Sectors,
|
||||
StartSector = 0, EndSector = image.Info.Sectors - 1
|
||||
};
|
||||
|
||||
var wholePart = new Partition
|
||||
{
|
||||
Name = "Whole device", Length = image.Info.Sectors,
|
||||
Size = image.Info.Sectors * image.Info.SectorSize
|
||||
};
|
||||
|
||||
@@ -587,9 +633,11 @@ namespace DiscImageChef.Core
|
||||
foreach(IFilesystem plugin in plugins.PluginsList.Values)
|
||||
try
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
if(!plugin.Identify(image, wholePart)) continue;
|
||||
if(!plugin.Identify(image, wholePart))
|
||||
continue;
|
||||
|
||||
if(plugin is IReadOnlyFilesystem fsPlugin &&
|
||||
fsPlugin.Mount(image, wholePart, encoding, null, null) == Errno.NoError)
|
||||
@@ -600,7 +648,8 @@ namespace DiscImageChef.Core
|
||||
|
||||
fsPlugin.Unmount();
|
||||
}
|
||||
else plugin.GetInformation(image, wholePart, out _, encoding);
|
||||
else
|
||||
plugin.GetInformation(image, wholePart, out _, encoding);
|
||||
|
||||
lstFs.Add(plugin.XmlFsType);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
@@ -612,12 +661,15 @@ namespace DiscImageChef.Core
|
||||
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[0].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0)
|
||||
sidecar.BlockMedia[0].FileSystemInformation[0].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
|
||||
UpdateStatus("Saving metadata...");
|
||||
|
||||
if(image.Info.Cylinders > 0 && image.Info.Heads > 0 && image.Info.SectorsPerTrack > 0)
|
||||
if(image.Info.Cylinders > 0 &&
|
||||
image.Info.Heads > 0 &&
|
||||
image.Info.SectorsPerTrack > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].CylindersSpecified = true;
|
||||
sidecar.BlockMedia[0].HeadsSpecified = true;
|
||||
@@ -630,8 +682,10 @@ namespace DiscImageChef.Core
|
||||
if(image.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
|
||||
{
|
||||
Identify.IdentifyDevice? ataId = Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
|
||||
|
||||
if(ataId.HasValue)
|
||||
if(ataId.Value.CurrentCylinders > 0 && ataId.Value.CurrentHeads > 0 &&
|
||||
if(ataId.Value.CurrentCylinders > 0 &&
|
||||
ataId.Value.CurrentHeads > 0 &&
|
||||
ataId.Value.CurrentSectorsPerTrack > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].CylindersSpecified = true;
|
||||
@@ -641,7 +695,9 @@ namespace DiscImageChef.Core
|
||||
sidecar.BlockMedia[0].Heads = ataId.Value.CurrentHeads;
|
||||
sidecar.BlockMedia[0].SectorsPerTrack = ataId.Value.CurrentSectorsPerTrack;
|
||||
}
|
||||
else if(ataId.Value.Cylinders > 0 && ataId.Value.Heads > 0 && ataId.Value.SectorsPerTrack > 0)
|
||||
else if(ataId.Value.Cylinders > 0 &&
|
||||
ataId.Value.Heads > 0 &&
|
||||
ataId.Value.SectorsPerTrack > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].CylindersSpecified = true;
|
||||
sidecar.BlockMedia[0].HeadsSpecified = true;
|
||||
@@ -652,7 +708,8 @@ namespace DiscImageChef.Core
|
||||
}
|
||||
}
|
||||
|
||||
if(image.DumpHardware != null) sidecar.BlockMedia[0].DumpHardwareArray = image.DumpHardware.ToArray();
|
||||
if(image.DumpHardware != null)
|
||||
sidecar.BlockMedia[0].DumpHardwareArray = image.DumpHardware.ToArray();
|
||||
|
||||
// TODO: This is more of a hack, redo it planned for >4.0
|
||||
string trkFormat = null;
|
||||
@@ -662,17 +719,21 @@ namespace DiscImageChef.Core
|
||||
case CommonTypes.MediaType.Apple32SS:
|
||||
case CommonTypes.MediaType.Apple32DS:
|
||||
trkFormat = "Apple GCR (DOS 3.2)";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.Apple33SS:
|
||||
case CommonTypes.MediaType.Apple33DS:
|
||||
trkFormat = "Apple GCR (DOS 3.3)";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.AppleSonySS:
|
||||
case CommonTypes.MediaType.AppleSonyDS:
|
||||
trkFormat = "Apple GCR (Sony)";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.AppleFileWare:
|
||||
trkFormat = "Apple GCR (Twiggy)";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.DOS_525_SS_DD_9:
|
||||
case CommonTypes.MediaType.DOS_525_DS_DD_8:
|
||||
@@ -720,6 +781,7 @@ namespace DiscImageChef.Core
|
||||
case CommonTypes.MediaType.Apricot_35:
|
||||
case CommonTypes.MediaType.CompactFloppy:
|
||||
trkFormat = "IBM MFM";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.ATARI_525_SD:
|
||||
case CommonTypes.MediaType.NEC_8_SD:
|
||||
@@ -733,18 +795,22 @@ namespace DiscImageChef.Core
|
||||
case CommonTypes.MediaType.IBM43FD_128:
|
||||
case CommonTypes.MediaType.IBM43FD_256:
|
||||
trkFormat = "IBM FM";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.CBM_35_DD:
|
||||
trkFormat = "Commodore MFM";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.CBM_AMIGA_35_HD:
|
||||
case CommonTypes.MediaType.CBM_AMIGA_35_DD:
|
||||
trkFormat = "Amiga MFM";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.CBM_1540:
|
||||
case CommonTypes.MediaType.CBM_1540_Ext:
|
||||
case CommonTypes.MediaType.CBM_1571:
|
||||
trkFormat = "Commodore GCR";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.SHARP_525_9:
|
||||
case CommonTypes.MediaType.SHARP_35_9: break;
|
||||
@@ -752,6 +818,7 @@ namespace DiscImageChef.Core
|
||||
case CommonTypes.MediaType.ECMA_99_26:
|
||||
case CommonTypes.MediaType.ECMA_99_8:
|
||||
trkFormat = "ISO MFM";
|
||||
|
||||
break;
|
||||
case CommonTypes.MediaType.ECMA_54:
|
||||
case CommonTypes.MediaType.ECMA_59:
|
||||
@@ -763,9 +830,11 @@ namespace DiscImageChef.Core
|
||||
case CommonTypes.MediaType.ECMA_78:
|
||||
case CommonTypes.MediaType.ECMA_78_2:
|
||||
trkFormat = "ISO FM";
|
||||
|
||||
break;
|
||||
default:
|
||||
trkFormat = "Unknown";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -773,22 +842,27 @@ namespace DiscImageChef.Core
|
||||
string scpFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
|
||||
Path.GetFileNameWithoutExtension(imagePath) + ".scp");
|
||||
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
if(File.Exists(scpFilePath))
|
||||
{
|
||||
UpdateStatus("Hashing SuperCardPro image...");
|
||||
SuperCardPro scpImage = new SuperCardPro();
|
||||
ZZZNoFilter scpFilter = new ZZZNoFilter();
|
||||
var scpImage = new SuperCardPro();
|
||||
var scpFilter = new ZZZNoFilter();
|
||||
scpFilter.Open(scpFilePath);
|
||||
|
||||
if(image.Info.Heads <= 2 && scpImage.Identify(scpFilter))
|
||||
if(image.Info.Heads <= 2 &&
|
||||
scpImage.Identify(scpFilter))
|
||||
{
|
||||
try { scpImage.Open(scpFilter); }
|
||||
try
|
||||
{
|
||||
scpImage.Open(scpFilter);
|
||||
}
|
||||
catch(NotImplementedException) { }
|
||||
|
||||
if(image.Info.Heads == 2 && scpImage.Header.heads == 0 || image.Info.Heads == 1 &&
|
||||
(scpImage.Header.heads == 1 || scpImage.Header.heads == 2))
|
||||
if(image.Info.Heads == 2 && scpImage.Header.heads == 0 ||
|
||||
image.Info.Heads == 1 && (scpImage.Header.heads == 1 || scpImage.Header.heads == 2))
|
||||
if(scpImage.Header.end + 1 >= image.Info.Cylinders)
|
||||
{
|
||||
List<BlockTrackType> scpBlockTrackTypes = new List<BlockTrackType>();
|
||||
@@ -797,16 +871,15 @@ namespace DiscImageChef.Core
|
||||
|
||||
for(byte t = scpImage.Header.start; t <= scpImage.Header.end; t++)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
BlockTrackType scpBlockTrackType = new BlockTrackType
|
||||
var scpBlockTrackType = new BlockTrackType
|
||||
{
|
||||
Cylinder = t / image.Info.Heads,
|
||||
Head = (ushort)(t % image.Info.Heads),
|
||||
Image = new ImageType
|
||||
Cylinder = t / image.Info.Heads, Head = (ushort)(t % image.Info.Heads), Image =
|
||||
new ImageType
|
||||
{
|
||||
format = scpImage.Format,
|
||||
Value = Path.GetFileName(scpFilePath),
|
||||
format = scpImage.Format, Value = Path.GetFileName(scpFilePath),
|
||||
offset = scpImage.Header.offsets[t]
|
||||
}
|
||||
};
|
||||
@@ -826,6 +899,7 @@ namespace DiscImageChef.Core
|
||||
byte[] trackContents =
|
||||
new byte[scpTrack.Entries.Last().dataOffset +
|
||||
scpTrack.Entries.Last().trackLength - scpImage.Header.offsets[t] + 1];
|
||||
|
||||
scpStream.Position = scpImage.Header.offsets[t];
|
||||
scpStream.Read(trackContents, 0, trackContents.Length);
|
||||
scpBlockTrackType.Size = (ulong)trackContents.Length;
|
||||
@@ -839,12 +913,12 @@ namespace DiscImageChef.Core
|
||||
scpBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
|
||||
}
|
||||
else
|
||||
DicConsole
|
||||
.ErrorWriteLine("SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
||||
DicConsole.
|
||||
ErrorWriteLine("SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
||||
scpImage.Header.end + 1, image.Info.Cylinders);
|
||||
else
|
||||
DicConsole
|
||||
.ErrorWriteLine("SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
||||
DicConsole.
|
||||
ErrorWriteLine("SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
||||
2, image.Info.Heads);
|
||||
}
|
||||
}
|
||||
@@ -852,33 +926,45 @@ namespace DiscImageChef.Core
|
||||
|
||||
#region KryoFlux
|
||||
string kfFile = null;
|
||||
|
||||
string basename = Path.Combine(Path.GetDirectoryName(imagePath),
|
||||
Path.GetFileNameWithoutExtension(imagePath));
|
||||
|
||||
bool kfDir = false;
|
||||
if(aborted) return;
|
||||
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
if(Directory.Exists(basename))
|
||||
{
|
||||
string[] possibleKfStarts = Directory.GetFiles(basename, "*.raw", SearchOption.TopDirectoryOnly);
|
||||
|
||||
if(possibleKfStarts.Length > 0)
|
||||
{
|
||||
kfFile = possibleKfStarts[0];
|
||||
kfDir = true;
|
||||
}
|
||||
}
|
||||
else if(File.Exists(basename + "00.0.raw")) kfFile = basename + "00.0.raw";
|
||||
else if(File.Exists(basename + "00.1.raw")) kfFile = basename + "00.1.raw";
|
||||
else if(File.Exists(basename + "00.0.raw"))
|
||||
kfFile = basename + "00.0.raw";
|
||||
else if(File.Exists(basename + "00.1.raw"))
|
||||
kfFile = basename + "00.1.raw";
|
||||
|
||||
if(kfFile != null)
|
||||
{
|
||||
UpdateStatus("Hashing KryoFlux images...");
|
||||
|
||||
KryoFlux kfImage = new KryoFlux();
|
||||
ZZZNoFilter kfFilter = new ZZZNoFilter();
|
||||
var kfImage = new KryoFlux();
|
||||
var kfFilter = new ZZZNoFilter();
|
||||
kfFilter.Open(kfFile);
|
||||
if(image.Info.Heads <= 2 && kfImage.Identify(kfFilter))
|
||||
|
||||
if(image.Info.Heads <= 2 &&
|
||||
kfImage.Identify(kfFilter))
|
||||
{
|
||||
try { kfImage.Open(kfFilter); }
|
||||
try
|
||||
{
|
||||
kfImage.Open(kfFilter);
|
||||
}
|
||||
catch(NotImplementedException) { }
|
||||
|
||||
if(kfImage.Info.Heads == image.Info.Heads)
|
||||
@@ -890,20 +976,19 @@ namespace DiscImageChef.Core
|
||||
|
||||
foreach(KeyValuePair<byte, IFilter> kvp in kfImage.tracks)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
BlockTrackType kfBlockTrackType = new BlockTrackType
|
||||
var kfBlockTrackType = new BlockTrackType
|
||||
{
|
||||
Cylinder = kvp.Key / image.Info.Heads,
|
||||
Head = (ushort)(kvp.Key % image.Info.Heads),
|
||||
Cylinder = kvp.Key / image.Info.Heads, Head = (ushort)(kvp.Key % image.Info.Heads),
|
||||
Image = new ImageType
|
||||
{
|
||||
format = kfImage.Format,
|
||||
Value = kfDir
|
||||
? Path
|
||||
.Combine(Path.GetFileName(Path.GetDirectoryName(kvp.Value.GetBasePath())),
|
||||
kvp.Value.GetFilename())
|
||||
: kvp.Value.GetFilename(),
|
||||
? Path.
|
||||
Combine(Path.GetFileName(Path.GetDirectoryName(kvp.Value.GetBasePath())),
|
||||
kvp.Value.GetFilename()) : kvp.Value.GetFilename(),
|
||||
offset = 0
|
||||
}
|
||||
};
|
||||
@@ -932,12 +1017,12 @@ namespace DiscImageChef.Core
|
||||
kfBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
|
||||
}
|
||||
else
|
||||
DicConsole
|
||||
.ErrorWriteLine("KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
||||
DicConsole.
|
||||
ErrorWriteLine("KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
||||
kfImage.Info.Cylinders, image.Info.Cylinders);
|
||||
else
|
||||
DicConsole
|
||||
.ErrorWriteLine("KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
||||
DicConsole.
|
||||
ErrorWriteLine("KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
||||
kfImage.Info.Heads, image.Info.Heads);
|
||||
}
|
||||
}
|
||||
@@ -947,16 +1032,23 @@ namespace DiscImageChef.Core
|
||||
string dfiFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
|
||||
Path.GetFileNameWithoutExtension(imagePath) + ".dfi");
|
||||
|
||||
if(aborted) return;
|
||||
if(!File.Exists(dfiFilePath)) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
DiscFerret dfiImage = new DiscFerret();
|
||||
ZZZNoFilter dfiFilter = new ZZZNoFilter();
|
||||
if(!File.Exists(dfiFilePath))
|
||||
return;
|
||||
|
||||
var dfiImage = new DiscFerret();
|
||||
var dfiFilter = new ZZZNoFilter();
|
||||
dfiFilter.Open(dfiFilePath);
|
||||
|
||||
if(!dfiImage.Identify(dfiFilter)) return;
|
||||
if(!dfiImage.Identify(dfiFilter))
|
||||
return;
|
||||
|
||||
try { dfiImage.Open(dfiFilter); }
|
||||
try
|
||||
{
|
||||
dfiImage.Open(dfiFilter);
|
||||
}
|
||||
catch(NotImplementedException) { }
|
||||
|
||||
UpdateStatus("Hashing DiscFerret image...");
|
||||
@@ -970,13 +1062,16 @@ namespace DiscImageChef.Core
|
||||
|
||||
foreach(int t in dfiImage.TrackOffsets.Keys)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
BlockTrackType dfiBlockTrackType = new BlockTrackType
|
||||
var dfiBlockTrackType = new BlockTrackType
|
||||
{
|
||||
Cylinder = (uint)(t / image.Info.Heads),
|
||||
Head = (ushort)(t % image.Info.Heads),
|
||||
Image = new ImageType {format = dfiImage.Format, Value = Path.GetFileName(dfiFilePath)}
|
||||
Cylinder = (uint)(t / image.Info.Heads), Head = (ushort)(t % image.Info.Heads), Image =
|
||||
new ImageType
|
||||
{
|
||||
format = dfiImage.Format, Value = Path.GetFileName(dfiFilePath)
|
||||
}
|
||||
};
|
||||
|
||||
if(dfiBlockTrackType.Cylinder < image.Info.Cylinders)
|
||||
@@ -1007,12 +1102,12 @@ namespace DiscImageChef.Core
|
||||
dfiBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
|
||||
}
|
||||
else
|
||||
DicConsole
|
||||
.ErrorWriteLine("DiscFerret image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
||||
DicConsole.
|
||||
ErrorWriteLine("DiscFerret image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
||||
dfiImage.Info.Cylinders, image.Info.Cylinders);
|
||||
else
|
||||
DicConsole
|
||||
.ErrorWriteLine("DiscFerret image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
||||
DicConsole.
|
||||
ErrorWriteLine("DiscFerret image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
||||
dfiImage.Info.Heads, image.Info.Heads);
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -52,9 +52,7 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
public partial class Sidecar
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a metadata sidecar for an optical disc (e.g. CD, DVD, GD, BD, XGD, GOD)
|
||||
/// </summary>
|
||||
/// <summary>Creates a metadata sidecar for an optical disc (e.g. CD, DVD, GD, BD, XGD, GOD)</summary>
|
||||
/// <param name="image">Image</param>
|
||||
/// <param name="filterId">Filter uuid</param>
|
||||
/// <param name="imagePath">Image path</param>
|
||||
@@ -62,30 +60,29 @@ namespace DiscImageChef.Core
|
||||
/// <param name="plugins">Image plugins</param>
|
||||
/// <param name="imgChecksums">List of image checksums</param>
|
||||
/// <param name="sidecar">Metadata sidecar</param>
|
||||
void OpticalDisc(IOpticalMediaImage image, Guid filterId, string imagePath,
|
||||
FileInfo fi, PluginBase plugins,
|
||||
void OpticalDisc(IOpticalMediaImage image, Guid filterId, string imagePath, FileInfo fi, PluginBase plugins,
|
||||
List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar, Encoding encoding)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
sidecar.OpticalDisc = new[]
|
||||
{
|
||||
new OpticalDiscType
|
||||
{
|
||||
Checksums = imgChecksums.ToArray(),
|
||||
Image = new ImageType
|
||||
Checksums = imgChecksums.ToArray(), Image = new ImageType
|
||||
{
|
||||
format = image.Format,
|
||||
offset = 0,
|
||||
offsetSpecified = true,
|
||||
Value = Path.GetFileName(imagePath)
|
||||
format = image.Format, offset = 0, offsetSpecified = true, Value = Path.GetFileName(imagePath)
|
||||
},
|
||||
Size = (ulong)fi.Length,
|
||||
Sequence = new SequenceType {MediaTitle = image.Info.MediaTitle}
|
||||
Size = (ulong)fi.Length, Sequence = new SequenceType
|
||||
{
|
||||
MediaTitle = image.Info.MediaTitle
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(image.Info.MediaSequence != 0 && image.Info.LastMediaSequence != 0)
|
||||
if(image.Info.MediaSequence != 0 &&
|
||||
image.Info.LastMediaSequence != 0)
|
||||
{
|
||||
sidecar.OpticalDisc[0].Sequence.MediaSequence = (uint)image.Info.MediaSequence;
|
||||
sidecar.OpticalDisc[0].Sequence.TotalMedia = (uint)image.Info.LastMediaSequence;
|
||||
@@ -99,9 +96,11 @@ namespace DiscImageChef.Core
|
||||
MediaType dskType = image.Info.MediaType;
|
||||
|
||||
UpdateStatus("Hashing media tags...");
|
||||
|
||||
foreach(MediaTagType tagType in image.Info.ReadableMediaTags)
|
||||
{
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
switch(tagType)
|
||||
{
|
||||
@@ -112,10 +111,15 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_ATIP)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.CD_ATIP).Length
|
||||
};
|
||||
|
||||
ATIP.CDATIP? atip = ATIP.Decode(image.ReadDiskTag(MediaTagType.CD_ATIP));
|
||||
|
||||
if(atip.HasValue)
|
||||
if(atip.Value.DDCD) dskType = atip.Value.DiscType ? MediaType.DDCDRW : MediaType.DDCDR;
|
||||
else dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR;
|
||||
if(atip.Value.DDCD)
|
||||
dskType = atip.Value.DiscType ? MediaType.DDCDRW : MediaType.DDCDR;
|
||||
else
|
||||
dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR;
|
||||
|
||||
break;
|
||||
case MediaTagType.DVD_BCA:
|
||||
sidecar.OpticalDisc[0].BCA = new DumpType
|
||||
@@ -124,6 +128,7 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_BCA)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.DVD_BCA).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.BD_BCA:
|
||||
sidecar.OpticalDisc[0].BCA = new DumpType
|
||||
@@ -132,6 +137,7 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.BD_BCA)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.BD_BCA).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.DVD_CMI:
|
||||
sidecar.OpticalDisc[0].CMI = new DumpType
|
||||
@@ -140,19 +146,24 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_CMI)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.DVD_CMI).Length
|
||||
};
|
||||
|
||||
CSS_CPRM.LeadInCopyright? cmi =
|
||||
CSS_CPRM.DecodeLeadInCopyright(image.ReadDiskTag(MediaTagType.DVD_CMI));
|
||||
|
||||
if(cmi.HasValue)
|
||||
switch(cmi.Value.CopyrightType)
|
||||
{
|
||||
case CopyrightType.AACS:
|
||||
sidecar.OpticalDisc[0].CopyProtection = "AACS";
|
||||
|
||||
break;
|
||||
case CopyrightType.CSS:
|
||||
sidecar.OpticalDisc[0].CopyProtection = "CSS";
|
||||
|
||||
break;
|
||||
case CopyrightType.CPRM:
|
||||
sidecar.OpticalDisc[0].CopyProtection = "CPRM";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -164,15 +175,24 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_DMI)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.DVD_DMI).Length
|
||||
};
|
||||
|
||||
if(DMI.IsXbox(image.ReadDiskTag(MediaTagType.DVD_DMI)))
|
||||
{
|
||||
dskType = MediaType.XGD;
|
||||
sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120, Thickness = 1.2};
|
||||
|
||||
sidecar.OpticalDisc[0].Dimensions = new DimensionsType
|
||||
{
|
||||
Diameter = 120, Thickness = 1.2
|
||||
};
|
||||
}
|
||||
else if(DMI.IsXbox360(image.ReadDiskTag(MediaTagType.DVD_DMI)))
|
||||
{
|
||||
dskType = MediaType.XGD2;
|
||||
sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120, Thickness = 1.2};
|
||||
|
||||
sidecar.OpticalDisc[0].Dimensions = new DimensionsType
|
||||
{
|
||||
Diameter = 120, Thickness = 1.2
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -183,65 +203,91 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_PFI)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.DVD_PFI).Length
|
||||
};
|
||||
|
||||
PFI.PhysicalFormatInformation? pfi = PFI.Decode(image.ReadDiskTag(MediaTagType.DVD_PFI));
|
||||
|
||||
if(pfi.HasValue)
|
||||
if(dskType != MediaType.XGD && dskType != MediaType.XGD2 &&
|
||||
if(dskType != MediaType.XGD &&
|
||||
dskType != MediaType.XGD2 &&
|
||||
dskType != MediaType.XGD3 &&
|
||||
dskType != MediaType.PS2DVD && dskType != MediaType.PS3DVD && dskType != MediaType.Nuon)
|
||||
dskType != MediaType.PS2DVD &&
|
||||
dskType != MediaType.PS3DVD &&
|
||||
dskType != MediaType.Nuon)
|
||||
{
|
||||
switch(pfi.Value.DiskCategory)
|
||||
{
|
||||
case DiskCategory.DVDPR:
|
||||
dskType = MediaType.DVDPR;
|
||||
|
||||
break;
|
||||
case DiskCategory.DVDPRDL:
|
||||
dskType = MediaType.DVDPRDL;
|
||||
|
||||
break;
|
||||
case DiskCategory.DVDPRW:
|
||||
dskType = MediaType.DVDPRW;
|
||||
|
||||
break;
|
||||
case DiskCategory.DVDPRWDL:
|
||||
dskType = MediaType.DVDPRWDL;
|
||||
|
||||
break;
|
||||
case DiskCategory.DVDR:
|
||||
dskType = MediaType.DVDR;
|
||||
|
||||
break;
|
||||
case DiskCategory.DVDRAM:
|
||||
dskType = MediaType.DVDRAM;
|
||||
|
||||
break;
|
||||
case DiskCategory.DVDROM:
|
||||
dskType = MediaType.DVDROM;
|
||||
|
||||
break;
|
||||
case DiskCategory.DVDRW:
|
||||
dskType = MediaType.DVDRW;
|
||||
|
||||
break;
|
||||
case DiskCategory.HDDVDR:
|
||||
dskType = MediaType.HDDVDR;
|
||||
|
||||
break;
|
||||
case DiskCategory.HDDVDRAM:
|
||||
dskType = MediaType.HDDVDRAM;
|
||||
|
||||
break;
|
||||
case DiskCategory.HDDVDROM:
|
||||
dskType = MediaType.HDDVDROM;
|
||||
|
||||
break;
|
||||
case DiskCategory.HDDVDRW:
|
||||
dskType = MediaType.HDDVDRW;
|
||||
|
||||
break;
|
||||
case DiskCategory.Nintendo:
|
||||
dskType = MediaType.GOD;
|
||||
|
||||
break;
|
||||
case DiskCategory.UMD:
|
||||
dskType = MediaType.UMD;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(dskType == MediaType.DVDR && pfi.Value.PartVersion == 6) dskType = MediaType.DVDRDL;
|
||||
if(dskType == MediaType.DVDRW && pfi.Value.PartVersion == 3)
|
||||
if(dskType == MediaType.DVDR &&
|
||||
pfi.Value.PartVersion == 6)
|
||||
dskType = MediaType.DVDRDL;
|
||||
|
||||
if(dskType == MediaType.DVDRW &&
|
||||
pfi.Value.PartVersion == 3)
|
||||
dskType = MediaType.DVDRWDL;
|
||||
if(dskType == MediaType.GOD && pfi.Value.DiscSize == DVDSize.OneTwenty)
|
||||
|
||||
if(dskType == MediaType.GOD &&
|
||||
pfi.Value.DiscSize == DVDSize.OneTwenty)
|
||||
dskType = MediaType.WOD;
|
||||
|
||||
sidecar.OpticalDisc[0].Dimensions = new DimensionsType();
|
||||
|
||||
if(dskType == MediaType.UMD)
|
||||
{
|
||||
sidecar.OpticalDisc[0].Dimensions.Height = 64;
|
||||
@@ -257,11 +303,13 @@ namespace DiscImageChef.Core
|
||||
sidecar.OpticalDisc[0].Dimensions.Diameter = 80;
|
||||
sidecar.OpticalDisc[0].Dimensions.DiameterSpecified = true;
|
||||
sidecar.OpticalDisc[0].Dimensions.Thickness = 1.2;
|
||||
|
||||
break;
|
||||
case DVDSize.OneTwenty:
|
||||
sidecar.OpticalDisc[0].Dimensions.Diameter = 120;
|
||||
sidecar.OpticalDisc[0].Dimensions.DiameterSpecified = true;
|
||||
sidecar.OpticalDisc[0].Dimensions.Thickness = 1.2;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -274,6 +322,7 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_PMA)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.CD_PMA).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.CD_FullTOC:
|
||||
sidecar.OpticalDisc[0].TOC = new DumpType
|
||||
@@ -282,6 +331,7 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_FullTOC)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.CD_FullTOC).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.CD_FirstTrackPregap:
|
||||
sidecar.OpticalDisc[0].FirstTrackPregrap = new[]
|
||||
@@ -289,12 +339,12 @@ namespace DiscImageChef.Core
|
||||
new BorderType
|
||||
{
|
||||
Image = Path.GetFileName(imagePath),
|
||||
Checksums = Checksum
|
||||
.GetChecksums(image.ReadDiskTag(MediaTagType.CD_FirstTrackPregap))
|
||||
.ToArray(),
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_FirstTrackPregap)).
|
||||
ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.CD_FirstTrackPregap).Length
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.CD_LeadIn:
|
||||
sidecar.OpticalDisc[0].LeadIn = new[]
|
||||
@@ -302,29 +352,26 @@ namespace DiscImageChef.Core
|
||||
new BorderType
|
||||
{
|
||||
Image = Path.GetFileName(imagePath),
|
||||
Checksums = Checksum
|
||||
.GetChecksums(image.ReadDiskTag(MediaTagType.CD_LeadIn)).ToArray(),
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_LeadIn)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.CD_LeadIn).Length
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.Xbox_SecuritySector:
|
||||
if(sidecar.OpticalDisc[0].Xbox == null) sidecar.OpticalDisc[0].Xbox = new XboxType();
|
||||
if(sidecar.OpticalDisc[0].Xbox == null)
|
||||
sidecar.OpticalDisc[0].Xbox = new XboxType();
|
||||
|
||||
sidecar.OpticalDisc[0].Xbox.SecuritySectors = new[]
|
||||
{
|
||||
new XboxSecuritySectorsType
|
||||
{
|
||||
RequestNumber = 0,
|
||||
RequestVersion = 1,
|
||||
SecuritySectors = new DumpType
|
||||
RequestNumber = 0, RequestVersion = 1, SecuritySectors = new DumpType
|
||||
{
|
||||
Image = Path.GetFileName(imagePath),
|
||||
Checksums =
|
||||
Checksum
|
||||
.GetChecksums(image.ReadDiskTag(MediaTagType
|
||||
.Xbox_SecuritySector))
|
||||
.ToArray(),
|
||||
Checksums = Checksum.
|
||||
GetChecksums(image.ReadDiskTag(MediaTagType.Xbox_SecuritySector)).
|
||||
ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.Xbox_SecuritySector).Length
|
||||
}
|
||||
}
|
||||
@@ -332,7 +379,8 @@ namespace DiscImageChef.Core
|
||||
|
||||
break;
|
||||
case MediaTagType.Xbox_PFI:
|
||||
if(sidecar.OpticalDisc[0].Xbox == null) sidecar.OpticalDisc[0].Xbox = new XboxType();
|
||||
if(sidecar.OpticalDisc[0].Xbox == null)
|
||||
sidecar.OpticalDisc[0].Xbox = new XboxType();
|
||||
|
||||
sidecar.OpticalDisc[0].Xbox.PFI = new DumpType
|
||||
{
|
||||
@@ -340,9 +388,11 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.Xbox_PFI)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.Xbox_PFI).Length
|
||||
};
|
||||
|
||||
break;
|
||||
case MediaTagType.Xbox_DMI:
|
||||
if(sidecar.OpticalDisc[0].Xbox == null) sidecar.OpticalDisc[0].Xbox = new XboxType();
|
||||
if(sidecar.OpticalDisc[0].Xbox == null)
|
||||
sidecar.OpticalDisc[0].Xbox = new XboxType();
|
||||
|
||||
sidecar.OpticalDisc[0].Xbox.DMI = new DumpType
|
||||
{
|
||||
@@ -350,6 +400,7 @@ namespace DiscImageChef.Core
|
||||
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.Xbox_DMI)).ToArray(),
|
||||
Size = (ulong)image.ReadDiskTag(MediaTagType.Xbox_DMI).Length
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -359,10 +410,14 @@ namespace DiscImageChef.Core
|
||||
List<Session> sessions = image.Sessions;
|
||||
sidecar.OpticalDisc[0].Sessions = (uint)(sessions?.Count ?? 1);
|
||||
}
|
||||
catch { sidecar.OpticalDisc[0].Sessions = 1; }
|
||||
catch
|
||||
{
|
||||
sidecar.OpticalDisc[0].Sessions = 1;
|
||||
}
|
||||
|
||||
List<Track> tracks = image.Tracks;
|
||||
List<TrackType> trksLst = null;
|
||||
|
||||
if(tracks != null)
|
||||
{
|
||||
sidecar.OpticalDisc[0].Tracks = new uint[1];
|
||||
@@ -370,10 +425,12 @@ namespace DiscImageChef.Core
|
||||
trksLst = new List<TrackType>();
|
||||
}
|
||||
|
||||
if(sidecar.OpticalDisc[0].Dimensions == null && image.Info.MediaType != MediaType.Unknown)
|
||||
if(sidecar.OpticalDisc[0].Dimensions == null &&
|
||||
image.Info.MediaType != MediaType.Unknown)
|
||||
sidecar.OpticalDisc[0].Dimensions = Dimensions.DimensionsFromMediaType(image.Info.MediaType);
|
||||
|
||||
if(aborted) return;
|
||||
if(aborted)
|
||||
return;
|
||||
|
||||
InitProgress();
|
||||
|
||||
@@ -382,61 +439,78 @@ namespace DiscImageChef.Core
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
|
||||
UpdateStatus("Hashing tracks...");
|
||||
|
||||
foreach(Track trk in tracks)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
TrackType xmlTrk = new TrackType();
|
||||
var xmlTrk = new TrackType();
|
||||
|
||||
switch(trk.TrackType)
|
||||
{
|
||||
case CommonTypes.Enums.TrackType.Audio:
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.audio;
|
||||
|
||||
break;
|
||||
case CommonTypes.Enums.TrackType.CdMode2Form2:
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.m2f2;
|
||||
|
||||
break;
|
||||
case CommonTypes.Enums.TrackType.CdMode2Formless:
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.mode2;
|
||||
|
||||
break;
|
||||
case CommonTypes.Enums.TrackType.CdMode2Form1:
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.m2f1;
|
||||
|
||||
break;
|
||||
case CommonTypes.Enums.TrackType.CdMode1:
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.mode1;
|
||||
|
||||
break;
|
||||
case CommonTypes.Enums.TrackType.Data:
|
||||
switch(sidecar.OpticalDisc[0].DiscType)
|
||||
{
|
||||
case"BD":
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.bluray;
|
||||
|
||||
break;
|
||||
case"DDCD":
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.ddcd;
|
||||
|
||||
break;
|
||||
case"DVD":
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.dvd;
|
||||
|
||||
break;
|
||||
case"HD DVD":
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.hddvd;
|
||||
|
||||
break;
|
||||
default:
|
||||
xmlTrk.TrackType1 = TrackTypeTrackType.mode1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
xmlTrk.Sequence =
|
||||
new TrackSequenceType {Session = trk.TrackSession, TrackNumber = trk.TrackSequence};
|
||||
xmlTrk.Sequence = new TrackSequenceType
|
||||
{
|
||||
Session = trk.TrackSession, TrackNumber = trk.TrackSequence
|
||||
};
|
||||
|
||||
xmlTrk.StartSector = trk.TrackStartSector;
|
||||
xmlTrk.EndSector = trk.TrackEndSector;
|
||||
|
||||
if(trk.Indexes != null && trk.Indexes.ContainsKey(0))
|
||||
if(trk.Indexes != null &&
|
||||
trk.Indexes.ContainsKey(0))
|
||||
if(trk.Indexes.TryGetValue(0, out ulong idx0))
|
||||
xmlTrk.StartSector = idx0;
|
||||
|
||||
@@ -446,14 +520,19 @@ namespace DiscImageChef.Core
|
||||
case"GD":
|
||||
xmlTrk.StartMSF = LbaToMsf((long)xmlTrk.StartSector);
|
||||
xmlTrk.EndMSF = LbaToMsf((long)xmlTrk.EndSector);
|
||||
|
||||
break;
|
||||
case"DDCD":
|
||||
xmlTrk.StartMSF = DdcdLbaToMsf((long)xmlTrk.StartSector);
|
||||
xmlTrk.EndMSF = DdcdLbaToMsf((long)xmlTrk.EndSector);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
xmlTrk.Image = new ImageType {Value = Path.GetFileName(trk.TrackFile), format = trk.TrackFileType};
|
||||
xmlTrk.Image = new ImageType
|
||||
{
|
||||
Value = Path.GetFileName(trk.TrackFile), format = trk.TrackFileType
|
||||
};
|
||||
|
||||
if(trk.TrackFileOffset > 0)
|
||||
{
|
||||
@@ -470,8 +549,10 @@ namespace DiscImageChef.Core
|
||||
|
||||
// If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum.
|
||||
if(image.Id == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") &&
|
||||
|
||||
// Only if filter is none...
|
||||
(filterId == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") ||
|
||||
|
||||
// ...or AppleDouble
|
||||
filterId == new Guid("1b2165ee-c9df-4b21-bbbb-9e5892b2df4d")))
|
||||
xmlTrk.Checksums = sidecar.OpticalDisc[0].Checksums;
|
||||
@@ -482,15 +563,17 @@ namespace DiscImageChef.Core
|
||||
// For fast debugging, skip checksum
|
||||
//goto skipChecksum;
|
||||
|
||||
Checksum trkChkWorker = new Checksum();
|
||||
var trkChkWorker = new Checksum();
|
||||
|
||||
InitProgress2();
|
||||
|
||||
while(doneSectors < sectors)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress();
|
||||
EndProgress2();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -499,16 +582,20 @@ namespace DiscImageChef.Core
|
||||
if(sectors - doneSectors >= sectorsToRead)
|
||||
{
|
||||
sector = image.ReadSectorsLong(doneSectors, sectorsToRead, xmlTrk.Sequence.TrackNumber);
|
||||
|
||||
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors,
|
||||
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
||||
|
||||
doneSectors += sectorsToRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector = image.ReadSectorsLong(doneSectors, (uint)(sectors - doneSectors),
|
||||
xmlTrk.Sequence.TrackNumber);
|
||||
|
||||
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors,
|
||||
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
||||
|
||||
doneSectors += sectors - doneSectors;
|
||||
}
|
||||
|
||||
@@ -526,7 +613,11 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
xmlTrk.SubChannel = new SubChannelType
|
||||
{
|
||||
Image = new ImageType {Value = trk.TrackSubchannelFile},
|
||||
Image = new ImageType
|
||||
{
|
||||
Value = trk.TrackSubchannelFile
|
||||
},
|
||||
|
||||
// TODO: Packed subchannel has different size?
|
||||
Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * 96
|
||||
};
|
||||
@@ -536,14 +627,17 @@ namespace DiscImageChef.Core
|
||||
case TrackSubchannelType.Packed:
|
||||
case TrackSubchannelType.PackedInterleaved:
|
||||
xmlTrk.SubChannel.Image.format = "rw";
|
||||
|
||||
break;
|
||||
case TrackSubchannelType.Raw:
|
||||
case TrackSubchannelType.RawInterleaved:
|
||||
xmlTrk.SubChannel.Image.format = "rw_raw";
|
||||
|
||||
break;
|
||||
case TrackSubchannelType.Q16:
|
||||
case TrackSubchannelType.Q16Interleaved:
|
||||
xmlTrk.SubChannel.Image.format = "q16";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -553,18 +647,20 @@ namespace DiscImageChef.Core
|
||||
xmlTrk.SubChannel.Image.offsetSpecified = true;
|
||||
}
|
||||
|
||||
Checksum subChkWorker = new Checksum();
|
||||
var subChkWorker = new Checksum();
|
||||
|
||||
sectors = xmlTrk.EndSector - xmlTrk.StartSector + 1;
|
||||
doneSectors = 0;
|
||||
|
||||
InitProgress2();
|
||||
|
||||
while(doneSectors < sectors)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress();
|
||||
EndProgress2();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -574,8 +670,10 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
sector = image.ReadSectorsTag(doneSectors, sectorsToRead, xmlTrk.Sequence.TrackNumber,
|
||||
SectorTagType.CdSectorSubchannel);
|
||||
|
||||
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors,
|
||||
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
||||
|
||||
doneSectors += sectorsToRead;
|
||||
}
|
||||
else
|
||||
@@ -583,8 +681,10 @@ namespace DiscImageChef.Core
|
||||
sector = image.ReadSectorsTag(doneSectors, (uint)(sectors - doneSectors),
|
||||
xmlTrk.Sequence.TrackNumber,
|
||||
SectorTagType.CdSectorSubchannel);
|
||||
|
||||
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors,
|
||||
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
||||
|
||||
doneSectors += sectors - doneSectors;
|
||||
}
|
||||
|
||||
@@ -601,25 +701,25 @@ namespace DiscImageChef.Core
|
||||
// For fast debugging, skip checksum
|
||||
//skipChecksum:
|
||||
|
||||
List<Partition> trkPartitions = partitions
|
||||
.Where(p => p.Start >= trk.TrackStartSector &&
|
||||
List<Partition> trkPartitions = partitions.
|
||||
Where(p => p.Start >= trk.TrackStartSector &&
|
||||
p.End <= trk.TrackEndSector).ToList();
|
||||
|
||||
xmlTrk.FileSystemInformation = new PartitionType[1];
|
||||
|
||||
if(trkPartitions.Count > 0)
|
||||
{
|
||||
xmlTrk.FileSystemInformation = new PartitionType[trkPartitions.Count];
|
||||
|
||||
for(int i = 0; i < trkPartitions.Count; i++)
|
||||
{
|
||||
xmlTrk.FileSystemInformation[i] = new PartitionType
|
||||
{
|
||||
Description = trkPartitions[i].Description,
|
||||
EndSector = trkPartitions[i].End,
|
||||
Name = trkPartitions[i].Name,
|
||||
Sequence = (uint)trkPartitions[i].Sequence,
|
||||
StartSector = trkPartitions[i].Start,
|
||||
Type = trkPartitions[i].Type
|
||||
Description = trkPartitions[i].Description, EndSector = trkPartitions[i].End,
|
||||
Name = trkPartitions[i].Name, Sequence = (uint)trkPartitions[i].Sequence,
|
||||
StartSector = trkPartitions[i].Start, Type = trkPartitions[i].Type
|
||||
};
|
||||
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
|
||||
foreach(IFilesystem plugin in plugins.PluginsList.Values)
|
||||
@@ -628,10 +728,12 @@ namespace DiscImageChef.Core
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!plugin.Identify(image, trkPartitions[i])) continue;
|
||||
if(!plugin.Identify(image, trkPartitions[i]))
|
||||
continue;
|
||||
|
||||
plugin.GetInformation(image, trkPartitions[i], out _, encoding);
|
||||
lstFs.Add(plugin.XmlFsType);
|
||||
@@ -641,15 +743,19 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
case"Opera":
|
||||
dskType = MediaType.ThreeDO;
|
||||
|
||||
break;
|
||||
case"PC Engine filesystem":
|
||||
dskType = MediaType.SuperCDROM2;
|
||||
|
||||
break;
|
||||
case"Nintendo Wii filesystem":
|
||||
dskType = MediaType.WOD;
|
||||
|
||||
break;
|
||||
case"Nintendo Gamecube filesystem":
|
||||
dskType = MediaType.GOD;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -660,7 +766,8 @@ namespace DiscImageChef.Core
|
||||
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0) xmlTrk.FileSystemInformation[i].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0)
|
||||
xmlTrk.FileSystemInformation[i].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -669,26 +776,27 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
EndSector = xmlTrk.EndSector, StartSector = xmlTrk.StartSector
|
||||
};
|
||||
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
|
||||
Partition xmlPart = new Partition
|
||||
var xmlPart = new Partition
|
||||
{
|
||||
Start = xmlTrk.StartSector,
|
||||
Length = xmlTrk.EndSector - xmlTrk.StartSector + 1,
|
||||
Type = xmlTrk.TrackType1.ToString(),
|
||||
Size = xmlTrk.Size,
|
||||
Sequence = xmlTrk.Sequence.TrackNumber
|
||||
Start = xmlTrk.StartSector, Length = xmlTrk.EndSector - xmlTrk.StartSector + 1,
|
||||
Type = xmlTrk.TrackType1.ToString(), Size = xmlTrk.Size, Sequence = xmlTrk.Sequence.TrackNumber
|
||||
};
|
||||
|
||||
foreach(IFilesystem plugin in plugins.PluginsList.Values)
|
||||
try
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
EndProgress();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!plugin.Identify(image, xmlPart)) continue;
|
||||
if(!plugin.Identify(image, xmlPart))
|
||||
continue;
|
||||
|
||||
plugin.GetInformation(image, xmlPart, out _, encoding);
|
||||
lstFs.Add(plugin.XmlFsType);
|
||||
@@ -698,15 +806,19 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
case"Opera":
|
||||
dskType = MediaType.ThreeDO;
|
||||
|
||||
break;
|
||||
case"PC Engine filesystem":
|
||||
dskType = MediaType.SuperCDROM2;
|
||||
|
||||
break;
|
||||
case"Nintendo Wii filesystem":
|
||||
dskType = MediaType.WOD;
|
||||
|
||||
break;
|
||||
case"Nintendo Gamecube filesystem":
|
||||
dskType = MediaType.GOD;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -717,7 +829,8 @@ namespace DiscImageChef.Core
|
||||
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0) xmlTrk.FileSystemInformation[0].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0)
|
||||
xmlTrk.FileSystemInformation[0].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
|
||||
trksLst.Add(xmlTrk);
|
||||
@@ -725,25 +838,29 @@ namespace DiscImageChef.Core
|
||||
|
||||
EndProgress();
|
||||
|
||||
if(trksLst != null) sidecar.OpticalDisc[0].Track = trksLst.ToArray();
|
||||
if(trksLst != null)
|
||||
sidecar.OpticalDisc[0].Track = trksLst.ToArray();
|
||||
|
||||
// All XGD3 all have the same number of blocks
|
||||
if(dskType == MediaType.XGD2 && sidecar.OpticalDisc[0].Track.Length == 1)
|
||||
if(dskType == MediaType.XGD2 &&
|
||||
sidecar.OpticalDisc[0].Track.Length == 1)
|
||||
{
|
||||
ulong blocks = sidecar.OpticalDisc[0].Track[0].EndSector - sidecar.OpticalDisc[0].Track[0].StartSector +
|
||||
1;
|
||||
|
||||
if(blocks == 25063 || // Locked (or non compatible drive)
|
||||
blocks == 4229664 || // Xtreme unlock
|
||||
blocks == 4246304) // Wxripper unlock
|
||||
dskType = MediaType.XGD3;
|
||||
}
|
||||
|
||||
CommonTypes.Metadata.MediaType.MediaTypeToString(dskType, out string dscType, out string dscSubType);
|
||||
sidecar.OpticalDisc[0].DiscType = dscType;
|
||||
sidecar.OpticalDisc[0].DiscSubType = dscSubType;
|
||||
(string type, string subType) discType = CommonTypes.Metadata.MediaType.MediaTypeToString(dskType);
|
||||
sidecar.OpticalDisc[0].DiscType = discType.type;
|
||||
sidecar.OpticalDisc[0].DiscSubType = discType.subType;
|
||||
Statistics.AddMedia(dskType, false);
|
||||
|
||||
if(image.DumpHardware != null) sidecar.OpticalDisc[0].DumpHardwareArray = image.DumpHardware.ToArray();
|
||||
if(image.DumpHardware != null)
|
||||
sidecar.OpticalDisc[0].DumpHardwareArray = image.DumpHardware.ToArray();
|
||||
else if(!string.IsNullOrEmpty(image.Info.DriveManufacturer) ||
|
||||
!string.IsNullOrEmpty(image.Info.DriveModel) ||
|
||||
!string.IsNullOrEmpty(image.Info.DriveFirmwareRevision) ||
|
||||
@@ -752,12 +869,17 @@ namespace DiscImageChef.Core
|
||||
{
|
||||
new DumpHardwareType
|
||||
{
|
||||
Extents = new[] {new ExtentType {Start = 0, End = image.Info.Sectors}},
|
||||
Manufacturer = image.Info.DriveManufacturer,
|
||||
Model = image.Info.DriveModel,
|
||||
Firmware = image.Info.DriveFirmwareRevision,
|
||||
Serial = image.Info.DriveSerialNumber,
|
||||
Software = new SoftwareType
|
||||
Extents = new[]
|
||||
{
|
||||
new ExtentType
|
||||
{
|
||||
Start = 0, End = image.Info.Sectors
|
||||
}
|
||||
},
|
||||
Manufacturer = image.Info.DriveManufacturer, Model = image.Info.DriveModel,
|
||||
Firmware = image.Info.DriveFirmwareRevision, Serial = image.Info.DriveSerialNumber,
|
||||
Software =
|
||||
new SoftwareType
|
||||
{
|
||||
Name = image.Info.Application, Version = image.Info.ApplicationVersion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user