BizHawk/BizHawk.Emulation.DiscSystem/DiscMountJob.MednaDisc.cs

117 lines
4.2 KiB
C#

namespace BizHawk.Emulation.DiscSystem
{
partial class DiscMountJob
{
class SS_MednaDisc : ISectorSynthJob2448
{
public void Synth(SectorSynthJob job)
{
//mednafen is always synthesizing everything, no need to worry about flags.. mostly./
job.Params.MednaDisc.Read_2442(job.LBA, job.DestBuffer2448, job.DestOffset);
//we may still need to deinterleave it if subcode was requested and it needs deinterleaving
if ((job.Parts & (ESectorSynthPart.SubcodeDeinterleave | ESectorSynthPart.SubcodeAny)) != 0)
{
SynthUtils.DeinterleaveSubcodeInplace(job.DestBuffer2448, 2352);
}
}
}
void RunMednaDisc()
{
var disc = new Disc();
OUT_Disc = disc;
//create a MednaDisc and give it to the disc for ownership
var md = new MednaDisc(IN_FromPath);
disc.DisposableResources.Add(md);
//"length of disc" for BizHawk's purposes (NOT a robust concept!) is determined by beginning of leadout track
var m_leadoutTrack = md.TOCTracks[100];
int nSectors = (int)m_leadoutTrack.lba;
//make synth param memos
disc.SynthParams.MednaDisc = md;
//this is the sole sector synthesizer we'll need
var synth = new SS_MednaDisc();
OUT_Disc.SynthProvider = new SimpleSectorSynthProvider { SS = synth };
//ADR (q-Mode) is necessarily 0x01 for a RawTOCEntry
const int kADR = 1;
const int kUnknownControl = 0;
//mednafen delivers us what is essentially but not exactly (or completely) a TOCRaw.
//we need to synth RawTOCEntries from this and then turn it into a proper TOCRaw
//when coming from mednafen, there are 101 entries.
//entry[0] is placeholder junk, not to be used
//entry[100] is the leadout track (A0)
//A1 and A2 are in the form of FirstRecordedTrackNumber and LastRecordedTrackNumber
for (int i = 1; i < 101; i++)
{
var m_te = md.TOCTracks[i];
//don't add invalid (absent) items
if (!m_te.Valid)
continue;
var m_ts = new Timestamp((int)m_te.lba + 150); //these are supposed to be absolute timestamps
var q = new SubchannelQ
{
q_status = SubchannelQ.ComputeStatus(kADR, (EControlQ)m_te.control),
q_tno = BCD2.FromDecimal(0), //unknown with mednadisc
q_index = BCD2.FromDecimal(i),
min = BCD2.FromDecimal(0), //unknown with mednadisc
sec = BCD2.FromDecimal(0), //unknown with mednadisc
frame = BCD2.FromDecimal(0), //unknown with mednadisc
zero = 0, //unknown with mednadisc
ap_min = BCD2.FromDecimal(m_ts.MIN),
ap_sec = BCD2.FromDecimal(m_ts.SEC),
ap_frame = BCD2.FromDecimal(m_ts.FRAC),
q_crc = 0 //meaningless
};
//a special fixup: mednafen's entry 100 is the lead-out track, so change it into the A2 raw toc entry
if (i == 100)
{
q.q_index.BCDValue = 0xA2;
}
disc.RawTOCEntries.Add(new RawTOCEntry { QData = q });
}
// synth A0 and A1 entries (indicating first and last recorded tracks and also session type)
var qA0 = new SubchannelQ
{
q_status = SubchannelQ.ComputeStatus(kADR, kUnknownControl),
q_tno = BCD2.FromDecimal(0), //unknown with mednadisc
q_index = BCD2.FromBCD(0xA0),
min = BCD2.FromDecimal(0), //unknown with mednadisc
sec = BCD2.FromDecimal(0), //unknown with mednadisc
frame = BCD2.FromDecimal(0), //unknown with mednadisc
zero = 0, //unknown with mednadisc
ap_min = BCD2.FromDecimal(md.TOC.first_track),
ap_sec = BCD2.FromDecimal(md.TOC.disc_type),
ap_frame = BCD2.FromDecimal(0),
q_crc = 0, //meaningless
};
disc.RawTOCEntries.Add(new RawTOCEntry { QData = qA0 });
var qA1 = new SubchannelQ
{
q_status = SubchannelQ.ComputeStatus(kADR, kUnknownControl),
q_tno = BCD2.FromDecimal(0), //unknown with mednadisc
q_index = BCD2.FromBCD(0xA1),
min = BCD2.FromDecimal(0), //unknown with mednadisc
sec = BCD2.FromDecimal(0), //unknown with mednadisc
frame = BCD2.FromDecimal(0), //unknown with mednadisc
zero = 0, //unknown with mednadisc
ap_min = BCD2.FromDecimal(md.TOC.last_track),
ap_sec = BCD2.FromDecimal(0),
ap_frame = BCD2.FromDecimal(0),
q_crc = 0, //meaningless
};
disc.RawTOCEntries.Add(new RawTOCEntry { QData = qA1 });
}
}
}