basic leadout track synthesis
This commit is contained in:
parent
64aa41c0e3
commit
e6e1716c02
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue