From 889de634fdb886f2f10ae2b9aeb45c1f3eb0d80b Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 26 Dec 2019 03:14:12 +0000 Subject: [PATCH] Add option to select desired subchannel to dump. --- .../Devices/Dumping/CompactDisc.cs | 179 ++++++++++++------ DiscImageChef.Core/Devices/Dumping/Dump.cs | 10 +- DiscImageChef.Gui/Forms/frmDump.xeto.cs | 2 +- DiscImageChef/Commands/DumpMedia.cs | 39 +++- 4 files changed, 165 insertions(+), 65 deletions(-) diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs index b66236085..d8d5f8ffe 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs @@ -152,44 +152,93 @@ namespace DiscImageChef.Core.Devices.Dumping UpdateStatus?.Invoke($"CD reading offset is {cdOffset.Offset} samples."); } - supportedSubchannel = MmcSubchannel.Raw; - _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) + switch(_subchannel) { - _dumpLog.WriteLine("Full raw subchannel reading supported..."); - UpdateStatus?.Invoke("Full raw subchannel reading supported..."); - subSize = 96; + case DumpSubchannel.Any: + if(SupportsRwSubchannel()) + 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; - _dumpLog.WriteLine("Checking if drive supports PQ subchannel reading..."); - 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) + if(!_force || + _subchannel != DumpSubchannel.Any) { - _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!"); - - subSize = 16; + _dumpLog.WriteLine("Output format does not support subchannels, continuing..."); + UpdateStatus?.Invoke("Output format does not support subchannels, continuing..."); } 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..."); 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!"); - UpdateStatus?.Invoke("Drive can only read without subchannel..."); + UpdateStatus?.Invoke("Drive can read without subchannel..."); UpdateStatus?. Invoke("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!"); 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; break; case MmcSubchannel.Raw: + _dumpLog.WriteLine("Full raw subchannel reading supported..."); + UpdateStatus?.Invoke("Full raw subchannel reading supported..."); subType = TrackSubchannelType.Raw; + subSize = 96; + readcd = true; break; 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; + subSize = 16; + readcd = true; break; default: @@ -316,6 +349,8 @@ namespace DiscImageChef.Core.Devices.Dumping return; } + blockSize = sectorSize + subSize; + // We discarded all discs that falsify a TOC before requesting a real TOC // No TOC, no CD (or an empty one) _dumpLog.WriteLine("Reading full TOC"); @@ -2649,5 +2684,25 @@ namespace DiscImageChef.Core.Devices.Dumping 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 _); + } } } \ No newline at end of file diff --git a/DiscImageChef.Core/Devices/Dumping/Dump.cs b/DiscImageChef.Core/Devices/Dumping/Dump.cs index 4cf0e0725..a661e929a 100644 --- a/DiscImageChef.Core/Devices/Dumping/Dump.cs +++ b/DiscImageChef.Core/Devices/Dumping/Dump.cs @@ -14,6 +14,12 @@ using Schemas; namespace DiscImageChef.Core.Devices.Dumping { + public enum DumpSubchannel + { + Any, Rw, RwOrPq, + Pq, None + } + public partial class Dump { readonly bool _debug; @@ -43,6 +49,7 @@ namespace DiscImageChef.Core.Devices.Dumping Resume _resume; Sidecar _sidecarClass; uint _skip; + readonly DumpSubchannel _subchannel; /// Initializes dumpers /// Should resume? @@ -69,7 +76,7 @@ namespace DiscImageChef.Core.Devices.Dumping bool force, bool dumpRaw, bool persistent, bool stopOnError, Resume resume, DumpLog dumpLog, Encoding encoding, string outputPrefix, string outputPath, Dictionary formatOptions, CICMMetadataType preSidecar, uint skip, bool nometadata, bool notrim, bool dumpFirstTrackPregap, - bool fixOffset, bool debug) + bool fixOffset, bool debug, DumpSubchannel subchannel) { _doResume = doResume; _dev = dev; @@ -95,6 +102,7 @@ namespace DiscImageChef.Core.Devices.Dumping _fixOffset = fixOffset; _debug = debug; _maximumReadable = 64; + _subchannel = subchannel; } /// Starts dumping with the stablished fields and autodetecting the device type diff --git a/DiscImageChef.Gui/Forms/frmDump.xeto.cs b/DiscImageChef.Gui/Forms/frmDump.xeto.cs index 2fd2ecd10..463be743c 100644 --- a/DiscImageChef.Gui/Forms/frmDump.xeto.cs +++ b/DiscImageChef.Gui/Forms/frmDump.xeto.cs @@ -527,7 +527,7 @@ namespace DiscImageChef.Gui.Forms chkStopOnError.Checked == true, _resume, dumpLog, encoding, _outputPrefix, txtDestination.Text, parsedOptions, _sidecar, (uint)stpSkipped.Value, chkExistingMetadata.Checked == false, chkTrim.Checked == false, - chkTrack1Pregap.Checked == true, true, false); + chkTrack1Pregap.Checked == true, true, false, DumpSubchannel.Any); new Thread(DoWork).Start(); } diff --git a/DiscImageChef/Commands/DumpMedia.cs b/DiscImageChef/Commands/DumpMedia.cs index 77bf9ccf6..1679cda3a 100644 --- a/DiscImageChef/Commands/DumpMedia.cs +++ b/DiscImageChef/Commands/DumpMedia.cs @@ -72,6 +72,7 @@ namespace DiscImageChef.Commands int _skip = 512; bool _stopOnError; string _wantedOutputFormat; + string _wantedSubchannel; 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("subchannel", + "Subchannel to dump. Only applicable to CD/GD. Values: any, rw, rw-or-pq, pq, none", + s => _wantedSubchannel = s); + /* TODO: Disabled temporarily 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", "--stop-on-error={0}", _stopOnError); DicConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", MainClass.Verbose); + DicConsole.DebugWriteLine("Dump-Media command", "--subchannel={0}", _wantedSubchannel); // TODO: Disabled temporarily //DicConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw); @@ -204,6 +210,37 @@ namespace DiscImageChef.Commands 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 && _devicePath[1] == ':' && _devicePath[0] != '/' && @@ -344,7 +381,7 @@ namespace DiscImageChef.Commands var dumper = new Dump(_doResume, dev, _devicePath, outputFormat, _retryPasses, _force, false, _persistent, _stopOnError, resume, dumpLog, encoding, outputPrefix, _outputFile, parsedOptions, sidecar, (uint)_skip, _noMetadata, _noTrim, _firstTrackPregap, _fixOffset, - MainClass.Debug); + MainClass.Debug, subchannel); dumper.UpdateStatus += Progress.UpdateStatus; dumper.ErrorMessage += Progress.ErrorMessage;