Ejemplo n.º 1
0
        public Yabause(CoreComm CoreComm, DiscSystem.Disc CD, object syncSettings)
        {
            ServiceProvider = new BasicServiceProvider(this);
            byte[] bios = CoreComm.CoreFileProvider.GetFirmware("SAT", "J", true, "Saturn BIOS is required.");
            CoreComm.RomStatusDetails = string.Format("Disk partial hash:{0}", new DiscSystem.DiscHasher(CD).OldHash());
            this.CoreComm             = CoreComm;
            this.CD          = CD;
            DiscSectorReader = new DiscSystem.DiscSectorReader(CD);

            SyncSettings = (SaturnSyncSettings)syncSettings ?? new SaturnSyncSettings();

            if (this.SyncSettings.UseGL && glContext == null)
            {
                glContext = CoreComm.RequestGLContext(2, 0, false);
            }

            ResetCounters();

            ActivateGL();
            Init(bios);

            InputCallbackH = new LibYabause.InputCallback(() => InputCallbacks.Call());
            LibYabause.libyabause_setinputcallback(InputCallbackH);
            ConnectTracer();
            DriveLightEnabled = true;

            DeactivateGL();
        }
Ejemplo n.º 2
0
        public DobieStation(CoreLoadParameters <object, DobieSyncSettings> lp)
            : base(lp.Comm, new Configuration
        {
            MaxWidth              = 640,
            MaxHeight             = 480,
            DefaultWidth          = 640,
            DefaultHeight         = 480,
            DefaultFpsNumerator   = 294912000,
            DefaultFpsDenominator = 4920115,
            MaxSamples            = 1024,
            SystemId              = "PS2"
        })
        {
            if (lp.Discs.Count != 1)
            {
                throw new InvalidOperationException("Must load a CD or DVD with PS2 core!");
            }
            ControllerDefinition = DualShock;
            _syncSettings        = lp.SyncSettings ?? new DobieSyncSettings();
            _syncSettingsActual  = lp.SyncSettings ?? new DobieSyncSettings();

            _disc       = new DiscSectorReader(lp.Discs[0].DiscData);
            _cdCallback = ReadCd;
            _core       = PreInit <LibDobieStation>(new WaterboxOptions
            {
                Filename                   = "dobie.wbx",
                SbrkHeapSizeKB             = 64 * 1024,
                SealedHeapSizeKB           = 4 * 1024,
                InvisibleHeapSizeKB        = 4 * 1024,
                PlainHeapSizeKB            = 256,
                MmapHeapSizeKB             = 2 * 1024 * 1024,
                SkipCoreConsistencyCheck   = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck),
                SkipMemoryConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck),
            }, new[] { _cdCallback });

            var bios = lp.Comm.CoreFileProvider.GetFirmware("PS2", "BIOS", true);

            _exe.AddReadonlyFile(new byte[0x840000], "MEMCARD0");

            var worked = _core.Initialize(bios,
                                          (ulong)(lp.Discs[0].DiscData.Session1.Tracks[2].LBA - lp.Discs[0].DiscData.Session1.Tracks[1].LBA) * 2048,
                                          _cdCallback,
                                          _syncSettingsActual.GetNativeSettings()
                                          );

            if (!worked)
            {
                throw new InvalidOperationException("Initialize failed!");
            }

            _exe.RemoveReadonlyFile("MEMCARD0");

            PostInit();

            _resampler = new SpeexResampler((SpeexResampler.Quality) 6, 480, 441, 48000, 44100, null, this);
            _serviceProvider.Register <ISoundProvider>(_resampler);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// applies an SBI file to the disc
        /// </summary>
        public void Run(Disc disc, SBI.SubQPatchData sbi, bool asMednafen)
        {
            //TODO - could implement as a blob, to avoid allocating so many byte buffers

            //save this, it's small, and we'll want it for disc processing a/b checks
            disc.Memos["sbi"] = sbi;

            DiscSectorReader dsr = new DiscSectorReader(disc);

            int n = sbi.ABAs.Count;
            int b = 0;

            for (int i = 0; i < n; i++)
            {
                int lba = sbi.ABAs[i] - 150;

                //create a synthesizer which can return the patched data
                var ss_patchq = new SS_PatchQ {
                    Original = disc._Sectors[lba + 150]
                };
                byte[] subQbuf = ss_patchq.Buffer_SubQ;

                //read the old subcode
                dsr.ReadLBA_SubQ(lba, subQbuf, 0);

                //insert patch
                disc._Sectors[lba + 150] = ss_patchq;

                //apply SBI patch
                for (int j = 0; j < 12; j++)
                {
                    short patch = sbi.subq[b++];
                    if (patch == -1)
                    {
                        continue;
                    }
                    else
                    {
                        subQbuf[j] = (byte)patch;
                    }
                }

                //Apply mednafen hacks
                //The reasoning here is that we know we expect these sectors to have a wrong checksum. therefore, generate a checksum, and make it wrong
                //However, this seems senseless to me. The whole point of the SBI data is that it stores the patches needed to generate an acceptable subQ, right?
                if (asMednafen)
                {
                    SynthUtils.SubQ_SynthChecksum(subQbuf, 0);
                    subQbuf[10] ^= 0xFF;
                    subQbuf[11] ^= 0xFF;
                }
            }
        }
