diff --git a/.idea/.idea.DiscImageChef/.idea/contentModel.xml b/.idea/.idea.DiscImageChef/.idea/contentModel.xml
index eeefcb0ce..68876f183 100644
--- a/.idea/.idea.DiscImageChef/.idea/contentModel.xml
+++ b/.idea/.idea.DiscImageChef/.idea/contentModel.xml
@@ -291,6 +291,7 @@
+
diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs
index c4b1edbe8..3edfbe8dd 100644
--- a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs
+++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs
@@ -1329,206 +1329,9 @@ namespace DiscImageChef.Core.Devices.Dumping
// Check offset
if(_fixOffset)
{
- 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.");
-
- _fixOffset = false;
- }
- else 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
- {
- bool offsetFound = false;
-
- if(tracks.Any(t => t.TrackType != TrackType.Audio))
- {
- Track 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);
-
- dataTrack.TrackStartSector -= 151;
-
- // 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
- };
-
- tmpBuf = new byte[sectorSync.Length];
-
- // Plextor READ CDDA
- if(_dbDev?.ATAPI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) ==
- true ||
- _dbDev?.SCSI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
- _dev.Manufacturer.ToLowerInvariant() ==
- "plextor")
- {
- sense = _dev.PlextorReadCdDa(out cmdBuf, out senseBuf,
- (uint)dataTrack.TrackStartSector, sectorSize, 3,
- PlextorSubchannel.None, _dev.Timeout, out _);
-
- if(!sense &&
- !_dev.Error)
- {
- 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(_debug ||
- _dbDev?.ATAPI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
- _dbDev?.SCSI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
- _dev.Manufacturer.ToLowerInvariant() == "hl-dt-st")
- {
- sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)dataTrack.TrackStartSector,
- sectorSize, 3, MmcSectorTypes.Cdda, false, false, false,
- MmcHeaderCodes.None, true, false, MmcErrorField.None,
- MmcSubchannel.None, _dev.Timeout, out _);
-
- if(!sense &&
- !_dev.Error)
- {
- 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(cdOffset is null)
- {
- 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.");
-
- UpdateStatus?.
- Invoke("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
-
- _fixOffset = false;
- }
- }
- else
- {
- if(offsetFound)
- {
- _dumpLog.
- WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)");
-
- 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.");
-
- offsetBytes = cdOffset.Offset * 4;
- }
-
- _dumpLog.WriteLine($"Offset is {offsetBytes} bytes.");
- UpdateStatus?.Invoke($"Offset is {offsetBytes} bytes.");
- }
- }
- }
- else
- {
- byte[] videoNowColorFrame = new byte[9 * sectorSize];
-
- sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize, 9, MmcSectorTypes.AllTypes, false,
- false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
- MmcSubchannel.None, _dev.Timeout, out _);
-
- if(sense || _dev.Error)
- {
- sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize, 9, MmcSectorTypes.Cdda, false,
- false, true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
- MmcSubchannel.None, _dev.Timeout, out _);
-
- if(sense || _dev.Error)
- {
- videoNowColorFrame = null;
- }
- }
-
- if(videoNowColorFrame is null)
- {
- _dumpLog.WriteLine("Could not find VideoNow Color frame offset, dump may not be correct.");
- UpdateStatus?.Invoke("Could not find VideoNow Color frame offset, dump may not be correct.");
- }
- else
- {
- offsetBytes = MMC.GetVideoNowColorOffset(videoNowColorFrame);
- _dumpLog.WriteLine($"VideoNow Color frame is offset {offsetBytes} bytes.");
- UpdateStatus?.Invoke($"VideoNow Color frame is offset {offsetBytes} bytes.");
- }
- }
-
- sectorsForOffset = offsetBytes / (int)sectorSize;
-
- if(sectorsForOffset < 0)
- sectorsForOffset *= -1;
-
- if(offsetBytes % sectorSize != 0)
- sectorsForOffset++;
+ _fixOffset = Media.Info.CompactDisc.GetOffset(cdOffset, _dbDev, _debug, _dev, dskType, _dumpLog,
+ out offsetBytes, readcd, out sectorsForOffset, tracks,
+ UpdateStatus);
}
else if(tracks.Any(t => t.TrackType == TrackType.Audio))
{
diff --git a/DiscImageChef.Core/DiscImageChef.Core.csproj b/DiscImageChef.Core/DiscImageChef.Core.csproj
index d617f8236..0aefb933b 100644
--- a/DiscImageChef.Core/DiscImageChef.Core.csproj
+++ b/DiscImageChef.Core/DiscImageChef.Core.csproj
@@ -61,6 +61,7 @@
+
diff --git a/DiscImageChef.Core/Media/Info/CompactDisc.cs b/DiscImageChef.Core/Media/Info/CompactDisc.cs
new file mode 100644
index 000000000..c9c20c2d6
--- /dev/null
+++ b/DiscImageChef.Core/Media/Info/CompactDisc.cs
@@ -0,0 +1,236 @@
+using System;
+using System.Linq;
+using DiscImageChef.CommonTypes;
+using DiscImageChef.CommonTypes.Enums;
+using DiscImageChef.CommonTypes.Structs;
+using DiscImageChef.Core.Logging;
+using DiscImageChef.Core.Media.Detection;
+using DiscImageChef.Database.Models;
+using DiscImageChef.Devices;
+using Device = DiscImageChef.Database.Models.Device;
+
+namespace DiscImageChef.Core.Media.Info
+{
+ public static class CompactDisc
+ {
+ /// Gets the offset bytes from a Compact Disc
+ /// Offset entry from database
+ /// Device entry from database
+ /// Debug
+ /// 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
+ /// 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)
+ {
+ byte[] cmdBuf;
+ bool sense;
+ bool offsetFound = false;
+ const uint sectorSize = 2352;
+ offsetBytes = 0;
+ sectorsForOffset = 0;
+
+ 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);
+
+ 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);
+
+ dataTrack.TrackStartSector -= 151;
+
+ // 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];
+
+ // Plextor READ CDDA
+ if(dbDev?.ATAPI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
+ dbDev?.SCSI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
+ dev.Manufacturer.ToLowerInvariant() == "plextor")
+ {
+ sense = dev.PlextorReadCdDa(out cmdBuf, out _, (uint)dataTrack.TrackStartSector, sectorSize,
+ 3, PlextorSubchannel.None, dev.Timeout, out _);
+
+ if(!sense &&
+ !dev.Error)
+ {
+ 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(debug ||
+ dbDev?.ATAPI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
+ dbDev?.SCSI?.RemovableMedias?.Any(d => d.CanReadCdScrambled == true) == true ||
+ dev.Manufacturer.ToLowerInvariant() == "hl-dt-st")
+ {
+ sense = dev.ReadCd(out cmdBuf, out _, (uint)dataTrack.TrackStartSector, sectorSize, 3,
+ MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, true,
+ false, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);
+
+ if(!sense &&
+ !dev.Error)
+ {
+ 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(cdOffset is null)
+ {
+ 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.");
+
+ updateStatus?.
+ Invoke("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
+
+ return false;
+ }
+ }
+ else
+ {
+ if(offsetFound)
+ {
+ dumpLog.
+ WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)");
+
+ 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.");
+
+ offsetBytes = cdOffset.Offset * 4;
+ }
+
+ dumpLog?.WriteLine($"Offset is {offsetBytes} bytes.");
+ updateStatus?.Invoke($"Offset is {offsetBytes} bytes.");
+ }
+ }
+ else
+ {
+ byte[] videoNowColorFrame = new byte[9 * sectorSize];
+
+ sense = dev.ReadCd(out cmdBuf, out _, 0, sectorSize, 9, MmcSectorTypes.AllTypes, false, false, true,
+ MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None,
+ dev.Timeout, out _);
+
+ if(sense || dev.Error)
+ {
+ sense = dev.ReadCd(out cmdBuf, out _, 0, sectorSize, 9, MmcSectorTypes.Cdda, false, false, true,
+ MmcHeaderCodes.None, true, true, MmcErrorField.None, MmcSubchannel.None,
+ dev.Timeout, out _);
+
+ if(sense || dev.Error)
+ {
+ videoNowColorFrame = null;
+ }
+ }
+
+ if(videoNowColorFrame is null)
+ {
+ dumpLog?.WriteLine("Could not find VideoNow Color frame offset, dump may not be correct.");
+ updateStatus?.Invoke("Could not find VideoNow Color frame offset, dump may not be correct.");
+ }
+ else
+ {
+ offsetBytes = MMC.GetVideoNowColorOffset(videoNowColorFrame);
+ dumpLog?.WriteLine($"VideoNow Color frame is offset {offsetBytes} bytes.");
+ updateStatus?.Invoke($"VideoNow Color frame is offset {offsetBytes} bytes.");
+ }
+ }
+
+ sectorsForOffset = offsetBytes / (int)sectorSize;
+
+ if(sectorsForOffset < 0)
+ sectorsForOffset *= -1;
+
+ if(offsetBytes % sectorSize != 0)
+ sectorsForOffset++;
+
+ return offsetFound;
+ }
+ }
+}
\ No newline at end of file