diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs
index a60648349..d3993e9ee 100644
--- a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs
+++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs
@@ -57,7 +57,10 @@ using MediaType = DiscImageChef.CommonTypes.MediaType;
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
using Session = DiscImageChef.Decoders.CD.Session;
using TrackType = DiscImageChef.CommonTypes.Enums.TrackType;
+
// ReSharper disable JoinDeclarationAndInitializer
+// ReSharper disable InlineOutVariableDeclaration
+// ReSharper disable TooWideLocalVariableScope
namespace DiscImageChef.Core.Devices.Dumping
{
@@ -70,12 +73,21 @@ namespace DiscImageChef.Core.Devices.Dumping
/// Disc type as detected in MMC layer
internal void CompactDisc(ref MediaType dskType)
{
- // Master database context
- DicContext ctx;
- // Device database entry
- Device dbDev;
- // Read offset from database
- CdOffset cdOffset;
+ DicContext
+ ctx; // Master database context
+
+ Device
+ dbDev; // Device database entry
+
+ CdOffset
+ cdOffset; // Read offset from database
+
+ bool sense; // Sense indicator
+ byte[] cmdBuf; // Data buffer
+ byte[] senseBuf; // Sense buffer
+ byte[] tmpBuf; // Temporary buffer
+ FullTOC.CDFullTOC? toc = null; // Full CD TOC
+ Dictionary mediaTags = new Dictionary(); // Media tags
if(dumpRaw)
{
@@ -89,14 +101,15 @@ namespace DiscImageChef.Core.Devices.Dumping
ctx = DicContext.Create(Settings.Settings.MasterDbPath);
// Search for device in master database
- dbDev = ctx.Devices.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer &&
- d.Model == dev.Model &&
- d.Revision == dev.Revision);
+ dbDev = ctx.Devices.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model &&
+ d.Revision == dev.Revision);
if(dbDev is null)
{
dumpLog.WriteLine("Device not in database, please create a device report and attach it to a Github issue.");
- UpdateStatus?.Invoke("Device not in database, please create a device report and attach it to a Github issue.");
+
+ UpdateStatus?.
+ Invoke("Device not in database, please create a device report and attach it to a Github issue.");
}
else
{
@@ -105,8 +118,7 @@ namespace DiscImageChef.Core.Devices.Dumping
}
// Search for read offset in master database
- cdOffset =
- ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model);
+ cdOffset = ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model);
if(cdOffset is null)
{
@@ -118,6 +130,24 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine($"CD reading offset is {cdOffset.Offset} samples.");
UpdateStatus?.Invoke($"CD reading offset is {cdOffset.Offset} samples.");
}
+
+ // We discarded all discs that falsify a TOC before requesting a real TOC
+ // No TOC, no CD (or an empty one)
+ dumpLog.WriteLine("Reading full TOC");
+ UpdateStatus?.Invoke("Reading full TOC");
+ sense = dev.ReadRawToc(out cmdBuf, out senseBuf, 0, dev.Timeout, out _);
+
+ if(!sense)
+ {
+ toc = FullTOC.Decode(cmdBuf);
+
+ if(toc.HasValue)
+ {
+ tmpBuf = new byte[cmdBuf.Length - 2];
+ Array.Copy(cmdBuf, 2, tmpBuf, 0, cmdBuf.Length - 2);
+ mediaTags.Add(MediaTagType.CD_FullTOC, tmpBuf);
+ }
+ }
}
/// Dumps a compact disc
@@ -138,165 +168,150 @@ namespace DiscImageChef.Core.Devices.Dumping
double minSpeed = double.MaxValue;
uint blocksToRead = 64;
Dictionary mediaTags = new Dictionary();
+ byte[] cmdBuf;
+ byte[] senseBuf;
+ byte[] tmpBuf;
dskType = MediaType.CD;
int sessions = 1;
- // We discarded all discs that falsify a TOC before requesting a real TOC
- // No TOC, no CD (or an empty one)
- dumpLog.WriteLine("Reading full TOC");
- UpdateStatus?.Invoke("Reading full TOC");
- bool tocSense = dev.ReadRawToc(out byte[] cmdBuf, out byte[] senseBuf, 0, dev.Timeout, out _);
+ // ATIP exists on blank CDs
+ dumpLog.WriteLine("Reading ATIP");
+ UpdateStatus?.Invoke("Reading ATIP");
+ sense = dev.ReadAtip(out cmdBuf, out senseBuf, dev.Timeout, out _);
- if(!tocSense)
+ if(!sense)
{
- toc = FullTOC.Decode(cmdBuf);
+ ATIP.CDATIP? atip = ATIP.Decode(cmdBuf);
- if(toc.HasValue)
+ if(atip.HasValue)
{
- byte[] tmpBuf = new byte[cmdBuf.Length - 2];
- Array.Copy(cmdBuf, 2, tmpBuf, 0, cmdBuf.Length - 2);
- mediaTags.Add(MediaTagType.CD_FullTOC, tmpBuf);
+ // Only CD-R and CD-RW have ATIP
+ dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR;
- // ATIP exists on blank CDs
- dumpLog.WriteLine("Reading ATIP");
- UpdateStatus?.Invoke("Reading ATIP");
- sense = dev.ReadAtip(out cmdBuf, out senseBuf, dev.Timeout, out _);
-
- if(!sense)
- {
- ATIP.CDATIP? atip = ATIP.Decode(cmdBuf);
-
- if(atip.HasValue)
- {
- // Only CD-R and CD-RW have ATIP
- dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR;
-
- tmpBuf = new byte[cmdBuf.Length - 4];
- Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
- mediaTags.Add(MediaTagType.CD_ATIP, tmpBuf);
- }
- }
-
- dumpLog.WriteLine("Reading Disc Information");
- UpdateStatus?.Invoke("Reading Disc Information");
-
- sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf,
- MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, out _);
-
- if(!sense)
- {
- DiscInformation.StandardDiscInformation? discInfo = DiscInformation.Decode000b(cmdBuf);
-
- if(discInfo.HasValue)
- if(dskType == MediaType.CD)
- switch(discInfo.Value.DiscType)
- {
- case 0x10:
- dskType = MediaType.CDI;
-
- break;
- case 0x20:
- dskType = MediaType.CDROMXA;
-
- break;
- }
- }
-
- int firstTrackLastSession = 0;
-
- dumpLog.WriteLine("Reading Session Information");
- UpdateStatus?.Invoke("Reading Session Information");
- sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out _);
-
- if(!sense)
- {
- Session.CDSessionInfo? session = Session.Decode(cmdBuf);
-
- if(session.HasValue)
- {
- sessions = session.Value.LastCompleteSession;
- firstTrackLastSession = session.Value.TrackDescriptors[0].TrackNumber;
- }
- }
-
- if(dskType == MediaType.CD ||
- dskType == MediaType.CDROMXA)
- {
- bool hasDataTrack = false;
- bool hasAudioTrack = false;
- bool allFirstSessionTracksAreAudio = true;
- bool hasVideoTrack = false;
-
- foreach(FullTOC.TrackDataDescriptor track in toc.Value.TrackDescriptors)
- {
- if(track.TNO == 1 &&
- ((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
- (TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental))
- allFirstSessionTracksAreAudio &= firstTrackLastSession != 1;
-
- if((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
- (TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental)
- {
- hasDataTrack = true;
- allFirstSessionTracksAreAudio &= track.POINT >= firstTrackLastSession;
- }
- else
- {
- hasAudioTrack = true;
- }
-
- hasVideoTrack |= track.ADR == 4;
- }
-
- if(hasDataTrack &&
- hasAudioTrack &&
- allFirstSessionTracksAreAudio &&
- sessions == 2)
- dskType = MediaType.CDPLUS;
-
- if(!hasDataTrack &&
- hasAudioTrack &&
- sessions == 1)
- dskType = MediaType.CDDA;
-
- if(hasDataTrack &&
- !hasAudioTrack &&
- sessions == 1)
- dskType = MediaType.CDROM;
-
- if(hasVideoTrack &&
- !hasDataTrack &&
- sessions == 1)
- dskType = MediaType.CDV;
- }
-
- dumpLog.WriteLine("Reading PMA");
- UpdateStatus?.Invoke("Reading PMA");
- sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out _);
-
- if(!sense)
- if(PMA.Decode(cmdBuf).HasValue)
- {
- tmpBuf = new byte[cmdBuf.Length - 4];
- Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
- mediaTags.Add(MediaTagType.CD_PMA, tmpBuf);
- }
-
- dumpLog.WriteLine("Reading CD-Text from Lead-In");
- UpdateStatus?.Invoke("Reading CD-Text from Lead-In");
- sense = dev.ReadCdText(out cmdBuf, out senseBuf, dev.Timeout, out _);
-
- if(!sense)
- if(CDTextOnLeadIn.Decode(cmdBuf).HasValue)
- {
- tmpBuf = new byte[cmdBuf.Length - 4];
- Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
- mediaTags.Add(MediaTagType.CD_TEXT, tmpBuf);
- }
+ tmpBuf = new byte[cmdBuf.Length - 4];
+ Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
+ mediaTags.Add(MediaTagType.CD_ATIP, tmpBuf);
}
}
+ dumpLog.WriteLine("Reading Disc Information");
+ UpdateStatus?.Invoke("Reading Disc Information");
+
+ sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation,
+ dev.Timeout, out _);
+
+ if(!sense)
+ {
+ DiscInformation.StandardDiscInformation? discInfo = DiscInformation.Decode000b(cmdBuf);
+
+ if(discInfo.HasValue)
+ if(dskType == MediaType.CD)
+ switch(discInfo.Value.DiscType)
+ {
+ case 0x10:
+ dskType = MediaType.CDI;
+
+ break;
+ case 0x20:
+ dskType = MediaType.CDROMXA;
+
+ break;
+ }
+ }
+
+ int firstTrackLastSession = 0;
+
+ dumpLog.WriteLine("Reading Session Information");
+ UpdateStatus?.Invoke("Reading Session Information");
+ sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out _);
+
+ if(!sense)
+ {
+ Session.CDSessionInfo? session = Session.Decode(cmdBuf);
+
+ if(session.HasValue)
+ {
+ sessions = session.Value.LastCompleteSession;
+ firstTrackLastSession = session.Value.TrackDescriptors[0].TrackNumber;
+ }
+ }
+
+ if(dskType == MediaType.CD ||
+ dskType == MediaType.CDROMXA)
+ {
+ bool hasDataTrack = false;
+ bool hasAudioTrack = false;
+ bool allFirstSessionTracksAreAudio = true;
+ bool hasVideoTrack = false;
+
+ foreach(FullTOC.TrackDataDescriptor track in toc.Value.TrackDescriptors)
+ {
+ if(track.TNO == 1 &&
+ ((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
+ (TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental))
+ allFirstSessionTracksAreAudio &= firstTrackLastSession != 1;
+
+ if((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
+ (TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental)
+ {
+ hasDataTrack = true;
+ allFirstSessionTracksAreAudio &= track.POINT >= firstTrackLastSession;
+ }
+ else
+ {
+ hasAudioTrack = true;
+ }
+
+ hasVideoTrack |= track.ADR == 4;
+ }
+
+ if(hasDataTrack &&
+ hasAudioTrack &&
+ allFirstSessionTracksAreAudio &&
+ sessions == 2)
+ dskType = MediaType.CDPLUS;
+
+ if(!hasDataTrack &&
+ hasAudioTrack &&
+ sessions == 1)
+ dskType = MediaType.CDDA;
+
+ if(hasDataTrack &&
+ !hasAudioTrack &&
+ sessions == 1)
+ dskType = MediaType.CDROM;
+
+ if(hasVideoTrack &&
+ !hasDataTrack &&
+ sessions == 1)
+ dskType = MediaType.CDV;
+ }
+
+ dumpLog.WriteLine("Reading PMA");
+ UpdateStatus?.Invoke("Reading PMA");
+ sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out _);
+
+ if(!sense)
+ if(PMA.Decode(cmdBuf).HasValue)
+ {
+ tmpBuf = new byte[cmdBuf.Length - 4];
+ Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
+ mediaTags.Add(MediaTagType.CD_PMA, tmpBuf);
+ }
+
+ dumpLog.WriteLine("Reading CD-Text from Lead-In");
+ UpdateStatus?.Invoke("Reading CD-Text from Lead-In");
+ sense = dev.ReadCdText(out cmdBuf, out senseBuf, dev.Timeout, out _);
+
+ if(!sense)
+ if(CDTextOnLeadIn.Decode(cmdBuf).HasValue)
+ {
+ tmpBuf = new byte[cmdBuf.Length - 4];
+ Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
+ mediaTags.Add(MediaTagType.CD_TEXT, tmpBuf);
+ }
+
// TODO: Add other detectors here
dumpLog.WriteLine("Detecting disc type...");
UpdateStatus?.Invoke("Detecting disc type...");
@@ -328,7 +343,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(MMC.IsVideoNowColor(videoNowColorFrame))
dskType = MediaType.VideoNowColor;
- var supportedSubchannel = MmcSubchannel.Raw;
+ MmcSubchannel supportedSubchannel = MmcSubchannel.Raw;
dumpLog.WriteLine("Checking if drive supports full raw subchannel reading...");
UpdateStatus?.Invoke("Checking if drive supports full raw subchannel reading...");
@@ -500,7 +515,7 @@ namespace DiscImageChef.Core.Devices.Dumping
List