Ejemplo n.º 4
0
        public static void Extract(Disc disc, string path, string fileBase)
        {
            var dsr = new DiscSectorReader(disc);

            bool confirmed = false;
            var  tracks    = disc.Session1.Tracks;

            foreach (var track in tracks)
            {
                if (!track.IsAudio)
                {
                    continue;
                }

                int trackLength = track.NextTrack.LBA - track.LBA;
                var waveData    = new byte[trackLength * 2352];
                int startLba    = track.LBA;
                for (int sector = 0; sector < trackLength; sector++)
                {
                    dsr.ReadLBA_2352(startLba + sector, waveData, sector * 2352);
                }

                string mp3Path = $"{Path.Combine(path, fileBase)} - Track {track.Number:D2}.mp3";
                if (File.Exists(mp3Path))
                {
                    if (!confirmed)
                    {
                        var dr = MessageBox.Show("This file already exists. Do you want extraction to proceed overwriting files, or cancel the entire operation immediately?", "File already exists", MessageBoxButtons.OKCancel);
                        if (dr == DialogResult.Cancel)
                        {
                            return;
                        }
                        confirmed = true;
                    }

                    File.Delete(mp3Path);
                }

                string tempfile = Path.GetTempFileName();

                try
                {
                    File.WriteAllBytes(tempfile, waveData);
                    var ffmpeg = new FFmpegService();
                    ffmpeg.Run("-f", "s16le", "-ar", "44100", "-ac", "2", "-i", tempfile, "-f", "mp3", "-ab", "192k", mp3Path);
                }
                finally
                {
                    File.Delete(tempfile);
                }
            }
        }
Ejemplo n.º 5
0
        public void Think()
        {
            if (RST)
            {
                ResetDevice();
                return;
            }

            if (DataReadInProgress && pce.Cpu.TotalExecutedCycles > DataReadWaitTimer)
            {
                if (SectorsLeftToRead > 0)
                {
                    pce.DriveLightOn = true;
                }

                if (DataIn.Count == 0)
                {
                    // read in a sector and shove it in the queue
                    DiscSystem.DiscSectorReader dsr = new DiscSectorReader(disc);                     //TODO - cache reader
                    dsr.ReadLBA_2048(CurrentReadingSector, DataIn.GetBuffer(), 0);
                    DataIn.SignalBufferFilled(2048);
                    CurrentReadingSector++;
                    SectorsLeftToRead--;

                    pce.IntDataTransferReady = true;

                    // If more sectors, should set the next think-clock to however long it takes to read 1 sector
                    // but I dont. I dont think transfers actually happen sector by sector
                    // like this, they probably become available as the bits come off the disc.
                    // but lets get some basic functionality before we go crazy.
                    //  Idunno, maybe they do come in a sector at a time.

                    //note to vecna: maybe not at the sector level, but at a level > 1 sample and <= 1 sector, samples come out in blocks
                    //due to the way they are jumbled up (seriously, like put into a blender) for error correction purposes.
                    //we may as well assume that the cd audio decoding magic works at the level of one sector, but it isnt one sample.

                    if (SectorsLeftToRead == 0)
                    {
                        DataReadInProgress  = false;
                        DataTransferWasDone = true;
                    }
                    SetPhase(BusPhase_DataIn);
                }
            }

            do
            {
                signalsChanged  = false;
                busPhaseChanged = false;

                if (SEL && !BSY)
                {
                    SetPhase(BusPhase_Command);
                }
                else if (ATN && !REQ && !ACK)
                {
                    SetPhase(BusPhase_MessageOut);
                }
                else
                {
                    switch (Phase)
                    {
                    case BusPhase_Command: ThinkCommandPhase(); break;

                    case BusPhase_DataIn: ThinkDataInPhase(); break;

                    case BusPhase_DataOut: ThinkDataOutPhase(); break;

                    case BusPhase_MessageIn: ThinkMessageInPhase(); break;

                    case BusPhase_MessageOut: ThinkMessageOutPhase(); break;

                    case BusPhase_Status: ThinkStatusPhase(); break;

                    default: break;
                    }
                }
            } while (signalsChanged || busPhaseChanged);
        }
