Ejemplo n.º 1
0
        public static BufferedSubcodeSector CloneFromBytesDeinterleaved(byte[] buffer)
        {
            var ret = new BufferedSubcodeSector();

            Buffer.BlockCopy(buffer, 0, ret.SubcodeDeinterleaved, 0, 96);
            return(ret);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// applies an SBI file to the disc
        /// </summary>
        public void ApplySBI(SBI_Format.SBIFile sbi)
        {
            //save this, it's small, and we'll want it for disc processing a/b checks
            Memos["sbi"] = sbi;

            int n = sbi.ABAs.Count;

            byte[] subcode = new byte[96];
            int    b       = 0;

            for (int i = 0; i < n; i++)
            {
                int aba        = sbi.ABAs[i];
                var oldSubcode = this.Sectors[aba].SubcodeSector;
                oldSubcode.ReadSubcodeDeinterleaved(subcode, 0);
                for (int j = 0; j < 12; j++)
                {
                    short patch = sbi.subq[b++];
                    if (patch == -1)
                    {
                        continue;
                    }
                    else
                    {
                        subcode[12 + j] = (byte)patch;
                    }
                }
                var bss = new BufferedSubcodeSector();
                Sectors[aba].SubcodeSector = BufferedSubcodeSector.CloneFromBytesDeinterleaved(subcode);
            }
        }
Ejemplo n.º 3
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++;
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// applies an SBI file to the disc
        /// </summary>
        public void ApplySBI(SBI_Format.SBIFile sbi)
        {
            //save this, it's small, and we'll want it for disc processing a/b checks
            Memos["sbi"] = sbi;

            int n = sbi.ABAs.Count;
            byte[] subcode = new byte[96];
            int b=0;
            for (int i = 0; i < n; i++)
            {
                int aba = sbi.ABAs[i];
                var oldSubcode = this.Sectors[aba].SubcodeSector;
                oldSubcode.ReadSubcodeDeinterleaved(subcode, 0);
                for (int j = 0; j < 12; j++)
                {
                    short patch = sbi.subq[b++];
                    if (patch == -1) continue;
                    else subcode[12 + j] = (byte)patch;
                }
                var bss = new BufferedSubcodeSector();
                Sectors[aba].SubcodeSector = BufferedSubcodeSector.CloneFromBytesDeinterleaved(subcode);
            }
        }
Ejemplo n.º 5
0
 public static BufferedSubcodeSector CloneFromBytesDeinterleaved(byte[] buffer)
 {
     var ret = new BufferedSubcodeSector();
     Buffer.BlockCopy(buffer, 0, ret.SubcodeDeinterleaved, 0, 96);
     return ret;
 }
Ejemplo n.º 6
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++;
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Loads a CCD at the specified path to a Disc object
        /// </summary>
        public Disc LoadCCDToDisc(string ccdPath)
        {
            var loadResults = LoadCCDPath(ccdPath);

            if (!loadResults.Valid)
            {
                throw loadResults.FailureException;
            }

            Disc disc = new Disc();

            var ccdf    = loadResults.ParsedCCDFile;
            var imgBlob = new Disc.Blob_RawFile()
            {
                PhysicalPath = loadResults.ImgPath
            };
            var subBlob = new Disc.Blob_RawFile()
            {
                PhysicalPath = loadResults.SubPath
            };

            disc.Blobs.Add(imgBlob);
            disc.Blobs.Add(subBlob);

            //generate DiscTOCRaw items from the ones specified in the CCD file
            //TODO - range validate these (too many truncations to byte)
            disc.RawTOCEntries = new List <RawTOCEntry>();
            BufferedSubcodeSector bss = new BufferedSubcodeSector();

            foreach (var entry in ccdf.TOCEntries)
            {
                var q = new SubchannelQ
                {
                    q_status = SubchannelQ.ComputeStatus(entry.ADR, (EControlQ)(entry.Control & 0xF)),
                    q_tno    = (byte)entry.TrackNo,
                    q_index  = (byte)entry.Point,
                    min      = BCD2.FromDecimal(entry.AMin),
                    sec      = BCD2.FromDecimal(entry.ASec),
                    frame    = BCD2.FromDecimal(entry.AFrame),
                    zero     = (byte)entry.Zero,
                    ap_min   = BCD2.FromDecimal(entry.PMin),
                    ap_sec   = BCD2.FromDecimal(entry.PSec),
                    ap_frame = BCD2.FromDecimal(entry.PFrame),
                };

                //CRC cant be calculated til we've got all the fields setup
                q.q_crc = bss.Synthesize_SubchannelQ(ref q, true);

                disc.RawTOCEntries.Add(new RawTOCEntry {
                    QData = q
                });
            }

            //generate the toc from the entries
            var tocSynth = new DiscTOCRaw.SynthesizeFromRawTOCEntriesJob()
            {
                Entries = disc.RawTOCEntries
            };

            tocSynth.Run();
            disc.TOCRaw = tocSynth.Result;

            //synthesize DiscStructure
            var structureSynth = new DiscStructure.SynthesizeFromDiscTOCRawJob()
            {
                TOCRaw = disc.TOCRaw
            };

            structureSynth.Run();
            disc.Structure = structureSynth.Result;

            //I *think* implicitly there is an index 0.. at.. i dunno, 0 maybe, for track 1
            {
                var dsi0 = new DiscStructure.Index();
                dsi0.LBA    = 0;
                dsi0.Number = 0;
                disc.Structure.Sessions[0].Tracks[0].Indexes.Add(dsi0);
            }

            //now, how to get the track types for the DiscStructure?
            //1. the CCD tells us (somehow the reader has judged)
            //2. scan it out of the Q subchannel
            //lets choose1.
            //TODO - better consider how to handle the situation where we have havent received all the [TRACK] items we need
            foreach (var st in disc.Structure.Sessions[0].Tracks)
            {
                var ccdt = ccdf.TracksByNumber[st.Number];
                switch (ccdt.Mode)
                {
                case 0:
                    st.TrackType = ETrackType.Audio;                             //for CCD, this means audio, apparently.
                    break;

                case 1:
                    st.TrackType = ETrackType.Mode1_2352;
                    break;

                case 2:
                    st.TrackType = ETrackType.Mode2_2352;
                    break;

                default:
                    throw new InvalidOperationException("Unsupported CCD mode");
                }

                //add indexes for this track
                foreach (var ccdi in ccdt.Indexes)
                {
                    var dsi = new DiscStructure.Index();
                    //if (ccdi.Key == 0) continue;
                    dsi.LBA    = ccdi.Value;
                    dsi.Number = ccdi.Key;
                    st.Indexes.Add(dsi);
                }
            }

            //add sectors for the lead-in, which isn't stored in the CCD file, I think
            //TODO - synthesize lead-in sectors from TOC, if the lead-in isn't available.
            //need a test case for that though.
            var leadin_sector_zero  = new Sector_Zero();
            var leadin_subcode_zero = new ZeroSubcodeSector();

            for (int i = 0; i < 150; i++)
            {
                var se = new SectorEntry(leadin_sector_zero);
                disc.Sectors.Add(se);
                se.SubcodeSector = leadin_subcode_zero;
            }

            //build the sectors:
            //set up as many sectors as we have img/sub for, even if the TOC doesnt reference them (TOC is unreliable, although the tracks should have covered it all)
            for (int i = 0; i < loadResults.NumImgSectors; i++)
            {
                var isec = new Sector_RawBlob();
                isec.Offset = ((long)i) * 2352;
                isec.Blob   = imgBlob;

                var se = new SectorEntry(isec);
                disc.Sectors.Add(se);

                var scsec = new BlobSubcodeSectorPreDeinterleaved();
                scsec.Offset     = ((long)i) * 96;
                scsec.Blob       = subBlob;
                se.SubcodeSector = scsec;
            }

            return(disc);
        }