mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Always calculate offset.
This commit is contained in:
@@ -123,20 +123,6 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
return;
|
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
|
// Check subchannels support
|
||||||
supportsPqSubchannel = SupportsPqSubchannel(_dev, _dumpLog, UpdateStatus);
|
supportsPqSubchannel = SupportsPqSubchannel(_dev, _dumpLog, UpdateStatus);
|
||||||
supportsRwSubchannel = SupportsRwSubchannel(_dev, _dumpLog, UpdateStatus);
|
supportsRwSubchannel = SupportsRwSubchannel(_dev, _dumpLog, UpdateStatus);
|
||||||
@@ -839,9 +825,24 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
// Check offset
|
// Check offset
|
||||||
if(_fixOffset)
|
if(_fixOffset)
|
||||||
{
|
{
|
||||||
_fixOffset = Media.Info.CompactDisc.GetOffset(cdOffset, _dbDev, _debug, _dev, dskType, _dumpLog,
|
if(tracks.All(t => t.TrackType != TrackType.Audio))
|
||||||
out offsetBytes, readcd, out sectorsForOffset, tracks,
|
{
|
||||||
UpdateStatus);
|
// 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))
|
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.");
|
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);
|
mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, _maximumReadable);
|
||||||
ibgLog = new IbgLog(_outputPrefix + ".ibg", 0x0008);
|
ibgLog = new IbgLog(_outputPrefix + ".ibg", 0x0008);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
@@ -21,61 +22,50 @@ namespace DiscImageChef.Core.Media.Info
|
|||||||
/// <param name="dev">Opened device</param>
|
/// <param name="dev">Opened device</param>
|
||||||
/// <param name="dskType">Detected disk type</param>
|
/// <param name="dskType">Detected disk type</param>
|
||||||
/// <param name="dumpLog">Dump log if applicable</param>
|
/// <param name="dumpLog">Dump log if applicable</param>
|
||||||
/// <param name="offsetBytes">Set to combined offset, in bytes</param>
|
|
||||||
/// <param name="readcd">If device supports READ CD command</param>
|
|
||||||
/// <param name="sectorsForOffset">Sectors needed to fix offset</param>
|
|
||||||
/// <param name="tracks">Disc track list</param>
|
/// <param name="tracks">Disc track list</param>
|
||||||
/// <param name="updateStatus">UpdateStatus event</param>
|
/// <param name="updateStatus">UpdateStatus event</param>
|
||||||
|
/// <param name="driveOffset">Drive offset</param>
|
||||||
|
/// <param name="combinedOffset">Combined offset</param>
|
||||||
/// <returns><c>true</c> if offset could be found, <c>false</c> otherwise</returns>
|
/// <returns><c>true</c> if offset could be found, <c>false</c> otherwise</returns>
|
||||||
public static bool GetOffset(CdOffset cdOffset, Device dbDev, bool debug, DiscImageChef.Devices.Device dev,
|
[SuppressMessage("ReSharper", "TooWideLocalVariableScope")]
|
||||||
MediaType dskType, DumpLog dumpLog, out int offsetBytes, bool readcd,
|
public static void GetOffset(CdOffset cdOffset, Device dbDev, bool debug, DiscImageChef.Devices.Device dev,
|
||||||
out int sectorsForOffset, Track[] tracks, UpdateStatusHandler updateStatus)
|
MediaType dskType, DumpLog dumpLog, Track[] tracks,
|
||||||
|
UpdateStatusHandler updateStatus, out int? driveOffset, out int? combinedOffset)
|
||||||
{
|
{
|
||||||
byte[] cmdBuf;
|
byte[] cmdBuf;
|
||||||
bool sense;
|
bool sense;
|
||||||
|
ulong minute;
|
||||||
|
ulong second;
|
||||||
|
ulong frame;
|
||||||
|
ulong remainder;
|
||||||
|
byte[] sectorSync;
|
||||||
|
byte[] tmpBuf;
|
||||||
|
Track dataTrack = default;
|
||||||
|
Track audioTrack = default;
|
||||||
bool offsetFound = false;
|
bool offsetFound = false;
|
||||||
const uint sectorSize = 2352;
|
const uint sectorSize = 2352;
|
||||||
offsetBytes = 0;
|
driveOffset = cdOffset?.Offset * 4;
|
||||||
sectorsForOffset = 0;
|
combinedOffset = null;
|
||||||
|
|
||||||
if(dskType != MediaType.VideoNowColor)
|
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))
|
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)
|
if(dataTrack.TrackSequence != 0)
|
||||||
{
|
{
|
||||||
dataTrack.TrackStartSector += 151;
|
dataTrack.TrackStartSector += 151;
|
||||||
|
|
||||||
// Calculate MSF
|
// Calculate MSF
|
||||||
ulong minute = dataTrack.TrackStartSector / 4500;
|
minute = dataTrack.TrackStartSector / 4500;
|
||||||
ulong second = (dataTrack.TrackStartSector - (minute * 4500)) / 75;
|
second = (dataTrack.TrackStartSector - (minute * 4500)) / 75;
|
||||||
ulong frame = dataTrack.TrackStartSector - (minute * 4500) - (second * 75);
|
frame = dataTrack.TrackStartSector - (minute * 4500) - (second * 75);
|
||||||
|
|
||||||
dataTrack.TrackStartSector -= 151;
|
dataTrack.TrackStartSector -= 151;
|
||||||
|
|
||||||
// Convert to BCD
|
// Convert to BCD
|
||||||
ulong remainder = minute % 10;
|
remainder = minute % 10;
|
||||||
minute = ((minute / 10) * 16) + remainder;
|
minute = ((minute / 10) * 16) + remainder;
|
||||||
remainder = second % 10;
|
remainder = second % 10;
|
||||||
second = ((second / 10) * 16) + remainder;
|
second = ((second / 10) * 16) + remainder;
|
||||||
@@ -87,13 +77,13 @@ namespace DiscImageChef.Core.Media.Info
|
|||||||
second ^= 0x80;
|
second ^= 0x80;
|
||||||
|
|
||||||
// Build sync
|
// Build sync
|
||||||
byte[] sectorSync =
|
sectorSync = new byte[]
|
||||||
{
|
{
|
||||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, (byte)minute,
|
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, (byte)minute,
|
||||||
(byte)second, (byte)frame
|
(byte)second, (byte)frame
|
||||||
};
|
};
|
||||||
|
|
||||||
byte[] tmpBuf = new byte[sectorSync.Length];
|
tmpBuf = new byte[sectorSync.Length];
|
||||||
|
|
||||||
// Plextor READ CDDA
|
// Plextor READ CDDA
|
||||||
if(dbDev?.ATAPI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
|
if(dbDev?.ATAPI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
|
||||||
@@ -113,8 +103,8 @@ namespace DiscImageChef.Core.Media.Info
|
|||||||
if(!tmpBuf.SequenceEqual(sectorSync))
|
if(!tmpBuf.SequenceEqual(sectorSync))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
offsetBytes = i - 2352;
|
combinedOffset = i - 2352;
|
||||||
offsetFound = true;
|
offsetFound = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -140,8 +130,8 @@ namespace DiscImageChef.Core.Media.Info
|
|||||||
if(!tmpBuf.SequenceEqual(sectorSync))
|
if(!tmpBuf.SequenceEqual(sectorSync))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
offsetBytes = i - 2352;
|
combinedOffset = i - 2352;
|
||||||
offsetFound = true;
|
offsetFound = true;
|
||||||
|
|
||||||
break;
|
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
|
// 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;
|
if(tracks[i - 1].TrackType == TrackType.Audio ||
|
||||||
Track audioTrack = default;
|
tracks[i].TrackType != TrackType.Audio)
|
||||||
|
continue;
|
||||||
|
|
||||||
for(int i = 1; i < tracks.Length; i++)
|
dataTrack = tracks[i - 1];
|
||||||
{
|
audioTrack = tracks[i];
|
||||||
if(tracks[i - 1].TrackType == TrackType.Audio ||
|
|
||||||
tracks[i].TrackType != TrackType.Audio)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
dataTrack = tracks[i - 1];
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, (byte)minute, (byte)second,
|
||||||
{
|
(byte)frame
|
||||||
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?.
|
tmpBuf = new byte[sectorSync.Length];
|
||||||
Invoke("Drive read offset is unknown, disabling offset fix. Dump may not be correct.");
|
|
||||||
|
|
||||||
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)
|
byte[] dataSide = new byte[2352 - i];
|
||||||
{
|
byte[] audioSide = new byte[2352 - i];
|
||||||
dumpLog?.
|
|
||||||
WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)");
|
|
||||||
|
|
||||||
updateStatus?.
|
Array.Copy(dataBuf, i, dataSide, 0, dataSide.Length);
|
||||||
Invoke($"Disc offsets is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)");
|
Array.Copy(cmdBuf, 0, audioSide, 0, audioSide.Length);
|
||||||
}
|
|
||||||
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;
|
if(!dataSide.SequenceEqual(audioSide))
|
||||||
}
|
continue;
|
||||||
|
|
||||||
dumpLog?.WriteLine($"Offset is {offsetBytes} bytes.");
|
combinedOffset = audioSide.Length;
|
||||||
updateStatus?.Invoke($"Offset is {offsetBytes} bytes.");
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -325,21 +268,11 @@ namespace DiscImageChef.Core.Media.Info
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offsetBytes = MMC.GetVideoNowColorOffset(videoNowColorFrame);
|
combinedOffset = MMC.GetVideoNowColorOffset(videoNowColorFrame);
|
||||||
dumpLog?.WriteLine($"VideoNow Color frame is offset {offsetBytes} bytes.");
|
dumpLog?.WriteLine($"VideoNow Color frame is offset {combinedOffset} bytes.");
|
||||||
updateStatus?.Invoke($"VideoNow Color frame is offset {offsetBytes} 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -580,37 +580,55 @@ namespace DiscImageChef.Commands.Media
|
|||||||
track.TrackSequence, track.TrackStartSector, track.TrackEndSector,
|
track.TrackSequence, track.TrackStartSector, track.TrackEndSector,
|
||||||
track.TrackPregap, track.TrackType);
|
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();
|
||||||
DicConsole.WriteLine("Offsets:");
|
DicConsole.WriteLine("Offsets:");
|
||||||
|
|
||||||
DicConsole.WriteLine(cdOffset != null
|
CdOffset cdOffset = null;
|
||||||
? $"Drive offset is {cdOffset.Offset * 4} bytes ({cdOffset.Offset} samples)"
|
|
||||||
: "Drive offset is unknown");
|
|
||||||
|
|
||||||
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
|
DicConsole.WriteLine("Disc write offset is unknown.");
|
||||||
? $"Disc offset is {offsetBytes - (cdOffset.Offset * 4)} bytes ({(offsetBytes / 4) - cdOffset.Offset} samples)"
|
}
|
||||||
: "Disc offset is unknown");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Combined offset is unknown");
|
int offsetBytes = combinedOffset.Value;
|
||||||
DicConsole.WriteLine("Disc offset is unknown");
|
|
||||||
|
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)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user