Exemple #1
0
		void MountBlobs()
		{
			IBlob file_blob = null;

			BlobInfos = new List<BlobInfo>();
			foreach (var ccf in IN_CompileJob.OUT_CompiledCueFiles)
			{
				var bi = new BlobInfo();
				BlobInfos.Add(bi);

				switch (ccf.Type)
				{
					case CompiledCueFileType.BIN:
					case CompiledCueFileType.Unknown:
						{
							//raw files:
							var blob = new Disc.Blob_RawFile { PhysicalPath = ccf.FullPath };
							OUT_Disc.DisposableResources.Add(file_blob = blob);
							bi.Length = blob.Length;
							break;
						}
					case CompiledCueFileType.ECM:
						{
							var blob = new Disc.Blob_ECM();
							OUT_Disc.DisposableResources.Add(file_blob = blob);
							blob.Load(ccf.FullPath);
							bi.Length = blob.Length;
							break;
						}
					case CompiledCueFileType.WAVE:
						{
							var blob = new Disc.Blob_WaveFile();
							OUT_Disc.DisposableResources.Add(file_blob = blob);
							blob.Load(ccf.FullPath);
							bi.Length = blob.Length;
							break;
						}
					case CompiledCueFileType.DecodeAudio:
						{
							FFMpeg ffmpeg = new FFMpeg();
							if (!ffmpeg.QueryServiceAvailable())
							{
								throw new DiscReferenceException(ccf.FullPath, "No decoding service was available (make sure ffmpeg.exe is available. even though this may be a wav, ffmpeg is used to load oddly formatted wave files. If you object to this, please send us a note and we'll see what we can do. It shouldn't be too hard.)");
							}
							AudioDecoder dec = new AudioDecoder();
							byte[] buf = dec.AcquireWaveData(ccf.FullPath);
							var blob = new Disc.Blob_WaveFile();
							OUT_Disc.DisposableResources.Add(file_blob = blob);
							blob.Load(new MemoryStream(buf));
							bi.Length = buf.Length;
							break;
						}
					default:
						throw new InvalidOperationException();
				} //switch(file type)

				//wrap all the blobs with zero padding
				bi.Blob = new Disc.Blob_ZeroPadAdapter(file_blob, bi.Length);
			}
		}
Exemple #2
0
        void MountBlobs()
        {
            IBlob file_blob = null;

            BlobInfos = new List <BlobInfo>();
            foreach (var ccf in IN_CompileJob.OUT_CompiledCueFiles)
            {
                var bi = new BlobInfo();
                BlobInfos.Add(bi);

                switch (ccf.Type)
                {
                case CompiledCueFileType.BIN:
                case CompiledCueFileType.Unknown:
                {
                    //raw files:
                    var blob = new Disc.Blob_RawFile {
                        PhysicalPath = ccf.FullPath
                    };
                    OUT_Disc.DisposableResources.Add(file_blob = blob);
                    bi.Length = blob.Length;
                    break;
                }

                case CompiledCueFileType.ECM:
                {
                    var blob = new Disc.Blob_ECM();
                    OUT_Disc.DisposableResources.Add(file_blob = blob);
                    blob.Load(ccf.FullPath);
                    bi.Length = blob.Length;
                    break;
                }

                case CompiledCueFileType.WAVE:
                {
                    var blob = new Disc.Blob_WaveFile();
                    OUT_Disc.DisposableResources.Add(file_blob = blob);
                    blob.Load(ccf.FullPath);
                    bi.Length = blob.Length;
                    break;
                }

                case CompiledCueFileType.DecodeAudio:
                {
                    FFMpeg ffmpeg = new FFMpeg();
                    if (!ffmpeg.QueryServiceAvailable())
                    {
                        throw new DiscReferenceException(ccf.FullPath, "No decoding service was available (make sure ffmpeg.exe is available. even though this may be a wav, ffmpeg is used to load oddly formatted wave files. If you object to this, please send us a note and we'll see what we can do. It shouldn't be too hard.)");
                    }
                    AudioDecoder dec  = new AudioDecoder();
                    byte[]       buf  = dec.AcquireWaveData(ccf.FullPath);
                    var          blob = new Disc.Blob_WaveFile();
                    OUT_Disc.DisposableResources.Add(file_blob = blob);
                    blob.Load(new MemoryStream(buf));
                    bi.Length = buf.Length;
                    break;
                }

                default:
                    throw new InvalidOperationException();
                }                 //switch(file type)

                //wrap all the blobs with zero padding
                bi.Blob = new Disc.Blob_ZeroPadAdapter(file_blob, bi.Length);
            }
        }
