Add option to select desired subchannel to dump.

This commit is contained in:
2019-12-26 03:14:12 +00:00
parent c57a42aaa3
commit 889de634fd
4 changed files with 165 additions and 65 deletions

View File

@@ -152,44 +152,93 @@ namespace DiscImageChef.Core.Devices.Dumping
UpdateStatus?.Invoke($"CD reading offset is {cdOffset.Offset} samples."); UpdateStatus?.Invoke($"CD reading offset is {cdOffset.Offset} samples.");
} }
supportedSubchannel = MmcSubchannel.Raw; switch(_subchannel)
_dumpLog.WriteLine("Checking if drive supports full raw subchannel reading...");
UpdateStatus?.Invoke("Checking if drive supports full raw subchannel reading...");
readcd = !_dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize + 96, 1, MmcSectorTypes.AllTypes, false,
false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
supportedSubchannel, _dev.Timeout, out _);
if(readcd)
{ {
_dumpLog.WriteLine("Full raw subchannel reading supported..."); case DumpSubchannel.Any:
UpdateStatus?.Invoke("Full raw subchannel reading supported..."); if(SupportsRwSubchannel())
subSize = 96; supportedSubchannel = MmcSubchannel.Raw;
else if(SupportsPqSubchannel())
supportedSubchannel = MmcSubchannel.Q16;
else
supportedSubchannel = MmcSubchannel.None;
break;
case DumpSubchannel.Rw:
if(SupportsRwSubchannel())
supportedSubchannel = MmcSubchannel.Raw;
else
{
_dumpLog.WriteLine("Drive does not support the requested subchannel format, not continuing...");
StoppingErrorMessage?.
Invoke("Drive does not support the requested subchannel format, not continuing...");
return;
}
break;
case DumpSubchannel.RwOrPq:
if(SupportsRwSubchannel())
supportedSubchannel = MmcSubchannel.Raw;
else if(SupportsPqSubchannel())
supportedSubchannel = MmcSubchannel.Q16;
else
{
_dumpLog.WriteLine("Drive does not support the requested subchannel format, not continuing...");
StoppingErrorMessage?.
Invoke("Drive does not support the requested subchannel format, not continuing...");
return;
}
break;
case DumpSubchannel.Pq:
if(SupportsPqSubchannel())
supportedSubchannel = MmcSubchannel.Q16;
else
{
_dumpLog.WriteLine("Drive does not support the requested subchannel format, not continuing...");
StoppingErrorMessage?.
Invoke("Drive does not support the requested subchannel format, not continuing...");
return;
}
break;
case DumpSubchannel.None:
supportedSubchannel = MmcSubchannel.None;
break;
default: throw new ArgumentOutOfRangeException();
} }
else
// Check if output format supports subchannels
if(!_outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) &&
supportedSubchannel != MmcSubchannel.None)
{ {
supportedSubchannel = MmcSubchannel.Q16; if(!_force ||
_dumpLog.WriteLine("Checking if drive supports PQ subchannel reading..."); _subchannel != DumpSubchannel.Any)
UpdateStatus?.Invoke("Checking if drive supports PQ subchannel reading...");
readcd = !_dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize + 16, 1, MmcSectorTypes.AllTypes, false,
false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
supportedSubchannel, _dev.Timeout, out _);
if(readcd)
{ {
_dumpLog.WriteLine("PQ subchannel reading supported..."); _dumpLog.WriteLine("Output format does not support subchannels, continuing...");
_dumpLog.WriteLine("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!"); UpdateStatus?.Invoke("Output format does not support subchannels, continuing...");
UpdateStatus?.Invoke("PQ subchannel reading supported...");
UpdateStatus?.
Invoke("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!");
subSize = 16;
} }
else else
{ {
supportedSubchannel = MmcSubchannel.None; _dumpLog.WriteLine("Output format does not support subchannels, not continuing...");
StoppingErrorMessage?.Invoke("Output format does not support subchannels, not continuing...");
return;
}
supportedSubchannel = MmcSubchannel.None;
subSize = 0;
}
switch(supportedSubchannel)
{
case MmcSubchannel.None:
_dumpLog.WriteLine("Checking if drive supports reading without subchannel..."); _dumpLog.WriteLine("Checking if drive supports reading without subchannel...");
UpdateStatus?.Invoke("Checking if drive supports reading without subchannel..."); UpdateStatus?.Invoke("Checking if drive supports reading without subchannel...");
@@ -259,52 +308,36 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
_dumpLog.WriteLine("Drive can only read without subchannel..."); _dumpLog.WriteLine("Drive can read without subchannel...");
_dumpLog.WriteLine("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!"); _dumpLog.WriteLine("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!");
UpdateStatus?.Invoke("Drive can only read without subchannel..."); UpdateStatus?.Invoke("Drive can read without subchannel...");
UpdateStatus?. UpdateStatus?.
Invoke("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!"); Invoke("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!");
subSize = 0; subSize = 0;
}
}
// Check if output format supports subchannels
if(!_outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) &&
supportedSubchannel != MmcSubchannel.None)
{
if(!_force)
{
_dumpLog.WriteLine("Output format does not support subchannels, continuing...");
UpdateStatus?.Invoke("Output format does not support subchannels, continuing...");
}
else
{
_dumpLog.WriteLine("Output format does not support subchannels, not continuing...");
StoppingErrorMessage?.Invoke("Output format does not support subchannels, not continuing...");
return;
}
supportedSubchannel = MmcSubchannel.None;
subSize = 0;
}
blockSize = sectorSize + subSize;
switch(supportedSubchannel)
{
case MmcSubchannel.None:
subType = TrackSubchannelType.None; subType = TrackSubchannelType.None;
break; break;
case MmcSubchannel.Raw: case MmcSubchannel.Raw:
_dumpLog.WriteLine("Full raw subchannel reading supported...");
UpdateStatus?.Invoke("Full raw subchannel reading supported...");
subType = TrackSubchannelType.Raw; subType = TrackSubchannelType.Raw;
subSize = 96;
readcd = true;
break; break;
case MmcSubchannel.Q16: case MmcSubchannel.Q16:
_dumpLog.WriteLine("PQ subchannel reading supported...");
_dumpLog.WriteLine("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!");
UpdateStatus?.Invoke("PQ subchannel reading supported...");
UpdateStatus?.
Invoke("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!");
subType = TrackSubchannelType.Q16; subType = TrackSubchannelType.Q16;
subSize = 16;
readcd = true;
break; break;
default: default:
@@ -316,6 +349,8 @@ namespace DiscImageChef.Core.Devices.Dumping
return; return;
} }
blockSize = sectorSize + subSize;
// We discarded all discs that falsify a TOC before requesting a real TOC // We discarded all discs that falsify a TOC before requesting a real TOC
// No TOC, no CD (or an empty one) // No TOC, no CD (or an empty one)
_dumpLog.WriteLine("Reading full TOC"); _dumpLog.WriteLine("Reading full TOC");
@@ -2649,5 +2684,25 @@ namespace DiscImageChef.Core.Devices.Dumping
Statistics.AddMedia(dskType, true); Statistics.AddMedia(dskType, true);
} }
bool SupportsRwSubchannel()
{
_dumpLog.WriteLine("Checking if drive supports full raw subchannel reading...");
UpdateStatus?.Invoke("Checking if drive supports full raw subchannel reading...");
return!_dev.ReadCd(out _, out _, 0, 2352 + 96, 1, MmcSectorTypes.AllTypes, false, false, true,
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Raw,
_dev.Timeout, out _);
}
bool SupportsPqSubchannel()
{
_dumpLog.WriteLine("Checking if drive supports PQ subchannel reading...");
UpdateStatus?.Invoke("Checking if drive supports PQ subchannel reading...");
return!_dev.ReadCd(out _, out _, 0, 2352 + 16, 1, MmcSectorTypes.AllTypes, false, false, true,
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16,
_dev.Timeout, out _);
}
} }
} }

