basic leadout track synthesis

This commit is contained in:
zeromus 2015-07-14 21:42:31 -05:00
parent 64aa41c0e3
commit e6e1716c02
4 changed files with 101 additions and 6 deletions

View File

@ -78,10 +78,19 @@ namespace BizHawk.Emulation.DiscSystem
var tocSynth = new Synthesize_DiscTOC_From_RawTOCEntries_Job() { Entries = OUT_Disc.RawTOCEntries };
tocSynth.Run();
OUT_Disc.TOC = tocSynth.Result;
//2. Structure frmo TOCRaw
//2. Structure from TOCRaw
var structureSynth = new Synthesize_DiscStructure_From_DiscTOC_Job() { IN_Disc = OUT_Disc, TOCRaw = OUT_Disc.TOC };
structureSynth.Run();
OUT_Disc.Structure = structureSynth.Result;
//insert a synth provider to take care of the leadout track
var ss_leadout = new SS_Leadout()
{
SessionNumber = 1,
Policy = IN_DiscMountPolicy
};
Func<int,bool> condition = (int lba) => lba >= OUT_Disc.Session1.LeadoutLBA;
new ConditionalSectorSynthProvider().Install(OUT_Disc, condition, ss_leadout);
}
FinishLog();

View File

@ -12,9 +12,8 @@ namespace BizHawk.Emulation.DiscSystem
public class DiscStructure
{
/// <summary>
/// This is a 0-indexed list of sessions (session 1 is at [0])
/// This is a 1-indexed list of sessions (session 1 is at [1])
/// Support for multiple sessions is thoroughly not working yet
/// TODO - make re-index me with a null session 0
/// </summary>
public List<Session> Sessions = new List<Session>();
@ -50,11 +49,13 @@ namespace BizHawk.Emulation.DiscSystem
/// <summary>
/// A reference to the first information track (Track 1)
/// The raw TOC may have specified something different; it's not clear how this discrepancy is handled.
/// </summary>
public Track FirstInformationTrack { get { return Tracks[1]; } }
/// <summary>
/// A reference to the first information track (Track 1)
/// A reference to the last information track on the disc.
/// The raw TOC may have specified something different; it's not clear how this discrepancy is handled.
/// </summary>
public Track LastInformationTrack { get { return Tracks[InformationTrackCount]; } }
@ -147,8 +148,8 @@ namespace BizHawk.Emulation.DiscSystem
public bool IsAudio { get { return Mode == 0; } }
/// <summary>
/// The 'control' properties of the track indicated by the subchannel Q.
/// This is as indicated by the disc TOC.
/// The 'control' properties of the track expected to be found in the track's subQ.
/// However, this is what's indicated by the disc TOC.
/// Actual sector contents may vary.
/// </summary>
public EControlQ Control;

View File

@ -99,6 +99,7 @@ namespace BizHawk.Emulation.DiscSystem
/// <summary>
/// Retrieves the second set of timestamps (ap_min, ap_sec, ap_frac) as a convenient Timestamp.
/// TODO - rename everything AP here, it's nonsense. (the P is)
/// </summary>
public Timestamp AP_Timestamp {
get { return new Timestamp(ap_min.DecimalValue, ap_sec.DecimalValue, ap_frame.DecimalValue); }

View File

@ -137,6 +137,29 @@ namespace BizHawk.Emulation.DiscSystem
}
}
/// <summary>
/// Returns 'Patch' synth if the provided condition is met
/// </summary>
class ConditionalSectorSynthProvider : ISectorSynthProvider
{
Func<int,bool> Condition;
ISectorSynthJob2448 Patch;
ISectorSynthProvider Parent;
public void Install(Disc disc, Func<int, bool> condition, ISectorSynthJob2448 patch)
{
Parent = disc.SynthProvider;
disc.SynthProvider = this;
Condition = condition;
Patch = patch;
}
public ISectorSynthJob2448 Get(int lba)
{
if (Condition(lba))
return Patch;
else return Parent.Get(lba);
}
}
/// <summary>
/// When creating a disc, this is set with a callback that can deliver an ISectorSynthJob2448 for the given LBA
/// </summary>
@ -177,5 +200,66 @@ namespace BizHawk.Emulation.DiscSystem
}
}
class SS_Leadout : ISectorSynthJob2448
{
public int SessionNumber;
public DiscMountPolicy Policy;
public void Synth(SectorSynthJob job)
{
//be lazy, just generate the whole sector unconditionally
//this is mostly based on mednafen's approach, which was probably finely tailored for PSX
//heres the comments on the subject:
// I'm not trusting that the "control" field for the TOC leadout entry will always be set properly, so | the control fields for the last track entry
// and the leadout entry together before extracting the D2 bit. Audio track->data leadout is fairly benign though maybe noisy(especially if we ever implement
// data scrambling properly), but data track->audio leadout could break things in an insidious manner for the more accurate drive emulation code).
var ses = job.Disc.Structure.Sessions[SessionNumber];
int lba_relative = job.LBA - ses.LeadoutTrack.LBA;
//data is zero
Timestamp ts = new Timestamp(lba_relative);
Timestamp ats = new Timestamp(job.LBA);
const int ADR = 0x1; // Q channel data encodes position
EControlQ control = ses.LeadoutTrack.Control;
//ehhh? CDI?
//if(toc.tracks[toc.last_track].valid)
// control |= toc.tracks[toc.last_track].control & 0x4;
//else if(toc.disc_type == DISC_TYPE_CD_I)
// control |= 0x4;
control |= (EControlQ)(((int)ses.LastInformationTrack.Control) & 4);
SubchannelQ sq = new SubchannelQ();
sq.SetStatus(ADR, control);
sq.q_index.DecimalValue = 0xAA;
sq.q_index.DecimalValue = 0x01;
sq.Timestamp = ts;
sq.AP_Timestamp = ats;
sq.zero = 0;
//finally, rely on a gap sector to do the heavy lifting to synthesize this
CUE.CueTrackType TrackType = CUE.CueTrackType.Audio;
if (ses.LeadoutTrack.IsData)
{
if (job.Disc.TOC.Session1Format == SessionFormat.Type20_CDXA || job.Disc.TOC.Session1Format == SessionFormat.Type10_CDI)
TrackType = CUE.CueTrackType.Mode2_2352;
else
TrackType = CUE.CueTrackType.Mode1_2352;
}
CUE.SS_Gap ss_gap = new CUE.SS_Gap()
{
Policy = Policy,
sq = sq,
TrackType = TrackType,
Pause = true //?
};
ss_gap.Synth(job);
}
}
}