diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs index 60dd12454..e6b32048c 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs @@ -83,7 +83,7 @@ namespace Aaru.Core.Devices.Dumping ref double minSpeed, out bool newTrim, bool nextData, int offsetBytes, bool read6, bool read10, bool read12, bool read16, bool readcd, int sectorsForOffset, uint subSize, MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration, - Track[] tracks, SubchannelLog subLog) + Track[] tracks, SubchannelLog subLog, MmcSubchannel desiredSubchannel) { ulong sectorSpeedStart = 0; // Used to calculate correct speed DateTime timeSpeedStart = DateTime.UtcNow; // Time of start for speed calculation @@ -384,7 +384,11 @@ namespace Aaru.Core.Devices.Dumping Array.Copy(cmdBuf, sectorSize, sub, 0, subSize); _outputPlugin.WriteSectorsLong(data, i + r, 1); - _outputPlugin.WriteSectorsTag(sub, i + r, 1, SectorTagType.CdSectorSubchannel); + + // TODO: Convert Q16 to RAW + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorsTag(sub, i + r, 1, SectorTagType.CdSectorSubchannel); + subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)(i + r), 1); } else @@ -421,8 +425,9 @@ namespace Aaru.Core.Devices.Dumping { _outputPlugin.WriteSectorsLong(new byte[sectorSize], i + r, 1); - _outputPlugin.WriteSectorsTag(new byte[subSize], i + r, 1, - SectorTagType.CdSectorSubchannel); + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorsTag(new byte[subSize], i + r, 1, + SectorTagType.CdSectorSubchannel); } else { @@ -496,7 +501,11 @@ namespace Aaru.Core.Devices.Dumping } _outputPlugin.WriteSectorsLong(data, i, blocksToRead); - _outputPlugin.WriteSectorsTag(sub, i, blocksToRead, SectorTagType.CdSectorSubchannel); + + // TODO: Convert Q16 to RAW + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorsTag(sub, i, blocksToRead, SectorTagType.CdSectorSubchannel); + subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)i, blocksToRead); } else @@ -549,8 +558,9 @@ namespace Aaru.Core.Devices.Dumping { _outputPlugin.WriteSectorsLong(new byte[sectorSize * _skip], i, _skip); - _outputPlugin.WriteSectorsTag(new byte[subSize * _skip], i, _skip, - SectorTagType.CdSectorSubchannel); + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorsTag(new byte[subSize * _skip], i, _skip, + SectorTagType.CdSectorSubchannel); } else { diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs index c591b97ed..c3b9a7d51 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -64,54 +64,54 @@ namespace Aaru.Core.Devices.Dumping /// Dumps a compact disc void CompactDisc() { - ExtentsULong audioExtents; // Extents with audio sectors - ulong blocks; // Total number of positive sectors - uint blockSize; // Size of the read sector in bytes - CdOffset cdOffset; // Read offset from database - byte[] cmdBuf; // Data buffer - DumpHardwareType currentTry = null; // Current dump hardware try - double currentSpeed = 0; // Current read speed - int? discOffset = null; // Disc write offset - DateTime dumpStart = DateTime.UtcNow; // Time of dump start - DateTime end; // Time of operation end - ExtentsULong extents = null; // Extents - bool hiddenData; // Hidden track is data - IbgLog ibgLog; // IMGBurn log - double imageWriteDuration = 0; // Duration of image write - long lastSector; // Last sector number - var leadOutExtents = new ExtentsULong(); // Lead-out extents + ExtentsULong audioExtents; // Extents with audio sectors + ulong blocks; // Total number of positive sectors + uint blockSize; // Size of the read sector in bytes + CdOffset cdOffset; // Read offset from database + byte[] cmdBuf; // Data buffer + DumpHardwareType currentTry = null; // Current dump hardware try + double currentSpeed = 0; // Current read speed + int? discOffset = null; // Disc write offset + DateTime dumpStart = DateTime.UtcNow; // Time of dump start + DateTime end; // Time of operation end + ExtentsULong extents = null; // Extents + bool hiddenData; // Hidden track is data + IbgLog ibgLog; // IMGBurn log + double imageWriteDuration = 0; // Duration of image write + long lastSector; // Last sector number + var leadOutExtents = new ExtentsULong(); // Lead-out extents Dictionary leadOutStarts = new Dictionary(); // Lead-out starts - double maxSpeed = double.MinValue; // Maximum speed - MhddLog mhddLog; // MHDD log - double minSpeed = double.MaxValue; // Minimum speed - bool newTrim; // Is trim a new one? - int offsetBytes = 0; // Read offset - bool read6 = false; // Device supports READ(6) - bool read10 = false; // Device supports READ(10) - bool read12 = false; // Device supports READ(12) - bool read16 = false; // Device supports READ(16) - bool readcd; // Device supports READ CD - bool ret; // Image writing return status - const uint sectorSize = 2352; // Full sector size - int sectorsForOffset = 0; // Sectors needed to fix offset - bool sense = true; // Sense indicator - int sessions; // Number of sessions in disc - DateTime start; // Start of operation - SubchannelLog subLog = null; // Subchannel log - uint subSize; // Subchannel size in bytes - TrackSubchannelType subType; // Track subchannel type - bool supportsLongSectors = true; // Supports reading EDC and ECC - bool supportsPqSubchannel; // Supports reading PQ subchannel - bool supportsRwSubchannel; // Supports reading RW subchannel - byte[] tmpBuf; // Temporary buffer - FullTOC.CDFullTOC? toc; // Full CD TOC - double totalDuration = 0; // Total commands duration + double maxSpeed = double.MinValue; // Maximum speed + MhddLog mhddLog; // MHDD log + double minSpeed = double.MaxValue; // Minimum speed + bool newTrim; // Is trim a new one? + int offsetBytes = 0; // Read offset + bool read6 = false; // Device supports READ(6) + bool read10 = false; // Device supports READ(10) + bool read12 = false; // Device supports READ(12) + bool read16 = false; // Device supports READ(16) + bool readcd; // Device supports READ CD + bool ret; // Image writing return status + const uint sectorSize = 2352; // Full sector size + int sectorsForOffset = 0; // Sectors needed to fix offset + bool sense = true; // Sense indicator + int sessions; // Number of sessions in disc + DateTime start; // Start of operation + SubchannelLog subLog = null; // Subchannel log + uint subSize; // Subchannel size in bytes + TrackSubchannelType subType; // Track subchannel type + bool supportsLongSectors = true; // Supports reading EDC and ECC + bool supportsPqSubchannel; // Supports reading PQ subchannel + bool supportsRwSubchannel; // Supports reading RW subchannel + byte[] tmpBuf; // Temporary buffer + FullTOC.CDFullTOC? toc; // Full CD TOC + double totalDuration = 0; // Total commands duration Dictionary trackFlags = new Dictionary(); // Track flags - Track[] tracks; // Tracks in disc - - int firstTrackLastSession; // Number of first track in last session - bool hiddenTrack; // Disc has a hidden track before track 1 - MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel + Track[] tracks; // Tracks in disc + int firstTrackLastSession; // Number of first track in last session + bool hiddenTrack; // Disc has a hidden track before track 1 + MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel + MmcSubchannel desiredSubchannel; // User requested subchannel Dictionary mediaTags = new Dictionary(); // Media tags @@ -129,20 +129,27 @@ namespace Aaru.Core.Devices.Dumping supportsPqSubchannel = SupportsPqSubchannel(_dev, _dumpLog, UpdateStatus); supportsRwSubchannel = SupportsRwSubchannel(_dev, _dumpLog, UpdateStatus); + if(supportsRwSubchannel) + supportedSubchannel = MmcSubchannel.Raw; + else if(supportsPqSubchannel) + supportedSubchannel = MmcSubchannel.Q16; + else + supportedSubchannel = MmcSubchannel.None; + switch(_subchannel) { case DumpSubchannel.Any: if(supportsRwSubchannel) - supportedSubchannel = MmcSubchannel.Raw; + desiredSubchannel = MmcSubchannel.Raw; else if(supportsPqSubchannel) - supportedSubchannel = MmcSubchannel.Q16; + desiredSubchannel = MmcSubchannel.Q16; else - supportedSubchannel = MmcSubchannel.None; + desiredSubchannel = MmcSubchannel.None; break; case DumpSubchannel.Rw: if(supportsRwSubchannel) - supportedSubchannel = MmcSubchannel.Raw; + desiredSubchannel = MmcSubchannel.Raw; else { _dumpLog.WriteLine("Drive does not support the requested subchannel format, not continuing..."); @@ -156,9 +163,9 @@ namespace Aaru.Core.Devices.Dumping break; case DumpSubchannel.RwOrPq: if(supportsRwSubchannel) - supportedSubchannel = MmcSubchannel.Raw; + desiredSubchannel = MmcSubchannel.Raw; else if(supportsPqSubchannel) - supportedSubchannel = MmcSubchannel.Q16; + desiredSubchannel = MmcSubchannel.Q16; else { _dumpLog.WriteLine("Drive does not support the requested subchannel format, not continuing..."); @@ -172,7 +179,7 @@ namespace Aaru.Core.Devices.Dumping break; case DumpSubchannel.Pq: if(supportsPqSubchannel) - supportedSubchannel = MmcSubchannel.Q16; + desiredSubchannel = MmcSubchannel.Q16; else { _dumpLog.WriteLine("Drive does not support the requested subchannel format, not continuing..."); @@ -185,15 +192,18 @@ namespace Aaru.Core.Devices.Dumping break; case DumpSubchannel.None: - supportedSubchannel = MmcSubchannel.None; + desiredSubchannel = MmcSubchannel.None; break; default: throw new ArgumentOutOfRangeException(); } + if(desiredSubchannel == MmcSubchannel.Q16 && supportsPqSubchannel) + supportedSubchannel = MmcSubchannel.Q16; + // Check if output format supports subchannels if(!_outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) && - supportedSubchannel != MmcSubchannel.None) + desiredSubchannel != MmcSubchannel.None) { if(_force || _subchannel == DumpSubchannel.None) { @@ -208,7 +218,7 @@ namespace Aaru.Core.Devices.Dumping return; } - supportedSubchannel = MmcSubchannel.None; + desiredSubchannel = MmcSubchannel.None; } switch(supportedSubchannel) @@ -460,7 +470,7 @@ namespace Aaru.Core.Devices.Dumping } if(tracks.Any(t => t.TrackType == TrackType.Audio) && - supportedSubchannel != MmcSubchannel.Raw) + desiredSubchannel != MmcSubchannel.Raw) { _dumpLog.WriteLine("WARNING: If disc says CD+G, CD+EG, CD-MIDI, CD Graphics or CD Enhanced Graphics, dump will be incorrect!"); @@ -723,7 +733,7 @@ namespace Aaru.Core.Devices.Dumping ret = (_outputPlugin as IWritableOpticalImage).SetTracks(tracks.ToList()); if(!ret && - supportedSubchannel == MmcSubchannel.None) + desiredSubchannel == MmcSubchannel.None) { _dumpLog.WriteLine("Error sending tracks to output image, not continuing."); _dumpLog.WriteLine(_outputPlugin.ErrorMessage); @@ -735,7 +745,8 @@ namespace Aaru.Core.Devices.Dumping } // If a subchannel is supported, check if output plugin allows us to write it. - if(supportedSubchannel != MmcSubchannel.None) + // TODO: Use image characteristics + if(desiredSubchannel != MmcSubchannel.None) { _dev.ReadCd(out cmdBuf, out _, 0, blockSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, supportedSubchannel, @@ -744,6 +755,7 @@ namespace Aaru.Core.Devices.Dumping tmpBuf = new byte[subSize]; Array.Copy(cmdBuf, sectorSize, tmpBuf, 0, subSize); + // TODO: Convert Q16 to RAW ret = _outputPlugin.WriteSectorTag(tmpBuf, 0, SectorTagType.CdSectorSubchannel); if(!ret) @@ -766,9 +778,9 @@ namespace Aaru.Core.Devices.Dumping return; } - supportedSubchannel = MmcSubchannel.None; - subSize = 0; - blockSize = sectorSize + subSize; + desiredSubchannel = MmcSubchannel.None; + subSize = 0; + blockSize = sectorSize + subSize; for(int t = 0; t < tracks.Length; t++) tracks[t].TrackSubchannelType = TrackSubchannelType.None; @@ -812,6 +824,7 @@ namespace Aaru.Core.Devices.Dumping } // Set MCN + // TODO: Use subchannels sense = _dev.ReadMcn(out string mcn, out _, out _, _dev.Timeout, out _); if(!sense && @@ -824,6 +837,7 @@ namespace Aaru.Core.Devices.Dumping } // Set ISRCs + // TODO: Use subchannels foreach(Track trk in tracks) { sense = _dev.ReadIsrc((byte)trk.TrackSequence, out string isrc, out _, out _, _dev.Timeout, out _); @@ -1008,13 +1022,13 @@ namespace Aaru.Core.Devices.Dumping ref imageWriteDuration, lastSector, leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, out newTrim, tracks[0].TrackType != TrackType.Audio, offsetBytes, read6, read10, read12, read16, readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors, ref totalDuration, - tracks, subLog); + tracks, subLog, desiredSubchannel); // TODO: Enable when underlying images support lead-outs /* DumpCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration, leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd, - supportedSubchannel, subSize, ref totalDuration, subLog); + supportedSubchannel, subSize, ref totalDuration, subLog, desiredSubchannel); */ end = DateTime.UtcNow; @@ -1041,10 +1055,10 @@ namespace Aaru.Core.Devices.Dumping TrimCdUserData(audioExtents, blockSize, currentTry, extents, newTrim, offsetBytes, read6, read10, read12, read16, readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors, - ref totalDuration, subLog); + ref totalDuration, subLog, desiredSubchannel); RetryCdUserData(audioExtents, blockSize, currentTry, extents, offsetBytes, readcd, sectorsForOffset, - subSize, supportedSubchannel, ref totalDuration, subLog); + subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel); // Write media tags to image if(!_aborted) diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs index 8fdb7fe38..00beec36c 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs @@ -51,7 +51,8 @@ namespace Aaru.Core.Devices.Dumping { void RetryCdUserData(ExtentsULong audioExtents, uint blockSize, DumpHardwareType currentTry, ExtentsULong extents, int offsetBytes, bool readcd, int sectorsForOffset, uint subSize, - MmcSubchannel supportedSubchannel, ref double totalDuration, SubchannelLog subLog) + MmcSubchannel supportedSubchannel, ref double totalDuration, SubchannelLog subLog, + MmcSubchannel desiredSubchannel) { bool sense = true; // Sense indicator byte[] cmdBuf = null; // Data buffer @@ -278,7 +279,11 @@ namespace Aaru.Core.Devices.Dumping Array.Copy(cmdBuf, 0, data, 0, sectorSize); Array.Copy(cmdBuf, sectorSize, sub, 0, subSize); _outputPlugin.WriteSectorLong(data, badSector); - _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); + + // TODO: Convert Q16 to RAW + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); + subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)badSector, 1); } else @@ -376,7 +381,11 @@ namespace Aaru.Core.Devices.Dumping Array.Copy(cmdBuf, 0, data, 0, sectorSize); Array.Copy(cmdBuf, sectorSize, sub, 0, subSize); _outputPlugin.WriteSectorLong(data, badSector); - _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); + + // TODO: Convert Q16 to RAW + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); + subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)badSector, 1); } else diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs b/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs index a50c4acfc..973126c7e 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs @@ -224,7 +224,7 @@ namespace Aaru.Core.Devices.Dumping ExtentsULong leadOutExtents, ref double maxSpeed, MhddLog mhddLog, ref double minSpeed, bool read6, bool read10, bool read12, bool read16, bool readcd, MmcSubchannel supportedSubchannel, uint subSize, ref double totalDuration, - SubchannelLog subLog) + SubchannelLog subLog, MmcSubchannel desiredSubchannel) { byte[] cmdBuf = null; // Data buffer const uint sectorSize = 2352; // Full sector size @@ -306,7 +306,11 @@ namespace Aaru.Core.Devices.Dumping } _outputPlugin.WriteSectorsLong(data, i, _maximumReadable); - _outputPlugin.WriteSectorsTag(sub, i, _maximumReadable, SectorTagType.CdSectorSubchannel); + + // TODO: Convert Q16 to RAW + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorsTag(sub, i, _maximumReadable, + SectorTagType.CdSectorSubchannel); subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)i, _maximumReadable); @@ -329,8 +333,9 @@ namespace Aaru.Core.Devices.Dumping { _outputPlugin.WriteSectorsLong(new byte[sectorSize * _skip], i, 1); - _outputPlugin.WriteSectorsTag(new byte[subSize * _skip], i, 1, - SectorTagType.CdSectorSubchannel); + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorsTag(new byte[subSize * _skip], i, 1, + SectorTagType.CdSectorSubchannel); } else _outputPlugin.WriteSectors(new byte[blockSize * _skip], i, 1); diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs index 5bb7877e8..b519daeaf 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs @@ -49,7 +49,7 @@ namespace Aaru.Core.Devices.Dumping ExtentsULong extents, bool newTrim, int offsetBytes, bool read6, bool read10, bool read12, bool read16, bool readcd, int sectorsForOffset, uint subSize, MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration, - SubchannelLog subLog) + SubchannelLog subLog, MmcSubchannel desiredSubchannel) { DateTime start; DateTime end; @@ -178,7 +178,11 @@ namespace Aaru.Core.Devices.Dumping Array.Copy(cmdBuf, 0, data, 0, sectorSize); Array.Copy(cmdBuf, sectorSize, sub, 0, subSize); _outputPlugin.WriteSectorLong(data, badSector); - _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); + + // TODO: Convert Q16 to RAW + if(desiredSubchannel != MmcSubchannel.None) + _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); + subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)badSector, 1); } else