View File

@@ -14,6 +14,12 @@ using Schemas;
namespace DiscImageChef.Core.Devices.Dumping namespace DiscImageChef.Core.Devices.Dumping
{ {
public enum DumpSubchannel
{
Any, Rw, RwOrPq,
Pq, None
}
public partial class Dump public partial class Dump
{ {
readonly bool _debug; readonly bool _debug;
@@ -43,6 +49,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Resume _resume; Resume _resume;
Sidecar _sidecarClass; Sidecar _sidecarClass;
uint _skip; uint _skip;
readonly DumpSubchannel _subchannel;
/// <summary>Initializes dumpers</summary> /// <summary>Initializes dumpers</summary>
/// <param name="doResume">Should resume?</param> /// <param name="doResume">Should resume?</param>
@@ -69,7 +76,7 @@ namespace DiscImageChef.Core.Devices.Dumping
bool force, bool dumpRaw, bool persistent, bool stopOnError, Resume resume, DumpLog dumpLog, bool force, bool dumpRaw, bool persistent, bool stopOnError, Resume resume, DumpLog dumpLog,
Encoding encoding, string outputPrefix, string outputPath, Dictionary<string, string> formatOptions, Encoding encoding, string outputPrefix, string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip, bool nometadata, bool notrim, bool dumpFirstTrackPregap, CICMMetadataType preSidecar, uint skip, bool nometadata, bool notrim, bool dumpFirstTrackPregap,
bool fixOffset, bool debug) bool fixOffset, bool debug, DumpSubchannel subchannel)
{ {
_doResume = doResume; _doResume = doResume;
_dev = dev; _dev = dev;
@@ -95,6 +102,7 @@ namespace DiscImageChef.Core.Devices.Dumping
_fixOffset = fixOffset; _fixOffset = fixOffset;
_debug = debug; _debug = debug;
_maximumReadable = 64; _maximumReadable = 64;
_subchannel = subchannel;
} }
/// <summary>Starts dumping with the stablished fields and autodetecting the device type</summary> /// <summary>Starts dumping with the stablished fields and autodetecting the device type</summary>

View File

@@ -527,7 +527,7 @@ namespace DiscImageChef.Gui.Forms
chkStopOnError.Checked == true, _resume, dumpLog, encoding, _outputPrefix, chkStopOnError.Checked == true, _resume, dumpLog, encoding, _outputPrefix,
txtDestination.Text, parsedOptions, _sidecar, (uint)stpSkipped.Value, txtDestination.Text, parsedOptions, _sidecar, (uint)stpSkipped.Value,
chkExistingMetadata.Checked == false, chkTrim.Checked == false, chkExistingMetadata.Checked == false, chkTrim.Checked == false,
chkTrack1Pregap.Checked == true, true, false); chkTrack1Pregap.Checked == true, true, false, DumpSubchannel.Any);
new Thread(DoWork).Start(); new Thread(DoWork).Start();
} }

