From 5bb7d5e70728aaa19a01d6afcf2988356c4b3a80 Mon Sep 17 00:00:00 2001 From: zeromus Date: Wed, 1 Jul 2015 05:26:10 -0500 Subject: [PATCH] cue postgap subQ. print negative Timestamps, even though I'm becoming less and less a fan of that class --- BizHawk.Emulation.DiscSystem/CCD_format.cs | 4 +- BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs | 64 +++++++++---------- .../CUE/CUE_Synths.cs | 21 +++++- BizHawk.Emulation.DiscSystem/Disc.cs | 13 +++- .../Jobs/DiscMountJob.MednaDisc.cs | 10 +-- .../Jobs/DiscMountJob.cs | 6 +- .../SectorInterfaces.cs | 7 +- BizHawk.Emulation.DiscSystem/Subcode.cs | 6 +- 8 files changed, 83 insertions(+), 48 deletions(-) diff --git a/BizHawk.Emulation.DiscSystem/CCD_format.cs b/BizHawk.Emulation.DiscSystem/CCD_format.cs index 0deac090cf..5bb6cd2be8 100644 --- a/BizHawk.Emulation.DiscSystem/CCD_format.cs +++ b/BizHawk.Emulation.DiscSystem/CCD_format.cs @@ -462,10 +462,10 @@ namespace BizHawk.Emulation.DiscSystem long ofs = job.LBA * 96; subBlob.Read(ofs, job.DestBuffer2448, 2352, 96); - //sub data comes to us deinterleved; we may still need to interleave it + //subcode comes to us deinterleved; we may still need to interleave it if ((job.Parts & (ESectorSynthPart.SubcodeDeinterleave)) == 0) { - SubcodeUtils.InterleaveInplace(job.DestBuffer2448, 2352); + SubcodeUtils.InterleaveInplace(job.DestBuffer2448, job.DestOffset + 2352); } } } diff --git a/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs b/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs index 1d2fa3234e..230ea8d415 100644 --- a/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs +++ b/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs @@ -219,6 +219,9 @@ namespace BizHawk.Emulation.DiscSystem OUT_Disc.Sectors.Add(se_pregap); } + //TODO - build track relative timestamp now and increment it continually + + //after this, pregap sectors are generated like a normal sector, but the subQ is specified as a pregap instead of a normal track (actually, TBD) //--------------------------------- @@ -274,19 +277,7 @@ namespace BizHawk.Emulation.DiscSystem break; } - //make the subcode - //TODO - according to policies, or better yet, defer this til it's needed (user delivers a policies object to disc reader apis) - //at any rate, we'd paste this logic into there so let's go ahead and write it here - var subcode = new BufferedSubcodeSector(); //(its lame that we have to use this; make a static method when we delete this class) - SubchannelQ sq = new SubchannelQ(); - byte ADR = 1; //absent some kind of policy for how to set it, this is a safe assumption: - sq.SetStatus(ADR, (EControlQ)(int)cct.Flags); - sq.q_tno = BCD2.FromDecimal(cct.Number); - sq.q_index = BCD2.FromDecimal(curr_index); - int LBA = OUT_Disc.Sectors.Count; - sq.ap_min = BCD2.FromDecimal(new Timestamp(LBA).MIN); - sq.ap_sec = BCD2.FromDecimal(new Timestamp(LBA).SEC); - sq.ap_frame = BCD2.FromDecimal(new Timestamp(LBA).FRAC); + //prepare fields for subQ int track_relative_msf = curr_blobMSF - cct.Indexes[1].FileMSF.Sector; //for index 0, negative MSF required and encoded oppositely. Read more at Policies declaration @@ -301,20 +292,21 @@ namespace BizHawk.Emulation.DiscSystem else if (track_relative_msf < 0) throw new InvalidOperationException("Severe error generating cue subQ (negative relMSF for non-pregap)"); - sq.min = BCD2.FromDecimal(new Timestamp(track_relative_msf).MIN); - sq.sec = BCD2.FromDecimal(new Timestamp(track_relative_msf).SEC); - sq.frame = BCD2.FromDecimal(new Timestamp(track_relative_msf).FRAC); - //finally we're done: synthesize subchannel - subcode.Synthesize_SubchannelQ(ref sq, true); + //setup subQ + byte ADR = 1; //absent some kind of policy for how to set it, this is a safe assumption: + ss.sq.SetStatus(ADR, (EControlQ)(int)cct.Flags); + ss.sq.q_tno = BCD2.FromDecimal(cct.Number); + ss.sq.q_index = BCD2.FromDecimal(curr_index); + ss.sq.AP_Timestamp = new Timestamp(OUT_Disc.Sectors.Count); + ss.sq.Timestamp = new Timestamp(track_relative_msf); - //generate subP + //setup subP if (curr_index == 0) ss.Pause = true; //make the SectorEntry (some temporary bullshit here) var se = new SectorEntry(null); se.SectorSynth = ss; - ss.sq = sq; OUT_Disc.Sectors.Add(se); curr_blobMSF++; @@ -342,14 +334,26 @@ namespace BizHawk.Emulation.DiscSystem for (int s = 0; s < specifiedPostgapLength; s++) { //TODO - do a better job synthesizing Q - var se_pregap = new SectorEntry(null); - var ss_pregap = new SS_Gap(); + var se= new SectorEntry(null); + var ss = new SS_Gap(); - //postgaps set pause flag. is this good enough? - ss_pregap.Pause = true; + //-subq- + //postgap addressing continues from + int lastSectorRelMSF = curr_blobMSF - cct.Indexes[1].FileMSF.Sector - 1; + int postgapSectorRelMSF = lastSectorRelMSF + s + 1; + byte ADR = 1; + ss.sq.SetStatus(ADR, (EControlQ)(int)cct.Flags); + ss.sq.q_tno = BCD2.FromDecimal(cct.Number); + ss.sq.q_index = BCD2.FromDecimal(curr_index); + ss.sq.AP_Timestamp = new Timestamp(OUT_Disc.Sectors.Count); + ss.sq.Timestamp = new Timestamp(postgapSectorRelMSF); - se_pregap.SectorSynth = ss_pregap; - OUT_Disc.Sectors.Add(se_pregap); + //-subP- + //always paused--is this good enough? + ss.Pause = true; + + se.SectorSynth = ss; + OUT_Disc.Sectors.Add(se); } @@ -370,13 +374,9 @@ namespace BizHawk.Emulation.DiscSystem tocSynth.Run(); OUT_Disc.TOCRaw = tocSynth.Result; - ////generate lead-out track with some canned number of sectors - ////TODO - move this somewhere else and make it controllable depending on which console is loading up the disc - ////TODO - we're not doing this yet - ////var synthLeadoutJob = new Disc.SynthesizeLeadoutJob { Disc = disc, Length = 150 }; - ////synthLeadoutJob.Run(); + //TODO - generate leadout, or delegates at least - ////blech, old crap, maybe + //blech, old crap, maybe //OUT_Disc.Structure.Synthesize_TOCPointsFromSessions(); //FinishLog(); diff --git a/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs b/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs index 8d3477b08b..080b3e08e5 100644 --- a/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs +++ b/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs @@ -6,6 +6,7 @@ namespace BizHawk.Emulation.DiscSystem { partial class CUE_Format2 { + abstract class SS_Base : ISectorSynthJob2448 { public IBlob Blob; @@ -17,17 +18,31 @@ namespace BizHawk.Emulation.DiscSystem protected void SynthSubcode(SectorSynthJob job) { + //synth P if needed if ((job.Parts & ESectorSynthPart.SubchannelP) != 0) { SynthUtils.SubP(job.DestBuffer2448, job.DestOffset + 2352, Pause); } + //synth Q if needed if ((job.Parts & ESectorSynthPart.SubchannelQ) != 0) { var subcode = new BufferedSubcodeSector(); subcode.Synthesize_SubchannelQ(ref sq, true); Buffer.BlockCopy(subcode.SubcodeDeinterleaved, 12, job.DestBuffer2448, job.DestOffset + 2352 + 12, 12); } + + //clear R-W if needed + if ((job.Parts & ESectorSynthPart.Subchannel_RSTUVW) != 0) + { + Array.Clear(job.DestBuffer2448, job.DestOffset + 2352 + 12 + 12, (12 * 6)); + } + + //subcode has been generated deinterleaved; we may still need to interleave it + if ((job.Parts & (ESectorSynthPart.SubcodeDeinterleave)) == 0) + { + SubcodeUtils.InterleaveInplace(job.DestBuffer2448, job.DestOffset + 2352); + } } } @@ -46,9 +61,9 @@ namespace BizHawk.Emulation.DiscSystem for (int i = 1; i < 11; i++) buffer[offset + i] = 0xFF; buffer[offset + 11] = 0x00; Timestamp ts = new Timestamp(LBA + 150); - buffer[offset + 12] = ts.MIN; - buffer[offset + 13] = ts.SEC; - buffer[offset + 14] = ts.FRAC; + buffer[offset + 12] = BCD2.IntToBCD(ts.MIN); + buffer[offset + 13] = BCD2.IntToBCD(ts.SEC); + buffer[offset + 14] = BCD2.IntToBCD(ts.FRAC); buffer[offset + 15] = mode; } diff --git a/BizHawk.Emulation.DiscSystem/Disc.cs b/BizHawk.Emulation.DiscSystem/Disc.cs index 2e8d598d43..50032b65dd 100644 --- a/BizHawk.Emulation.DiscSystem/Disc.cs +++ b/BizHawk.Emulation.DiscSystem/Disc.cs @@ -425,10 +425,12 @@ namespace BizHawk.Emulation.DiscSystem SEC = (byte)((str[3] - '0') * 10 + (str[4] - '0')); FRAC = (byte)((str[6] - '0') * 10 + (str[7] - '0')); Valid = true; + Negative = false; return; BOGUS: MIN = SEC = FRAC = 0; Valid = false; + Negative = false; return; } @@ -440,12 +442,12 @@ namespace BizHawk.Emulation.DiscSystem get { if (!Valid) return "--:--:--"; - return string.Format("{0:D2}:{1:D2}:{2:D2}", MIN, SEC, FRAC); + return string.Format("{0}{1:D2}:{2:D2}:{3:D2}", Negative?'-':'+',MIN, SEC, FRAC); } } public readonly byte MIN, SEC, FRAC; - public readonly bool Valid; + public readonly bool Valid, Negative; /// /// The fully multiplied out flat-address Sector number @@ -461,6 +463,7 @@ namespace BizHawk.Emulation.DiscSystem SEC = (byte)s; FRAC = (byte)f; Valid = true; + Negative = false; } /// @@ -468,6 +471,12 @@ namespace BizHawk.Emulation.DiscSystem /// public Timestamp(int SectorNumber) { + if (SectorNumber < 0) + { + SectorNumber = -SectorNumber; + Negative = true; + } + else Negative = false; MIN = (byte)(SectorNumber / (60 * 75)); SEC = (byte)((SectorNumber / 75) % 60); FRAC = (byte)(SectorNumber % 75); diff --git a/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs b/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs index 6864c84356..ef58bfb819 100644 --- a/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs +++ b/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs @@ -42,14 +42,14 @@ namespace BizHawk.Emulation.DiscSystem var synth = new SS_MednaDisc(); //make sector interfaces: - //1. right now for dumb reasons we have 150 lead-in sectors. I want to get rid of this crap. - var leadin_sector_zero = new Sector_Zero(); - var leadin_subcode_zero = new ZeroSubcodeSector(); + var pregap_sector_zero = new Sector_Zero(); + var pregap_subcode_zero = new ZeroSubcodeSector(); for (int i = 0; i < 150; i++) { - var se = new SectorEntry(leadin_sector_zero); + var se = new SectorEntry(pregap_sector_zero); + se.SectorSynth = synth; disc.Sectors.Add(se); - se.SubcodeSector = leadin_subcode_zero; + se.SubcodeSector = pregap_subcode_zero; } //2. actual sectors diff --git a/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.cs b/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.cs index adbaf394fc..b3effbe596 100644 --- a/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.cs +++ b/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.cs @@ -19,8 +19,10 @@ namespace BizHawk.Emulation.DiscSystem /// During the Pause this relative time decreases and /// --B-- equals zero in the last Section" /// This is a contradiction. - /// By choosing true, mode A is selected, and the final sector of the pause is -1. I like this better. Defaulting until proven otherwise (write test case here) - /// By choosing false, mode B is selected, and the final sector of the pause is 0. Mednafen does it this way. + /// By choosing true, mode A is selected, and the final sector of the pause is -1. + /// (I like this better. Defaulting until proven otherwise [write test case here]) + /// By choosing false, mode B is selected, and the final sector of the pause is 0. + /// (Mednafen does it this way) /// Discs (including PSX) exist using A, or B, or possibly (reference please) neither. /// public bool CUE_PauseContradictionModeA = true; diff --git a/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs b/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs index 4d04aed806..6ed5c54f7f 100644 --- a/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs +++ b/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs @@ -88,10 +88,15 @@ namespace BizHawk.Emulation.DiscSystem /// SubchannelQ = 32, + /// + /// Subchannels R-W (all except for P and Q) + /// + Subchannel_RSTUVW = (64|128|256|512|1024|2048), + /// /// Complete subcode is required /// - SubcodeComplete = (16|32|64|128|256|512|1024|2048), + SubcodeComplete = (SubchannelP | SubchannelQ | Subchannel_RSTUVW), /// /// Any of the subcode might be required (just another way of writing SubcodeComplete) diff --git a/BizHawk.Emulation.DiscSystem/Subcode.cs b/BizHawk.Emulation.DiscSystem/Subcode.cs index 1b60755aa1..45ba1bebb5 100644 --- a/BizHawk.Emulation.DiscSystem/Subcode.cs +++ b/BizHawk.Emulation.DiscSystem/Subcode.cs @@ -310,7 +310,11 @@ namespace BizHawk.Emulation.DiscSystem /// /// Retrieves the initial set of timestamps (min,sec,frac) as a convenient Timestamp /// - public Timestamp Timestamp { get { return new Timestamp(min.DecimalValue, sec.DecimalValue, frame.DecimalValue); } } + public Timestamp Timestamp + { + get { return new Timestamp(min.DecimalValue, sec.DecimalValue, frame.DecimalValue); } + set { min.DecimalValue = value.MIN; sec.DecimalValue = value.SEC; frame.DecimalValue = value.FRAC; } + } /// /// Retrieves the second set of timestamps (ap_min, ap_sec, ap_frac) as a convenient Timestamp.