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,153 +1323,188 @@ 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))
{ {
// No audio tracks so no need to fix offset if(tracks.All(t => t.TrackType != TrackType.Audio))
_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); // 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.");
if(dataTrack.TrackSequence != 0) _fixOffset = false;
{
dataTrack.TrackEndSector += 149;
// Calculate MSF
ulong minute = dataTrack.TrackEndSector / 4500;
ulong second = (dataTrack.TrackEndSector - (minute * 4500)) / 75;
ulong frame = dataTrack.TrackEndSector - (minute * 4500) - (second * 75);
dataTrack.TrackEndSector -= 149;
// 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;
// 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.TrackEndSector - 2, 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.TrackEndSector - 2),
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;
}
}
}
}
} }
else if(!readcd)
if(cdOffset is null)
{ {
if(offsetFound) _dumpLog.
{ WriteLine("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
_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?. UpdateStatus?.
Invoke("Drive read offset is unknown, disabling offset fix. Dump may not be correct."); Invoke("READ CD command is not supported, disabling offset fix. Dump may not be correct.");
_fixOffset = false; _fixOffset = false;
}
} }
else else
{ {
if(offsetFound) bool offsetFound = false;
if(tracks.Any(t => t.TrackType != TrackType.Audio))
{ {
_dumpLog.WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}"); Track dataTrack = tracks.FirstOrDefault(t => t.TrackType != TrackType.Audio);
UpdateStatus?.Invoke($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}");
if(dataTrack.TrackSequence != 0)
{
dataTrack.TrackEndSector += 149;
// Calculate MSF
ulong minute = dataTrack.TrackEndSector / 4500;
ulong second = (dataTrack.TrackEndSector - (minute * 4500)) / 75;
ulong frame = dataTrack.TrackEndSector - (minute * 4500) - (second * 75);
dataTrack.TrackEndSector -= 149;
// 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;
// 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.TrackEndSector - 2, 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.TrackEndSector - 2),
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 else
{ {
_dumpLog.WriteLine("Disc write offset is unknown, dump may not be correct."); if(offsetFound)
UpdateStatus?.Invoke("Disc write offset is unknown, dump may not be correct."); {
_dumpLog.WriteLine($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}");
UpdateStatus?.Invoke($"Disc offsets is {offsetBytes - (cdOffset.Offset * 2 * -1)}");
}
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 * 2 * -1; offsetBytes = cdOffset.Offset * 2 * -1;
}
_dumpLog.WriteLine($"Offset is {offsetBytes} bytes.");
UpdateStatus?.Invoke($"Offset is {offsetBytes} bytes.");
} }
}
}
else
{
byte[] videoNowColorFrame = new byte[9 * sectorSize];
_dumpLog.WriteLine($"Offset is {offsetBytes} bytes."); sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize, 9, MmcSectorTypes.AllTypes, false,
UpdateStatus?.Invoke($"Offset is {offsetBytes} bytes."); 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.");
} }
} }

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;
}
} }
} }