Example #1
0
        /// <summary>
        /// Automagically loads a disc, without any fine-tuned control at all
        /// </summary>
        public static Disc LoadAutomagic(string path)
        {
            var job = new DiscMountJob(fromPath: path /*, discInterface: DiscInterface.MednaDisc <-- TEST*/);

            job.Run();
            return(job.OUT_Disc);
        }
Example #2
0
        private static Disc CreateImpl(DiscType?type, string path, Action <string> errorCallback)
        {
            //--- load the disc in a context which will let us abort if it's going to take too long
            var discMountJob = new DiscMountJob(fromPath: path, slowLoadAbortThreshold: 8);

            discMountJob.Run();
            var disc = discMountJob.OUT_Disc ?? throw new InvalidOperationException($"Can't find the file specified: {path}");

            if (discMountJob.OUT_SlowLoadAborted)
            {
                errorCallback("This disc would take too long to load. Run it through DiscoHawk first, or find a new rip because this one is probably junk");
                return(null);
            }

            if (discMountJob.OUT_ErrorLevel)
            {
                throw new InvalidOperationException($"\r\n{discMountJob.OUT_Log}");
            }

            var discType = new DiscIdentifier(disc).DetectDiscType();

            if (type.HasValue && discType != type)
            {
                errorCallback($"Not a {type} disc");
                return(null);
            }

            return(disc);
        }
Example #3
0
		/// <summary>
		/// Automagically loads a disc, without any fine-tuned control at all
		/// </summary>
		public static Disc LoadAutomagic(string path)
		{
			var job = new DiscMountJob { IN_FromPath = path };
			//job.IN_DiscInterface = DiscInterface.MednaDisc; //TEST
			job.Run();
			return job.OUT_Disc;
		}
Example #4
0
		private void lblMagicDragArea_DragDrop(object sender, DragEventArgs e)
		{
			List<string> files = validateDrop(e.Data);
			if (files.Count == 0) return;
			try
			{
				this.Cursor = Cursors.WaitCursor;
				foreach (var file in files)
				{
					var job = new DiscMountJob { IN_FromPath = file };
					job.Run();
					var disc = job.OUT_Disc;
					if (job.OUT_ErrorLevel)
					{
						System.Windows.Forms.MessageBox.Show(job.OUT_Log, "Error loading disc");
						break;
					}

					string baseName = Path.GetFileNameWithoutExtension(file);
					baseName += "_hawked";
					string outfile = Path.Combine(Path.GetDirectoryName(file), baseName) + ".ccd";
					CCD_Format.Dump(disc, outfile);
				}
				this.Cursor = Cursors.Default;
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.ToString(), "Error loading disc");
				throw;
			}
		}
