From 912ab555fb9eeb48fabe62315ed370c987578609 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Wed, 1 Jan 2020 21:50:49 +0000 Subject: [PATCH] Calculate and use track pregaps. --- .../Devices/Dumping/CompactDisc/Dump.cs | 4 +- .../Devices/Dumping/CompactDisc/Pregap.cs | 112 ++++++++++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs index f486dca3e..6204ef517 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -57,7 +57,7 @@ namespace DiscImageChef.Core.Devices.Dumping { /// Implement dumping Compact Discs - // TODO: Barcode and pregaps + // TODO: Barcode partial class Dump { /// Dumps a compact disc @@ -345,6 +345,8 @@ namespace DiscImageChef.Core.Devices.Dumping if(tracks is null) return; + SolveTrackPregaps(tracks, supportsPqSubchannel, supportsRwSubchannel); + for(int t = 1; t < tracks.Length; t++) tracks[t - 1].TrackEndSector = tracks[t].TrackStartSector - 1; diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs index c2a9dddb5..81bf7cf45 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs @@ -34,6 +34,7 @@ using System; using System.Collections.Generic; using System.IO; using DiscImageChef.CommonTypes.Enums; +using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Devices; // ReSharper disable JoinDeclarationAndInitializer @@ -116,5 +117,116 @@ namespace DiscImageChef.Core.Devices.Dumping firstTrackPregapMs.Close(); } + + void SolveTrackPregaps(Track[] tracks, bool supportsPqSubchannel, bool supportsRwSubchannel) + { + bool sense; // Sense indicator + byte[] cmdBuf; // Data buffer + + if(!supportsPqSubchannel && + !supportsRwSubchannel) + return; + + for(int i = 1; i < tracks.Length; i++) + { + uint lba = (uint)tracks[i].TrackStartSector - 150; + int trackPregap = 0; + bool previousSense = false; + + while(lba > tracks[i - 1].TrackStartSector) + { + if(supportsPqSubchannel) + sense = _dev.ReadCd(out cmdBuf, out _, lba, 16, 1, MmcSectorTypes.AllTypes, false, false, false, + MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Q16, + _dev.Timeout, out _); + else + { + sense = _dev.ReadCd(out cmdBuf, out _, lba, 16, 1, MmcSectorTypes.AllTypes, false, false, false, + MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Q16, + _dev.Timeout, out _); + + sense = _dev.ReadCd(out cmdBuf, out _, lba, 96, 1, MmcSectorTypes.AllTypes, false, false, false, + MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Raw, + _dev.Timeout, out _); + + if(!sense) + { + int[] q = new int[cmdBuf.Length / 8]; + + // De-interlace Q subchannel + for(int iq = 0; iq < cmdBuf.Length; iq += 8) + { + q[iq / 8] = (cmdBuf[iq] & 0x40) << 1; + q[iq / 8] += cmdBuf[iq + 1] & 0x40; + q[iq / 8] += (cmdBuf[iq + 2] & 0x40) >> 1; + q[iq / 8] += (cmdBuf[iq + 3] & 0x40) >> 2; + q[iq / 8] += (cmdBuf[iq + 4] & 0x40) >> 3; + q[iq / 8] += (cmdBuf[iq + 5] & 0x40) >> 4; + q[iq / 8] += (cmdBuf[iq + 6] & 0x40) >> 5; + q[iq / 8] += (cmdBuf[iq + 7] & 0x40) >> 6; + } + + cmdBuf = new byte[q.Length]; + + for(int iq = 0; iq < cmdBuf.Length; iq++) + { + cmdBuf[iq] = (byte)q[iq]; + } + + cmdBuf[1] = (byte)(((cmdBuf[1] / 16) * 10) + (cmdBuf[1] & 0x0F)); + cmdBuf[2] = (byte)(((cmdBuf[2] / 16) * 10) + (cmdBuf[2] & 0x0F)); + cmdBuf[3] = (byte)(((cmdBuf[3] / 16) * 10) + (cmdBuf[3] & 0x0F)); + cmdBuf[4] = (byte)(((cmdBuf[4] / 16) * 10) + (cmdBuf[4] & 0x0F)); + cmdBuf[5] = (byte)(((cmdBuf[5] / 16) * 10) + (cmdBuf[5] & 0x0F)); + cmdBuf[6] = (byte)(((cmdBuf[6] / 16) * 10) + (cmdBuf[6] & 0x0F)); + cmdBuf[7] = (byte)(((cmdBuf[7] / 16) * 10) + (cmdBuf[7] & 0x0F)); + cmdBuf[8] = (byte)(((cmdBuf[8] / 16) * 10) + (cmdBuf[8] & 0x0F)); + cmdBuf[9] = (byte)(((cmdBuf[9] / 16) * 10) + (cmdBuf[9] & 0x0F)); + } + } + + if(!sense) + { + // Q position + if((cmdBuf[0] & 0xF) != 1) + continue; + + if(cmdBuf[1] != tracks[i].TrackSequence || + cmdBuf[2] != 0) + { + lba++; + trackPregap = (int)(tracks[i].TrackStartSector - lba); + + if(previousSense) + break; + + continue; + } + + int pregapQ = (cmdBuf[3] * 60 * 75) + (cmdBuf[4] * 75) + cmdBuf[5]; + + if(pregapQ > trackPregap) + trackPregap = pregapQ; + else + break; + + lba--; + } + else + { + previousSense = true; + lba--; + } + } + + #if DEBUG + _dumpLog.WriteLine($"Track {tracks[i].TrackSequence} pregap is {trackPregap} sectors"); + UpdateStatus?.Invoke($"Track {tracks[i].TrackSequence} pregap is {trackPregap} sectors"); + #endif + + tracks[i].TrackPregap = (ulong)trackPregap; + tracks[i].TrackStartSector -= tracks[i].TrackPregap; + } + } } } \ No newline at end of file