mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Added support for dumping subchannel in a separate file.
This commit is contained in:
@@ -50,7 +50,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal class CompactDisc
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel)
|
||||
{
|
||||
MHDDLog mhddLog;
|
||||
IBGLog ibgLog;
|
||||
@@ -60,7 +60,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
double duration;
|
||||
ulong blocks = 0;
|
||||
// TODO: Check subchannel support
|
||||
uint blockSize = 2448;
|
||||
uint blockSize = 0;
|
||||
uint subSize = 0;
|
||||
byte[] tmpBuf;
|
||||
Decoders.CD.FullTOC.CDFullTOC? toc = null;
|
||||
DateTime start;
|
||||
@@ -234,7 +235,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
blockSize = blockSize;
|
||||
// TODO: Support variable subchannel kinds
|
||||
blockSize = 2448;
|
||||
subSize = 96;
|
||||
int sectorSize;
|
||||
if(separateSubchannel)
|
||||
sectorSize = (int)(blockSize - subSize);
|
||||
else
|
||||
sectorSize = (int)blockSize;
|
||||
|
||||
if(toc == null)
|
||||
{
|
||||
@@ -452,20 +460,39 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
DataFile subFile = null;
|
||||
if(separateSubchannel)
|
||||
subFile = new DataFile(outputPrefix + ".sub");
|
||||
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IBGLog(outputPrefix + ".ibg", 0x0008);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
for(int t = 0; t < tracks.Count(); t++)
|
||||
{
|
||||
tracks[t].BytesPerSector = (int)blockSize;
|
||||
//tracks[0].Checksums = sidecar.OpticalDisc[0].Checksums;
|
||||
tracks[t].BytesPerSector = (int)sectorSize;
|
||||
tracks[t].Image = new ImageType();
|
||||
tracks[t].Image.format = "BINARY";
|
||||
tracks[t].Image.offset = dumpFile.Position;
|
||||
tracks[t].Image.offsetSpecified = true;
|
||||
tracks[t].Image.Value = outputPrefix + ".bin";
|
||||
tracks[t].Size = (long)((tracks[t].EndSector - tracks[t].StartSector + 1) * blockSize);
|
||||
tracks[t].Size = (long)((tracks[t].EndSector - tracks[t].StartSector + 1) * sectorSize);
|
||||
tracks[t].SubChannel = new SubChannelType();
|
||||
tracks[t].SubChannel.Image = new ImageType();
|
||||
tracks[t].SubChannel.Image.format = "rw_raw";
|
||||
tracks[t].SubChannel.Image.offsetSpecified = true;
|
||||
tracks[t].SubChannel.Size = (long)((tracks[t].EndSector - tracks[t].StartSector + 1) * subSize);
|
||||
|
||||
if(separateSubchannel)
|
||||
{
|
||||
tracks[t].SubChannel.Image.offset = subFile.Position;
|
||||
tracks[t].SubChannel.Image.Value = outputPrefix + ".sub";
|
||||
}
|
||||
else
|
||||
{
|
||||
tracks[t].SubChannel.Image.offset = tracks[t].Image.offset;
|
||||
tracks[t].SubChannel.Image.Value = tracks[t].Image.Value;
|
||||
}
|
||||
|
||||
bool checkedDataFormat = false;
|
||||
|
||||
for(ulong i = (ulong)tracks[t].StartSector; i <= (ulong)tracks[t].EndSector; i += blocksToRead)
|
||||
@@ -498,6 +525,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
if(separateSubchannel)
|
||||
{
|
||||
for(int b = 0; b < blocksToRead; b++)
|
||||
{
|
||||
dumpFile.Write(readBuffer, (int)(0 + b * blockSize), sectorSize);
|
||||
subFile.Write(readBuffer, (int)(sectorSize + b * blockSize), (int)subSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
dumpFile.Write(readBuffer);
|
||||
}
|
||||
else
|
||||
@@ -507,6 +543,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
return; // TODO: Return more cleanly
|
||||
|
||||
// Write empty data
|
||||
if(separateSubchannel)
|
||||
{
|
||||
dumpFile.Write(new byte[sectorSize * blocksToRead]);
|
||||
subFile.Write(new byte[subSize * blocksToRead]);
|
||||
}
|
||||
else
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
|
||||
// TODO: Record error on mapfile
|
||||
@@ -595,13 +637,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
totalDuration += cmdDuration;
|
||||
}
|
||||
|
||||
if(!sense && !dev.Error)
|
||||
if((!sense && !dev.Error) || runningPersistent)
|
||||
{
|
||||
if(!sense && !dev.Error)
|
||||
unreadableSectors.Remove(badSector);
|
||||
|
||||
if(separateSubchannel)
|
||||
{
|
||||
dumpFile.WriteAt(readBuffer, badSector, (uint)sectorSize, 0, sectorSize);
|
||||
subFile.WriteAt(readBuffer, badSector, subSize, sectorSize, (int)subSize);
|
||||
}
|
||||
else
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && unreadableSectors.Count > 0)
|
||||
@@ -683,11 +731,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
dataChk = new Checksum();
|
||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||
if(separateSubchannel)
|
||||
subFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
for(int t = 0; t < tracks.Count(); t++)
|
||||
{
|
||||
Checksum trkChk = new Checksum();
|
||||
Checksum subChk = new Checksum();
|
||||
|
||||
for(ulong i = (ulong)tracks[t].StartSector; i <= (ulong)tracks[t].EndSector; i += blocksToRead)
|
||||
{
|
||||
@@ -702,8 +753,24 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DateTime chkStart = DateTime.UtcNow;
|
||||
byte[] dataToCheck = new byte[blockSize * blocksToRead];
|
||||
dumpFile.Read(dataToCheck, 0, (int)(blockSize * blocksToRead));
|
||||
if(separateSubchannel)
|
||||
{
|
||||
byte[] data = new byte[sectorSize];
|
||||
byte[] sub = new byte[subSize];
|
||||
for(int b = 0; b < blocksToRead; b++)
|
||||
{
|
||||
Array.Copy(dataToCheck, 0, data, 0, sectorSize);
|
||||
Array.Copy(dataToCheck, sectorSize, sub, 0, subSize);
|
||||
dataChk.Update(data);
|
||||
trkChk.Update(data);
|
||||
subChk.Update(sub);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dataChk.Update(dataToCheck);
|
||||
trkChk.Update(dataToCheck);
|
||||
}
|
||||
DateTime chkEnd = DateTime.UtcNow;
|
||||
|
||||
double chkDuration = (chkEnd - chkStart).TotalMilliseconds;
|
||||
@@ -715,6 +782,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
tracks[t].Checksums = trkChk.End().ToArray();
|
||||
if(separateSubchannel)
|
||||
tracks[t].SubChannel.Checksums = subChk.End().ToArray();
|
||||
else
|
||||
tracks[t].SubChannel.Checksums = tracks[t].Checksums;
|
||||
}
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class MMC
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel)
|
||||
{
|
||||
byte[] cmdBuf = null;
|
||||
byte[] senseBuf = null;
|
||||
@@ -163,7 +163,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(compactDisc)
|
||||
{
|
||||
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType);
|
||||
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
public class SCSI
|
||||
{
|
||||
// TODO: Get cartridge serial number from Certance vendor EVPD
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, bool separateSubchannel)
|
||||
{
|
||||
byte[] senseBuf = null;
|
||||
bool sense = false;
|
||||
@@ -145,7 +145,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType);
|
||||
MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel);
|
||||
|
||||
DicConsole.WriteLine("Writing metadata sidecar");
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
* Options.cs:
|
||||
* Commands/DumpMedia.cs:
|
||||
Added support for dumping subchannel in a separate file.
|
||||
|
||||
* Commands/Ls.cs:
|
||||
* Commands/ExtractFiles.cs:
|
||||
Add support for encodings.
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace DiscImageChef.Commands
|
||||
DicConsole.DebugWriteLine("Dump-Media command", "--force={0}", options.Force);
|
||||
DicConsole.DebugWriteLine("Dump-Media command", "--retry-passes={0}", options.RetryPasses);
|
||||
DicConsole.DebugWriteLine("Dump-Media command", "--persistent={0}", options.Persistent);
|
||||
DicConsole.DebugWriteLine("Dump-Media command", "--separate-subchannel={0}", options.SeparateSubchannel);
|
||||
|
||||
if(!File.Exists(options.DevicePath))
|
||||
{
|
||||
@@ -100,7 +101,7 @@ namespace DiscImageChef.Commands
|
||||
break;
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
SCSI.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError);
|
||||
SCSI.Dump(dev, options.DevicePath, options.OutputPrefix, options.RetryPasses, options.Force, options.Raw, options.Persistent, options.StopOnError, options.SeparateSubchannel);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Unknown device type.");
|
||||
|
||||
@@ -299,6 +299,9 @@ namespace DiscImageChef
|
||||
HelpText = "Try to recover partial or incorrect data.")]
|
||||
public bool Persistent { get; set; }
|
||||
|
||||
[Option("separate-subchannel", Default = false,
|
||||
HelpText = "Save subchannel in a separate file. Only applicable to CD/DDCD/GD.")]
|
||||
public bool SeparateSubchannel { get; set; }
|
||||
}
|
||||
|
||||
[Verb("device-report", HelpText = "Tests the device capabilities and creates an XML report of them.")]
|
||||
|
||||
Reference in New Issue
Block a user