Example #5
0
        /// <summary>
        /// Automagically loads a disc, without any fine-tuned control at all
        /// </summary>
        public static Disc LoadAutomagic(string path)
        {
            var job = new DiscMountJob {
                IN_FromPath = path
            };

            //job.IN_DiscInterface = DiscInterface.MednaDisc; //TEST
            job.Run();
            return(job.OUT_Disc);
        }
        public static void RunWithArgs(string[] args, Action <string> showComparisonResultsCallback)
        {
            bool   scanCues              = false;
            string dirArg                = null;
            string infile                = null;
            var    loadDiscInterface     = DiscInterface.BizHawk;
            var    compareDiscInterfaces = new List <DiscInterface>();
            bool   hawk = false;

            int idx = 0;

            while (idx < args.Length)
            {
                string a  = args[idx++];
                string au = a.ToUpperInvariant();
                if (au == "LOAD")
                {
                    loadDiscInterface = (DiscInterface)Enum.Parse(typeof(DiscInterface), args[idx++], true);
                }
                else if (au == "COMPARE")
                {
                    compareDiscInterfaces.Add((DiscInterface)Enum.Parse(typeof(DiscInterface), args[idx++], true));
                }
                else if (au == "HAWK")
                {
                    hawk = true;
                }
                else if (au == "CUEDIR")
                {
                    dirArg   = args[idx++];
                    scanCues = true;
                }
                else
                {
                    infile = a;
                }
            }

            if (hawk)
            {
                if (infile == null)
                {
                    return;
                }

                // TODO - write it out
                var dmj = new DiscMountJob(fromPath: infile, discInterface: loadDiscInterface);
                dmj.Run();
            }

            bool verbose = true;

            if (scanCues)
            {
                verbose = false;
                var todo = FindCuesRecurse(dirArg);
                var po   = new ParallelOptions();
                var cts  = new CancellationTokenSource();
                po.CancellationToken      = cts.Token;
                po.MaxDegreeOfParallelism = 1;
                if (po.MaxDegreeOfParallelism < 0)
                {
                    po.MaxDegreeOfParallelism = 1;
                }
                object olock   = new object();
                int    ctr     = 0;
                bool   blocked = false;
                try
                {
                    Parallel.ForEach(todo, po, (fp) =>
                    {
                        lock (olock)
                        {
                            ctr++;
                            int strlen = todo.Count.ToString().Length;
                            string fmt = string.Format("{{0,{0}}}/{{1,{0}}} {{2}}", strlen);
                            Console.WriteLine(fmt, ctr, todo.Count, Path.GetFileNameWithoutExtension(fp));
                        }

                        if (!blocked)
                        {
                            foreach (var cmpif in compareDiscInterfaces)
                            {
                                var sw       = new StringWriter();
                                bool success = CompareFile(fp, loadDiscInterface, cmpif, verbose, cts, sw);
                                if (!success)
                                {
                                    lock (Console.Out)
                                        Console.Out.Write(sw.ToString());

                                    cts.Cancel();
                                    return;
                                }
                            }
                        }
                    });
                }
                catch (AggregateException ae) {
                    Console.WriteLine(ae.ToString());
                }
                catch (OperationCanceledException oce)
                {
                    Console.WriteLine(oce.ToString());
                }
                Console.WriteLine("--TERMINATED--");
                return;
            }

            if (compareDiscInterfaces.Count != 0)
            {
                var sw = new StringWriter();
                foreach (var cmpif in compareDiscInterfaces)
                {
                    CompareFile(infile, loadDiscInterface, cmpif, verbose, null, sw);
                }

                sw.Flush();
                string results = sw.ToString();
                showComparisonResultsCallback(results);
            }
        }
        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(
                    fromPath: infile,
                    discMountPolicy: new DiscMountPolicy {
                    CUE_PregapContradictionModeA = cmpif != DiscInterface.MednaDisc
                },
                    discInterface: loadDiscInterface);
                dmj.Run();
                srcDisc = dmj.OUT_Disc;

                var dstDmj = new DiscMountJob(fromPath: infile, discInterface: cmpif);
                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();
            }
        }
Example #8
0
        static bool CompareFile(string infile, DiscInterface loadDiscInterface, DiscInterface cmpif, bool verbose, CancellationTokenSource cancelToken, StringWriter sw)
        {
            Disc src_disc = null, dst_disc = 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_FromPath = infile };
                if (cmpif == DiscInterface.MednaDisc)
                {
                    dmj.IN_DiscMountPolicy.CUE_PregapContradictionModeA = false;
                }
                dmj.Run();

                src_disc = dmj.OUT_Disc;

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

                var src_dsr = new DiscSectorReader(src_disc);
                var dst_dsr = new DiscSectorReader(dst_disc);

                var src_toc = src_disc.TOC;
                var dst_toc = dst_disc.TOC;

                var src_databuf = new byte[2448];
                var dst_databuf = new byte[2448];

                Action<DiscTOC.TOCItem> sw_dump_toc_one = (item) =>
                {
                    if (!item.Exists)
                        sw.Write("(---missing---)");
                    else
                        sw.Write("({0:X2} - {1})", (byte)item.Control, item.LBA);
                };

                Action<int> sw_dump_toc = (index) =>
                {
                    sw.Write("SRC TOC#{0,3} ", index); sw_dump_toc_one(src_toc.TOCItems[index]); sw.WriteLine();
                    sw.Write("DST TOC#{0,3} ", index); sw_dump_toc_one(dst_toc.TOCItems[index]); sw.WriteLine();
                };

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

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

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

                Action<string, int, byte[], int, int> sw_dump_chunk_one = (comment, lba, buf, addr, 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];
                Action<int, int, int, int, int> sw_dump_chunk = (lba, dispaddr, addr, count, 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();
                    sw_dump_chunk_one(string.Format("SRC #{0,6} ({1})", lba, new Timestamp(lba)), lba, src_databuf, addr, count);
                    sw_dump_chunk_one(string.Format("DST #{0,6} ({1})", lba, new Timestamp(lba)), lba, dst_databuf, addr, count);
                };

                //verify each sector contents
                int nSectors = src_disc.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;

                    src_dsr.ReadLBA_2448(lba, src_databuf, 0);
                    dst_dsr.ReadLBA_2448(lba, dst_databuf, 0);

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

                    //check userdata
                    for (int b = 16; b < 2352; b++)
                    {
                        if (src_databuf[b] != dst_databuf[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 (src_databuf[b] != dst_databuf[b])
                            {
                                offenders[numOffenders++] = e;
                            }
                        }
                        if (numOffenders != 0)
                        {
                            sw.Write("LBA {0} mismatch(es) at subchannel {1}; terminating sector cmp\n", lba, (char)('P' + c));
                            sw_dump_chunk(lba, 0, 2352 + c * 12, 12, numOffenders);
                            goto SKIPPO;
                        }
                    }
                }

                success = true;

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

                return success;
            }
            finally
            {
                if (src_disc != null)
                    src_disc.Dispose();
                if (dst_disc != null)
                    dst_disc.Dispose();
            }
        }
