BizHawk/BizHawk.Client.DiscoHawk/MednadiscTester.cs

121 lines
3.4 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using BizHawk.Emulation.DiscSystem;
class MednadiscTester
{
[DllImport("mednadisc.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mednadisc_LoadCD(string path);
[DllImport("mednadisc.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mednadisc_ReadSector(IntPtr disc, int lba, byte[] buf2448);
[DllImport("mednadisc.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void mednadisc_CloseCD(IntPtr disc);
public class QuickSubcodeReader
{
public QuickSubcodeReader(byte[] buffer)
{
this.buffer = buffer;
}
public void ReadLBA_SubchannelQ(int offset, ref SubchannelQ sq)
{
sq.q_status = buffer[offset + 0];
sq.q_tno = buffer[offset + 1];
sq.q_index = buffer[offset + 2];
sq.min.BCDValue = buffer[offset + 3];
sq.sec.BCDValue = buffer[offset + 4];
sq.frame.BCDValue = buffer[offset + 5];
//nothing in byte[6]
sq.ap_min.BCDValue = buffer[offset + 7];
sq.ap_sec.BCDValue = buffer[offset + 8];
sq.ap_frame.BCDValue = buffer[offset + 9];
//CRC is stored inverted and big endian.. so... do the opposite
byte hibyte = (byte)(~buffer[offset + 10]);
byte lobyte = (byte)(~buffer[offset + 11]);
sq.q_crc = (ushort)((hibyte << 8) | lobyte);
}
byte[] buffer;
}
public void TestDirectory(string dpTarget)
{
foreach (var fi in new DirectoryInfo(dpTarget).GetFiles())
{
if (fi.Extension.ToLower() == ".cue") { }
else if (fi.Extension.ToLower() == ".ccd") { }
else continue;
NewTest(fi.FullName);
}
}
static bool NewTest(string path)
{
bool ret = false;
Disc disc;
if (Path.GetExtension(path).ToLower() == ".cue") disc = Disc.FromCuePath(path, new CueBinPrefs());
else disc = Disc.FromCCDPath(path);
IntPtr mednadisc = mednadisc_LoadCD(path);
//TODO - test leadout a bit, or determine length some superior way
//TODO - check length against mednadisc
int nSectors = (int)(disc.Structure.BinarySize / 2352) - 150;
var subbuf = new byte[96];
var discbuf = new byte[2352 + 96];
var monkeybuf = new byte[2352 + 96];
var disc_qbuf = new byte[96];
var monkey_qbuf = new byte[96];
for (int i = 0; i < nSectors; i++)
{
mednadisc_ReadSector(mednadisc, i, monkeybuf);
disc.ReadLBA_2352(i, discbuf, 0);
disc.ReadLBA_SectorEntry(i).SubcodeSector.ReadSubcodeDeinterleaved(subbuf, 0);
SubcodeUtils.Interleave(subbuf, 0, discbuf, 2352);
//remove P
for (int q = 2352; q < 2352 + 96; q++)
{
discbuf[q] &= 0x7F;
monkeybuf[q] &= 0x7F;
}
for (int q = 0; q < 2352 + 96; q++)
{
if (discbuf[q] != monkeybuf[q])
{
Console.WriteLine("MISMATCH: " + Path.GetFileName(path));
//decode Q subchannels for manual investigation
SubcodeUtils.Deinterleave(discbuf, 2352, disc_qbuf, 0);
var asr = new QuickSubcodeReader(disc_qbuf);
SubchannelQ disc_q = new SubchannelQ();
asr.ReadLBA_SubchannelQ(12, ref disc_q);
SubcodeUtils.Deinterleave(monkeybuf, 2352, monkey_qbuf, 0);
asr = new QuickSubcodeReader(monkey_qbuf);
SubchannelQ monkey_q = new SubchannelQ();
asr.ReadLBA_SubchannelQ(12, ref monkey_q);
goto END;
}
}
}
ret = true;
END:
disc.Dispose();
mednadisc_CloseCD(mednadisc);
return ret;
}
}