Ejemplo n.º 6
0
 public ScsiCDBus(PCEngine pce, Disc disc)
 {
     this.pce         = pce;
     this.disc        = disc;
     DiscSectorReader = new DiscSectorReader(disc);
 }
Ejemplo n.º 7
0
        }         //Run()

        private static bool CompareFile(string infile, DiscInterface loadDiscInterface, DiscInterface cmpif, bool verbose, CancellationTokenSource cancelToken, StringWriter sw)
        {
            Disc srcDisc = null, dstDisc = null;

            try
            {
                bool success = false;

                sw.WriteLine("BEGIN COMPARE: {0}\nSRC {1} vs DST {2}", infile, loadDiscInterface, cmpif);

                //reload the original disc, with new policies as needed
                var dmj = new DiscMountJob
                {
                    IN_DiscInterface   = loadDiscInterface,
                    IN_DiscMountPolicy = new DiscMountPolicy {
                        CUE_PregapContradictionModeA = cmpif != DiscInterface.MednaDisc
                    },
                    IN_FromPath = infile
                };

                dmj.Run();

                srcDisc = dmj.OUT_Disc;

                var dstDmj = new DiscMountJob {
                    IN_DiscInterface = cmpif, IN_FromPath = infile
                };
                dstDmj.Run();
                dstDisc = dstDmj.OUT_Disc;

                var srcDsr = new DiscSectorReader(srcDisc);
                var dstDsr = new DiscSectorReader(dstDisc);

                var srcToc = srcDisc.TOC;
                var dstToc = dstDisc.TOC;

                var srcDataBuf = new byte[2448];
                var dstDataBuf = new byte[2448];

                void SwDumpTocOne(DiscTOC.TOCItem item)
                {
                    if (!item.Exists)
                    {
                        sw.Write("(---missing---)");
                    }
                    else
                    {
                        sw.Write("({0:X2} - {1})", (byte)item.Control, item.LBA);
                    }
                }

                void SwDumpToc(int index)
                {
                    sw.Write("SRC TOC#{0,3} ", index);
                    SwDumpTocOne(srcToc.TOCItems[index]);
                    sw.WriteLine();
                    sw.Write("DST TOC#{0,3} ", index);
                    SwDumpTocOne(dstToc.TOCItems[index]);
                    sw.WriteLine();
                }

                //verify sector count
                if (srcDisc.Session1.LeadoutLBA != dstDisc.Session1.LeadoutLBA)
                {
                    sw.Write("LeadoutTrack.LBA {0} vs {1}\n", srcDisc.Session1.LeadoutTrack.LBA, dstDisc.Session1.LeadoutTrack.LBA);
                    goto SKIPPO;
                }

                //verify TOC match
                if (srcDisc.TOC.FirstRecordedTrackNumber != dstDisc.TOC.FirstRecordedTrackNumber ||
                    srcDisc.TOC.LastRecordedTrackNumber != dstDisc.TOC.LastRecordedTrackNumber)
                {
                    sw.WriteLine("Mismatch of RecordedTrackNumbers: {0}-{1} vs {2}-{3}",
                                 srcDisc.TOC.FirstRecordedTrackNumber, srcDisc.TOC.LastRecordedTrackNumber,
                                 dstDisc.TOC.FirstRecordedTrackNumber, dstDisc.TOC.LastRecordedTrackNumber
                                 );
                    goto SKIPPO;
                }

                bool badToc = false;
                for (int t = 0; t < 101; t++)
                {
                    if (srcToc.TOCItems[t].Exists != dstToc.TOCItems[t].Exists ||
                        srcToc.TOCItems[t].Control != dstToc.TOCItems[t].Control ||
                        srcToc.TOCItems[t].LBA != dstToc.TOCItems[t].LBA
                        )
                    {
                        sw.WriteLine("Mismatch in TOCItem");
                        SwDumpToc(t);
                        badToc = true;
                    }
                }
                if (badToc)
                {
                    goto SKIPPO;
                }

                void SwDumpChunkOne(string comment, int lba, byte[] buf, int addr, int count)
                {
                    sw.Write("{0} -  ", comment);
                    for (int i = 0; i < count; i++)
                    {
                        if (i + addr >= buf.Length)
                        {
                            continue;
                        }
                        sw.Write("{0:X2}{1}", buf[addr + i], (i == count - 1) ? " " : "  ");
                    }

                    sw.WriteLine();
                }

                int[] offenders = new int[12];

                void SwDumpChunk(int lba, int dispAddr, int addr, int count, int numOffenders)
                {
                    var hashedOffenders = new HashSet <int>();

                    for (int i = 0; i < numOffenders; i++)
                    {
                        hashedOffenders.Add(offenders[i]);
                    }

                    sw.Write("                          ");
                    for (int i = 0; i < count; i++)
                    {
                        sw.Write((hashedOffenders.Contains(dispAddr + i)) ? "vvv " : "    ");
                    }

                    sw.WriteLine();
                    sw.Write("                          ");
                    for (int i = 0; i < count; i++)
                    {
                        sw.Write("{0:X3} ", dispAddr + i, (i == count - 1) ? " " : "  ");
                    }

                    sw.WriteLine();
                    sw.Write("                          ");
                    sw.Write(new string('-', count * 4));
                    sw.WriteLine();
                    SwDumpChunkOne($"SRC #{lba,6} ({new Timestamp(lba)})", lba, srcDataBuf, addr, count);
                    SwDumpChunkOne($"DST #{lba,6} ({new Timestamp(lba)})", lba, dstDataBuf, addr, count);
                }

                //verify each sector contents
                int nSectors = srcDisc.Session1.LeadoutLBA;
                for (int lba = -150; lba < nSectors; lba++)
                {
                    if (verbose)
                    {
                        if (lba % 1000 == 0)
                        {
                            Console.WriteLine("LBA {0} of {1}", lba, nSectors);
                        }
                    }

                    if (cancelToken != null)
                    {
                        if (cancelToken.Token.IsCancellationRequested)
                        {
                            return(false);
                        }
                    }

                    srcDsr.ReadLBA_2448(lba, srcDataBuf, 0);
                    dstDsr.ReadLBA_2448(lba, dstDataBuf, 0);

                    //check the header
                    for (int b = 0; b < 16; b++)
                    {
                        if (srcDataBuf[b] != dstDataBuf[b])
                        {
                            sw.WriteLine("Mismatch in sector header at byte {0}", b);
                            offenders[0] = b;
                            SwDumpChunk(lba, 0, 0, 16, 1);
                            goto SKIPPO;
                        }
                    }

                    // check userData
                    for (int b = 16; b < 2352; b++)
                    {
                        if (srcDataBuf[b] != dstDataBuf[b])
                        {
                            sw.Write("LBA {0} mismatch at userdata byte {1}; terminating sector cmp\n", lba, b);
                            goto SKIPPO;
                        }
                    }

                    // check subChannels
                    for (int c = 0, b = 2352; c < 8; c++)
                    {
                        int numOffenders = 0;
                        for (int e = 0; e < 12; e++, b++)
                        {
                            if (srcDataBuf[b] != dstDataBuf[b])
                            {
                                offenders[numOffenders++] = e;
                            }
                        }

                        if (numOffenders != 0)
                        {
                            sw.Write("LBA {0} mismatch(es) at subchannel {1}; terminating sector cmp\n", lba, (char)('P' + c));
                            SwDumpChunk(lba, 0, 2352 + c * 12, 12, numOffenders);
                            goto SKIPPO;
                        }
                    }
                }

                success = true;

SKIPPO:
                sw.WriteLine("END COMPARE");
                sw.WriteLine("-----------------------------");

                return(success);
            }
            finally
            {
                srcDisc?.Dispose();
                dstDisc?.Dispose();
            }
        } //CompareFile