Exemple #3
0
        /// <summary>
        /// Loads a CCD at the specified path to a Disc object
        /// </summary>
        public Disc LoadCCDToDisc(string ccdPath, DiscMountPolicy IN_DiscMountPolicy)
        {
            var loadResults = LoadCCDPath(ccdPath);

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

            Disc disc = new Disc();

            IBlob imgBlob = null, subBlob = null;
            long  imgLen = -1, subLen;

            //mount the IMG file
            //first check for a .ecm in place of the img
            var imgPath = loadResults.ImgPath;

            if (!File.Exists(imgPath))
            {
                var ecmPath = Path.ChangeExtension(imgPath, ".img.ecm");
                if (File.Exists(ecmPath))
                {
                    if (Disc.Blob_ECM.IsECM(ecmPath))
                    {
                        var ecm = new Disc.Blob_ECM();
                        ecm.Load(ecmPath);
                        imgBlob = ecm;
                        imgLen  = ecm.Length;
                    }
                }
            }
            if (imgBlob == null)
            {
                if (!File.Exists(loadResults.ImgPath))
                {
                    throw new CCDParseException("Malformed CCD format: nonexistent IMG file!");
                }
                var imgFile = new Disc.Blob_RawFile()
                {
                    PhysicalPath = loadResults.ImgPath
                };
                imgLen  = imgFile.Length;
                imgBlob = imgFile;
            }
            disc.DisposableResources.Add(imgBlob);

            //mount the SUB file
            if (!File.Exists(loadResults.SubPath))
            {
                throw new CCDParseException("Malformed CCD format: nonexistent SUB file!");
            }
            var subFile = new Disc.Blob_RawFile()
            {
                PhysicalPath = loadResults.SubPath
            };

            subBlob = subFile;
            disc.DisposableResources.Add(subBlob);
            subLen = subFile.Length;

            //quick integrity check of file sizes
            if (imgLen % 2352 != 0)
            {
                throw new CCDParseException("Malformed CCD format: IMG file length not multiple of 2352");
            }
            int NumImgSectors = (int)(imgLen / 2352);

            if (subLen != NumImgSectors * 96)
            {
                throw new CCDParseException("Malformed CCD format: SUB file length not matching IMG");
            }

            var ccdf = loadResults.ParsedCCDFile;

            //the only instance of a sector synthesizer we'll need
            SS_CCD synth = new SS_CCD();

            //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>();
            foreach (var entry in ccdf.TOCEntries)
            {
                BCD2 tno, ino;

                //this should actually be zero. im not sure if this is stored as BCD2 or not
                tno = BCD2.FromDecimal(entry.TrackNo);

                //these are special values.. I think, taken from this:
                //http://www.staff.uni-mainz.de/tacke/scsi/SCSI2-14.html
                //the CCD will contain Points as decimal values except for these specially converted decimal values which should stay as BCD.
                //Why couldn't they all be BCD? I don't know. I guess because BCD is inconvenient, but only A0 and friends have special meaning. It's confusing.
                ino = BCD2.FromDecimal(entry.Point);
                if (entry.Point == 0xA0)
                {
                    ino.BCDValue = 0xA0;
                }
                else if (entry.Point == 0xA1)
                {
                    ino.BCDValue = 0xA1;
                }
                else if (entry.Point == 0xA2)
                {
                    ino.BCDValue = 0xA2;
                }

                var q = new SubchannelQ
                {
                    q_status = SubchannelQ.ComputeStatus(entry.ADR, (EControlQ)(entry.Control & 0xF)),
                    q_tno    = tno,
                    q_index  = ino,
                    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),
                    q_crc    = 0, //meaningless
                };

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

            //analyze the RAWTocEntries to figure out what type of track track 1 is
            var tocSynth = new Synthesize_DiscTOC_From_RawTOCEntries_Job()
            {
                Entries = disc.RawTOCEntries
            };

            tocSynth.Run();

            //Add sectors for the mandatory track 1 pregap, which isn't stored in the CCD file
            //We reuse some CUE code for this.
            //If we load other formats later we might should abstract this even further (to a synthesizer job)
            //It can't really be abstracted from cue files though due to the necessity of merging this with other track 1 pregaps
            CUE.CueTrackType pregapTrackType = CUE.CueTrackType.Audio;
            if (tocSynth.Result.TOCItems[1].IsData)
            {
                if (tocSynth.Result.Session1Format == SessionFormat.Type20_CDXA)
                {
                    pregapTrackType = CUE.CueTrackType.Mode2_2352;
                }
                else if (tocSynth.Result.Session1Format == SessionFormat.Type10_CDI)
                {
                    pregapTrackType = CUE.CueTrackType.CDI_2352;
                }
                else if (tocSynth.Result.Session1Format == SessionFormat.Type00_CDROM_CDDA)
                {
                    pregapTrackType = CUE.CueTrackType.Mode1_2352;
                }
            }
            for (int i = 0; i < 150; i++)
            {
                var ss_gap = new CUE.SS_Gap()
                {
                    Policy    = IN_DiscMountPolicy,
                    TrackType = pregapTrackType
                };
                disc._Sectors.Add(ss_gap);

                int qRelMSF = i - 150;

                //tweak relMSF due to ambiguity/contradiction in yellowbook docs
                if (!IN_DiscMountPolicy.CUE_PregapContradictionModeA)
                {
                    qRelMSF++;
                }

                //setup subQ
                byte ADR = 1; //absent some kind of policy for how to set it, this is a safe assumption:
                ss_gap.sq.SetStatus(ADR, tocSynth.Result.TOCItems[1].Control);
                ss_gap.sq.q_tno        = BCD2.FromDecimal(1);
                ss_gap.sq.q_index      = BCD2.FromDecimal(0);
                ss_gap.sq.AP_Timestamp = i;
                ss_gap.sq.Timestamp    = qRelMSF;

                //setup subP
                ss_gap.Pause = true;
            }

            //build the sectors:
            //set up as many sectors as we have img/sub for, even if the TOC doesnt reference them
            //(the TOC is unreliable, and the Track records are redundant)
            for (int i = 0; i < NumImgSectors; i++)
            {
                disc._Sectors.Add(synth);
            }

            return(disc);
        }