From 6a5b18bf457732404bd575379e2e728143af0059 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 13 Jul 2020 22:32:47 +0100 Subject: [PATCH] Add option to generate subchannels for undumped ones. --- Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs | 3 + .../Devices/Dumping/CompactDisc/Subchannel.cs | 59 ++++++++++++++++++- Aaru.Core/Devices/Dumping/Dump.cs | 4 +- Aaru.Core/Logging/SubchannelLog.cs | 13 +++- .../ViewModels/Windows/MediaDumpViewModel.cs | 2 +- Aaru/Commands/Media/Dump.cs | 13 +++- 6 files changed, 85 insertions(+), 9 deletions(-) diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs index 8e4b9e55b..7c1570ed3 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -1218,6 +1218,9 @@ namespace Aaru.Core.Devices.Dumping _resume.BadSubchannels.AddRange(subchannelExtents); _resume.BadSubchannels.Sort(); + if(_generateSubchannels && _outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel)) + GenerateSubchannels(subchannelExtents, tracks, trackFlags, blocks, subLog); + // TODO: Disc ID var metadata = new CommonTypes.Structs.ImageInfo { diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs index bf0cbcf6c..6d8307827 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Aaru.Checksums; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Structs; @@ -80,7 +81,8 @@ namespace Aaru.Core.Devices.Dumping desiredSubchannel != MmcSubchannel.None) _outputPlugin.WriteSectorsTag(sub, sectorAddress, length, SectorTagType.CdSectorSubchannel); - subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)sectorAddress, length); + subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)sectorAddress, length, false, + false); byte[] deSub = Subchannel.Deinterleave(sub); @@ -269,7 +271,7 @@ namespace Aaru.Core.Devices.Dumping subchannelExtents.Remove(aPos); if(@fixed) - subLog?.WriteEntry(posSub, supportedSubchannel == MmcSubchannel.Raw, lba, 1); + subLog?.WriteEntry(posSub, supportedSubchannel == MmcSubchannel.Raw, lba, 1, false, true); } return indexesChanged; @@ -1429,5 +1431,58 @@ namespace Aaru.Core.Devices.Dumping return false; } + + void GenerateSubchannels(HashSet subchannelExtents, Track[] tracks, Dictionary trackFlags, + ulong blocks, SubchannelLog subLog) + { + InitProgress?.Invoke(); + + foreach(int sector in subchannelExtents) + { + Track track = tracks.LastOrDefault(t => (int)t.TrackStartSector <= sector); + byte trkFlags; + byte flags; + ulong trackStart; + ulong pregap; + + // Hidden track + if(track.TrackSequence == 0) + { + track = tracks.FirstOrDefault(t => (int)t.TrackSequence == 1); + trackStart = 0; + pregap = track.TrackStartSector; + } + else + { + trackStart = track.TrackStartSector; + pregap = track.TrackPregap; + } + + if(!trackFlags.TryGetValue((byte)track.TrackSequence, out trkFlags) && + track.TrackType != TrackType.Audio) + flags = (byte)CdFlags.DataTrack; + else + flags = trkFlags; + + byte index; + + if(track.Indexes?.Count > 0) + index = (byte)track.Indexes.LastOrDefault(i => i.Value >= sector).Key; + else + index = 0; + + UpdateProgress?.Invoke($"Generating subchannel for sector {sector}...", sector, (long)blocks); + _dumpLog?.WriteLine($"Generating subchannel for sector {sector}."); + + byte[] sub = Subchannel.Generate(sector, track.TrackSequence, (int)pregap, (int)trackStart, flags, + index); + + _outputPlugin.WriteSectorsTag(sub, (ulong)sector, 1, SectorTagType.CdSectorSubchannel); + + subLog.WriteEntry(sub, true, sector, 1, true, false); + } + + EndProgress?.Invoke(); + } } } \ No newline at end of file diff --git a/Aaru.Core/Devices/Dumping/Dump.cs b/Aaru.Core/Devices/Dumping/Dump.cs index dd357da73..232c77c37 100644 --- a/Aaru.Core/Devices/Dumping/Dump.cs +++ b/Aaru.Core/Devices/Dumping/Dump.cs @@ -84,6 +84,7 @@ namespace Aaru.Core.Devices.Dumping Database.Models.Device _dbDev; // Device database entry bool _dumpFirstTrackPregap; bool _fixOffset; + readonly bool _generateSubchannels; uint _maximumReadable; // Maximum number of sectors drive can read at once Resume _resume; Sidecar _sidecarClass; @@ -120,7 +121,7 @@ namespace Aaru.Core.Devices.Dumping CICMMetadataType preSidecar, uint skip, bool metadata, bool trim, bool dumpFirstTrackPregap, bool fixOffset, bool debug, DumpSubchannel subchannel, int speed, bool @private, bool fixSubchannelPosition, bool retrySubchannel, bool fixSubchannel, bool fixSubchannelCrc, - bool skipCdireadyHole, ErrorLog errorLog) + bool skipCdireadyHole, ErrorLog errorLog, bool generateSubchannels) { _doResume = doResume; _dev = dev; @@ -156,6 +157,7 @@ namespace Aaru.Core.Devices.Dumping _fixSubchannelCrc = fixSubchannelCrc; _skipCdireadyHole = skipCdireadyHole; _errorLog = errorLog; + _generateSubchannels = generateSubchannels; } /// Starts dumping with the stablished fields and autodetecting the device type diff --git a/Aaru.Core/Logging/SubchannelLog.cs b/Aaru.Core/Logging/SubchannelLog.cs index 83f65e8b5..5aa46ba89 100644 --- a/Aaru.Core/Logging/SubchannelLog.cs +++ b/Aaru.Core/Logging/SubchannelLog.cs @@ -34,7 +34,7 @@ namespace Aaru.Core.Logging _logSw.Close(); } - public void WriteEntry(byte[] subchannel, bool raw, long startingLba, uint blocks) + public void WriteEntry(byte[] subchannel, bool raw, long startingLba, uint blocks, bool generated, bool @fixed) { if(subchannel.Length / _subSize != blocks) { @@ -179,8 +179,15 @@ namespace Aaru.Core.Logging subBuf[10] = (byte)q[10 + (block * 12)]; subBuf[11] = (byte)q[11 + (block * 12)]; - _logSw.WriteLine(Subchannel.PrettifyQ(subBuf, _bcd, startingLba + block, corruptedPause, pause, - rwEmpty)); + string prettyQ = Subchannel.PrettifyQ(subBuf, generated || _bcd, startingLba + block, corruptedPause, + pause, rwEmpty); + + if(generated) + prettyQ += " (GENERATED)"; + else if(@fixed) + prettyQ += " (FIXED)"; + + _logSw.WriteLine(prettyQ); } _logSw.Flush(); diff --git a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs index 0af5da691..204fd8e08 100644 --- a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs +++ b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs @@ -803,7 +803,7 @@ namespace Aaru.Gui.ViewModels.Windows Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination, parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false, Track1Pregap, true, false, DumpSubchannel.Any, 0, false, false, false, false, false, - true, errorLog); + true, errorLog, false); new Thread(DoWork).Start(); } diff --git a/Aaru/Commands/Media/Dump.cs b/Aaru/Commands/Media/Dump.cs index 25b94a9b0..42487a4b5 100644 --- a/Aaru/Commands/Media/Dump.cs +++ b/Aaru/Commands/Media/Dump.cs @@ -215,6 +215,14 @@ namespace Aaru.Commands.Media Argument = new Argument(() => false), Required = false }); + Add(new Option(new[] + { + "--generate-subchannels" + }, "Generates missing subchannels (they don't count as dumped in resume file).") + { + Argument = new Argument(() => true), Required = false + }); + Add(new Option(new[] { "--skip-cdiready-hole" @@ -231,7 +239,7 @@ namespace Aaru.Commands.Media bool trim, string outputPath, string options, bool persistent, ushort retryPasses, uint skip, byte speed, bool stopOnError, string format, string subchannel, bool @private, bool fixSubchannelPosition, bool retrySubchannel, bool fixSubchannel, - bool fixSubchannelCrc, bool skipCdireadyHole) + bool fixSubchannelCrc, bool generateSubchannels, bool skipCdireadyHole) { MainClass.PrintCopyright(); @@ -273,6 +281,7 @@ namespace Aaru.Commands.Media AaruConsole.DebugWriteLine("Dump-Media command", "--retry-subchannel={0}", retrySubchannel); AaruConsole.DebugWriteLine("Dump-Media command", "--fix-subchannel={0}", fixSubchannel); AaruConsole.DebugWriteLine("Dump-Media command", "--fix-subchannel-crc={0}", fixSubchannelCrc); + AaruConsole.DebugWriteLine("Dump-Media command", "--generate-subchannels={0}", generateSubchannels); AaruConsole.DebugWriteLine("Dump-Media command", "--skip-cdiready-hole={0}", skipCdireadyHole); // TODO: Disabled temporarily @@ -475,7 +484,7 @@ namespace Aaru.Commands.Media stopOnError, resumeClass, dumpLog, encodingClass, outputPrefix, outputPath, parsedOptions, sidecar, skip, metadata, trim, firstPregap, fixOffset, debug, wantedSubchannel, speed, @private, fixSubchannelPosition, retrySubchannel, - fixSubchannel, fixSubchannelCrc, skipCdireadyHole, errorLog); + fixSubchannel, fixSubchannelCrc, skipCdireadyHole, errorLog, generateSubchannels); dumper.UpdateStatus += Progress.UpdateStatus; dumper.ErrorMessage += Progress.ErrorMessage;