Ejemplo n.º 8
0
        private PicoDrive(CoreComm comm, GameInfo game, byte[] rom, Disc cd, bool deterministic, SyncSettings syncSettings)
            : base(comm, new Configuration
        {
            MaxSamples    = 2048,
            DefaultWidth  = 320,
            DefaultHeight = 224,
            MaxWidth      = 320,
            MaxHeight     = 480,
            SystemId      = "GEN"
        })
        {
            var biosg      = comm.CoreFileProvider.GetFirmware("32X", "G", false);
            var biosm      = comm.CoreFileProvider.GetFirmware("32X", "M", false);
            var bioss      = comm.CoreFileProvider.GetFirmware("32X", "S", false);
            var has32xBios = biosg != null && biosm != null && bioss != null;

            if (deterministic && !has32xBios)
            {
                throw new InvalidOperationException("32X BIOS files are required for deterministic mode");
            }
            deterministic |= has32xBios;

            _syncSettings = syncSettings ?? new SyncSettings();

            _core = PreInit <LibPicoDrive>(new PeRunnerOptions
            {
                Filename            = "picodrive.wbx",
                SbrkHeapSizeKB      = 64,
                SealedHeapSizeKB    = 18 * 1024,
                InvisibleHeapSizeKB = 1024,
                MmapHeapSizeKB      = 4096,
                PlainHeapSizeKB     = 64,
            });

            if (has32xBios)
            {
                _exe.AddReadonlyFile(biosg, "32x.g");
                _exe.AddReadonlyFile(biosm, "32x.m");
                _exe.AddReadonlyFile(bioss, "32x.s");
                Console.WriteLine("Using supplied 32x BIOS files");
            }
            if (cd != null)
            {
                _exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_EU", true), "cd.eu");
                _exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_US", true), "cd.us");
                _exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_JP", true), "cd.jp");
                _exe.AddReadonlyFile(gpgx.GPGX.GetCDData(cd), "toc");
                _cd         = cd;
                _cdReader   = new DiscSectorReader(_cd);
                _cdcallback = CDRead;
                _core.SetCDReadCallback(_cdcallback);
                DriveLightEnabled = true;
            }
            else
            {
                _exe.AddReadonlyFile(rom, "romfile.md");
            }

            var regionAutoOrder = (LibPicoDrive.Region)(
                (int)_syncSettings.FirstChoice |
                (int)_syncSettings.SecondChoice << 4 |
                    (int)_syncSettings.ThirdChoice << 8);

            if (!_core.Init(cd != null, game["32X"], regionAutoOrder, _syncSettings.RegionOverride))
            {
                throw new InvalidOperationException("Core rejected the file!");
            }

            if (cd != null)
            {
                _exe.RemoveReadonlyFile("cd.eu");
                _exe.RemoveReadonlyFile("cd.us");
                _exe.RemoveReadonlyFile("cd.jp");
                _exe.RemoveReadonlyFile("toc");
                _core.SetCDReadCallback(null);
            }
            else
            {
                _exe.RemoveReadonlyFile("romfile.md");
            }
            if (has32xBios)
            {
                _exe.RemoveReadonlyFile("32x.g");
                _exe.RemoveReadonlyFile("32x.m");
                _exe.RemoveReadonlyFile("32x.s");
            }

            PostInit();
            ControllerDefinition   = PicoDriveController;
            DeterministicEmulation = deterministic;
            _core.SetCDReadCallback(_cdcallback);

            _isPal           = _core.IsPal();
            VsyncNumerator   = _isPal ? 53203424 : 53693175;
            VsyncDenominator = _isPal ? 3420 * 313 : 3420 * 262;
        }
