diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs
index ad6ef743d..fec4b30d3 100644
--- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs
+++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs
@@ -138,8 +138,8 @@ namespace DiscImageChef.Core.Devices.Dumping
}
// Check subchannels support
- supportsPqSubchannel = SupportsPqSubchannel();
- supportsRwSubchannel = SupportsRwSubchannel();
+ supportsPqSubchannel = SupportsPqSubchannel(_dev, _dumpLog, UpdateStatus);
+ supportsRwSubchannel = SupportsRwSubchannel(_dev, _dumpLog, UpdateStatus);
switch(_subchannel)
{
@@ -207,8 +207,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!_outputPlugin.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) &&
supportedSubchannel != MmcSubchannel.None)
{
- if(_force ||
- _subchannel == DumpSubchannel.None)
+ if(_force || _subchannel == DumpSubchannel.None)
{
_dumpLog.WriteLine("Output format does not support subchannels, continuing...");
UpdateStatus?.Invoke("Output format does not support subchannels, continuing...");
@@ -339,13 +338,13 @@ namespace DiscImageChef.Core.Devices.Dumping
blockSize = sectorSize + subSize;
- tracks = GetCdTracks(ref blockSize, dskType, out lastSector, leadOutStarts, mediaTags, out toc, trackFlags,
- subType);
+ tracks = GetCdTracks(ref blockSize, _dev, dskType, _dumpLog, _force, out lastSector, leadOutStarts,
+ mediaTags, StoppingErrorMessage, subType, out toc, trackFlags, UpdateStatus);
if(tracks is null)
return;
- SolveTrackPregaps(tracks, supportsPqSubchannel, supportsRwSubchannel);
+ SolveTrackPregaps(_dev, _dumpLog, UpdateStatus, tracks, supportsPqSubchannel, supportsRwSubchannel);
for(int t = 1; t < tracks.Length; t++)
tracks[t - 1].TrackEndSector = tracks[t].TrackStartSector - 1;
@@ -872,7 +871,8 @@ namespace DiscImageChef.Core.Devices.Dumping
ReadCdData(audioExtents, blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog,
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);
+ readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors, ref totalDuration,
+ tracks);
// TODO: Enable when underlying images support lead-outs
/*
diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs
index f0e112789..2fc2a9bf2 100644
--- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs
+++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Pregap.cs
@@ -35,6 +35,7 @@ using System.Collections.Generic;
using System.IO;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs;
+using DiscImageChef.Core.Logging;
using DiscImageChef.Devices;
// ReSharper disable JoinDeclarationAndInitializer
@@ -118,7 +119,8 @@ namespace DiscImageChef.Core.Devices.Dumping
firstTrackPregapMs.Close();
}
- void SolveTrackPregaps(Track[] tracks, bool supportsPqSubchannel, bool supportsRwSubchannel)
+ public static void SolveTrackPregaps(Device dev, DumpLog dumpLog, UpdateStatusHandler updateStatus,
+ Track[] tracks, bool supportsPqSubchannel, bool supportsRwSubchannel)
{
bool sense; // Sense indicator
byte[] cmdBuf; // Data buffer
@@ -136,14 +138,14 @@ namespace DiscImageChef.Core.Devices.Dumping
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 _);
+ 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, 96, 1, MmcSectorTypes.AllTypes, false, false, false,
- MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Raw,
- _dev.Timeout, out _);
+ MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Raw,
+ dev.Timeout, out _);
if(!sense)
{
@@ -229,8 +231,8 @@ namespace DiscImageChef.Core.Devices.Dumping
}
#if DEBUG
- _dumpLog.WriteLine($"Track {tracks[i].TrackSequence} pregap is {trackPregap} sectors");
- UpdateStatus?.Invoke($"Track {tracks[i].TrackSequence} pregap is {trackPregap} sectors");
+ 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;
diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Subchannel.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Subchannel.cs
index bc242446b..61a107387 100644
--- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Subchannel.cs
+++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Subchannel.cs
@@ -30,31 +30,8 @@
// Copyright © 2011-2019 Natalia Portillo
// ****************************************************************************/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Xml.Serialization;
-using DiscImageChef.CommonTypes;
-using DiscImageChef.CommonTypes.Enums;
-using DiscImageChef.CommonTypes.Extents;
-using DiscImageChef.CommonTypes.Interfaces;
-using DiscImageChef.CommonTypes.Metadata;
-using DiscImageChef.CommonTypes.Structs;
-using DiscImageChef.Console;
using DiscImageChef.Core.Logging;
-using DiscImageChef.Core.Media.Detection;
-using DiscImageChef.Decoders.CD;
-using DiscImageChef.Decoders.SCSI;
-using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Devices;
-using Schemas;
-using CdOffset = DiscImageChef.Database.Models.CdOffset;
-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
@@ -64,24 +41,24 @@ namespace DiscImageChef.Core.Devices.Dumping
{
partial class Dump
{
- bool SupportsRwSubchannel()
+ public static bool SupportsRwSubchannel(Device dev, DumpLog dumpLog, UpdateStatusHandler updateStatus)
{
- _dumpLog.WriteLine("Checking if drive supports full raw subchannel reading...");
- UpdateStatus?.Invoke("Checking if drive supports full raw subchannel reading...");
+ dumpLog?.WriteLine("Checking if drive supports full raw subchannel reading...");
+ updateStatus?.Invoke("Checking if drive supports full raw subchannel reading...");
- return!_dev.ReadCd(out _, out _, 0, 2352 + 96, 1, MmcSectorTypes.AllTypes, false, false, true,
- MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Raw,
- _dev.Timeout, out _);
+ return!dev.ReadCd(out _, out _, 0, 2352 + 96, 1, MmcSectorTypes.AllTypes, false, false, true,
+ MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout,
+ out _);
}
- bool SupportsPqSubchannel()
+ public static bool SupportsPqSubchannel(Device dev, DumpLog dumpLog, UpdateStatusHandler updateStatus)
{
- _dumpLog.WriteLine("Checking if drive supports PQ subchannel reading...");
- UpdateStatus?.Invoke("Checking if drive supports PQ subchannel reading...");
+ dumpLog?.WriteLine("Checking if drive supports PQ subchannel reading...");
+ updateStatus?.Invoke("Checking if drive supports PQ subchannel reading...");
- return!_dev.ReadCd(out _, out _, 0, 2352 + 16, 1, MmcSectorTypes.AllTypes, false, false, true,
- MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16,
- _dev.Timeout, out _);
+ return!dev.ReadCd(out _, out _, 0, 2352 + 16, 1, MmcSectorTypes.AllTypes, false, false, true,
+ MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16, dev.Timeout,
+ out _);
}
}
}
\ No newline at end of file
diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Tracks.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Tracks.cs
index bcb78ef44..b4be82a11 100644
--- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Tracks.cs
+++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Tracks.cs
@@ -36,7 +36,9 @@ using System.Linq;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.CommonTypes.Structs;
+using DiscImageChef.Core.Logging;
using DiscImageChef.Decoders.CD;
+using DiscImageChef.Devices;
// ReSharper disable JoinDeclarationAndInitializer
// ReSharper disable InlineOutVariableDeclaration
@@ -48,17 +50,25 @@ namespace DiscImageChef.Core.Devices.Dumping
{
/// Reads the TOC, processes it, returns the track list and last sector
/// Size of the read sector in bytes
+ /// Device
/// Disc type
+ /// Dump log
+ /// Force dump enabled
/// Last sector number
/// Lead-out starts
/// Media tags
+ /// Stopping error message handler
+ /// Track subchannel type
/// Full CD TOC
/// Track flags
- /// Track subchannel type
+ /// Update status handler
/// List of tracks
- Track[] GetCdTracks(ref uint blockSize, MediaType dskType, out long lastSector,
- Dictionary leadOutStarts, Dictionary mediaTags,
- out FullTOC.CDFullTOC? toc, Dictionary trackFlags, TrackSubchannelType subType)
+ public static Track[] GetCdTracks(ref uint blockSize, Device dev, MediaType dskType, DumpLog dumpLog,
+ bool force, out long lastSector, Dictionary leadOutStarts,
+ Dictionary mediaTags,
+ ErrorMessageHandler stoppingErrorMessage, TrackSubchannelType subType,
+ out FullTOC.CDFullTOC? toc, Dictionary trackFlags,
+ UpdateStatusHandler updateStatus)
{
byte[] cmdBuf = null; // Data buffer
const uint sectorSize = 2352; // Full sector size
@@ -71,9 +81,9 @@ namespace DiscImageChef.Core.Devices.Dumping
// 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 _, 0, _dev.Timeout, out _);
+ dumpLog?.WriteLine("Reading full TOC");
+ updateStatus?.Invoke("Reading full TOC");
+ sense = dev.ReadRawToc(out cmdBuf, out _, 0, dev.Timeout, out _);
if(!sense)
{
@@ -83,12 +93,12 @@ namespace DiscImageChef.Core.Devices.Dumping
{
tmpBuf = new byte[cmdBuf.Length - 2];
Array.Copy(cmdBuf, 2, tmpBuf, 0, cmdBuf.Length - 2);
- mediaTags.Add(MediaTagType.CD_FullTOC, tmpBuf);
+ mediaTags?.Add(MediaTagType.CD_FullTOC, tmpBuf);
}
}
- UpdateStatus?.Invoke("Building track map...");
- _dumpLog.WriteLine("Building track map...");
+ updateStatus?.Invoke("Building track map...");
+ dumpLog?.WriteLine("Building track map...");
if(toc.HasValue)
{
@@ -113,7 +123,7 @@ namespace DiscImageChef.Core.Devices.Dumping
TrackSubchannelType = subType
});
- trackFlags.Add(trk.POINT, trk.CONTROL);
+ trackFlags?.Add(trk.POINT, trk.CONTROL);
}
else if(trk.POINT == 0xA2)
{
@@ -154,7 +164,7 @@ namespace DiscImageChef.Core.Devices.Dumping
}
lastSector = ((phour * 3600 * 75) + (pmin * 60 * 75) + (psec * 75) + pframe) - 150;
- leadOutStarts.Add(trk.SessionNumber, lastSector + 1);
+ leadOutStarts?.Add(trk.SessionNumber, lastSector + 1);
}
else if(trk.POINT == 0xA0 &&
trk.ADR == 1)
@@ -181,18 +191,18 @@ namespace DiscImageChef.Core.Devices.Dumping
}
else
{
- UpdateStatus?.Invoke("Cannot read RAW TOC, requesting processed one...");
- _dumpLog.WriteLine("Cannot read RAW TOC, requesting processed one...");
- sense = _dev.ReadToc(out cmdBuf, out _, false, 0, _dev.Timeout, out _);
+ updateStatus?.Invoke("Cannot read RAW TOC, requesting processed one...");
+ dumpLog?.WriteLine("Cannot read RAW TOC, requesting processed one...");
+ sense = dev.ReadToc(out cmdBuf, out _, false, 0, dev.Timeout, out _);
TOC.CDTOC? oldToc = TOC.Decode(cmdBuf);
if((sense || !oldToc.HasValue) &&
- !_force)
+ !force)
{
- _dumpLog.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...");
- StoppingErrorMessage?.
+ stoppingErrorMessage?.
Invoke("Could not read TOC, if you want to continue, use force, and will try from LBA 0 to 360000...");
return null;
@@ -214,7 +224,7 @@ namespace DiscImageChef.Core.Devices.Dumping
TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType
});
- trackFlags.Add(trk.TrackNumber, trk.CONTROL);
+ trackFlags?.Add(trk.TrackNumber, trk.CONTROL);
}
else if(trk.TrackNumber == 0xAA)
{
@@ -229,8 +239,8 @@ namespace DiscImageChef.Core.Devices.Dumping
if(trackList.Count == 0)
{
- UpdateStatus?.Invoke("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");
+ updateStatus?.Invoke("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
{
@@ -240,12 +250,12 @@ namespace DiscImageChef.Core.Devices.Dumping
TrackSubchannelType = subType
});
- trackFlags.Add(1, (byte)(leadoutTrackType == TrackType.Audio ? 0 : 4));
+ trackFlags?.Add(1, (byte)(leadoutTrackType == TrackType.Audio ? 0 : 4));
}
if(lastSector == 0)
{
- sense = _dev.ReadCapacity16(out cmdBuf, out _, _dev.Timeout, out _);
+ sense = dev.ReadCapacity16(out cmdBuf, out _, dev.Timeout, out _);
if(!sense)
{
@@ -258,7 +268,7 @@ namespace DiscImageChef.Core.Devices.Dumping
}
else
{
- sense = _dev.ReadCapacity(out cmdBuf, out _, _dev.Timeout, out _);
+ sense = dev.ReadCapacity(out cmdBuf, out _, dev.Timeout, out _);
if(!sense)
{
@@ -269,21 +279,21 @@ namespace DiscImageChef.Core.Devices.Dumping
if(lastSector <= 0)
{
- if(!_force)
+ if(!force)
{
- StoppingErrorMessage?.
+ stoppingErrorMessage?.
Invoke("Could not find Lead-Out, if you want to continue use force option and will continue until 360000 sectors...");
- _dumpLog.
+ dumpLog?.
WriteLine("Could not find Lead-Out, if you want to continue use force option and will continue until 360000 sectors...");
return null;
}
- UpdateStatus?.
+ updateStatus?.
Invoke("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;
}
}
diff --git a/DiscImageChef/Commands/DeviceInfo.cs b/DiscImageChef/Commands/DeviceInfo.cs
index 21502255d..3b4d973e8 100644
--- a/DiscImageChef/Commands/DeviceInfo.cs
+++ b/DiscImageChef/Commands/DeviceInfo.cs
@@ -33,15 +33,20 @@
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
+using System.Linq;
using DiscImageChef.CommonTypes.Enums;
using DiscImageChef.Console;
using DiscImageChef.Core;
+using DiscImageChef.Database;
+using DiscImageChef.Database.Models;
using DiscImageChef.Decoders.ATA;
using DiscImageChef.Decoders.PCMCIA;
using DiscImageChef.Decoders.SCSI;
using DiscImageChef.Decoders.SCSI.MMC;
using DiscImageChef.Decoders.SCSI.SSC;
using DiscImageChef.Devices;
+using Command = System.CommandLine.Command;
+using Device = DiscImageChef.Devices.Device;
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
namespace DiscImageChef.Commands
@@ -1066,6 +1071,33 @@ namespace DiscImageChef.Commands
dev.Close();
+ DicConsole.WriteLine();
+
+ // Open master database
+ var ctx = DicContext.Create(Settings.Settings.MasterDbPath);
+
+ // Search for device in master database
+ Database.Models.Device dbDev =
+ ctx.Devices.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model &&
+ d.Revision == dev.Revision);
+
+ if(dbDev is null)
+ DicConsole.WriteLine("Device not in database, please create a device report and attach it to a Github issue.");
+ else
+ {
+ DicConsole.WriteLine($"Device in database since {dbDev.LastSynchronized}.");
+
+ if(dbDev.OptimalMultipleSectorsRead > 0)
+ DicConsole.WriteLine($"Optimal multiple read is {dbDev.LastSynchronized} sectors.");
+ }
+
+ // Search for read offset in master database
+ CdOffset cdOffset =
+ ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model);
+
+ DicConsole.WriteLine(cdOffset is null ? "CD reading offset not found in database."
+ : $"CD reading offset is {cdOffset.Offset} samples ({cdOffset.Offset * 4} bytes).");
+
return(int)ErrorNumber.NoError;
}
}
diff --git a/DiscImageChef/Commands/MediaInfo.cs b/DiscImageChef/Commands/MediaInfo.cs
index 8f67ba617..b612f031a 100644
--- a/DiscImageChef/Commands/MediaInfo.cs
+++ b/DiscImageChef/Commands/MediaInfo.cs
@@ -35,8 +35,10 @@ using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using DiscImageChef.CommonTypes.Enums;
+using DiscImageChef.CommonTypes.Structs;
using DiscImageChef.Console;
using DiscImageChef.Core;
+using DiscImageChef.Core.Devices.Dumping;
using DiscImageChef.Core.Media.Info;
using DiscImageChef.Decoders.Bluray;
using DiscImageChef.Decoders.CD;
@@ -50,6 +52,7 @@ using BCA = DiscImageChef.Decoders.Bluray.BCA;
using Cartridge = DiscImageChef.Decoders.DVD.Cartridge;
using DDS = DiscImageChef.Decoders.DVD.DDS;
using DMI = DiscImageChef.Decoders.Xbox.DMI;
+using Session = DiscImageChef.Decoders.CD.Session;
using Spare = DiscImageChef.Decoders.DVD.Spare;
namespace DiscImageChef.Commands
@@ -530,6 +533,38 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Media identified as {0}", scsiInfo.MediaType);
Statistics.AddMedia(scsiInfo.MediaType, true);
+ if(scsiInfo.Toc != null ||
+ scsiInfo.RawToc != null)
+ {
+ uint blockSize = 2352;
+
+ Track[] tracks = Dump.GetCdTracks(ref blockSize, dev, scsiInfo.MediaType, null, false,
+ out long lastSector, null, null, null, TrackSubchannelType.None,
+ out _, null, null);
+
+ if(tracks != null)
+ {
+ bool supportsPqSubchannel = Dump.SupportsPqSubchannel(dev, null, null);
+ bool supportsRwSubchannel = Dump.SupportsRwSubchannel(dev, null, null);
+
+ Dump.SolveTrackPregaps(dev, null, null, tracks, supportsPqSubchannel, supportsRwSubchannel);
+
+ for(int t = 1; t < tracks.Length; t++)
+ tracks[t - 1].TrackEndSector = tracks[t].TrackStartSector - 1;
+
+ tracks[tracks.Length - 1].TrackEndSector = (ulong)lastSector;
+
+ DicConsole.WriteLine();
+ DicConsole.WriteLine("Track calculations:");
+
+ foreach(Track track in tracks)
+ DicConsole.
+ WriteLine("Track {0} starts at LBA {1}, ends at LBA {2}, has a pregap of {3} sectors and is of type {4}",
+ track.TrackSequence, track.TrackStartSector, track.TrackEndSector,
+ track.TrackPregap, track.TrackType);
+ }
+ }
+
dev.Close();
}
}