From db975493066dd6539c0fe363a8559c1d0f8ec86a Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 13 Jun 2020 17:27:30 +0100 Subject: [PATCH] Add option to fix subchannel position on dump. --- .../Devices/Dumping/CompactDisc/Subchannel.cs | 69 ++++++++++++++++++- Aaru.Core/Devices/Dumping/Dump.cs | 63 +++++++++-------- .../ViewModels/Windows/MediaDumpViewModel.cs | 2 +- Aaru/Commands/Media/Dump.cs | 13 +++- 4 files changed, 113 insertions(+), 34 deletions(-) diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs index cb7fef6b1..2eba65531 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs @@ -75,13 +75,80 @@ namespace Aaru.Core.Devices.Dumping if(supportedSubchannel == MmcSubchannel.Q16) sub = Subchannel.ConvertQToRaw(sub); - if(desiredSubchannel != MmcSubchannel.None) + if(!_fixSubchannelPosition && + desiredSubchannel != MmcSubchannel.None) _outputPlugin.WriteSectorsTag(sub, sectorAddress, length, SectorTagType.CdSectorSubchannel); subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)sectorAddress, length); byte[] deSub = Subchannel.Deinterleave(sub); + bool indexesChanged = CheckIndexesFromSubchannel(deSub, isrcs, currentTrack, ref mcn, tracks); + + int prePos = int.MinValue; + + // Check subchannel + for(int subPos = 0; subPos < deSub.Length; subPos += 96) + { + byte[] q = new byte[12]; + Array.Copy(deSub, subPos + 12, q, 0, 12); + + CRC16CCITTContext.Data(q, 10, out byte[] crc); + bool crcOk = crc[0] == q[10] && crc[1] == q[11]; + + if(!_fixSubchannelPosition || + desiredSubchannel == MmcSubchannel.None) + continue; + + // TODO: Check CRC OK + + int aPos = int.MinValue; + + byte aframe = (byte)(((q[9] / 16) * 10) + (q[9] & 0x0F)); + + if((q[0] & 0x3) == 1) + { + byte amin = (byte)(((q[7] / 16) * 10) + (q[7] & 0x0F)); + byte asec = (byte)(((q[8] / 16) * 10) + (q[8] & 0x0F)); + aPos = ((amin * 60 * 75) + (asec * 75) + aframe) - 150; + } + else + { + ulong expectedSectorAddress = sectorAddress + (ulong)(subPos / 96) + 150; + byte smin = (byte)(expectedSectorAddress / 60 / 75); + expectedSectorAddress -= (ulong)(smin * 60 * 75); + byte ssec = (byte)(expectedSectorAddress / 75); + expectedSectorAddress -= (ulong)(smin * 75); + byte sframe = (byte)(expectedSectorAddress - ((ulong)ssec * 75)); + + aPos = ((smin * 60 * 75) + (ssec * 75) + aframe) - 150; + + // Next second + if(aPos < prePos) + aPos += 75; + } + + // TODO: Negative sectors + if(aPos < 0) + continue; + + prePos = aPos; + + byte[] posSub = new byte[96]; + Array.Copy(deSub, subPos, posSub, 0, 96); + posSub = Subchannel.Interleave(posSub); + + if(!_fixSubchannelPosition && + desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorTag(posSub, (ulong)aPos, SectorTagType.CdSectorSubchannel); + } + + return indexesChanged; + } + + bool CheckIndexesFromSubchannel(byte[] deSub, Dictionary isrcs, byte currentTrack, ref string mcn, + Track[] tracks) + { // Check subchannel for(int subPos = 0; subPos < deSub.Length; subPos += 96) { diff --git a/Aaru.Core/Devices/Dumping/Dump.cs b/Aaru.Core/Devices/Dumping/Dump.cs index 962854672..c1bd6b3e9 100644 --- a/Aaru.Core/Devices/Dumping/Dump.cs +++ b/Aaru.Core/Devices/Dumping/Dump.cs @@ -69,6 +69,7 @@ namespace Aaru.Core.Devices.Dumping readonly string _outputPrefix; readonly bool _persistent; readonly CICMMetadataType _preSidecar; + readonly bool _private; readonly ushort _retryPasses; readonly bool _stopOnError; readonly DumpSubchannel _subchannel; @@ -78,8 +79,8 @@ namespace Aaru.Core.Devices.Dumping Database.Models.Device _dbDev; // Device database entry bool _dumpFirstTrackPregap; bool _fixOffset; + readonly bool _fixSubchannelPosition; uint _maximumReadable; // Maximum number of sectors drive can read at once - readonly bool _private; Resume _resume; Sidecar _sidecarClass; uint _skip; @@ -112,36 +113,38 @@ namespace Aaru.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 metadata, bool trim, bool dumpFirstTrackPregap, - bool fixOffset, bool debug, DumpSubchannel subchannel, int speed, bool @private) + bool fixOffset, bool debug, DumpSubchannel subchannel, int speed, bool @private, + bool fixSubchannelPosition) { - _doResume = doResume; - _dev = dev; - _devicePath = devicePath; - _outputPlugin = outputPlugin; - _retryPasses = retryPasses; - _force = force; - _dumpRaw = dumpRaw; - _persistent = persistent; - _stopOnError = stopOnError; - _resume = resume; - _dumpLog = dumpLog; - _encoding = encoding; - _outputPrefix = outputPrefix; - _outputPath = outputPath; - _formatOptions = formatOptions; - _preSidecar = preSidecar; - _skip = skip; - _metadata = metadata; - _trim = trim; - _dumpFirstTrackPregap = dumpFirstTrackPregap; - _aborted = false; - _fixOffset = fixOffset; - _debug = debug; - _maximumReadable = 64; - _subchannel = subchannel; - _speedMultiplier = -1; - _speed = speed; - _private = @private; + _doResume = doResume; + _dev = dev; + _devicePath = devicePath; + _outputPlugin = outputPlugin; + _retryPasses = retryPasses; + _force = force; + _dumpRaw = dumpRaw; + _persistent = persistent; + _stopOnError = stopOnError; + _resume = resume; + _dumpLog = dumpLog; + _encoding = encoding; + _outputPrefix = outputPrefix; + _outputPath = outputPath; + _formatOptions = formatOptions; + _preSidecar = preSidecar; + _skip = skip; + _metadata = metadata; + _trim = trim; + _dumpFirstTrackPregap = dumpFirstTrackPregap; + _aborted = false; + _fixOffset = fixOffset; + _debug = debug; + _maximumReadable = 64; + _subchannel = subchannel; + _speedMultiplier = -1; + _speed = speed; + _private = @private; + _fixSubchannelPosition = fixSubchannelPosition; } /// Starts dumping with the stablished fields and autodetecting the device type diff --git a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs index f9a383ac4..10aaf8990 100644 --- a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs +++ b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs @@ -800,7 +800,7 @@ namespace Aaru.Gui.ViewModels.Windows _dumper = new Dump(Resume, _dev, _devicePath, SelectedPlugin.Plugin, (ushort)Retries, Force, false, Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination, parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false, - Track1Pregap, true, false, DumpSubchannel.Any, 0, false); + Track1Pregap, true, false, DumpSubchannel.Any, 0, false, false); new Thread(DoWork).Start(); } diff --git a/Aaru/Commands/Media/Dump.cs b/Aaru/Commands/Media/Dump.cs index add2e5bc1..280f26348 100644 --- a/Aaru/Commands/Media/Dump.cs +++ b/Aaru/Commands/Media/Dump.cs @@ -183,6 +183,14 @@ namespace Aaru.Commands.Media Argument = new Argument(() => false), Required = false }); + Add(new Option(new[] + { + "--fix-subchannel-position" + }, "Store subchannel according to the sector they describe.") + { + Argument = new Argument(() => true), Required = false + }); + Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); } @@ -190,7 +198,7 @@ namespace Aaru.Commands.Media string encoding, bool firstPregap, bool fixOffset, bool force, bool metadata, bool trim, string outputPath, string options, bool persistent, ushort retryPasses, uint skip, byte speed, bool stopOnError, string format, string subchannel, - bool @private) + bool @private, bool fixSubchannelPosition) { MainClass.PrintCopyright(); @@ -222,6 +230,7 @@ namespace Aaru.Commands.Media AaruConsole.DebugWriteLine("Dump-Media command", "--verbose={0}", verbose); AaruConsole.DebugWriteLine("Dump-Media command", "--subchannel={0}", subchannel); AaruConsole.DebugWriteLine("Dump-Media command", "--private={0}", @private); + AaruConsole.DebugWriteLine("Dump-Media command", "--fix-subchannel-position={0}", fixSubchannelPosition); // TODO: Disabled temporarily //AaruConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw); @@ -419,7 +428,7 @@ namespace Aaru.Commands.Media var dumper = new Dump(resume, dev, devicePath, outputFormat, retryPasses, force, false, persistent, stopOnError, resumeClass, dumpLog, encodingClass, outputPrefix, outputPath, parsedOptions, sidecar, skip, metadata, trim, firstPregap, fixOffset, debug, - wantedSubchannel, speed, @private); + wantedSubchannel, speed, @private, fixSubchannelPosition); dumper.UpdateStatus += Progress.UpdateStatus; dumper.ErrorMessage += Progress.ErrorMessage;