Ejemplo n.º 9
0
 public CDAudio(Disc disc, int maxVolume = short.MaxValue)
 {
     Disc             = disc;
     DiscSectorReader = new DiscSectorReader(disc);
     MaxVolume        = maxVolume;
 }
        public void Run()
        {
            var dsr = new DiscSectorReader(IN_Disc);

            dsr.Policy.DeterministicClearBuffer = false;

            Result = new DiscStructure();
            var session = new DiscStructure.Session();

            Result.Sessions.Add(null); //placeholder session for reindexing
            Result.Sessions.Add(session);

            session.Number = 1;

            //if (TOCRaw.FirstRecordedTrackNumber != 1)
            //throw new InvalidOperationException("Unsupported: FirstRecordedTrackNumber != 1");

            //add a lead-in track
            session.Tracks.Add(new DiscStructure.Track()
            {
                Number  = 0,
                Control = EControlQ.None,                   //we'll set this later
                LBA     = -new Timestamp(99, 99, 99).Sector //obvious garbage
            });

            int ntracks = TOCRaw.LastRecordedTrackNumber - TOCRaw.FirstRecordedTrackNumber + 1;

            for (int i = 0; i < ntracks; i++)
            {
                var item  = TOCRaw.TOCItems[i + 1];
                var track = new DiscStructure.Track()
                {
                    Number  = i + 1,
                    Control = item.Control,
                    LBA     = item.LBA
                };
                session.Tracks.Add(track);

                if (!item.IsData)
                {
                    track.Mode = 0;
                }
                else
                {
                    //determine the mode by a hardcoded heuristic: check mode of first sector
                    track.Mode = dsr.ReadLBA_Mode(track.LBA);
                }

                //determine track length according to... how? It isn't clear.
                //Let's not do this until it's needed.
                //if (i == ntracks - 1)
                //  track.Length = TOCRaw.LeadoutLBA.Sector - track.LBA;
                //else track.Length = (TOCRaw.TOCItems[i + 2].LBATimestamp.Sector - track.LBA);
            }

            //add lead-out track
            session.Tracks.Add(new DiscStructure.Track()
            {
                Number = 0xA0, //right?
                               //kind of a guess, but not completely
                Control = session.Tracks[session.Tracks.Count - 1].Control,
                Mode    = session.Tracks[session.Tracks.Count - 1].Mode,
                LBA     = TOCRaw.LeadoutLBA
            });

            //link track list
            for (int i = 0; i < session.Tracks.Count - 1; i++)
            {
                session.Tracks[i].NextTrack = session.Tracks[i + 1];
            }

            //fix lead-in track type
            //guesses:
            session.Tracks[0].Control = session.Tracks[1].Control;
            session.Tracks[0].Mode    = session.Tracks[1].Mode;
        }
