public void Dispose() { if (!Disposed) { ActivateGL(); if (SaveRamModified) { DisposedSaveRam = CloneSaveRam(); } LibYabause.libyabause_setvidbuff(IntPtr.Zero); LibYabause.libyabause_setsndbuff(IntPtr.Zero); LibYabause.libyabause_deinit(); VideoHandle.Free(); SoundHandle.Free(); CD.Dispose(); Disposed = true; DeactivateGL(); } }
} //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