Detect VideoNow Color offset.

This commit is contained in:
2019-12-26 01:24:57 +00:00
parent 0a5d194a00
commit 271cee4d93
2 changed files with 236 additions and 168 deletions

View File

@@ -857,7 +857,7 @@ namespace DiscImageChef.Core.Devices.Dumping
false, false, true, MmcHeaderCodes.None, true, true, MmcErrorField.None, false, false, true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
MmcSubchannel.None, _dev.Timeout, out _); MmcSubchannel.None, _dev.Timeout, out _);
if(sense || !_dev.Error) if(sense || _dev.Error)
{ {
videoNowColorFrame = null; videoNowColorFrame = null;
@@ -1323,8 +1323,8 @@ namespace DiscImageChef.Core.Devices.Dumping
// Check offset // Check offset
if(_fixOffset) if(_fixOffset)
{ {
// TODO: VideoNow if(dskType != MediaType.VideoNowColor)
{
if(tracks.All(t => t.TrackType != TrackType.Audio)) if(tracks.All(t => t.TrackType != TrackType.Audio))
{ {
// No audio tracks so no need to fix offset // No audio tracks so no need to fix offset
@@ -1335,7 +1335,8 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
else if(!readcd) else if(!readcd)
{ {
_dumpLog.WriteLine("READ CD command is not supported, disabling offset fix. Dump may not be correct."); _dumpLog.
WriteLine("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
UpdateStatus?. UpdateStatus?.
Invoke("READ CD command is not supported, disabling offset fix. Dump may not be correct."); Invoke("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
@@ -1372,8 +1373,8 @@ namespace DiscImageChef.Core.Devices.Dumping
// Build sync // Build sync
byte[] sectorSync = byte[] sectorSync =
{ {
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)second, (byte)frame (byte)minute, (byte)second, (byte)frame
}; };
tmpBuf = new byte[sectorSync.Length]; tmpBuf = new byte[sectorSync.Length];
@@ -1381,7 +1382,8 @@ namespace DiscImageChef.Core.Devices.Dumping
// 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 ||
dbDev?.SCSI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true || dbDev?.SCSI?.RemovableMedias?.Any(d => d.SupportsPlextorReadCDDA == true) == true ||
_dev.Manufacturer.ToLowerInvariant() == "plextor") _dev.Manufacturer.ToLowerInvariant() ==
"plextor")
{ {
sense = _dev.PlextorReadCdDa(out cmdBuf, out senseBuf, sense = _dev.PlextorReadCdDa(out cmdBuf, out senseBuf,
(uint)dataTrack.TrackEndSector - 2, sectorSize, 3, (uint)dataTrack.TrackEndSector - 2, sectorSize, 3,
@@ -1472,6 +1474,39 @@ namespace DiscImageChef.Core.Devices.Dumping
UpdateStatus?.Invoke($"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; sectorsForOffset = offsetBytes / (int)sectorSize;

View File

@@ -37,79 +37,112 @@ namespace DiscImageChef.Core.Media.Detection
{ {
public static class MMC public static class MMC
{ {
/// <summary> /// <summary>This is some kind of header. Every 10 bytes there's an audio byte.</summary>
/// This is some kind of header. Every 10 bytes there's an audio byte.
/// </summary>
static readonly byte[] VideoNowColorFrameMarker = static readonly byte[] VideoNowColorFrameMarker =
{ {
0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81,
0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3,
0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00,
0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81,
0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3,
0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00,
0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3,
0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81,
0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7,
0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x00, 0x00, 0x02, 0x01, 0x04, 0x02, 0x06, 0x03, 0xFF, 0x00, 0x08, 0x04,
0xC7, 0x00, 0x00, 0x00, 0x02, 0x01, 0x04, 0x02, 0x06, 0x03, 0xFF, 0x00, 0x08, 0x04, 0x0A, 0x05, 0x0C, 0x0A, 0x05, 0x0C, 0x06, 0x0E, 0x07, 0xFF, 0x00, 0x11, 0x08, 0x13, 0x09, 0x15, 0x0A, 0x17, 0x0B, 0xFF, 0x00,
0x06, 0x0E, 0x07, 0xFF, 0x00, 0x11, 0x08, 0x13, 0x09, 0x15, 0x0A, 0x17, 0x0B, 0xFF, 0x00, 0x19, 0x0C, 0x19, 0x0C, 0x1B, 0x0D, 0x1D, 0x0E, 0x1F, 0x0F, 0xFF, 0x00, 0x00, 0x28, 0x02, 0x29, 0x04, 0x2A, 0x06, 0x2B,
0x1B, 0x0D, 0x1D, 0x0E, 0x1F, 0x0F, 0xFF, 0x00, 0x00, 0x28, 0x02, 0x29, 0x04, 0x2A, 0x06, 0x2B, 0xFF, 0xFF, 0x00, 0x08, 0x2C, 0x0A, 0x2D, 0x0C, 0x2E, 0x0E, 0x2F, 0xFF, 0x00, 0x11, 0x30, 0x13, 0x31, 0x15, 0x32,
0x00, 0x08, 0x2C, 0x0A, 0x2D, 0x0C, 0x2E, 0x0E, 0x2F, 0xFF, 0x00, 0x11, 0x30, 0x13, 0x31, 0x15, 0x32, 0x17, 0x33, 0xFF, 0x00, 0x19, 0x34, 0x1B, 0x35, 0x1D, 0x36, 0x1F, 0x37, 0xFF, 0x00, 0x00, 0x38, 0x02, 0x39,
0x17, 0x33, 0xFF, 0x00, 0x19, 0x34, 0x1B, 0x35, 0x1D, 0x36, 0x1F, 0x37, 0xFF, 0x00, 0x00, 0x38, 0x02, 0x04, 0x3A, 0x06, 0x3B, 0xFF, 0x00, 0x08, 0x3C, 0x0A, 0x3D, 0x0C, 0x3E, 0x0E, 0x3F, 0xFF, 0x00, 0x11, 0x40,
0x39, 0x04, 0x3A, 0x06, 0x3B, 0xFF, 0x00, 0x08, 0x3C, 0x0A, 0x3D, 0x0C, 0x3E, 0x0E, 0x3F, 0xFF, 0x00, 0x13, 0x41, 0x15, 0x42, 0x17, 0x43, 0xFF, 0x00, 0x19, 0x44, 0x1B, 0x45, 0x1D, 0x46, 0x1F, 0x47, 0xFF, 0x00,
0x11, 0x40, 0x13, 0x41, 0x15, 0x42, 0x17, 0x43, 0xFF, 0x00, 0x19, 0x44, 0x1B, 0x45, 0x1D, 0x46, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x47, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
}; };
/// <summary> /// <summary>Checks if the media corresponds to CD-i.</summary>
/// Checks if the media corresponds to CD-i.
/// </summary>
/// <param name="sector0">Contents of LBA 0, with all headers.</param> /// <param name="sector0">Contents of LBA 0, with all headers.</param>
/// <param name="sector16">Contents of LBA 0, with all headers.</param> /// <param name="sector16">Contents of LBA 0, with all headers.</param>
/// <returns><c>true</c> if it corresponds to a CD-i, <c>false</c>otherwise.</returns> /// <returns><c>true</c> if it corresponds to a CD-i, <c>false</c>otherwise.</returns>
public static bool IsCdi(byte[] sector0, byte[] sector16) public static bool IsCdi(byte[] sector0, byte[] sector16)
{ {
if(sector0?.Length != 2352 || sector16?.Length != 2352) return false; if(sector0?.Length != 2352 ||
sector16?.Length != 2352)
return false;
byte[] syncMark =
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
};
byte[] cdiMark =
{
0x01, 0x43, 0x44, 0x2D
};
byte[] syncMark = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
byte[] cdiMark = {0x01, 0x43, 0x44, 0x2D};
byte[] testMark = new byte[12]; byte[] testMark = new byte[12];
Array.Copy(sector0, 0, testMark, 0, 12); Array.Copy(sector0, 0, testMark, 0, 12);
bool hiddenData = syncMark.SequenceEqual(testMark) && bool hiddenData = syncMark.SequenceEqual(testMark) &&
(sector0[0xF] == 0 || sector0[0xF] == 1 || sector0[0xF] == 2); (sector0[0xF] == 0 || sector0[0xF] == 1 || sector0[0xF] == 2);
if(!hiddenData || sector0[0xF] != 2) return false; if(!hiddenData ||
sector0[0xF] != 2)
return false;
testMark = new byte[4]; testMark = new byte[4];
Array.Copy(sector16, 24, testMark, 0, 4); Array.Copy(sector16, 24, testMark, 0, 4);
return cdiMark.SequenceEqual(testMark); return cdiMark.SequenceEqual(testMark);
} }
public static bool IsVideoNowColor(byte[] videoFrame) public static bool IsVideoNowColor(byte[] videoFrame)
{ {
if(videoFrame is null || videoFrame.Length < VideoNowColorFrameMarker.Length) return false; if(videoFrame is null ||
videoFrame.Length < VideoNowColorFrameMarker.Length)
return false;
byte[] buffer = new byte[VideoNowColorFrameMarker.Length]; byte[] buffer = new byte[VideoNowColorFrameMarker.Length];
for(int framePosition = 0; framePosition + buffer.Length < videoFrame.Length; framePosition++) for(int framePosition = 0; framePosition + buffer.Length < videoFrame.Length; framePosition++)
{ {
Array.Copy(videoFrame, framePosition, buffer, 0, buffer.Length); Array.Copy(videoFrame, framePosition, buffer, 0, buffer.Length);
for(int ab = 9; ab < buffer.Length; ab += 10) buffer[ab] = 0; for(int ab = 9; ab < buffer.Length; ab += 10)
buffer[ab] = 0;
if(!VideoNowColorFrameMarker.SequenceEqual(buffer)) continue; if(!VideoNowColorFrameMarker.SequenceEqual(buffer))
continue;
return true; return true;
} }
return false; return false;
} }
public static int GetVideoNowColorOffset(byte[] data)
{
byte[] buffer = new byte[VideoNowColorFrameMarker.Length];
for(int framePosition = 0; framePosition + buffer.Length < data.Length; framePosition++)
{
Array.Copy(data, framePosition, buffer, 0, buffer.Length);
for(int ab = 9; ab < buffer.Length; ab += 10)
buffer[ab] = 0;
if(!VideoNowColorFrameMarker.SequenceEqual(buffer))
continue;
return 18032 - framePosition;
}
return 0;
}
} }
} }