Ejemplo n.º 11
0
        public static void Extract(Disc disc, string path, string fileBase, Func <bool?> getOverwritePolicy)
        {
            var dsr = new DiscSectorReader(disc);

            var  shouldHalt        = false;
            bool?overwriteExisting = null;              // true = overwrite, false = skip existing, null = unset

            var tracks = disc.Session1.Tracks;

            Parallel.ForEach(tracks, track =>
            {
                if (shouldHalt)
                {
                    return;
                }

                if (!track.IsAudio)
                {
                    return;
                }

                if (track.NextTrack == null)
                {
                    return;
                }

                int trackLength = track.NextTrack.LBA - track.LBA;
                var waveData    = new byte[trackLength * 2352];
                int startLba    = track.LBA;
                lock (disc)
                    for (int sector = 0; sector < trackLength; sector++)
                    {
                        dsr.ReadLBA_2352(startLba + sector, waveData, sector * 2352);
                    }

                string mp3Path = $"{Path.Combine(path, fileBase)} - Track {track.Number:D2}.mp3";
                if (File.Exists(mp3Path))
                {
                    overwriteExisting ??= getOverwritePolicy();
                    switch (overwriteExisting)
                    {
                    case true:                             // "Yes" -- overwrite
                        File.Delete(mp3Path);
                        break;

                    case false:                             // "No" -- skip
                        return;

                    case null:                             // "Cancel" -- halt
                        shouldHalt = true;
                        return;
                    }
                }

                string tempfile = Path.GetTempFileName();

                try
                {
                    File.WriteAllBytes(tempfile, waveData);
                    FFmpegService.Run("-f", "s16le", "-ar", "44100", "-ac", "2", "-i", tempfile, "-f", "mp3", "-ab", "192k", mp3Path);
                }
                finally
                {
                    File.Delete(tempfile);
                }
            });
        }
