diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs
index c1c242562..577083131 100644
--- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs
+++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs
@@ -123,20 +123,6 @@ namespace DiscImageChef.Core.Devices.Dumping
return;
}
- // Search for read offset in master database
- cdOffset = _ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == _dev.Manufacturer && d.Model == _dev.Model);
-
- if(cdOffset is null)
- {
- _dumpLog.WriteLine("CD reading offset not found in database.");
- UpdateStatus?.Invoke("CD reading offset not found in database.");
- }
- else
- {
- _dumpLog.WriteLine($"CD reading offset is {cdOffset.Offset} samples.");
- UpdateStatus?.Invoke($"CD reading offset is {cdOffset.Offset} samples.");
- }
-
// Check subchannels support
supportsPqSubchannel = SupportsPqSubchannel(_dev, _dumpLog, UpdateStatus);
supportsRwSubchannel = SupportsRwSubchannel(_dev, _dumpLog, UpdateStatus);
@@ -839,9 +825,24 @@ namespace DiscImageChef.Core.Devices.Dumping
// Check offset
if(_fixOffset)
{
- _fixOffset = Media.Info.CompactDisc.GetOffset(cdOffset, _dbDev, _debug, _dev, dskType, _dumpLog,
- out offsetBytes, readcd, out sectorsForOffset, tracks,
- UpdateStatus);
+ if(tracks.All(t => t.TrackType != TrackType.Audio))
+ {
+ // No audio tracks so no need to fix offset
+ _dumpLog.WriteLine("No audio tracks, disabling offset fix.");
+ UpdateStatus.Invoke("No audio tracks, disabling offset fix.");
+
+ _fixOffset = false;
+ }
+
+ if(!readcd)
+ {
+ _dumpLog.WriteLine("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
+
+ UpdateStatus?.
+ Invoke("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
+
+ _fixOffset = false;
+ }
}
else if(tracks.Any(t => t.TrackType == TrackType.Audio))
{
@@ -849,6 +850,90 @@ namespace DiscImageChef.Core.Devices.Dumping
UpdateStatus?.Invoke("There are audio tracks and offset fixing is disabled, dump may not be correct.");
}
+ // Search for read offset in master database
+ cdOffset = _ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == _dev.Manufacturer && d.Model == _dev.Model);
+
+ Media.Info.CompactDisc.GetOffset(cdOffset, _dbDev, _debug, _dev, dskType, _dumpLog, tracks, UpdateStatus,
+ out int? driveOffset, out int? combinedOffset);
+
+ if(combinedOffset is null)
+ {
+ if(driveOffset is null)
+ {
+ _dumpLog.WriteLine("Drive reading offset not found in database.");
+ UpdateStatus?.Invoke("Drive reading offset not found in database.");
+ _dumpLog.WriteLine("Disc offset cannot be calculated.");
+ UpdateStatus?.Invoke("Disc offset cannot be calculated.");
+
+ if(tracks.Any(t => t.TrackType == TrackType.Audio))
+ {
+ _dumpLog.WriteLine("Dump may not be correct.");
+
+ UpdateStatus?.Invoke("Dump may not be correct.");
+ }
+
+ if(_fixOffset)
+ _fixOffset = false;
+ }
+ else
+ {
+ _dumpLog.WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
+ UpdateStatus?.Invoke($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
+
+ _dumpLog.WriteLine("Disc write offset is unknown, dump may not be correct.");
+ UpdateStatus?.Invoke("Disc write offset is unknown, dump may not be correct.");
+
+ offsetBytes = driveOffset.Value;
+
+ sectorsForOffset = offsetBytes / (int)sectorSize;
+
+ if(sectorsForOffset < 0)
+ sectorsForOffset *= -1;
+
+ if(offsetBytes % sectorSize != 0)
+ sectorsForOffset++;
+ }
+ }
+ else
+ {
+ offsetBytes = combinedOffset.Value;
+ sectorsForOffset = offsetBytes / (int)sectorSize;
+
+ if(sectorsForOffset < 0)
+ sectorsForOffset *= -1;
+
+ if(offsetBytes % sectorSize != 0)
+ sectorsForOffset++;
+
+ if(driveOffset is null)
+ {
+ _dumpLog.WriteLine("Drive reading offset not found in database.");
+ UpdateStatus?.Invoke("Drive reading offset not found in database.");
+ _dumpLog.WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4} samples).");
+
+ UpdateStatus?.
+ Invoke($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4} samples).");
+ }
+ else
+ {
+ _dumpLog.WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
+ UpdateStatus?.Invoke($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
+
+ int? discOffset = offsetBytes - driveOffset;
+
+ _dumpLog.WriteLine($"Disc offsets is {discOffset} bytes ({discOffset / 4} samples)");
+
+ UpdateStatus?.Invoke($"Disc offsets is {discOffset} bytes ({discOffset / 4} samples)");
+ }
+ }
+
+ if(!_fixOffset ||
+ tracks.All(t => t.TrackType != TrackType.Audio))
+ {
+ offsetBytes = 0;
+ sectorsForOffset = 0;
+ }
+
mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, _maximumReadable);
ibgLog = new IbgLog(_outputPrefix + ".ibg", 0x0008);
diff --git a/DiscImageChef.Core/Media/Info/CompactDisc.cs b/DiscImageChef.Core/Media/Info/CompactDisc.cs
index 62d28ba7d..0a67decb7 100644
--- a/DiscImageChef.Core/Media/Info/CompactDisc.cs
+++ b/DiscImageChef.Core/Media/Info/CompactDisc.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using DiscImageChef.CommonTypes;
using DiscImageChef.CommonTypes.Enums;
@@ -21,61 +22,50 @@ namespace DiscImageChef.Core.Media.Info
/// Opened device
/// Detected disk type
/// Dump log if applicable
- /// Set to combined offset, in bytes
- /// If device supports READ CD command
- /// Sectors needed to fix offset
/// Disc track list
/// UpdateStatus event
+ /// Drive offset
+ /// Combined offset
/// true if offset could be found, false otherwise
- public static bool GetOffset(CdOffset cdOffset, Device dbDev, bool debug, DiscImageChef.Devices.Device dev,
- MediaType dskType, DumpLog dumpLog, out int offsetBytes, bool readcd,
- out int sectorsForOffset, Track[] tracks, UpdateStatusHandler updateStatus)
+ [SuppressMessage("ReSharper", "TooWideLocalVariableScope")]
+ public static void GetOffset(CdOffset cdOffset, Device dbDev, bool debug, DiscImageChef.Devices.Device dev,
+ MediaType dskType, DumpLog dumpLog, Track[] tracks,
+ UpdateStatusHandler updateStatus, out int? driveOffset, out int? combinedOffset)
{
byte[] cmdBuf;
bool sense;
+ ulong minute;
+ ulong second;
+ ulong frame;
+ ulong remainder;
+ byte[] sectorSync;
+ byte[] tmpBuf;
+ Track dataTrack = default;
+ Track audioTrack = default;
bool offsetFound = false;
const uint sectorSize = 2352;
- offsetBytes = 0;
- sectorsForOffset = 0;
+ driveOffset = cdOffset?.Offset * 4;
+ combinedOffset = null;
if(dskType != MediaType.VideoNowColor)
{
- if(tracks.All(t => t.TrackType != TrackType.Audio))
- {
- // No audio tracks so no need to fix offset
- dumpLog?.WriteLine("No audio tracks, disabling offset fix.");
- updateStatus?.Invoke("No audio tracks, disabling offset fix.");
-
- return false;
- }
-
- if(!readcd)
- {
- dumpLog?.WriteLine("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
-
- updateStatus?.
- Invoke("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
-
- return false;
- }
-
if(tracks.Any(t => t.TrackType != TrackType.Audio))
{
- Track dataTrack = tracks.FirstOrDefault(t => t.TrackType != TrackType.Audio);
+ dataTrack = tracks.FirstOrDefault(t => t.TrackType != TrackType.Audio);
if(dataTrack.TrackSequence != 0)
{
dataTrack.TrackStartSector += 151;
// Calculate MSF
- ulong minute = dataTrack.TrackStartSector / 4500;
- ulong second = (dataTrack.TrackStartSector - (minute * 4500)) / 75;
- ulong frame = dataTrack.TrackStartSector - (minute * 4500) - (second * 75);
+ minute = dataTrack.TrackStartSector / 4500;
+ second = (dataTrack.TrackStartSector - (minute * 4500)) / 75;
+ frame = dataTrack.TrackStartSector - (minute * 4500) - (second * 75);
dataTrack.TrackStartSector -= 151;
// Convert to BCD
- ulong remainder = minute % 10;
+ remainder = minute % 10;
minute = ((minute / 10) * 16) + remainder;
remainder = second % 10;
second = ((second / 10) * 16) + remainder;
@@ -87,13 +77,13 @@ namespace DiscImageChef.Core.Media.Info
second ^= 0x80;
// Build sync
- byte[] sectorSync =
+ sectorSync = new byte[]
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, (byte)minute,
(byte)second, (byte)frame
};
- byte[] tmpBuf = new byte[sectorSync.Length];
+ tmpBuf = new byte[sectorSync.Length];
// Plextor READ CDDA
if(dbDev?.ATAPI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
@@ -113,8 +103,8 @@ namespace DiscImageChef.Core.Media.Info
if(!tmpBuf.SequenceEqual(sectorSync))
continue;
- offsetBytes = i - 2352;
- offsetFound = true;
+ combinedOffset = i - 2352;
+ offsetFound = true;
break;
}
@@ -140,8 +130,8 @@ namespace DiscImageChef.Core.Media.Info
if(!tmpBuf.SequenceEqual(sectorSync))
continue;
- offsetBytes = i - 2352;
- offsetFound = true;
+ combinedOffset = i - 2352;
+ offsetFound = true;
break;
}
@@ -150,152 +140,105 @@ namespace DiscImageChef.Core.Media.Info
}
}
+ if(offsetFound)
+ return;
+
// Try to get another the offset some other way, we need an audio track just after a data track, same session
- if(!offsetFound)
+
+ for(int i = 1; i < tracks.Length; i++)
{
- Track dataTrack = default;
- Track audioTrack = default;
+ if(tracks[i - 1].TrackType == TrackType.Audio ||
+ tracks[i].TrackType != TrackType.Audio)
+ continue;
- for(int i = 1; i < tracks.Length; i++)
- {
- if(tracks[i - 1].TrackType == TrackType.Audio ||
- tracks[i].TrackType != TrackType.Audio)
- continue;
+ dataTrack = tracks[i - 1];
+ audioTrack = tracks[i];
- dataTrack = tracks[i - 1];
- audioTrack = tracks[i];
-
- break;
- }
-
- // Found them
- if(dataTrack.TrackSequence != 0 &&
- audioTrack.TrackSequence != 0)
- {
- sense = dev.ReadCd(out cmdBuf, out _, (uint)audioTrack.TrackStartSector, sectorSize, 3,
- MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, true, false,
- MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);
-
- if(!sense &&
- !dev.Error)
- {
- dataTrack.TrackEndSector += 150;
-
- // Calculate MSF
- ulong minute = dataTrack.TrackEndSector / 4500;
- ulong second = (dataTrack.TrackEndSector - (minute * 4500)) / 75;
- ulong frame = dataTrack.TrackEndSector - (minute * 4500) - (second * 75);
-
- dataTrack.TrackEndSector -= 150;
-
- // Convert to BCD
- ulong remainder = minute % 10;
- minute = ((minute / 10) * 16) + remainder;
- remainder = second % 10;
- second = ((second / 10) * 16) + remainder;
- remainder = frame % 10;
- frame = ((frame / 10) * 16) + remainder;
-
- // Scramble M and S
- minute ^= 0x01;
- second ^= 0x80;
-
- // Build sync
- byte[] sectorSync =
- {
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, (byte)minute,
- (byte)second, (byte)frame
- };
-
- byte[] tmpBuf = new byte[sectorSync.Length];
-
- for(int i = 0; i < cmdBuf.Length - sectorSync.Length; i++)
- {
- Array.Copy(cmdBuf, i, tmpBuf, 0, sectorSync.Length);
-
- if(!tmpBuf.SequenceEqual(sectorSync))
- continue;
-
- offsetBytes = i + 2352;
- offsetFound = true;
-
- break;
- }
-
- if(!offsetFound &&
- audioTrack.TrackPregap > 0)
- {
- sense = dev.ReadCd(out byte[] dataBuf, out _, (uint)dataTrack.TrackEndSector,
- sectorSize, 1, MmcSectorTypes.AllTypes, false, false, true,
- MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
- MmcSubchannel.None, dev.Timeout, out _);
-
- if(!sense &&
- !dev.Error)
- {
- for(int i = 0; i < dataBuf.Length; i++)
- dataBuf[i] ^= Sector.ScrambleTable[i];
-
- for(int i = 0; i < 2352; i++)
- {
- byte[] dataSide = new byte[2352 - i];
- byte[] audioSide = new byte[2352 - i];
-
- Array.Copy(dataBuf, i, dataSide, 0, dataSide.Length);
- Array.Copy(cmdBuf, 0, audioSide, 0, audioSide.Length);
-
- if(!dataSide.SequenceEqual(audioSide))
- continue;
-
- offsetBytes = audioSide.Length;
- offsetFound = true;
-
- break;
- }
- }
- }
- }
- }
+ break;
}
- if(cdOffset is null)
+ if(dataTrack.TrackSequence == 0 ||
+ audioTrack.TrackSequence == 0)
+ return;
+
+ // Found them
+ sense = dev.ReadCd(out cmdBuf, out _, (uint)audioTrack.TrackStartSector, sectorSize, 3,
+ MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, true, false,
+ MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);
+
+ if(sense || dev.Error)
+ return;
+
+ dataTrack.TrackEndSector += 150;
+
+ // Calculate MSF
+ minute = dataTrack.TrackEndSector / 4500;
+ second = (dataTrack.TrackEndSector - (minute * 4500)) / 75;
+ frame = dataTrack.TrackEndSector - (minute * 4500) - (second * 75);
+
+ dataTrack.TrackEndSector -= 150;
+
+ // Convert to BCD
+ remainder = minute % 10;
+ minute = ((minute / 10) * 16) + remainder;
+ remainder = second % 10;
+ second = ((second / 10) * 16) + remainder;
+ remainder = frame % 10;
+ frame = ((frame / 10) * 16) + remainder;
+
+ // Scramble M and S
+ minute ^= 0x01;
+ second ^= 0x80;
+
+ // Build sync
+ sectorSync = new byte[]
{
- if(offsetFound)
- {
- dumpLog?.WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes");
- updateStatus?.Invoke($"Combined disc and drive offsets are {offsetBytes} bytes");
- }
- else
- {
- dumpLog?.
- WriteLine("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, (byte)minute, (byte)second,
+ (byte)frame
+ };
- updateStatus?.
- Invoke("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
+ tmpBuf = new byte[sectorSync.Length];
- return false;
- }
+ for(int i = 0; i < cmdBuf.Length - sectorSync.Length; i++)
+ {
+ Array.Copy(cmdBuf, i, tmpBuf, 0, sectorSync.Length);
+
+ if(!tmpBuf.SequenceEqual(sectorSync))
+ continue;
+
+ combinedOffset = i + 2352;
+ offsetFound = true;
+
+ break;
}
- else
+
+ if(offsetFound || audioTrack.TrackPregap <= 0)
+ return;
+
+ sense = dev.ReadCd(out byte[] dataBuf, out _, (uint)dataTrack.TrackEndSector, sectorSize, 1,
+ MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true,
+ MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);
+
+ if(sense || dev.Error)
+ return;
+
+ for(int i = 0; i < dataBuf.Length; i++)
+ dataBuf[i] ^= Sector.ScrambleTable[i];
+
+ for(int i = 0; i < 2352; i++)
{
- if(offsetFound)
- {
- dumpLog?.
- WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)");
+ byte[] dataSide = new byte[2352 - i];
+ byte[] audioSide = new byte[2352 - i];
- updateStatus?.
- Invoke($"Disc offsets is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)");
- }
- else
- {
- dumpLog?.WriteLine("Disc write offset is unknown, dump may not be correct.");
- updateStatus?.Invoke("Disc write offset is unknown, dump may not be correct.");
+ Array.Copy(dataBuf, i, dataSide, 0, dataSide.Length);
+ Array.Copy(cmdBuf, 0, audioSide, 0, audioSide.Length);
- offsetBytes = cdOffset.Offset * 4;
- }
+ if(!dataSide.SequenceEqual(audioSide))
+ continue;
- dumpLog?.WriteLine($"Offset is {offsetBytes} bytes.");
- updateStatus?.Invoke($"Offset is {offsetBytes} bytes.");
+ combinedOffset = audioSide.Length;
+
+ break;
}
}
else
@@ -325,21 +268,11 @@ namespace DiscImageChef.Core.Media.Info
}
else
{
- offsetBytes = MMC.GetVideoNowColorOffset(videoNowColorFrame);
- dumpLog?.WriteLine($"VideoNow Color frame is offset {offsetBytes} bytes.");
- updateStatus?.Invoke($"VideoNow Color frame is offset {offsetBytes} bytes.");
+ combinedOffset = MMC.GetVideoNowColorOffset(videoNowColorFrame);
+ dumpLog?.WriteLine($"VideoNow Color frame is offset {combinedOffset} bytes.");
+ updateStatus?.Invoke($"VideoNow Color frame is offset {combinedOffset} bytes.");
}
}
-
- sectorsForOffset = offsetBytes / (int)sectorSize;
-
- if(sectorsForOffset < 0)
- sectorsForOffset *= -1;
-
- if(offsetBytes % sectorSize != 0)
- sectorsForOffset++;
-
- return offsetFound;
}
}
}
\ No newline at end of file
diff --git a/DiscImageChef/Commands/Media/Info.cs b/DiscImageChef/Commands/Media/Info.cs
index 15459bd88..ff32784e6 100644
--- a/DiscImageChef/Commands/Media/Info.cs
+++ b/DiscImageChef/Commands/Media/Info.cs
@@ -580,37 +580,55 @@ namespace DiscImageChef.Commands.Media
track.TrackSequence, track.TrackStartSector, track.TrackEndSector,
track.TrackPregap, track.TrackType);
- CdOffset cdOffset = null;
-
- if(dbDev != null)
- {
- // Search for read offset in master database
- cdOffset = ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer &&
- d.Model == dev.Model);
- }
-
- bool gotOffset = CompactDisc.GetOffset(cdOffset, dbDev, debug, dev, scsiInfo.MediaType, null,
- out int offsetBytes, true, out _, tracks, null);
-
DicConsole.WriteLine();
DicConsole.WriteLine("Offsets:");
- DicConsole.WriteLine(cdOffset != null
- ? $"Drive offset is {cdOffset.Offset * 4} bytes ({cdOffset.Offset} samples)"
- : "Drive offset is unknown");
+ CdOffset cdOffset = null;
- if(gotOffset)
+ // Search for read offset in master database
+ cdOffset = ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer &&
+ d.Model == dev.Model);
+
+ CompactDisc.GetOffset(cdOffset, dbDev, debug, dev, scsiInfo.MediaType, null, tracks, null,
+ out int? driveOffset, out int? combinedOffset);
+
+ if(combinedOffset is null)
{
- DicConsole.WriteLine($"Combined offset is {offsetBytes} bytes ({offsetBytes / 4} samples)");
+ if(driveOffset is null)
+ {
+ DicConsole.WriteLine("Drive reading offset not found in database.");
+ DicConsole.WriteLine("Disc offset cannot be calculated.");
+ }
+ else
+ {
+ DicConsole.
+ WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
- DicConsole.WriteLine(cdOffset != null
- ? $"Disc offset is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)"
- : "Disc offset is unknown");
+ DicConsole.WriteLine("Disc write offset is unknown.");
+ }
}
else
{
- DicConsole.WriteLine("Combined offset is unknown");
- DicConsole.WriteLine("Disc offset is unknown");
+ int offsetBytes = combinedOffset.Value;
+
+ if(driveOffset is null)
+ {
+ DicConsole.WriteLine("Drive reading offset not found in database.");
+
+ DicConsole.
+ WriteLine($"Combined disc and drive offset are {offsetBytes} bytes ({offsetBytes / 4} samples).");
+ }
+ else
+ {
+ DicConsole.
+ WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
+
+ DicConsole.WriteLine($"Combined offset is {offsetBytes} bytes ({offsetBytes / 4} samples)");
+
+ int? discOffset = offsetBytes - driveOffset;
+
+ DicConsole.WriteLine($"Disc offset is {discOffset} bytes ({discOffset / 4} samples)");
+ }
}
}
}