Rework how track map is built from TOC.

This commit is contained in:
2018-02-04 22:06:14 +00:00
parent a0ebde3b38
commit a14476671f

View File

@@ -233,12 +233,6 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(toc == null)
{
DicConsole.ErrorWriteLine("Error trying to decode TOC...");
return;
}
MmcSubchannel supportedSubchannel = MmcSubchannel.Raw; MmcSubchannel supportedSubchannel = MmcSubchannel.Raw;
dumpLog.WriteLine("Checking if drive supports full raw subchannel reading..."); dumpLog.WriteLine("Checking if drive supports full raw subchannel reading...");
DicConsole.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<Track> trackList = new List<Track>();
long lastSector = 0;
// Check if output format supports subchannels // Check if output format supports subchannels
if(!outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) && if(!outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) &&
supportedSubchannel != MmcSubchannel.None) supportedSubchannel != MmcSubchannel.None)
@@ -335,64 +324,78 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine("Building track map..."); DicConsole.WriteLine("Building track map...");
dumpLog.WriteLine("Building track map..."); dumpLog.WriteLine("Building track map...");
foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => trk.ADR == 1 || trk.ADR == 4)) List<Track> trackList = new List<Track>();
if(trk.POINT >= 0x01 && trk.POINT <= 0x63) long lastSector = 0;
trackList.Add(new Track Dictionary<byte, byte> trackFlags = new Dictionary<byte, byte>();
{ TrackType firstTrackType = TrackType.Audio;
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;
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; psec = 59;
phour = trk.PHOUR - 1;
if(trk.PMIN == 0)
{
pmin = 59;
phour = trk.PHOUR - 1;
}
else
{
pmin = trk.PMIN - 1;
phour = trk.PHOUR;
}
} }
else else
{ {
pmin = trk.PMIN - 1; psec = trk.PSEC - 1;
pmin = trk.PMIN;
phour = trk.PHOUR; phour = trk.PHOUR;
} }
} }
else else
{ {
psec = trk.PSEC - 1; pframe = trk.PFRAME - 1;
pmin = trk.PMIN; psec = trk.PSEC;
phour = trk.PHOUR; 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; lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150;
} }
else if(trk.POINT == 0xA0 && trk.ADR == 1) else if(trk.POINT == 0xA0 && trk.ADR == 1)
{ {
switch(trk.PSEC) switch(trk.PSEC)
{ {
case 0x10: case 0x10:
@@ -402,52 +405,94 @@ namespace DiscImageChef.Core.Devices.Dumping
dskType = MediaType.CDROMXA; dskType = MediaType.CDROMXA;
break; break;
} }
}
if(trackList.Count == 0) firstTrackType =
{
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 =
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental
? TrackType.Data ? TrackType.Data
: TrackType.Audio, : TrackType.Audio;
TrackStartSector = trk.TrackStartAddress, }
TrackBytesPerSector = (int)SECTOR_SIZE, }
TrackRawBytesPerSector = (int)SECTOR_SIZE, else
TrackSubchannelType = subType {
}); DicConsole.WriteLine("Cannot read RAW TOC, requesting processed one...");
else if(trk.TrackNumber == 0xAA) dumpLog.WriteLine("Cannot read RAW TOC, requesting processed one...");
lastSector = trk.TrackStartAddress - 1; 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(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..."); 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..."); dumpLog.WriteLine("WARNING: Could not find Lead-Out start, will try to read up to 360000 sectors, probably will fail before...");
lastSector = 360000; lastSector = 360000;
} }
Track[] tracks = trackList.ToArray(); Track[] tracks = trackList.ToArray();
for(int t = 1; t < tracks.Length; t++) tracks[t - 1].TrackEndSector = tracks[t].TrackStartSector - 1; 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 // Set track flags
foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => (trk.ADR == 1 || trk.ADR == 4) && foreach(KeyValuePair<byte, byte> kvp in trackFlags)
trk.POINT >= 0x01 &&
trk.POINT <= 0x63))
{ {
Track track = tracks.FirstOrDefault(t => t.TrackSequence == trk.POINT); Track track = tracks.FirstOrDefault(t => t.TrackSequence == kvp.Key);
if(track.TrackSequence == 0) continue; if(track.TrackSequence == 0) continue;
dumpLog.WriteLine("Setting flags for track {0}...", track.TrackSequence); dumpLog.WriteLine("Setting flags for track {0}...", track.TrackSequence);
DicConsole.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); 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(stopOnError) return; // TODO: Return more cleanly
if(i + skip > blocks) skip = (uint)(blocks - i); if(i + skip > blocks) skip = (uint)(blocks - i);
// Write empty data // Write empty data
DateTime writeStart = DateTime.Now; DateTime writeStart = DateTime.Now;
if(supportedSubchannel != MmcSubchannel.None) if(supportedSubchannel != MmcSubchannel.None)