/// <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); }
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); }
/// <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; }
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; } }
/// <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(); } }
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(); } }
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(); } }