Esempio n. 1
0
        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

            int ts  = lba_relative;
            int ats = 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_tno.BCDValue   = 0xAA;
            sq.q_index.BCDValue = 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);
        }
Esempio n. 2
0
        public void Run()
        {
            //TODO: encode_mode2_form2_sector

            var leadoutTs        = Disc.TOC.LeadoutLBA;
            var lastTrackTOCItem = Disc.TOC.TOCItems[Disc.TOC.LastRecordedTrackNumber];             //NOTE: in case LastRecordedTrackNumber is al ie, this will malfunction

            //leadout flags.. let's set them the same as the last track.
            //THIS IS NOT EXACTLY THE SAME WAY MEDNAFEN DOES IT
            EControlQ leadoutFlags = lastTrackTOCItem.Control;

            //TODO - needs to be encoded as a certain mode (mode 2 form 2 for psx... i guess...)

            for (int i = 0; i < Length; i++)
            {
                //var se = new SectorEntry(sz);
                //Disc.Sectors.Add(se);
                SubchannelQ sq = new SubchannelQ();

                int track_relative_msf = i;
                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);

                int absolute_msf = i + leadoutTs;
                sq.ap_min   = BCD2.FromDecimal(new Timestamp(absolute_msf + 150).MIN);
                sq.ap_sec   = BCD2.FromDecimal(new Timestamp(absolute_msf + 150).SEC);
                sq.ap_frame = BCD2.FromDecimal(new Timestamp(absolute_msf + 150).FRAC);

                sq.q_tno.DecimalValue   = 0xAA;               //special value for leadout
                sq.q_index.DecimalValue = 1;

                byte ADR = 1;
                sq.SetStatus(ADR, leadoutFlags);

                //TODO - actually stash the subQ
            }
        }
Esempio n. 3
0
 /// <summary>
 /// computes a status byte from the provided adr/qmode and control values
 /// </summary>
 public static byte ComputeStatus(int adr_or_qmode, EControlQ control)
 {
     return((byte)(adr_or_qmode | (((int)control) << 4)));
 }
Esempio n. 4
0
 /// <summary>
 /// sets the status byte from the provided adr/qmode and control values
 /// </summary>
 public void SetStatus(byte adr_or_qmode, EControlQ control)
 {
     q_status = ComputeStatus(adr_or_qmode, control);
 }
Esempio n. 5
0
 /// <summary>
 /// sets the status byte from the provided adr and control values
 /// </summary>
 public void SetStatus(byte adr, EControlQ control)
 {
     q_status = ComputeStatus(adr, control);
 }
Esempio n. 6
0
 /// <summary>
 /// computes a status byte from the provided adr and control values
 /// </summary>
 public static byte ComputeStatus(int adr, EControlQ control)
 {
     return (byte)(adr | (((int)control) << 4));
 }
Esempio n. 7
0
 /// <summary>
 /// sets the status byte from the provided adr and control values
 /// </summary>
 public void SetStatus(byte adr, EControlQ control)
 {
     q_status = ComputeStatus(adr, control);
 }
Esempio n. 8
0
        /// <summary>
        /// Creates the subcode (really, just subchannel Q) for this disc from its current TOC.
        /// Depends on the TOCPoints existing in the structure
        /// TODO - do we need a fully 0xFF P-subchannel for PSX?
        /// </summary>
        void Synthesize_SubcodeFromStructure()
        {
            int aba     = 0;
            int dpIndex = 0;

            //TODO - from mednafen (on PC-FX chip chan kick)
            //If we're more than 2 seconds(150 sectors) from the real "start" of the track/INDEX 01, and the track is a data track,
            //and the preceding track is an audio track, encode it as audio(by taking the SubQ control field from the preceding

            //NOTE: discs may have subcode which is nonsense or possibly not recoverable from a sensible disc structure.
            //but this function does what it says.

            //SO: heres the main idea of how this works.
            //we have the Structure.Points (whose name we dont like) which is a list of sectors where the tno/index changes.
            //So for each sector, we see if we've advanced to the next point.
            //TODO - check if this is synthesized correctly when producing a structure from a TOCRaw
            while (aba < Sectors.Count)
            {
                if (dpIndex < Structure.Points.Count - 1)
                {
                    while (aba >= Structure.Points[dpIndex + 1].ABA)
                    {
                        dpIndex++;
                    }
                }
                var dp = Structure.Points[dpIndex];


                var se = Sectors[aba];

                EControlQ control = dp.Control;
                bool      pause   = true;
                if (dp.Num != 0)                 //TODO - shouldnt this be IndexNum?
                {
                    pause = false;
                }
                if ((dp.Control & EControlQ.DataUninterrupted) != 0)
                {
                    pause = false;
                }

                int adr = dp.ADR;

                SubchannelQ sq = new SubchannelQ();
                sq.q_status = SubchannelQ.ComputeStatus(adr, control);
                sq.q_tno    = BCD2.FromDecimal(dp.TrackNum).BCDValue;
                sq.q_index  = BCD2.FromDecimal(dp.IndexNum).BCDValue;

                int track_relative_aba = aba - dp.Track.Indexes[1].aba;
                track_relative_aba = Math.Abs(track_relative_aba);
                Timestamp track_relative_timestamp = new Timestamp(track_relative_aba);
                sq.min   = BCD2.FromDecimal(track_relative_timestamp.MIN);
                sq.sec   = BCD2.FromDecimal(track_relative_timestamp.SEC);
                sq.frame = BCD2.FromDecimal(track_relative_timestamp.FRAC);
                sq.zero  = 0;
                Timestamp absolute_timestamp = new Timestamp(aba);
                sq.ap_min   = BCD2.FromDecimal(absolute_timestamp.MIN);
                sq.ap_sec   = BCD2.FromDecimal(absolute_timestamp.SEC);
                sq.ap_frame = BCD2.FromDecimal(absolute_timestamp.FRAC);

                var bss = new BufferedSubcodeSector();
                bss.Synthesize_SubchannelQ(ref sq, true);

                //TEST: need this for psx?
                if (pause)
                {
                    bss.Synthesize_SubchannelP(true);
                }

                se.SubcodeSector = bss;

                aba++;
            }
        }
Esempio n. 9
0
		/// <summary>
		/// sets the status byte from the provided adr/qmode and control values
		/// </summary>
		public void SetStatus(byte adr_or_qmode, EControlQ control)
		{
			q_status = ComputeStatus(adr_or_qmode, control);
		}