Example #9
0
        public void Run(string[] args)
        {
            if (args.Length == 0)
            {
                var dialog = new MainDiscoForm();
                dialog.ShowDialog();
                return;
            }

            bool scanCues = false;
            string dirArg = null;
            string infile = null;
            var loadDiscInterface = DiscInterface.BizHawk;
            var compareDiscInterfaces = new List<DiscInterface> ();
            bool hawk = false;

            int idx = 0;
            while (idx < args.Length)
            {
                string a = args[idx++];
                string au = a.ToUpperInvariant();
                if (au == "LOAD")
                    loadDiscInterface = (DiscInterface)Enum.Parse(typeof(DiscInterface), args[idx++], true);
                else if (au == "COMPARE")
                    compareDiscInterfaces.Add((DiscInterface)Enum.Parse(typeof(DiscInterface), args[idx++], true));
                else if (au == "HAWK")
                    hawk = true;
                else if (au == "CUEDIR")
                {
                    dirArg = args[idx++];
                    scanCues = true;
                }
                else infile = a;
            }

            if (hawk)
            {
                if (infile == null)
                    return;

                //TODO - write it out
                var dmj = new DiscMountJob { IN_DiscInterface = loadDiscInterface, IN_FromPath = infile };
                dmj.Run();
                //var disc = dmj.OUT_Disc;
            }

            bool verbose = true;

            if (scanCues)
            {
                verbose = false;
                var todo = FindCuesRecurse(dirArg);
                var po = new ParallelOptions();
                var cts = new CancellationTokenSource();
                po.CancellationToken = cts.Token;
                po.MaxDegreeOfParallelism = 1;
                //po.MaxDegreeOfParallelism = System.Environment.ProcessorCount - 2; //I'm disk or network bound, no sense hammering this
                if(po.MaxDegreeOfParallelism < 0) po.MaxDegreeOfParallelism = 1;
                object olock = new object();
                int ctr=0;
                bool blocked = false;
                try
                {
                    Parallel.ForEach(todo, po, (fp) =>
                    {
                        lock (olock)
                        {
                            ctr++;
                            int strlen = todo.Count.ToString().Length;
                            string fmt = string.Format("{{0,{0}}}/{{1,{0}}} {{2}}", strlen);
                            Console.WriteLine(fmt, ctr, todo.Count, Path.GetFileNameWithoutExtension(fp));
                            //if (fp.Contains("Break Out"))
                            //  blocked = false;
                        }

                        if(!blocked)
                            foreach (var cmpif in compareDiscInterfaces)
                            {
                                StringWriter sw = new StringWriter();
                                bool success = CompareFile(fp, loadDiscInterface, cmpif, verbose, cts, sw);
                                if (!success)
                                {
                                    lock (Console.Out)
                                        Console.Out.Write(sw.ToString());

                                    cts.Cancel();
                                    return;
                                }
                        }
                    });
                }
                catch (AggregateException ae) {
                    Console.WriteLine(ae.ToString());
                }
                catch (OperationCanceledException oce)
                {
                    Console.WriteLine(oce.ToString());
                }
                Console.WriteLine("--TERMINATED--");
                return;
            }

            if (compareDiscInterfaces.Count != 0)
            {
                StringWriter sw = new StringWriter();
                foreach (var cmpif in compareDiscInterfaces)
                    CompareFile(infile, loadDiscInterface, cmpif, verbose, null, sw);
                sw.Flush();
                string results = sw.ToString();
                var cr = new ComparisonResults();
                cr.textBox1.Text = results;
                cr.ShowDialog();
            }
        }