Ejemplo n.º 12
0
        public static void Dump(Disc disc, string path)
        {
            using (var sw = new StreamWriter(path))
            {
                //NOTE: IsoBuster requires the A0,A1,A2 RawTocEntries to be first or else it can't do anything with the tracks
                //if we ever get them in a different order, we'll have to re-order them here

                sw.WriteLine("[CloneCD]");
                sw.WriteLine("Version=3");
                sw.WriteLine();
                sw.WriteLine("[Disc]");
                sw.WriteLine("TocEntries={0}", disc.RawTOCEntries.Count);
                sw.WriteLine("Sessions=1");
                sw.WriteLine("DataTracksScrambled=0");
                sw.WriteLine("CDTextLength=0"); //not supported anyway
                sw.WriteLine();
                sw.WriteLine("[Session 1]");
                sw.WriteLine("PreGapMode=2");
                sw.WriteLine("PreGapSubC=1");
                sw.WriteLine();
                for (int i = 0; i < disc.RawTOCEntries.Count; i++)
                {
                    var entry = disc.RawTOCEntries[i];

                    //ehhh something's wrong with how I track these
                    int point = entry.QData.q_index.DecimalValue;
                    if (point == 100)
                    {
                        point = 0xA0;
                    }
                    if (point == 101)
                    {
                        point = 0xA1;
                    }
                    if (point == 102)
                    {
                        point = 0xA2;
                    }

                    sw.WriteLine("[Entry {0}]", i);
                    sw.WriteLine("Session=1");
                    sw.WriteLine("Point=0x{0:x2}", point);
                    sw.WriteLine("ADR=0x{0:x2}", entry.QData.ADR);
                    sw.WriteLine("Control=0x{0:x2}", (int)entry.QData.CONTROL);
                    sw.WriteLine("TrackNo={0}", entry.QData.q_tno.DecimalValue);
                    sw.WriteLine("AMin={0}", entry.QData.min.DecimalValue);
                    sw.WriteLine("ASec={0}", entry.QData.sec.DecimalValue);
                    sw.WriteLine("AFrame={0}", entry.QData.frame.DecimalValue);
                    sw.WriteLine("ALBA={0}", entry.QData.Timestamp - 150); //remember to adapt the absolute MSF to an LBA (this field is redundant...)
                    sw.WriteLine("Zero={0}", entry.QData.zero);
                    sw.WriteLine("PMin={0}", entry.QData.ap_min.DecimalValue);
                    sw.WriteLine("PSec={0}", entry.QData.ap_sec.DecimalValue);
                    sw.WriteLine("PFrame={0}", entry.QData.ap_frame.DecimalValue);
                    sw.WriteLine("PLBA={0}", entry.QData.AP_Timestamp - 150); //remember to adapt the absolute MSF to an LBA (this field is redundant...)
                    sw.WriteLine();
                }

                //this is nonsense, really. the whole CCD track list shouldn't be needed.
                //but in order to make a high quality CCD which can be inspected by various other tools, we need it
                //now, regarding the indexes.. theyre truly useless. having indexes written out with the tracks is bad news.
                //index information is only truly stored in subQ
                for (int tnum = 1; tnum <= disc.Session1.LastInformationTrack.Number; tnum++)
                {
                    var track = disc.Session1.Tracks[tnum];
                    sw.WriteLine("[TRACK {0}]", track.Number);
                    sw.WriteLine("MODE={0}", track.Mode);
                    //indexes are BS, dont write them. but we certainly need an index 1
                    sw.WriteLine("INDEX 1={0}", track.LBA);
                    sw.WriteLine();
                }
            }

            //TODO - actually re-add
            //dump the img and sub
            //TODO - acquire disk size first
            string           imgPath = Path.ChangeExtension(path, ".img");
            string           subPath = Path.ChangeExtension(path, ".sub");
            var              buf2448 = new byte[2448];
            DiscSectorReader dsr     = new DiscSectorReader(disc);

            using (var imgFile = File.OpenWrite(imgPath))
                using (var subFile = File.OpenWrite(subPath))
                {
                    int nLBA = disc.Session1.LeadoutLBA;
                    for (int lba = 0; lba < nLBA; lba++)
                    {
                        dsr.ReadLBA_2448(lba, buf2448, 0);
                        imgFile.Write(buf2448, 0, 2352);
                        subFile.Write(buf2448, 2352, 96);
                    }
                }
        }