From a14476671f719152f7634b25c91e9c2b9fbc5943 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 4 Feb 2018 22:06:14 +0000 Subject: [PATCH] Rework how track map is built from TOC. --- .../Devices/Dumping/CompactDisc.cs | 233 +++++++++++------- 1 file changed, 138 insertions(+), 95 deletions(-) diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs index e0b31d4a..0b4a2906 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs @@ -233,12 +233,6 @@ namespace DiscImageChef.Core.Devices.Dumping } } - if(toc == null) - { - DicConsole.ErrorWriteLine("Error trying to decode TOC..."); - return; - } - MmcSubchannel supportedSubchannel = MmcSubchannel.Raw; dumpLog.WriteLine("Checking if drive supports full raw subchannel reading..."); DicConsole.WriteLine("Checking if drive supports full raw subchannel reading..."); @@ -292,11 +286,6 @@ namespace DiscImageChef.Core.Devices.Dumping } } - FullTOC.TrackDataDescriptor[] sortedTracks = - toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray(); - List trackList = new List(); - long lastSector = 0; - // Check if output format supports subchannels if(!outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) && supportedSubchannel != MmcSubchannel.None) @@ -335,64 +324,78 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.WriteLine("Building track map..."); dumpLog.WriteLine("Building track map..."); - foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => trk.ADR == 1 || trk.ADR == 4)) - if(trk.POINT >= 0x01 && trk.POINT <= 0x63) - trackList.Add(new Track - { - TrackSequence = trk.POINT, - TrackSession = trk.SessionNumber, - TrackType = - (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || - (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental - ? TrackType.Data - : TrackType.Audio, - TrackStartSector = - (ulong)(trk.PHOUR * 3600 * 75 + trk.PMIN * 60 * 75 + trk.PSEC * 75 + trk.PFRAME - 150), - TrackBytesPerSector = (int)SECTOR_SIZE, - TrackRawBytesPerSector = (int)SECTOR_SIZE, - TrackSubchannelType = subType - }); - else if(trk.POINT == 0xA2) - { - int phour, pmin, psec, pframe; - if(trk.PFRAME == 0) - { - pframe = 74; + List trackList = new List(); + long lastSector = 0; + Dictionary trackFlags = new Dictionary(); + TrackType firstTrackType = TrackType.Audio; - if(trk.PSEC == 0) + if(toc.HasValue) + { + FullTOC.TrackDataDescriptor[] sortedTracks = + toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray(); + + foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => trk.ADR == 1 || trk.ADR == 4)) + if(trk.POINT >= 0x01 && + trk.POINT <= 0x63) + { + trackList.Add(new Track { - psec = 59; + TrackSequence = trk.POINT, + TrackSession = trk.SessionNumber, + TrackType = + (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || + (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental + ? TrackType.Data + : TrackType.Audio, + TrackStartSector = + (ulong)(trk.PHOUR * 3600 * 75 + trk.PMIN * 60 * 75 + trk.PSEC * 75 + trk.PFRAME - 150), + TrackBytesPerSector = (int)SECTOR_SIZE, + TrackRawBytesPerSector = (int)SECTOR_SIZE, + TrackSubchannelType = subType + }); + trackFlags.Add(trk.POINT, trk.CONTROL); + } + else if(trk.POINT == 0xA2) + { + int phour, pmin, psec, pframe; + if(trk.PFRAME == 0) + { + pframe = 74; - if(trk.PMIN == 0) + if(trk.PSEC == 0) { - pmin = 59; - phour = trk.PHOUR - 1; + psec = 59; + + if(trk.PMIN == 0) + { + pmin = 59; + phour = trk.PHOUR - 1; + } + else + { + pmin = trk.PMIN - 1; + phour = trk.PHOUR; + } } else { - pmin = trk.PMIN - 1; + psec = trk.PSEC - 1; + pmin = trk.PMIN; phour = trk.PHOUR; } } else { - psec = trk.PSEC - 1; - pmin = trk.PMIN; - phour = trk.PHOUR; + pframe = trk.PFRAME - 1; + psec = trk.PSEC; + pmin = trk.PMIN; + phour = trk.PHOUR; } - } - else - { - pframe = trk.PFRAME - 1; - psec = trk.PSEC; - pmin = trk.PMIN; - phour = trk.PHOUR; - } - lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150; - } - else if(trk.POINT == 0xA0 && trk.ADR == 1) - { + lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150; + } + else if(trk.POINT == 0xA0 && trk.ADR == 1) + { switch(trk.PSEC) { case 0x10: @@ -402,52 +405,94 @@ namespace DiscImageChef.Core.Devices.Dumping dskType = MediaType.CDROMXA; break; } - } - if(trackList.Count == 0) - { - DicConsole.WriteLine("TOC with no tracks found, trying old method..."); - dumpLog.WriteLine("TOC with no tracks found, trying old method..."); - dumpLog.WriteLine("Reading old TOC"); - tocSense = dev.ReadToc(out cmdBuf, out senseBuf, false, 0, dev.Timeout, out _); - - TOC.CDTOC? oldToc = Decoders.CD.TOC.Decode(cmdBuf); - if(tocSense ||!oldToc.HasValue) - { - DicConsole.WriteLine("Could not read TOC, cannot continue..."); - dumpLog.WriteLine("Could not read TOC, cannot continue..."); - return; - } - - lastSector = 0; - - foreach(TOC.CDTOCTrackDataDescriptor trk in oldToc.Value.TrackDescriptors.OrderBy(t=>t.TrackNumber).Where(trk => trk.ADR == 1 || trk.ADR == 4)) - if(trk.TrackNumber >= 0x01 && trk.TrackNumber <= 0x63) - trackList.Add(new Track - { - TrackSequence = trk.TrackNumber, - TrackSession = 1, - TrackType = + firstTrackType = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data - : TrackType.Audio, - TrackStartSector = trk.TrackStartAddress, - TrackBytesPerSector = (int)SECTOR_SIZE, - TrackRawBytesPerSector = (int)SECTOR_SIZE, - TrackSubchannelType = subType - }); - else if(trk.TrackNumber == 0xAA) - lastSector = trk.TrackStartAddress - 1; + : TrackType.Audio; + } + } + else + { + DicConsole.WriteLine("Cannot read RAW TOC, requesting processed one..."); + dumpLog.WriteLine("Cannot read RAW TOC, requesting processed one..."); + tocSense = dev.ReadToc(out cmdBuf, out senseBuf, false, 0, dev.Timeout, out _); + + TOC.CDTOC? oldToc = TOC.Decode(cmdBuf); + if((tocSense || !oldToc.HasValue) && !force) + { + DicConsole + .WriteLine("Could not read TOC, if you want to continue, use force, and will try from LBA 0 to 360000..."); + dumpLog.WriteLine("Could not read TOC, if you want to continue, use force, and will try from LBA 0 to 360000..."); + return; + } + + foreach(TOC.CDTOCTrackDataDescriptor trk in oldToc + .Value.TrackDescriptors.OrderBy(t => t.TrackNumber) + .Where(trk => trk.ADR == 1 || trk.ADR == 4)) + if(trk.TrackNumber >= 0x01 && trk.TrackNumber <= 0x63) + { + trackList.Add(new Track + { + TrackSequence = trk.TrackNumber, + TrackSession = 1, + TrackType = + (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || + (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental + ? TrackType.Data + : TrackType.Audio, + TrackStartSector = trk.TrackStartAddress, + TrackBytesPerSector = (int)SECTOR_SIZE, + TrackRawBytesPerSector = (int)SECTOR_SIZE, + TrackSubchannelType = subType + }); + trackFlags.Add(trk.TrackNumber, trk.CONTROL); + } + else if(trk.TrackNumber == 0xAA) + { + firstTrackType = + (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || + (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental + ? TrackType.Data + : TrackType.Audio; + lastSector = trk.TrackStartAddress - 1; + } + } + + if(trackList.Count == 0) + { + DicConsole.WriteLine("No tracks found, adding a single track from 0 to Lead-Out"); + dumpLog.WriteLine("No tracks found, adding a single track from 0 to Lead-Out"); + + trackList.Add(new Track + { + TrackSequence = 1, + TrackSession = 1, + TrackType = firstTrackType, + TrackStartSector = 0, + TrackBytesPerSector = (int)SECTOR_SIZE, + TrackRawBytesPerSector = (int)SECTOR_SIZE, + TrackSubchannelType = subType + }); + trackFlags.Add(1, (byte)(firstTrackType == TrackType.Audio ? 0 : 4)); } if(lastSector == 0) { + if(!force) + { + DicConsole + .WriteLine("Could not find Lead-Out, if you want to continue use force option and will continue until 360000 sectors..."); + dumpLog.WriteLine("Could not find Lead-Out, if you want to continue use force option and will continue until 360000 sectors..."); + return; + } + DicConsole.WriteLine("WARNING: Could not find Lead-Out start, will try to read up to 360000 sectors, probably will fail before..."); dumpLog.WriteLine("WARNING: Could not find Lead-Out start, will try to read up to 360000 sectors, probably will fail before..."); lastSector = 360000; } - + Track[] tracks = trackList.ToArray(); for(int t = 1; t < tracks.Length; t++) tracks[t - 1].TrackEndSector = tracks[t].TrackStartSector - 1; @@ -701,17 +746,15 @@ namespace DiscImageChef.Core.Devices.Dumping } // Set track flags - foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => (trk.ADR == 1 || trk.ADR == 4) && - trk.POINT >= 0x01 && - trk.POINT <= 0x63)) + foreach(KeyValuePair kvp in trackFlags) { - Track track = tracks.FirstOrDefault(t => t.TrackSequence == trk.POINT); + Track track = tracks.FirstOrDefault(t => t.TrackSequence == kvp.Key); if(track.TrackSequence == 0) continue; dumpLog.WriteLine("Setting flags for track {0}...", track.TrackSequence); DicConsole.WriteLine("Setting flags for track {0}...", track.TrackSequence); - outputPlugin.WriteSectorTag(new[] {trk.CONTROL}, track.TrackStartSector, SectorTagType.CdTrackFlags); + outputPlugin.WriteSectorTag(new[] {kvp.Value}, track.TrackStartSector, SectorTagType.CdTrackFlags); } if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock); @@ -788,7 +831,7 @@ namespace DiscImageChef.Core.Devices.Dumping if(stopOnError) return; // TODO: Return more cleanly if(i + skip > blocks) skip = (uint)(blocks - i); - + // Write empty data DateTime writeStart = DateTime.Now; if(supportedSubchannel != MmcSubchannel.None)