View File

@@ -72,6 +72,7 @@ namespace DiscImageChef.Commands
int _skip = 512; int _skip = 512;
bool _stopOnError; bool _stopOnError;
string _wantedOutputFormat; string _wantedOutputFormat;
string _wantedSubchannel;
public DumpMediaCommand() : base("dump-media", "Dumps the media inserted on a device to a media image.") public DumpMediaCommand() : base("dump-media", "Dumps the media inserted on a device to a media image.")
{ {
@@ -118,6 +119,10 @@ namespace DiscImageChef.Commands
Options.Add("help|h|?", "Show this message and exit.", v => _showHelp = v != null); Options.Add("help|h|?", "Show this message and exit.", v => _showHelp = v != null);
Options.Add("subchannel",
"Subchannel to dump. Only applicable to CD/GD. Values: any, rw, rw-or-pq, pq, none",
s => _wantedSubchannel = s);
/* TODO: Disabled temporarily /* TODO: Disabled temporarily
Options.Add("raw|r", "Dump sectors with tags included. For optical media, dump scrambled sectors.", (b) => raw = b != null);*/ Options.Add("raw|r", "Dump sectors with tags included. For optical media, dump scrambled sectors.", (b) => raw = b != null);*/
} }
@@ -177,6 +182,7 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", _skip); DicConsole.DebugWriteLine("Dump-Media command", "--skip={0}", _skip);
DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", _stopOnError); DicConsole.DebugWriteLine("Dump-Media command", "--stop-on-error={0}", _stopOnError);
DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose); DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose);
DicConsole.DebugWriteLine("Dump-Media command", "--subchannel={0}", _wantedSubchannel);
// TODO: Disabled temporarily // TODO: Disabled temporarily
//DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw); //DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw);
@@ -204,6 +210,37 @@ namespace DiscImageChef.Commands
return(int)ErrorNumber.EncodingUnknown; return(int)ErrorNumber.EncodingUnknown;
} }
DumpSubchannel subchannel = DumpSubchannel.Any;
switch(_wantedSubchannel?.ToLowerInvariant())
{
case"any":
case null:
subchannel = DumpSubchannel.Any;
break;
case"rw":
subchannel = DumpSubchannel.Rw;
break;
case"rw-or-pq":
subchannel = DumpSubchannel.RwOrPq;
break;
case"pq":
subchannel = DumpSubchannel.Pq;
break;
case"none":
subchannel = DumpSubchannel.None;
break;
default:
DicConsole.WriteLine("Incorrect subchannel type \"{0}\" requested.", _wantedSubchannel);
break;
}
if(_devicePath.Length == 2 && if(_devicePath.Length == 2 &&
_devicePath[1] == ':' && _devicePath[1] == ':' &&
_devicePath[0] != '/' && _devicePath[0] != '/' &&
@@ -344,7 +381,7 @@ namespace DiscImageChef.Commands
var dumper = new Dump(_doResume, dev, _devicePath, outputFormat, _retryPasses, _force, false, _persistent, var dumper = new Dump(_doResume, dev, _devicePath, outputFormat, _retryPasses, _force, false, _persistent,
_stopOnError, resume, dumpLog, encoding, outputPrefix, _outputFile, parsedOptions, _stopOnError, resume, dumpLog, encoding, outputPrefix, _outputFile, parsedOptions,
sidecar, (uint)_skip, _noMetadata, _noTrim, _firstTrackPregap, _fixOffset, sidecar, (uint)_skip, _noMetadata, _noTrim, _firstTrackPregap, _fixOffset,
MainClass.Debug); MainClass.Debug, subchannel);
dumper.UpdateStatus += Progress.UpdateStatus; dumper.UpdateStatus += Progress.UpdateStatus;
dumper.ErrorMessage += Progress.ErrorMessage; dumper.ErrorMessage += Progress.ErrorMessage;