static void CheckGdromReadability(string devPath, Device dev) { string strDev; int item; bool tocIsNotBcd = false; bool sense; byte[] buffer; byte[] senseBuffer; int retries; start: System.Console.Clear(); AaruConsole.WriteLine("Ejecting disc..."); dev.AllowMediumRemoval(out _, dev.Timeout, out _); dev.EjectTray(out _, dev.Timeout, out _); AaruConsole.WriteLine("Please insert trap disc inside..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); retries = 0; do { retries++; sense = dev.ScsiTestUnitReady(out senseBuffer, dev.Timeout, out _); if (!sense) { break; } var decodedSense = Sense.Decode(senseBuffer); if (decodedSense.Value.ASC != 0x04) { break; } if (decodedSense.Value.ASCQ != 0x01) { break; } Thread.Sleep(2000); } while(retries < 25); sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); if (sense) { AaruConsole.WriteLine("READ FULL TOC failed..."); AaruConsole.WriteLine("{0}", Sense.PrettifySense(senseBuffer)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } FullTOC.CDFullTOC?decodedToc = FullTOC.Decode(buffer); if (decodedToc is null) { AaruConsole.WriteLine("Could not decode TOC..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } FullTOC.CDFullTOC toc = decodedToc.Value; FullTOC.TrackDataDescriptor leadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); if (leadOutTrack.POINT != 0xA2) { AaruConsole.WriteLine("Cannot find lead-out..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } int min = 0, sec, frame; if (leadOutTrack.PMIN == 122) { tocIsNotBcd = true; } if (leadOutTrack.PMIN >= 0xA0 && !tocIsNotBcd) { min += 90; leadOutTrack.PMIN -= 0x90; } if (tocIsNotBcd) { min = leadOutTrack.PMIN; sec = leadOutTrack.PSEC; frame = leadOutTrack.PFRAME; } else { min += ((leadOutTrack.PMIN >> 4) * 10) + (leadOutTrack.PMIN & 0x0F); sec = ((leadOutTrack.PSEC >> 4) * 10) + (leadOutTrack.PSEC & 0x0F); frame = ((leadOutTrack.PFRAME >> 4) * 10) + (leadOutTrack.PFRAME & 0x0F); } int sectors = ((min * 60 * 75) + (sec * 75) + frame) - 150; AaruConsole.WriteLine("Trap disc shows {0} sectors...", sectors); if (sectors < 450000) { AaruConsole.WriteLine("Trap disc doesn't have enough sectors..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } AaruConsole.WriteLine("Stopping motor..."); dev.StopUnit(out _, dev.Timeout, out _); AaruConsole.WriteLine("Please MANUALLY get the trap disc out and put the GD-ROM disc inside..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); AaruConsole.WriteLine("Waiting 5 seconds..."); Thread.Sleep(5000); AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); retries = 0; do { retries++; sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); if (!sense) { break; } var decodedSense = Sense.Decode(senseBuffer); if (decodedSense.Value.ASC != 0x04) { break; } if (decodedSense.Value.ASCQ != 0x01) { break; } } while(retries < 25); if (sense) { AaruConsole.WriteLine("READ FULL TOC failed..."); AaruConsole.WriteLine("{0}", Sense.PrettifySense(senseBuffer)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } decodedToc = FullTOC.Decode(buffer); if (decodedToc is null) { AaruConsole.WriteLine("Could not decode TOC..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } toc = decodedToc.Value; FullTOC.TrackDataDescriptor newLeadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); if (newLeadOutTrack.POINT != 0xA2) { AaruConsole.WriteLine("Cannot find lead-out..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } if (newLeadOutTrack.PMIN >= 0xA0 && !tocIsNotBcd) { newLeadOutTrack.PMIN -= 0x90; } if (newLeadOutTrack.PMIN != leadOutTrack.PMIN || newLeadOutTrack.PSEC != leadOutTrack.PSEC || newLeadOutTrack.PFRAME != leadOutTrack.PFRAME) { AaruConsole.WriteLine("Lead-out has changed, this drive does not support hot swapping discs..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } dev.SetCdSpeed(out _, RotationalControl.PureCav, 170, 0, dev.Timeout, out _); AaruConsole.Write("Reading LBA 0... "); bool lba0Result = dev.ReadCd(out byte[] lba0Buffer, out byte[] lba0Sense, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba0Result ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA 0 as audio (scrambled)... "); bool lba0ScrambledResult = dev.ReadCd(out byte[] lba0ScrambledBuffer, out byte[] lba0ScrambledSense, 0, 2352, 1, MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba0ScrambledResult ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA 100000... "); bool lba100000Result = dev.ReadCd(out byte[] lba100000Buffer, out byte[] lba100000Sense, 100000, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba100000Result ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA 50000... "); bool lba50000Result = dev.ReadCd(out byte[] lba50000Buffer, out byte[] lba50000Sense, 50000, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba50000Result ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA 450000... "); bool lba450000Result = dev.ReadCd(out byte[] lba450000Buffer, out byte[] lba450000Sense, 450000, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba450000Result ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA 400000... "); bool lba400000Result = dev.ReadCd(out byte[] lba400000Buffer, out byte[] lba400000Sense, 400000, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba400000Result ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA 45000... "); bool lba45000Result = dev.ReadCd(out byte[] lba45000Buffer, out byte[] lba45000Sense, 45000, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba45000Result ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA 44990... "); bool lba44990Result = dev.ReadCd(out byte[] lba44990Buffer, out byte[] lba44990Sense, 44990, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(lba44990Result ? "FAIL!" : "Success!"); menu: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("Device {0} read HD area.", lba450000Result ? "cannot" : "can"); AaruConsole.WriteLine("LBA 0 sense is {0}, buffer is {1}, sense buffer is {2}.", lba0Result, lba0Buffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba0Buffer) ? "empty" : $"{lba0Buffer.Length} bytes", lba0Sense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(lba0Sense) ? "empty" : $"{lba0Sense.Length}"); AaruConsole.WriteLine("LBA 0 (scrambled) sense is {0}, buffer is {1}, sense buffer is {2}.", lba0ScrambledResult, lba0ScrambledBuffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba0ScrambledBuffer) ? "empty" : $"{lba0ScrambledBuffer.Length} bytes", lba0ScrambledSense is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba0ScrambledSense) ? "empty" : $"{lba0ScrambledSense.Length}"); AaruConsole.WriteLine("LBA 44990 sense is {0}, buffer is {1}, sense buffer is {2}.", lba44990Result, lba44990Buffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba44990Buffer) ? "empty" : $"{lba44990Buffer.Length} bytes", lba44990Sense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(lba44990Sense) ? "empty" : $"{lba44990Sense.Length}"); AaruConsole.WriteLine("LBA 45000 sense is {0}, buffer is {1}, sense buffer is {2}.", lba45000Result, lba45000Buffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba45000Buffer) ? "empty" : $"{lba45000Buffer.Length} bytes", lba45000Sense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(lba45000Sense) ? "empty" : $"{lba45000Sense.Length}"); AaruConsole.WriteLine("LBA 50000 sense is {0}, buffer is {1}, sense buffer is {2}.", lba50000Result, lba50000Buffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba50000Buffer) ? "empty" : $"{lba50000Buffer.Length} bytes", lba50000Sense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(lba50000Sense) ? "empty" : $"{lba50000Sense.Length}"); AaruConsole.WriteLine("LBA 100000 sense is {0}, buffer is {1}, sense buffer is {2}.", lba100000Result, lba100000Buffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba100000Buffer) ? "empty" : $"{lba100000Buffer.Length} bytes", lba100000Sense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(lba100000Sense) ? "empty" : $"{lba100000Sense.Length}"); AaruConsole.WriteLine("LBA 400000 sense is {0}, buffer is {1}, sense buffer is {2}.", lba400000Result, lba400000Buffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba400000Buffer) ? "empty" : $"{lba400000Buffer.Length} bytes", lba400000Sense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(lba400000Sense) ? "empty" : $"{lba400000Sense.Length}"); AaruConsole.WriteLine("LBA 450000 sense is {0}, buffer is {1}, sense buffer is {2}.", lba450000Result, lba450000Buffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(lba450000Buffer) ? "empty" : $"{lba450000Buffer.Length} bytes", lba450000Sense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(lba450000Sense) ? "empty" : $"{lba450000Sense.Length}"); AaruConsole.WriteLine(); AaruConsole.WriteLine("Choose what to do:"); AaruConsole.WriteLine("1.- Print LBA 0 buffer."); AaruConsole.WriteLine("2.- Print LBA 0 sense buffer."); AaruConsole.WriteLine("3.- Decode LBA 0 sense buffer."); AaruConsole.WriteLine("4.- Print LBA 0 (scrambled) buffer."); AaruConsole.WriteLine("5.- Print LBA 0 (scrambled) sense buffer."); AaruConsole.WriteLine("6.- Decode LBA 0 (scrambled) sense buffer."); AaruConsole.WriteLine("7.- Print LBA 44990 buffer."); AaruConsole.WriteLine("8.- Print LBA 44990 sense buffer."); AaruConsole.WriteLine("9.- Decode LBA 44990 sense buffer."); AaruConsole.WriteLine("10.- Print LBA 45000 buffer."); AaruConsole.WriteLine("11.- Print LBA 45000 sense buffer."); AaruConsole.WriteLine("12.- Decode LBA 45000 sense buffer."); AaruConsole.WriteLine("13.- Print LBA 50000 buffer."); AaruConsole.WriteLine("14.- Print LBA 50000 sense buffer."); AaruConsole.WriteLine("15.- Decode LBA 50000 sense buffer."); AaruConsole.WriteLine("16.- Print LBA 100000 buffer."); AaruConsole.WriteLine("17.- Print LBA 100000 sense buffer."); AaruConsole.WriteLine("18.- Decode LBA 100000 sense buffer."); AaruConsole.WriteLine("19.- Print LBA 400000 buffer."); AaruConsole.WriteLine("20.- Print LBA 400000 sense buffer."); AaruConsole.WriteLine("21.- Decode LBA 400000 sense buffer."); AaruConsole.WriteLine("22.- Print LBA 450000 buffer."); AaruConsole.WriteLine("23.- Print LBA 450000 sense buffer."); AaruConsole.WriteLine("24.- Decode LBA 450000 sense buffer."); AaruConsole.WriteLine("25.- Send command again."); AaruConsole.WriteLine("0.- Return to special SCSI MultiMedia Commands menu."); AaruConsole.Write("Choose: "); strDev = System.Console.ReadLine(); if (!int.TryParse(strDev, out item)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); goto menu; } switch (item) { case 0: AaruConsole.WriteLine("Returning to special SCSI MultiMedia Commands menu..."); return; case 1: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 0 response:"); if (buffer != null) { PrintHex.PrintHexArray(lba0Buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 2: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 0 sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba0Sense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 3: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 0 decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba0Sense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 4: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 0 (scrambled) response:"); if (buffer != null) { PrintHex.PrintHexArray(lba0ScrambledBuffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 5: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 0 (scrambled) sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba0ScrambledSense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 6: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 0 (scrambled) decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba0ScrambledSense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 7: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 44990 response:"); if (buffer != null) { PrintHex.PrintHexArray(lba44990Buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 8: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 44990 sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba44990Sense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 9: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 44990 decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba44990Sense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 10: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 45000 response:"); if (buffer != null) { PrintHex.PrintHexArray(lba45000Buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 11: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 45000 sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba45000Sense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 12: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 45000 decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba45000Sense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 13: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 50000 response:"); if (buffer != null) { PrintHex.PrintHexArray(lba50000Buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 14: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 50000 sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba50000Sense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 15: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 50000 decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba50000Sense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 16: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 100000 response:"); if (buffer != null) { PrintHex.PrintHexArray(lba100000Buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 17: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 100000 sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba100000Sense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 18: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 100000 decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba100000Sense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 19: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 400000 response:"); if (buffer != null) { PrintHex.PrintHexArray(lba400000Buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 20: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 400000 sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba400000Sense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 21: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 400000 decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba400000Sense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 22: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 450000 response:"); if (buffer != null) { PrintHex.PrintHexArray(lba450000Buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 23: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 450000 sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(lba450000Sense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 24: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA 450000 decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(lba450000Sense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 25: goto start; default: AaruConsole.WriteLine("Incorrect option. Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); goto menu; } }
public bool Close() { if (!IsWriting) { ErrorMessage = "Image is not opened for writing"; return(false); } _dataStream.Flush(); _dataStream.Close(); _subStream?.Flush(); _subStream?.Close(); FullTOC.CDFullTOC?nullableToc = null; FullTOC.CDFullTOC toc; // Easy, just decode the real toc if (_fulltoc != null) { byte[] tmp = new byte[_fulltoc.Length + 2]; Array.Copy(BigEndianBitConverter.GetBytes((ushort)_fulltoc.Length), 0, tmp, 0, 2); Array.Copy(_fulltoc, 0, tmp, 2, _fulltoc.Length); nullableToc = FullTOC.Decode(tmp); } // Not easy, create a toc from scratch if (nullableToc == null) { toc = new FullTOC.CDFullTOC(); Dictionary <byte, byte> sessionEndingTrack = new Dictionary <byte, byte>(); toc.FirstCompleteSession = byte.MaxValue; toc.LastCompleteSession = byte.MinValue; List <FullTOC.TrackDataDescriptor> trackDescriptors = new List <FullTOC.TrackDataDescriptor>(); byte currentTrack = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { if (track.TrackSession < toc.FirstCompleteSession) { toc.FirstCompleteSession = (byte)track.TrackSession; } if (track.TrackSession <= toc.LastCompleteSession) { currentTrack = (byte)track.TrackSequence; continue; } if (toc.LastCompleteSession > 0) { sessionEndingTrack.Add(toc.LastCompleteSession, currentTrack); } toc.LastCompleteSession = (byte)track.TrackSession; } byte currentSession = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { _trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl); if (trackControl == 0 && track.TrackType != TrackType.Audio) { trackControl = (byte)CdFlags.DataTrack; } // Lead-Out if (track.TrackSession > currentSession && currentSession != 0) { (byte minute, byte second, byte frame)leadoutAmsf = LbaToMsf(track.TrackStartSector - 150); (byte minute, byte second, byte frame)leadoutPmsf = LbaToMsf(Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last(). TrackStartSector); // Lead-out trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xB0, ADR = 5, CONTROL = 0, HOUR = 0, Min = leadoutAmsf.minute, Sec = leadoutAmsf.second, Frame = leadoutAmsf.frame, PHOUR = 2, PMIN = leadoutPmsf.minute, PSEC = leadoutPmsf.second, PFRAME = leadoutPmsf.frame }); // This seems to be constant? It should not exist on CD-ROM but CloneCD creates them anyway // Format seems like ATIP, but ATIP should not be as 0xC0 in TOC... trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xC0, ADR = 5, CONTROL = 0, Min = 128, PMIN = 97, PSEC = 25 }); } // Lead-in if (track.TrackSession > currentSession) { currentSession = (byte)track.TrackSession; sessionEndingTrack.TryGetValue(currentSession, out byte endingTrackNumber); (byte minute, byte second, byte frame)leadinPmsf = LbaToMsf(Tracks.FirstOrDefault(t => t.TrackSequence == endingTrackNumber)?.TrackEndSector ?? 0 + 1); // Starting track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA0, ADR = 1, CONTROL = trackControl, PMIN = (byte)track.TrackSequence }); // Ending track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA1, ADR = 1, CONTROL = trackControl, PMIN = endingTrackNumber }); // Lead-out start trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA2, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = leadinPmsf.minute, PSEC = leadinPmsf.second, PFRAME = leadinPmsf.frame }); } (byte minute, byte second, byte frame)pmsf = LbaToMsf(track.TrackStartSector); // Track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = (byte)track.TrackSession, POINT = (byte)track.TrackSequence, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = pmsf.minute, PSEC = pmsf.second, PFRAME = pmsf.frame }); } toc.TrackDescriptors = trackDescriptors.ToArray(); } else { toc = nullableToc.Value; } _descriptorStream.WriteLine("[CloneCD]"); _descriptorStream.WriteLine("Version=2"); _descriptorStream.WriteLine("[Disc]"); _descriptorStream.WriteLine("TocEntries={0}", toc.TrackDescriptors.Length); _descriptorStream.WriteLine("Sessions={0}", toc.LastCompleteSession); _descriptorStream.WriteLine("DataTracksScrambled=0"); _descriptorStream.WriteLine("CDTextLength=0"); if (!string.IsNullOrEmpty(_catalog)) { _descriptorStream.WriteLine("CATALOG={0}", _catalog); } for (int i = 1; i <= toc.LastCompleteSession; i++) { _descriptorStream.WriteLine("[Session {0}]", i); Track firstSessionTrack = Tracks.FirstOrDefault(t => t.TrackSession == i); switch (firstSessionTrack?.TrackType) { case TrackType.Audio: // CloneCD always writes this value for first track in disc, however the Rainbow Books // say the first track pregap is no different from other session pregaps, same mode as // the track they belong to. _descriptorStream.WriteLine("PreGapMode=0"); break; case TrackType.Data: case TrackType.CdMode1: _descriptorStream.WriteLine("PreGapMode=1"); break; case TrackType.CdMode2Formless: case TrackType.CdMode2Form1: case TrackType.CdMode2Form2: _descriptorStream.WriteLine("PreGapMode=2"); break; default: throw new ArgumentOutOfRangeException(); } _descriptorStream.WriteLine("PreGapSubC=0"); } for (int i = 0; i < toc.TrackDescriptors.Length; i++) { long alba = MsfToLba((toc.TrackDescriptors[i].Min, toc.TrackDescriptors[i].Sec, toc.TrackDescriptors[i].Frame)); long plba = MsfToLba((toc.TrackDescriptors[i].PMIN, toc.TrackDescriptors[i].PSEC, toc.TrackDescriptors[i].PFRAME)); if (alba > 405000) { alba = ((alba - 405000) + 300) * -1; } if (plba > 405000) { plba = ((plba - 405000) + 300) * -1; } _descriptorStream.WriteLine("[Entry {0}]", i); _descriptorStream.WriteLine("Session={0}", toc.TrackDescriptors[i].SessionNumber); _descriptorStream.WriteLine("Point=0x{0:x2}", toc.TrackDescriptors[i].POINT); _descriptorStream.WriteLine("ADR=0x{0:x2}", toc.TrackDescriptors[i].ADR); _descriptorStream.WriteLine("Control=0x{0:x2}", toc.TrackDescriptors[i].CONTROL); _descriptorStream.WriteLine("TrackNo={0}", toc.TrackDescriptors[i].TNO); _descriptorStream.WriteLine("AMin={0}", toc.TrackDescriptors[i].Min); _descriptorStream.WriteLine("ASec={0}", toc.TrackDescriptors[i].Sec); _descriptorStream.WriteLine("AFrame={0}", toc.TrackDescriptors[i].Frame); _descriptorStream.WriteLine("ALBA={0}", alba); _descriptorStream.WriteLine("Zero={0}", ((toc.TrackDescriptors[i].HOUR & 0x0F) << 4) + (toc.TrackDescriptors[i].PHOUR & 0x0F)); _descriptorStream.WriteLine("PMin={0}", toc.TrackDescriptors[i].PMIN); _descriptorStream.WriteLine("PSec={0}", toc.TrackDescriptors[i].PSEC); _descriptorStream.WriteLine("PFrame={0}", toc.TrackDescriptors[i].PFRAME); _descriptorStream.WriteLine("PLBA={0}", plba); } _descriptorStream.Flush(); _descriptorStream.Close(); IsWriting = false; ErrorMessage = ""; return(true); }
public bool Close() { if (!IsWriting) { ErrorMessage = "Image is not opened for writing"; return(false); } dataStream.Flush(); dataStream.Close(); subStream?.Flush(); subStream?.Close(); FullTOC.CDFullTOC?nullableToc = null; FullTOC.CDFullTOC toc; // Easy, just decode the real toc if (fulltoc != null) { nullableToc = FullTOC.Decode(fulltoc); } // Not easy, create a toc from scratch if (nullableToc == null) { toc = new FullTOC.CDFullTOC(); Dictionary <byte, byte> sessionEndingTrack = new Dictionary <byte, byte>(); toc.FirstCompleteSession = byte.MaxValue; toc.LastCompleteSession = byte.MinValue; List <FullTOC.TrackDataDescriptor> trackDescriptors = new List <FullTOC.TrackDataDescriptor>(); byte currentTrack = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { if (track.TrackSession < toc.FirstCompleteSession) { toc.FirstCompleteSession = (byte)track.TrackSession; } if (track.TrackSession <= toc.LastCompleteSession) { currentTrack = (byte)track.TrackSequence; continue; } if (toc.LastCompleteSession > 0) { sessionEndingTrack.Add(toc.LastCompleteSession, currentTrack); } toc.LastCompleteSession = (byte)track.TrackSession; } byte currentSession = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl); if (trackControl == 0 && track.TrackType != TrackType.Audio) { trackControl = (byte)CdFlags.DataTrack; } // Lead-Out if (track.TrackSession > currentSession && currentSession != 0) { (byte minute, byte second, byte frame)leadoutAmsf = LbaToMsf(track.TrackStartSector - 150); (byte minute, byte second, byte frame)leadoutPmsf = LbaToMsf(Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last() .TrackStartSector); // Lead-out trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xB0, ADR = 5, CONTROL = 0, HOUR = 0, Min = leadoutAmsf.minute, Sec = leadoutAmsf.second, Frame = leadoutAmsf.frame, PHOUR = 2, PMIN = leadoutPmsf.minute, PSEC = leadoutPmsf.second, PFRAME = leadoutPmsf.frame }); // This seems to be constant? It should not exist on CD-ROM but CloneCD creates them anyway // Format seems like ATIP, but ATIP should not be as 0xC0 in TOC... trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xC0, ADR = 5, CONTROL = 0, Min = 128, PMIN = 97, PSEC = 25 }); } // Lead-in if (track.TrackSession > currentSession) { currentSession = (byte)track.TrackSession; sessionEndingTrack.TryGetValue(currentSession, out byte endingTrackNumber); (byte minute, byte second, byte frame)leadinPmsf = LbaToMsf(Tracks.FirstOrDefault(t => t.TrackSequence == endingTrackNumber).TrackEndSector + 1); // Starting track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA0, ADR = 1, CONTROL = trackControl, PMIN = (byte)track.TrackSequence }); // Ending track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA1, ADR = 1, CONTROL = trackControl, PMIN = endingTrackNumber }); // Lead-out start trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA2, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = leadinPmsf.minute, PSEC = leadinPmsf.second, PFRAME = leadinPmsf.frame }); } (byte minute, byte second, byte frame)pmsf = LbaToMsf(track.TrackStartSector); // Track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = (byte)track.TrackSession, POINT = (byte)track.TrackSequence, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = pmsf.minute, PSEC = pmsf.second, PFRAME = pmsf.frame }); } toc.TrackDescriptors = trackDescriptors.ToArray(); } else { toc = nullableToc.Value; } descriptorStream.WriteLine("[CloneCD]"); descriptorStream.WriteLine("Version=2"); descriptorStream.WriteLine("[Disc]"); descriptorStream.WriteLine("TocEntries={0}", toc.TrackDescriptors.Length); descriptorStream.WriteLine("Sessions={0}", toc.LastCompleteSession); descriptorStream.WriteLine("DataTracksScrambled=0"); descriptorStream.WriteLine("CDTextLength=0"); if (!string.IsNullOrEmpty(catalog)) { descriptorStream.WriteLine("CATALOG={0}", catalog); } for (int i = 1; i <= toc.LastCompleteSession; i++) { // TODO: Use first track of session info descriptorStream.WriteLine("[Session {0}]", i); descriptorStream.WriteLine("PreGapMode=0"); descriptorStream.WriteLine("PreGapSubC=0"); } for (int i = 0; i < toc.TrackDescriptors.Length; i++) { long alba = MsfToLba((toc.TrackDescriptors[i].Min, toc.TrackDescriptors[i].Sec, toc.TrackDescriptors[i].Frame)); long plba = MsfToLba((toc.TrackDescriptors[i].PMIN, toc.TrackDescriptors[i].PSEC, toc.TrackDescriptors[i].PFRAME)); if (alba > 405000) { alba = (alba - 405000 + 300) * -1; } if (plba > 405000) { plba = (plba - 405000 + 300) * -1; } descriptorStream.WriteLine("[Entry {0}]", i); descriptorStream.WriteLine("Session={0}", toc.TrackDescriptors[i].SessionNumber); descriptorStream.WriteLine("Point=0x{0:x2}", toc.TrackDescriptors[i].POINT); descriptorStream.WriteLine("ADR=0x{0:x2}", toc.TrackDescriptors[i].ADR); descriptorStream.WriteLine("Control=0x{0:x2}", toc.TrackDescriptors[i].CONTROL); descriptorStream.WriteLine("TrackNo={0}", toc.TrackDescriptors[i].TNO); descriptorStream.WriteLine("AMin={0}", toc.TrackDescriptors[i].Min); descriptorStream.WriteLine("ASec={0}", toc.TrackDescriptors[i].Sec); descriptorStream.WriteLine("AFrame={0}", toc.TrackDescriptors[i].Frame); descriptorStream.WriteLine("ALBA={0}", alba); descriptorStream.WriteLine("Zero={0}", ((toc.TrackDescriptors[i].HOUR & 0x0F) << 4) + (toc.TrackDescriptors[i].PHOUR & 0x0F)); descriptorStream.WriteLine("PMin={0}", toc.TrackDescriptors[i].PMIN); descriptorStream.WriteLine("PSec={0}", toc.TrackDescriptors[i].PSEC); descriptorStream.WriteLine("PFrame={0}", toc.TrackDescriptors[i].PFRAME); descriptorStream.WriteLine("PLBA={0}", plba); } descriptorStream.Flush(); descriptorStream.Close(); IsWriting = false; ErrorMessage = ""; return(true); }
static void ReadLeadOutUsingTrapDisc(string devPath, Device dev) { string strDev; int item; bool tocIsNotBcd = false; bool sense; byte[] buffer; byte[] senseBuffer; int retries; start: System.Console.Clear(); AaruConsole.WriteLine("Ejecting disc..."); dev.AllowMediumRemoval(out _, dev.Timeout, out _); dev.EjectTray(out _, dev.Timeout, out _); AaruConsole.WriteLine("Please insert a data only disc inside..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); retries = 0; do { retries++; sense = dev.ScsiTestUnitReady(out senseBuffer, dev.Timeout, out _); if (!sense) { break; } DecodedSense?decodedSense = Sense.Decode(senseBuffer); if (decodedSense.Value.ASC != 0x04) { break; } if (decodedSense.Value.ASCQ != 0x01) { break; } Thread.Sleep(2000); } while(retries < 25); sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); if (sense) { AaruConsole.WriteLine("READ FULL TOC failed..."); AaruConsole.WriteLine("{0}", Sense.PrettifySense(senseBuffer)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } FullTOC.CDFullTOC?decodedToc = FullTOC.Decode(buffer); if (decodedToc is null) { AaruConsole.WriteLine("Could not decode TOC..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } FullTOC.CDFullTOC toc = decodedToc.Value; FullTOC.TrackDataDescriptor leadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); if (leadOutTrack.POINT != 0xA2) { AaruConsole.WriteLine("Cannot find lead-out..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } int min = ((leadOutTrack.PMIN >> 4) * 10) + (leadOutTrack.PMIN & 0x0F); int sec = ((leadOutTrack.PSEC >> 4) * 10) + (leadOutTrack.PSEC & 0x0F); int frame = ((leadOutTrack.PFRAME >> 4) * 10) + (leadOutTrack.PFRAME & 0x0F); int sectors = (min * 60 * 75) + (sec * 75) + frame - 150; AaruConsole.WriteLine("Data disc shows {0} sectors...", sectors); AaruConsole.WriteLine("Ejecting disc..."); dev.AllowMediumRemoval(out _, dev.Timeout, out _); dev.EjectTray(out _, dev.Timeout, out _); AaruConsole.WriteLine("Please insert the trap disc inside..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); retries = 0; do { retries++; sense = dev.ScsiTestUnitReady(out senseBuffer, dev.Timeout, out _); if (!sense) { break; } DecodedSense?decodedSense = Sense.Decode(senseBuffer); if (decodedSense.Value.ASC != 0x04) { break; } if (decodedSense.Value.ASCQ != 0x01) { break; } Thread.Sleep(2000); } while(retries < 25); sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); if (sense) { AaruConsole.WriteLine("READ FULL TOC failed..."); AaruConsole.WriteLine("{0}", Sense.PrettifySense(senseBuffer)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } decodedToc = FullTOC.Decode(buffer); if (decodedToc is null) { AaruConsole.WriteLine("Could not decode TOC..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } toc = decodedToc.Value; leadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); if (leadOutTrack.POINT != 0xA2) { AaruConsole.WriteLine("Cannot find lead-out..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } min = 0; if (leadOutTrack.PMIN == 122) { tocIsNotBcd = true; } if (leadOutTrack.PMIN >= 0xA0 && !tocIsNotBcd) { min += 90; leadOutTrack.PMIN -= 0x90; } if (tocIsNotBcd) { min = leadOutTrack.PMIN; sec = leadOutTrack.PSEC; frame = leadOutTrack.PFRAME; } else { min += ((leadOutTrack.PMIN >> 4) * 10) + (leadOutTrack.PMIN & 0x0F); sec = ((leadOutTrack.PSEC >> 4) * 10) + (leadOutTrack.PSEC & 0x0F); frame = ((leadOutTrack.PFRAME >> 4) * 10) + (leadOutTrack.PFRAME & 0x0F); } int trapSectors = (min * 60 * 75) + (sec * 75) + frame - 150; AaruConsole.WriteLine("Trap disc shows {0} sectors...", trapSectors); if (trapSectors < sectors + 100) { AaruConsole.WriteLine("Trap disc doesn't have enough sectors..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } AaruConsole.WriteLine("Stopping motor..."); dev.StopUnit(out _, dev.Timeout, out _); AaruConsole.WriteLine("Please MANUALLY get the trap disc out and put the data disc back inside..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); AaruConsole.WriteLine("Waiting 5 seconds..."); Thread.Sleep(5000); AaruConsole.WriteLine("Sending READ FULL TOC to the device..."); retries = 0; do { retries++; sense = dev.ReadRawToc(out buffer, out senseBuffer, 1, dev.Timeout, out _); if (!sense) { break; } DecodedSense?decodedSense = Sense.Decode(senseBuffer); if (decodedSense.Value.ASC != 0x04) { break; } if (decodedSense.Value.ASCQ != 0x01) { break; } } while(retries < 25); if (sense) { AaruConsole.WriteLine("READ FULL TOC failed..."); AaruConsole.WriteLine("{0}", Sense.PrettifySense(senseBuffer)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } decodedToc = FullTOC.Decode(buffer); if (decodedToc is null) { AaruConsole.WriteLine("Could not decode TOC..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } toc = decodedToc.Value; FullTOC.TrackDataDescriptor newLeadOutTrack = toc.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA2); if (newLeadOutTrack.POINT != 0xA2) { AaruConsole.WriteLine("Cannot find lead-out..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } if (newLeadOutTrack.PMIN >= 0xA0 && !tocIsNotBcd) { newLeadOutTrack.PMIN -= 0x90; } if (newLeadOutTrack.PMIN != leadOutTrack.PMIN || newLeadOutTrack.PSEC != leadOutTrack.PSEC || newLeadOutTrack.PFRAME != leadOutTrack.PFRAME) { AaruConsole.WriteLine("Lead-out has changed, this drive does not support hot swapping discs..."); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadLine(); return; } AaruConsole.Write("Reading LBA {0}... ", sectors + 5); bool dataResult = dev.ReadCd(out byte[] dataBuffer, out byte[] dataSense, (uint)(sectors + 5), 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(dataResult ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA {0} as audio (scrambled)... ", sectors + 5); bool scrambledResult = dev.ReadCd(out byte[] scrambledBuffer, out byte[] scrambledSense, (uint)(sectors + 5), 2352, 1, MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); AaruConsole.WriteLine(scrambledResult ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA {0}'s PQ subchannel... ", sectors + 5); bool pqResult = dev.ReadCd(out byte[] pqBuffer, out byte[] pqSense, (uint)(sectors + 5), 16, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Q16, dev.Timeout, out _); if (pqResult) { pqResult = dev.ReadCd(out pqBuffer, out pqSense, (uint)(sectors + 5), 16, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Q16, dev.Timeout, out _); } AaruConsole.WriteLine(pqResult ? "FAIL!" : "Success!"); AaruConsole.Write("Reading LBA {0}'s PQ subchannel... ", sectors + 5); bool rwResult = dev.ReadCd(out byte[] rwBuffer, out byte[] rwSense, (uint)(sectors + 5), 16, 1, MmcSectorTypes.AllTypes, false, false, false, MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Rw, dev.Timeout, out _); if (rwResult) { rwResult = dev.ReadCd(out rwBuffer, out rwSense, (uint)(sectors + 5), 16, 1, MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Rw, dev.Timeout, out _); } AaruConsole.WriteLine(pqResult ? "FAIL!" : "Success!"); menu: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("Device {0} read Lead-Out.", dataResult && scrambledResult ? "cannot" : "can"); AaruConsole.WriteLine("LBA {0} sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, dataResult, dataBuffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(dataBuffer) ? "empty" : $"{dataBuffer.Length} bytes", dataSense is null ? "null" : ArrayHelpers. ArrayIsNullOrEmpty(dataSense) ? "empty" : $"{dataSense.Length}"); AaruConsole.WriteLine("LBA {0} (scrambled) sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, scrambledResult, scrambledBuffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(scrambledBuffer) ? "empty" : $"{scrambledBuffer.Length} bytes", scrambledSense is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(scrambledSense) ? "empty" : $"{scrambledSense.Length}"); AaruConsole.WriteLine("LBA {0}'s PQ sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, pqResult, pqBuffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(pqBuffer) ? "empty" : $"{pqBuffer.Length} bytes", pqSense is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(pqSense) ? "empty" : $"{pqSense.Length}"); AaruConsole.WriteLine("LBA {0}'s RW sense is {1}, buffer is {2}, sense buffer is {3}.", sectors + 5, rwResult, rwBuffer is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(rwBuffer) ? "empty" : $"{rwBuffer.Length} bytes", rwSense is null ? "null" : ArrayHelpers.ArrayIsNullOrEmpty(rwSense) ? "empty" : $"{rwSense.Length}"); AaruConsole.WriteLine(); AaruConsole.WriteLine("Choose what to do:"); AaruConsole.WriteLine("1.- Print LBA {0} buffer.", sectors + 5); AaruConsole.WriteLine("2.- Print LBA {0} sense buffer.", sectors + 5); AaruConsole.WriteLine("3.- Decode LBA {0} sense buffer.", sectors + 5); AaruConsole.WriteLine("4.- Print LBA {0} (scrambled) buffer.", sectors + 5); AaruConsole.WriteLine("5.- Print LBA {0} (scrambled) sense buffer.", sectors + 5); AaruConsole.WriteLine("6.- Decode LBA {0} (scrambled) sense buffer.", sectors + 5); AaruConsole.WriteLine("7.- Print LBA {0}'s PQ buffer.", sectors + 5); AaruConsole.WriteLine("8.- Print LBA {0}'s PQ sense buffer.", sectors + 5); AaruConsole.WriteLine("9.- Decode LBA {0}'s PQ sense buffer.", sectors + 5); AaruConsole.WriteLine("10.- Print LBA {0}'s RW buffer.", sectors + 5); AaruConsole.WriteLine("11.- Print LBA {0}'s RW sense buffer.", sectors + 5); AaruConsole.WriteLine("12.- Decode LBA {0}'s RW sense buffer.", sectors + 5); AaruConsole.WriteLine("13.- Send command again."); AaruConsole.WriteLine("0.- Return to special SCSI MultiMedia Commands menu."); AaruConsole.Write("Choose: "); strDev = System.Console.ReadLine(); if (!int.TryParse(strDev, out item)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); goto menu; } switch (item) { case 0: AaruConsole.WriteLine("Returning to special SCSI MultiMedia Commands menu..."); return; case 1: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA {0} response:", sectors + 5); if (buffer != null) { PrintHex.PrintHexArray(dataBuffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 2: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA {0} sense:", sectors + 5); if (senseBuffer != null) { PrintHex.PrintHexArray(dataSense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 3: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA {0} decoded sense:", sectors + 5); AaruConsole.Write("{0}", Sense.PrettifySense(dataSense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 4: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA {0} (scrambled) response:", sectors + 5); if (buffer != null) { PrintHex.PrintHexArray(scrambledBuffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 5: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA {0} (scrambled) sense:", sectors + 5); if (senseBuffer != null) { PrintHex.PrintHexArray(scrambledSense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 6: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA {0} (scrambled) decoded sense:", sectors + 5); AaruConsole.Write("{0}", Sense.PrettifySense(scrambledSense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 7: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA's PQ {0} response:", sectors + 5); if (buffer != null) { PrintHex.PrintHexArray(pqBuffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 8: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA's PQ {0} sense:", sectors + 5); if (senseBuffer != null) { PrintHex.PrintHexArray(pqSense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 9: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA's PQ {0} decoded sense:", sectors + 5); AaruConsole.Write("{0}", Sense.PrettifySense(pqSense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 10: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA's RW {0} response:", sectors + 5); if (buffer != null) { PrintHex.PrintHexArray(rwBuffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 11: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA's RW {0} sense:", sectors + 5); if (senseBuffer != null) { PrintHex.PrintHexArray(rwSense, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 12: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("LBA's RW {0} decoded sense:", sectors + 5); AaruConsole.Write("{0}", Sense.PrettifySense(rwSense)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); goto menu; case 13: goto start; default: AaruConsole.WriteLine("Incorrect option. Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); goto menu; } }
public async void Init(AaruFormat image, bool autoPlay = false) { this.Image = image; if (await Task.Run(() => image.Info.ReadableMediaTags?.Contains(MediaTagType.CD_FullTOC)) != true) { Console.WriteLine("Full TOC not found"); return; } byte[] tocBytes = await Task.Run(() => image.ReadDiskTag(MediaTagType.CD_FullTOC)); if ((tocBytes?.Length ?? 0) == 0) { Console.WriteLine("Error reading TOC from disc image"); return; } if (Swapping.Swap(BitConverter.ToUInt16(tocBytes, 0)) + 2 != tocBytes.Length) { byte[] tmp = new byte[tocBytes.Length + 2]; Array.Copy(tocBytes, 0, tmp, 2, tocBytes.Length); tmp[0] = (byte)((tocBytes.Length & 0xFF00) >> 8); tmp[1] = (byte)(tocBytes.Length & 0xFF); tocBytes = tmp; } FullTOC.CDFullTOC?nullableToc = await Task.Run(() => FullTOC.Decode(tocBytes)); if (nullableToc == null) { Console.WriteLine("Error decoding TOC"); return; } toc = nullableToc.Value; Console.WriteLine(FullTOC.Prettify(toc)); if (deEmphasisFilterLeft == null) { deEmphasisFilterLeft = new DeEmphasisFilter(); deEmphasisFilterRight = new DeEmphasisFilter(); } else { deEmphasisFilterLeft.Reset(); deEmphasisFilterRight.Reset(); } if (source == null) { source = new PlayerSource(ProviderRead); soundOut = new ALSoundOut(100); soundOut.Initialize(source); } else { soundOut.Stop(); } CurrentTrack = 0; LoadTrack(0); if (autoPlay) { soundOut.Play(); } else { TotalIndexes = 0; } TotalTracks = image.Tracks.Count; TrackDataDescriptor firstTrack = toc.TrackDescriptors.First(d => d.ADR == 1 && d.POINT == 1); TimeOffset = (ulong)(firstTrack.PMIN * 60 * 75 + firstTrack.PSEC * 75 + firstTrack.PFRAME); TotalTime = TimeOffset + image.Tracks.Last().TrackEndSector; Volume = App.Settings.Volume; Initialized = true; source.Start(); }