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); }
public bool Close() { if (!IsWriting) { ErrorMessage = "Image is not opened for writing"; return(false); } byte sessions = byte.MinValue; foreach (Track t in writingTracks) { if (t.TrackSession > byte.MinValue) { sessions = (byte)t.TrackSession; } } AlcoholHeader header = new AlcoholHeader { signature = alcoholSignature, version = new byte[] { 1, 5 }, type = MediaTypeToAlcohol(imageInfo.MediaType), sessions = sessions, structuresOffset = (uint)(pfi == null ? 0 : 96), sessionOffset = (uint)(pfi == null ? 96 : 4196), unknown1 = new ushort[2], unknown2 = new uint[2], unknown3 = new uint[6], unknown4 = new uint[3] }; // Alcohol sets this always, Daemon Tool expects this header.unknown1[0] = 2; alcSessions = new Dictionary <int, AlcoholSession>(); alcTracks = new Dictionary <int, AlcoholTrack>(); alcToc = new Dictionary <int, Dictionary <int, AlcoholTrack> >(); writingTracks = writingTracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).ToList(); alcTrackExtras = new Dictionary <int, AlcoholTrackExtra>(); long currentTrackOffset = header.sessionOffset + Marshal.SizeOf <AlcoholSession>() * sessions; FullTOC.CDFullTOC?decodedToc = FullTOC.Decode(fullToc); long currentExtraOffset = currentTrackOffset; for (int i = 1; i <= sessions; i++) { if (decodedToc.HasValue) { currentExtraOffset += Marshal.SizeOf <AlcoholTrack>() * decodedToc.Value.TrackDescriptors.Count(t => t.SessionNumber == i); } else { currentExtraOffset += Marshal.SizeOf <AlcoholTrack>() * 3; currentExtraOffset += Marshal.SizeOf <AlcoholTrack>() * writingTracks.Count(t => t.TrackSession == i); if (i < sessions) { currentExtraOffset += Marshal.SizeOf <AlcoholTrack>() * 2; } } } long footerOffset = currentExtraOffset + Marshal.SizeOf <AlcoholTrackExtra>() * writingTracks.Count; if (bca != null) { header.bcaOffset = (uint)footerOffset; footerOffset += bca.Length; } if (isDvd) { alcSessions.Add(1, new AlcoholSession { sessionEnd = (int)(writingTracks[0].TrackEndSector - writingTracks[0].TrackStartSector + 1), sessionSequence = 1, allBlocks = 1, nonTrackBlocks = 3, firstTrack = 1, lastTrack = 1, trackOffset = 4220 }); footerOffset = 4300; if (bca != null) { footerOffset += bca.Length; } alcTracks.Add(1, new AlcoholTrack { mode = AlcoholTrackMode.DVD, adrCtl = 20, point = 1, extraOffset = (uint)(writingTracks[0].TrackEndSector - writingTracks[0].TrackStartSector + 1), sectorSize = 2048, files = 1, footerOffset = (uint)footerOffset, unknown = new byte[18], unknown2 = new byte[24] }); alcToc.Add(1, alcTracks); } else { for (int i = 1; i <= sessions; i++) { Track firstTrack = writingTracks.First(t => t.TrackSession == i); Track lastTrack = writingTracks.Last(t => t.TrackSession == i); alcSessions.Add(i, new AlcoholSession { sessionStart = (int)firstTrack.TrackStartSector - 150, sessionEnd = (int)lastTrack.TrackEndSector + 1, sessionSequence = (ushort)i, allBlocks = (byte)(decodedToc?.TrackDescriptors.Count(t => t.SessionNumber == i) ?? writingTracks.Count(t => t.TrackSession == i) + 3), nonTrackBlocks = (byte)(decodedToc?.TrackDescriptors.Count(t => t.SessionNumber == i && t.POINT >= 0xA0 && t.POINT <= 0xAF) ?? 3), firstTrack = (ushort)firstTrack.TrackSequence, lastTrack = (ushort)lastTrack.TrackSequence, trackOffset = (uint)currentTrackOffset }); Dictionary <int, AlcoholTrack> thisSessionTracks = new Dictionary <int, AlcoholTrack>(); trackFlags.TryGetValue((byte)firstTrack.TrackSequence, out byte firstTrackControl); trackFlags.TryGetValue((byte)lastTrack.TrackSequence, out byte lastTrackControl); if (firstTrackControl == 0 && firstTrack.TrackType != TrackType.Audio) { firstTrackControl = (byte)CdFlags.DataTrack; } if (lastTrackControl == 0 && lastTrack.TrackType != TrackType.Audio) { lastTrackControl = (byte)CdFlags.DataTrack; } (byte minute, byte second, byte frame)leadinPmsf = LbaToMsf(lastTrack.TrackEndSector + 1); if (decodedToc.HasValue && decodedToc.Value.TrackDescriptors.Any(t => t.SessionNumber == i && t.POINT >= 0xA0 && t.POINT <= 0xAF)) { foreach (FullTOC.TrackDataDescriptor tocTrk in decodedToc.Value.TrackDescriptors.Where(t => t.SessionNumber == i && t.POINT >= 0xA0 && t.POINT <= 0xAF)) { thisSessionTracks.Add(tocTrk.POINT, new AlcoholTrack { adrCtl = (byte)((tocTrk.ADR << 4) + tocTrk.CONTROL), tno = tocTrk.TNO, point = tocTrk.POINT, min = tocTrk.Min, sec = tocTrk.Sec, frame = tocTrk.Frame, zero = tocTrk.Zero, pmin = tocTrk.PMIN, psec = tocTrk.PSEC, pframe = tocTrk.PFRAME, mode = AlcoholTrackMode.NoData, unknown = new byte[18], unknown2 = new byte[24] }); currentTrackOffset += Marshal.SizeOf <AlcoholTrack>(); } } else { thisSessionTracks.Add(0xA0, new AlcoholTrack { adrCtl = (byte)((1 << 4) + firstTrackControl), pmin = (byte)firstTrack.TrackSequence, mode = AlcoholTrackMode.NoData, point = 0xA0, unknown = new byte[18], unknown2 = new byte[24], psec = (byte)(imageInfo.MediaType == MediaType.CDI ? 0x10 : writingTracks.Any(t => t.TrackType == TrackType.CdMode2Form1 || t.TrackType == TrackType.CdMode2Form2 || t.TrackType == TrackType.CdMode2Formless) ? 0x20 : 0) }); thisSessionTracks.Add(0xA1, new AlcoholTrack { adrCtl = (byte)((1 << 4) + lastTrackControl), pmin = (byte)lastTrack.TrackSequence, mode = AlcoholTrackMode.NoData, point = 0xA1, unknown = new byte[18], unknown2 = new byte[24] }); thisSessionTracks.Add(0xA2, new AlcoholTrack { adrCtl = (byte)((1 << 4) + firstTrackControl), zero = 0, pmin = leadinPmsf.minute, psec = leadinPmsf.second, pframe = leadinPmsf.frame, mode = AlcoholTrackMode.NoData, point = 0xA2, unknown = new byte[18], unknown2 = new byte[24] }); currentTrackOffset += Marshal.SizeOf <AlcoholTrack>() * 3; } foreach (Track track in writingTracks.Where(t => t.TrackSession == i).OrderBy(t => t.TrackSequence)) { AlcoholTrack alcTrk = new AlcoholTrack(); if (decodedToc.HasValue && decodedToc.Value.TrackDescriptors.Any(t => t.SessionNumber == i && t.POINT == track.TrackSequence)) { FullTOC.TrackDataDescriptor tocTrk = decodedToc.Value.TrackDescriptors.First(t => t.SessionNumber == i && t.POINT == track.TrackSequence); alcTrk.adrCtl = (byte)((tocTrk.ADR << 4) + tocTrk.CONTROL); alcTrk.tno = tocTrk.TNO; alcTrk.point = tocTrk.POINT; alcTrk.min = tocTrk.Min; alcTrk.sec = tocTrk.Sec; alcTrk.frame = tocTrk.Frame; alcTrk.zero = tocTrk.Zero; alcTrk.pmin = tocTrk.PMIN; alcTrk.psec = tocTrk.PSEC; alcTrk.pframe = tocTrk.PFRAME; } else { (byte minute, byte second, byte frame)msf = LbaToMsf(track.TrackStartSector); trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl); if (trackControl == 0 && track.TrackType != TrackType.Audio) { trackControl = (byte)CdFlags.DataTrack; } alcTrk.adrCtl = (byte)((1 << 4) + trackControl); alcTrk.point = (byte)track.TrackSequence; alcTrk.zero = 0; alcTrk.pmin = msf.minute; alcTrk.psec = msf.second; alcTrk.pframe = msf.frame; } alcTrk.mode = TrackTypeToAlcohol(track.TrackType); alcTrk.subMode = track.TrackSubchannelType != TrackSubchannelType.None ? AlcoholSubchannelMode.Interleaved : AlcoholSubchannelMode.None; alcTrk.sectorSize = (ushort)(track.TrackRawBytesPerSector + (track.TrackSubchannelType != TrackSubchannelType.None ? 96 : 0)); alcTrk.startLba = (uint)track.TrackStartSector; alcTrk.startOffset = track.TrackFileOffset; alcTrk.files = 1; alcTrk.extraOffset = (uint)currentExtraOffset; alcTrk.footerOffset = (uint)footerOffset; // Alcohol seems to set that for all CD tracks // Daemon Tools expect it to be like this alcTrk.unknown = new byte[] { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; alcTrk.unknown2 = new byte[24]; thisSessionTracks.Add((int)track.TrackSequence, alcTrk); currentTrackOffset += Marshal.SizeOf <AlcoholTrack>(); currentExtraOffset += Marshal.SizeOf <AlcoholTrackExtra>(); AlcoholTrackExtra trkExtra = new AlcoholTrackExtra { sectors = (uint)(track.TrackEndSector - track.TrackStartSector + 1) }; // When track mode changes there's a mandatory gap, Alcohol needs it if (track.TrackSequence == firstTrack.TrackSequence) { trkExtra.pregap = 150; } else if (thisSessionTracks.TryGetValue((int)(track.TrackSequence - 1), out AlcoholTrack previousTrack) && alcTrackExtras.TryGetValue((int)(track.TrackSequence - 1), out AlcoholTrackExtra previousExtra) && previousTrack.mode != alcTrk.mode) { previousExtra.sectors -= 150; trkExtra.pregap = 150; alcTrackExtras.Remove((int)(track.TrackSequence - 1)); alcTrackExtras.Add((int)(track.TrackSequence - 1), previousExtra); } else { trkExtra.pregap = 0; } alcTrackExtras.Add((int)track.TrackSequence, trkExtra); } if (decodedToc.HasValue && decodedToc.Value.TrackDescriptors.Any(t => t.SessionNumber == i && t.POINT >= 0xB0)) { foreach (FullTOC.TrackDataDescriptor tocTrk in decodedToc.Value.TrackDescriptors.Where(t => t.SessionNumber == i && t.POINT >= 0xB0)) { thisSessionTracks.Add(tocTrk.POINT, new AlcoholTrack { adrCtl = (byte)((tocTrk.ADR << 4) + tocTrk.CONTROL), tno = tocTrk.TNO, point = tocTrk.POINT, min = tocTrk.Min, sec = tocTrk.Sec, frame = tocTrk.Frame, zero = tocTrk.Zero, pmin = tocTrk.PMIN, psec = tocTrk.PSEC, pframe = tocTrk.PFRAME, mode = AlcoholTrackMode.NoData, unknown = new byte[18], unknown2 = new byte[24] }); currentTrackOffset += Marshal.SizeOf <AlcoholTrack>(); } } else if (i < sessions) { (byte minute, byte second, byte frame)leadoutAmsf = LbaToMsf(writingTracks.First(t => t.TrackSession == i + 1).TrackStartSector - 150); (byte minute, byte second, byte frame)leadoutPmsf = LbaToMsf(writingTracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last() .TrackStartSector); thisSessionTracks.Add(0xB0, new AlcoholTrack { point = 0xB0, adrCtl = 0x50, zero = 0, min = leadoutAmsf.minute, sec = leadoutAmsf.second, frame = leadoutAmsf.frame, pmin = leadoutPmsf.minute, psec = leadoutPmsf.second, pframe = leadoutPmsf.frame, unknown = new byte[18], unknown2 = new byte[24] }); thisSessionTracks.Add(0xC0, new AlcoholTrack { point = 0xC0, adrCtl = 0x50, min = 128, pmin = 97, psec = 25, unknown = new byte[18], unknown2 = new byte[24] }); currentTrackOffset += Marshal.SizeOf <AlcoholTrack>() * 2; } alcToc.Add(i, thisSessionTracks); } } alcFooter = new AlcoholFooter { filenameOffset = (uint)(footerOffset + Marshal.SizeOf <AlcoholFooter>()), widechar = 1 }; byte[] filename = Encoding.Unicode.GetBytes("*.mdf"); // Yup, Alcohol stores no filename but a wildcard. IntPtr blockPtr; // Write header descriptorStream.Seek(0, SeekOrigin.Begin); byte[] block = new byte[Marshal.SizeOf <AlcoholHeader>()]; blockPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf <AlcoholHeader>()); System.Runtime.InteropServices.Marshal.StructureToPtr(header, blockPtr, true); System.Runtime.InteropServices.Marshal.Copy(blockPtr, block, 0, block.Length); System.Runtime.InteropServices.Marshal.FreeHGlobal(blockPtr); descriptorStream.Write(block, 0, block.Length); // Write DVD structures if pressent if (header.structuresOffset != 0) { if (dmi != null) { descriptorStream.Seek(header.structuresOffset, SeekOrigin.Begin); if (dmi.Length == 2052) { descriptorStream.Write(dmi, 0, 2052); } else if (dmi.Length == 2048) { descriptorStream.Write(new byte[] { 0x08, 0x02, 0x00, 0x00 }, 0, 4); descriptorStream.Write(dmi, 0, 2048); } } // TODO: Create fake PFI if none present if (pfi != null) { descriptorStream.Seek(header.structuresOffset + 2052, SeekOrigin.Begin); descriptorStream.Write(pfi, pfi.Length - 2048, 2048); } } // Write sessions descriptorStream.Seek(header.sessionOffset, SeekOrigin.Begin); foreach (AlcoholSession session in alcSessions.Values) { block = new byte[Marshal.SizeOf <AlcoholSession>()]; blockPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf <AlcoholSession>()); System.Runtime.InteropServices.Marshal.StructureToPtr(session, blockPtr, true); System.Runtime.InteropServices.Marshal.Copy(blockPtr, block, 0, block.Length); System.Runtime.InteropServices.Marshal.FreeHGlobal(blockPtr); descriptorStream.Write(block, 0, block.Length); } // Write tracks foreach (KeyValuePair <int, Dictionary <int, AlcoholTrack> > kvp in alcToc) { descriptorStream.Seek(alcSessions.First(t => t.Key == kvp.Key).Value.trackOffset, SeekOrigin.Begin); foreach (AlcoholTrack track in kvp.Value.Values) { block = new byte[Marshal.SizeOf <AlcoholTrack>()]; blockPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf <AlcoholTrack>()); System.Runtime.InteropServices.Marshal.StructureToPtr(track, blockPtr, true); System.Runtime.InteropServices.Marshal.Copy(blockPtr, block, 0, block.Length); System.Runtime.InteropServices.Marshal.FreeHGlobal(blockPtr); descriptorStream.Write(block, 0, block.Length); if (isDvd) { continue; } // Write extra long position = descriptorStream.Position; descriptorStream.Seek(track.extraOffset, SeekOrigin.Begin); if (alcTrackExtras.TryGetValue(track.point, out AlcoholTrackExtra extra)) { block = new byte[Marshal.SizeOf <AlcoholTrackExtra>()]; blockPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf <AlcoholTrackExtra>()); System.Runtime.InteropServices.Marshal.StructureToPtr(extra, blockPtr, true); System.Runtime.InteropServices.Marshal.Copy(blockPtr, block, 0, block.Length); System.Runtime.InteropServices.Marshal.FreeHGlobal(blockPtr); descriptorStream.Write(block, 0, block.Length); } descriptorStream.Seek(position, SeekOrigin.Begin); } } // Write BCA if (bca != null) { descriptorStream.Seek(header.bcaOffset, SeekOrigin.Begin); descriptorStream.Write(bca, 0, bca.Length); } // Write footer descriptorStream.Seek(footerOffset, SeekOrigin.Begin); block = new byte[Marshal.SizeOf <AlcoholFooter>()]; blockPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf <AlcoholFooter>()); System.Runtime.InteropServices.Marshal.StructureToPtr(alcFooter, blockPtr, true); System.Runtime.InteropServices.Marshal.Copy(blockPtr, block, 0, block.Length); System.Runtime.InteropServices.Marshal.FreeHGlobal(blockPtr); descriptorStream.Write(block, 0, block.Length); // Write filename descriptorStream.Write(filename, 0, filename.Length); // Write filename null termination descriptorStream.Write(new byte[] { 0, 0 }, 0, 2); descriptorStream.Flush(); descriptorStream.Close(); imageStream.Flush(); imageStream.Close(); IsWriting = false; ErrorMessage = ""; return(true); }
public static void PrintImageInfo(IMediaImage imageFormat) { DicConsole.WriteLine("Image information:"); if (!string.IsNullOrWhiteSpace(imageFormat.Info.Version)) { DicConsole.WriteLine("Format: {0} version {1}", imageFormat.Format, imageFormat.Info.Version); } else { DicConsole.WriteLine("Format: {0}", imageFormat.Format); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application) && !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion)) { DicConsole.WriteLine("Was created with {0} version {1}", imageFormat.Info.Application, imageFormat.Info.ApplicationVersion); } else if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application)) { DicConsole.WriteLine("Was created with {0}", imageFormat.Info.Application); } DicConsole.WriteLine("Image without headers is {0} bytes long", imageFormat.Info.ImageSize); DicConsole.WriteLine("Contains a media of {0} sectors with a maximum sector size of {1} bytes (if all sectors are of the same size this would be {2} bytes)", imageFormat.Info.Sectors, imageFormat.Info.SectorSize, imageFormat.Info.Sectors * imageFormat.Info.SectorSize); if (!string.IsNullOrWhiteSpace(imageFormat.Info.Creator)) { DicConsole.WriteLine("Created by: {0}", imageFormat.Info.Creator); } if (imageFormat.Info.CreationTime != DateTime.MinValue) { DicConsole.WriteLine("Created on {0}", imageFormat.Info.CreationTime); } if (imageFormat.Info.LastModificationTime != DateTime.MinValue) { DicConsole.WriteLine("Last modified on {0}", imageFormat.Info.LastModificationTime); } DicConsole.WriteLine("Contains a media of type {0} and XML type {1}", imageFormat.Info.MediaType, imageFormat.Info.XmlMediaType); DicConsole.WriteLine("{0} partitions", imageFormat.Info.HasPartitions ? "Has" : "Doesn't have"); DicConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have"); if (!string.IsNullOrWhiteSpace(imageFormat.Info.Comments)) { DicConsole.WriteLine("Comments: {0}", imageFormat.Info.Comments); } if (imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0) { DicConsole.WriteLine("Media is number {0} on a set of {1} medias", imageFormat.Info.MediaSequence, imageFormat.Info.LastMediaSequence); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle)) { DicConsole.WriteLine("Media title: {0}", imageFormat.Info.MediaTitle); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer)) { DicConsole.WriteLine("Media manufacturer: {0}", imageFormat.Info.MediaManufacturer); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel)) { DicConsole.WriteLine("Media model: {0}", imageFormat.Info.MediaModel); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber)) { DicConsole.WriteLine("Media serial number: {0}", imageFormat.Info.MediaSerialNumber); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode)) { DicConsole.WriteLine("Media barcode: {0}", imageFormat.Info.MediaBarcode); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber)) { DicConsole.WriteLine("Media part number: {0}", imageFormat.Info.MediaPartNumber); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer)) { DicConsole.WriteLine("Drive manufacturer: {0}", imageFormat.Info.DriveManufacturer); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel)) { DicConsole.WriteLine("Drive model: {0}", imageFormat.Info.DriveModel); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber)) { DicConsole.WriteLine("Drive serial number: {0}", imageFormat.Info.DriveSerialNumber); } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision)) { DicConsole.WriteLine("Drive firmware info: {0}", imageFormat.Info.DriveFirmwareRevision); } if (imageFormat.Info.Cylinders > 0 && imageFormat.Info.Heads > 0 && imageFormat.Info.SectorsPerTrack > 0 && imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc) { DicConsole.WriteLine("Media geometry: {0} cylinders, {1} heads, {2} sectors per track", imageFormat.Info.Cylinders, imageFormat.Info.Heads, imageFormat.Info.SectorsPerTrack); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Count > 0) { DicConsole.WriteLine("Contains {0} readable media tags:", imageFormat.Info.ReadableMediaTags.Count); foreach (MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t)) { DicConsole.Write("{0} ", tag); } DicConsole.WriteLine(); } if (imageFormat.Info.ReadableSectorTags != null && imageFormat.Info.ReadableSectorTags.Count > 0) { DicConsole.WriteLine("Contains {0} readable sector tags:", imageFormat.Info.ReadableSectorTags.Count); foreach (SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t)) { DicConsole.Write("{0} ", tag); } DicConsole.WriteLine(); } DicConsole.WriteLine(); PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess; byte[] scsiVendorId = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_INQUIRY)) { byte[] inquiry = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY); scsiDeviceType = (PeripheralDeviceTypes)(inquiry[0] & 0x1F); if (inquiry.Length >= 16) { scsiVendorId = new byte[8]; Array.Copy(inquiry, 8, scsiVendorId, 0, 8); } DicConsole.WriteLine("SCSI INQUIRY contained in image:"); DicConsole.Write("{0}", Inquiry.Prettify(inquiry)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) { byte[] identify = imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY); DicConsole.WriteLine("ATA IDENTIFY contained in image:"); DicConsole.Write("{0}", Identify.Prettify(identify)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATAPI_IDENTIFY)) { byte[] identify = imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY); DicConsole.WriteLine("ATAPI IDENTIFY contained in image:"); DicConsole.Write("{0}", Identify.Prettify(identify)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_10)) { byte[] modeSense10 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10); Modes.DecodedMode?decMode = Modes.DecodeMode10(modeSense10, scsiDeviceType); if (decMode.HasValue) { DicConsole.WriteLine("SCSI MODE SENSE (10) contained in image:"); PrintScsiModePages.Print(decMode.Value, scsiDeviceType, scsiVendorId); DicConsole.WriteLine(); } } else if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_6)) { byte[] modeSense6 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6); Modes.DecodedMode?decMode = Modes.DecodeMode6(modeSense6, scsiDeviceType); if (decMode.HasValue) { DicConsole.WriteLine("SCSI MODE SENSE (6) contained in image:"); PrintScsiModePages.Print(decMode.Value, scsiDeviceType, scsiVendorId); DicConsole.WriteLine(); } } else if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODEPAGE_2A)) { byte[] mode2A = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODEPAGE_2A); DicConsole.Write("{0}", Modes.PrettifyModePage_2A(mode2A)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_FullTOC)) { byte[] toc = imageFormat.ReadDiskTag(MediaTagType.CD_FullTOC); ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0)); if (dataLen + 2 != toc.Length) { byte[] tmp = new byte[toc.Length + 2]; Array.Copy(toc, 0, tmp, 2, toc.Length); tmp[0] = (byte)((toc.Length & 0xFF00) >> 8); tmp[1] = (byte)(toc.Length & 0xFF); toc = tmp; } DicConsole.WriteLine("CompactDisc Table of Contents contained in image:"); DicConsole.Write("{0}", FullTOC.Prettify(toc)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_PMA)) { byte[] pma = imageFormat.ReadDiskTag(MediaTagType.CD_PMA); ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0)); if (dataLen + 2 != pma.Length) { byte[] tmp = new byte[pma.Length + 2]; Array.Copy(pma, 0, tmp, 2, pma.Length); tmp[0] = (byte)((pma.Length & 0xFF00) >> 8); tmp[1] = (byte)(pma.Length & 0xFF); pma = tmp; } DicConsole.WriteLine("CompactDisc Power Management Area contained in image:"); DicConsole.Write("{0}", PMA.Prettify(pma)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_ATIP)) { byte[] atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0)); if (dataLen + 4 != atip.Length) { byte[] tmp = new byte[atip.Length + 4]; Array.Copy(atip, 0, tmp, 4, atip.Length); tmp[0] = (byte)((atip.Length & 0xFF000000) >> 24); tmp[1] = (byte)((atip.Length & 0xFF0000) >> 16); tmp[2] = (byte)((atip.Length & 0xFF00) >> 8); tmp[3] = (byte)(atip.Length & 0xFF); atip = tmp; } DicConsole.WriteLine("CompactDisc Absolute Time In Pregroove (ATIP) contained in image:"); DicConsole.Write("{0}", ATIP.Prettify(atip)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_TEXT)) { byte[] cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0)); if (dataLen + 4 != cdtext.Length) { byte[] tmp = new byte[cdtext.Length + 4]; Array.Copy(cdtext, 0, tmp, 4, cdtext.Length); tmp[0] = (byte)((cdtext.Length & 0xFF000000) >> 24); tmp[1] = (byte)((cdtext.Length & 0xFF0000) >> 16); tmp[2] = (byte)((cdtext.Length & 0xFF00) >> 8); tmp[3] = (byte)(cdtext.Length & 0xFF); cdtext = tmp; } DicConsole.WriteLine("CompactDisc Lead-in's CD-Text contained in image:"); DicConsole.Write("{0}", CDTextOnLeadIn.Prettify(cdtext)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_MCN)) { byte[] mcn = imageFormat.ReadDiskTag(MediaTagType.CD_MCN); DicConsole.WriteLine("CompactDisc Media Catalogue Number contained in image: {0}", Encoding.UTF8.GetString(mcn)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_PFI)) { byte[] pfi = imageFormat.ReadDiskTag(MediaTagType.DVD_PFI); DicConsole.WriteLine("DVD Physical Format Information contained in image:"); DicConsole.Write("{0}", PFI.Prettify(pfi)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_DDS)) { byte[] dds = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_DDS); DicConsole.WriteLine("DVD-RAM Disc Definition Structure contained in image:"); DicConsole.Write("{0}", DDS.Prettify(dds)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_PFI)) { byte[] pfi = imageFormat.ReadDiskTag(MediaTagType.DVDR_PFI); DicConsole.WriteLine("DVD-R Physical Format Information contained in image:"); DicConsole.Write("{0}", PFI.Prettify(pfi)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DI)) { byte[] di = imageFormat.ReadDiskTag(MediaTagType.BD_DI); DicConsole.WriteLine("Bluray Disc Information contained in image:"); DicConsole.Write("{0}", DI.Prettify(di)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DDS)) { byte[] dds = imageFormat.ReadDiskTag(MediaTagType.BD_DDS); DicConsole.WriteLine("Bluray Disc Definition Structure contained in image:"); DicConsole.Write("{0}", Decoders.Bluray.DDS.Prettify(dds)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS)) { byte[] cis = imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS); DicConsole.WriteLine("PCMCIA CIS:"); Tuple[] tuples = CIS.GetTuples(cis); if (tuples != null) { foreach (Tuple tuple in tuples) { switch (tuple.Code) { case TupleCodes.CISTPL_NULL: case TupleCodes.CISTPL_END: break; case TupleCodes.CISTPL_DEVICEGEO: case TupleCodes.CISTPL_DEVICEGEO_A: DicConsole.WriteLine("{0}", CIS.PrettifyDeviceGeometryTuple(tuple)); break; case TupleCodes.CISTPL_MANFID: DicConsole.WriteLine("{0}", CIS.PrettifyManufacturerIdentificationTuple(tuple)); break; case TupleCodes.CISTPL_VERS_1: DicConsole.WriteLine("{0}", CIS.PrettifyLevel1VersionTuple(tuple)); break; case TupleCodes.CISTPL_ALTSTR: case TupleCodes.CISTPL_BAR: case TupleCodes.CISTPL_BATTERY: case TupleCodes.CISTPL_BYTEORDER: case TupleCodes.CISTPL_CFTABLE_ENTRY: case TupleCodes.CISTPL_CFTABLE_ENTRY_CB: case TupleCodes.CISTPL_CHECKSUM: case TupleCodes.CISTPL_CONFIG: case TupleCodes.CISTPL_CONFIG_CB: case TupleCodes.CISTPL_DATE: case TupleCodes.CISTPL_DEVICE: case TupleCodes.CISTPL_DEVICE_A: case TupleCodes.CISTPL_DEVICE_OA: case TupleCodes.CISTPL_DEVICE_OC: case TupleCodes.CISTPL_EXTDEVIC: case TupleCodes.CISTPL_FORMAT: case TupleCodes.CISTPL_FORMAT_A: case TupleCodes.CISTPL_FUNCE: case TupleCodes.CISTPL_FUNCID: case TupleCodes.CISTPL_GEOMETRY: case TupleCodes.CISTPL_INDIRECT: case TupleCodes.CISTPL_JEDEC_A: case TupleCodes.CISTPL_JEDEC_C: case TupleCodes.CISTPL_LINKTARGET: case TupleCodes.CISTPL_LONGLINK_A: case TupleCodes.CISTPL_LONGLINK_C: case TupleCodes.CISTPL_LONGLINK_CB: case TupleCodes.CISTPL_LONGLINK_MFC: case TupleCodes.CISTPL_NO_LINK: case TupleCodes.CISTPL_ORG: case TupleCodes.CISTPL_PWR_MGMNT: case TupleCodes.CISTPL_SPCL: case TupleCodes.CISTPL_SWIL: case TupleCodes.CISTPL_VERS_2: DicConsole.DebugWriteLine("Device-Info command", "Found undecoded tuple ID {0}", tuple.Code); break; default: DicConsole.DebugWriteLine("Device-Info command", "Found unknown tuple ID 0x{0:X2}", (byte)tuple.Code); break; } } } else { DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples"); } } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CID)) { byte[] cid = imageFormat.ReadDiskTag(MediaTagType.SD_CID); DicConsole.WriteLine("SecureDigital CID contained in image:"); DicConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifyCID(cid)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CSD)) { byte[] csd = imageFormat.ReadDiskTag(MediaTagType.SD_CSD); DicConsole.WriteLine("SecureDigital CSD contained in image:"); DicConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifyCSD(csd)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_SCR)) { byte[] scr = imageFormat.ReadDiskTag(MediaTagType.SD_SCR); DicConsole.WriteLine("SecureDigital SCR contained in image:"); DicConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifySCR(scr)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_OCR)) { byte[] ocr = imageFormat.ReadDiskTag(MediaTagType.SD_OCR); DicConsole.WriteLine("SecureDigital OCR contained in image:"); DicConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifyOCR(ocr)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CID)) { byte[] cid = imageFormat.ReadDiskTag(MediaTagType.MMC_CID); DicConsole.WriteLine("MultiMediaCard CID contained in image:"); DicConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyCID(cid)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CSD)) { byte[] csd = imageFormat.ReadDiskTag(MediaTagType.MMC_CSD); DicConsole.WriteLine("MultiMediaCard CSD contained in image:"); DicConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyCSD(csd)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_ExtendedCSD)) { byte[] ecsd = imageFormat.ReadDiskTag(MediaTagType.MMC_ExtendedCSD); DicConsole.WriteLine("MultiMediaCard ExtendedCSD contained in image:"); DicConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyExtendedCSD(ecsd)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_OCR)) { byte[] ocr = imageFormat.ReadDiskTag(MediaTagType.MMC_OCR); DicConsole.WriteLine("MultiMediaCard OCR contained in image:"); DicConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyOCR(ocr)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_PFI)) { byte[] xpfi = imageFormat.ReadDiskTag(MediaTagType.Xbox_PFI); DicConsole.WriteLine("Xbox Physical Format Information contained in image:"); DicConsole.Write("{0}", PFI.Prettify(xpfi)); DicConsole.WriteLine(); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_DMI)) { byte[] xdmi = imageFormat.ReadDiskTag(MediaTagType.Xbox_DMI); if (DMI.IsXbox(xdmi)) { DMI.XboxDMI?xmi = DMI.DecodeXbox(xdmi); if (xmi.HasValue) { DicConsole.WriteLine("Xbox DMI contained in image:"); DicConsole.Write("{0}", DMI.PrettifyXbox(xmi)); DicConsole.WriteLine(); } } if (DMI.IsXbox360(xdmi)) { DMI.Xbox360DMI?xmi = DMI.DecodeXbox360(xdmi); if (xmi.HasValue) { DicConsole.WriteLine("Xbox 360 DMI contained in image:"); DicConsole.Write("{0}", DMI.PrettifyXbox360(xmi)); DicConsole.WriteLine(); } } } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_SecuritySector)) { byte[] toc = imageFormat.ReadDiskTag(MediaTagType.Xbox_SecuritySector); DicConsole.WriteLine("Xbox Security Sectors contained in image:"); DicConsole.Write("{0}", SS.Prettify(toc)); DicConsole.WriteLine(); } try { if (imageFormat.Sessions != null && imageFormat.Sessions.Count > 0) { DicConsole.WriteLine("Image sessions:"); DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", "Session", "First track", "Last track", "Start", "End"); DicConsole.WriteLine("========================================================="); foreach (Session session in imageFormat.Sessions) { DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", session.SessionSequence, session.StartTrack, session.EndTrack, session.StartSector, session.EndSector); } DicConsole.WriteLine(); } } catch { // ignored } try { if (imageFormat.Tracks != null && imageFormat.Tracks.Count > 0) { DicConsole.WriteLine("Image tracks:"); DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", "Track", "Type", "Bps", "Raw bps", "Subchannel", "Pregap", "Start", "End"); DicConsole.WriteLine("================================================================================="); foreach (Track track in imageFormat.Tracks) { DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", track.TrackSequence, track.TrackType, track.TrackBytesPerSector, track.TrackRawBytesPerSector, track.TrackSubchannelType, track.TrackPregap, track.TrackStartSector, track.TrackEndSector); } DicConsole.WriteLine(); } } catch { // ignored } if (imageFormat.DumpHardware == null) { return; } const string MANUFACTURER_STRING = "Manufacturer"; const string MODEL_STRING = "Model"; const string SERIAL_STRING = "Serial"; const string SOFTWARE_STRING = "Software"; const string VERSION_STRING = "Version"; const string OS_STRING = "Operating system"; const string START_STRING = "Start"; const string END_STRING = "End"; int manufacturerLen = MANUFACTURER_STRING.Length; int modelLen = MODEL_STRING.Length; int serialLen = SERIAL_STRING.Length; int softwareLen = SOFTWARE_STRING.Length; int versionLen = VERSION_STRING.Length; int osLen = OS_STRING.Length; int sectorLen = START_STRING.Length; foreach (DumpHardwareType dump in imageFormat.DumpHardware) { if (dump.Manufacturer?.Length > manufacturerLen) { manufacturerLen = dump.Manufacturer.Length; } if (dump.Model?.Length > modelLen) { modelLen = dump.Model.Length; } if (dump.Serial?.Length > serialLen) { serialLen = dump.Serial.Length; } if (dump.Software?.Name?.Length > softwareLen) { softwareLen = dump.Software.Name.Length; } if (dump.Software?.Version?.Length > versionLen) { versionLen = dump.Software.Version.Length; } if (dump.Software?.OperatingSystem?.Length > osLen) { osLen = dump.Software.OperatingSystem.Length; } foreach (ExtentType extent in dump.Extents) { if ($"{extent.Start}".Length > sectorLen) { sectorLen = $"{extent.Start}".Length; } if ($"{extent.End}".Length > sectorLen) { sectorLen = $"{extent.End}".Length; } } } manufacturerLen += 2; modelLen += 2; serialLen += 2; softwareLen += 2; versionLen += 2; osLen += 2; sectorLen += 2; sectorLen += 2; char[] separator = new char[manufacturerLen + modelLen + serialLen + softwareLen + versionLen + osLen + sectorLen + sectorLen]; for (int i = 0; i < separator.Length; i++) { separator[i] = '='; } string format = $"{{0,-{manufacturerLen}}}{{1,-{modelLen}}}{{2,-{serialLen}}}{{3,-{softwareLen}}}{{4,-{versionLen}}}{{5,-{osLen}}}{{6,-{sectorLen}}}{{7,-{sectorLen}}}"; DicConsole.WriteLine("Dump hardware information:"); DicConsole.WriteLine(format, MANUFACTURER_STRING, MODEL_STRING, SERIAL_STRING, SOFTWARE_STRING, VERSION_STRING, OS_STRING, START_STRING, END_STRING); DicConsole.WriteLine(new string(separator)); foreach (DumpHardwareType dump in imageFormat.DumpHardware) { foreach (ExtentType extent in dump.Extents) { DicConsole.WriteLine(format, dump.Manufacturer, dump.Model, dump.Serial, dump.Software.Name, dump.Software.Version, dump.Software.OperatingSystem, extent.Start, extent.End); } } DicConsole.WriteLine(); }
// TODO: More graphically aware decoders void OnCmbTagSelectedIndexChanged(object sender, EventArgs e) { if (!(cmbTag.SelectedValue is MediaTagWithData tagWithData)) { return; } // TODO: Decoders should be able to handle tags with/without length header txtPrintHex.Text = PrintHex.ByteArrayToHexArrayString(tagWithData.Data, HEX_COLUMNS); tabDecoded.Visible = true; switch (tagWithData.Tag) { case MediaTagType.CD_TOC: txtDecoded.Text = TOC.Prettify(tagWithData.Data); break; case MediaTagType.CD_SessionInfo: txtDecoded.Text = Session.Prettify(tagWithData.Data); break; case MediaTagType.CD_FullTOC: txtDecoded.Text = FullTOC.Prettify(tagWithData.Data); break; case MediaTagType.CD_PMA: txtDecoded.Text = PMA.Prettify(tagWithData.Data); break; case MediaTagType.CD_ATIP: txtDecoded.Text = ATIP.Prettify(tagWithData.Data); break; case MediaTagType.CD_TEXT: txtDecoded.Text = CDTextOnLeadIn.Prettify(tagWithData.Data); break; case MediaTagType.CD_MCN: txtDecoded.Text = Encoding.ASCII.GetString(tagWithData.Data); break; case MediaTagType.DVD_PFI: txtDecoded.Text = PFI.Prettify(tagWithData.Data); break; case MediaTagType.DVD_CMI: txtDecoded.Text = CSS_CPRM.PrettifyLeadInCopyright(tagWithData.Data); break; case MediaTagType.DVDRAM_DDS: txtDecoded.Text = DDS.Prettify(tagWithData.Data); break; case MediaTagType.DVDRAM_SpareArea: txtDecoded.Text = Spare.Prettify(tagWithData.Data); break; case MediaTagType.DVDR_PFI: txtDecoded.Text = PFI.Prettify(tagWithData.Data); break; case MediaTagType.HDDVD_MediumStatus: txtDecoded.Text = PFI.Prettify(tagWithData.Data); break; case MediaTagType.BD_DI: txtDecoded.Text = DI.Prettify(tagWithData.Data); break; case MediaTagType.BD_BCA: txtDecoded.Text = BCA.Prettify(tagWithData.Data); break; case MediaTagType.BD_DDS: txtDecoded.Text = Decoders.Bluray.DDS.Prettify(tagWithData.Data); break; case MediaTagType.BD_CartridgeStatus: txtDecoded.Text = Cartridge.Prettify(tagWithData.Data); break; case MediaTagType.BD_SpareArea: txtDecoded.Text = Decoders.Bluray.Spare.Prettify(tagWithData.Data); break; case MediaTagType.MMC_WriteProtection: txtDecoded.Text = WriteProtect.PrettifyWriteProtectionStatus(tagWithData.Data); break; case MediaTagType.MMC_DiscInformation: txtDecoded.Text = DiscInformation.Prettify(tagWithData.Data); break; case MediaTagType.SCSI_INQUIRY: txtDecoded.Text = Inquiry.Prettify(tagWithData.Data); break; case MediaTagType.SCSI_MODEPAGE_2A: txtDecoded.Text = Modes.PrettifyModePage_2A(tagWithData.Data); break; case MediaTagType.ATA_IDENTIFY: case MediaTagType.ATAPI_IDENTIFY: txtDecoded.Text = Identify.Prettify(tagWithData.Data); break; case MediaTagType.Xbox_SecuritySector: txtDecoded.Text = SS.Prettify(tagWithData.Data); break; case MediaTagType.SCSI_MODESENSE_6: txtDecoded.Text = Modes.PrettifyModeHeader6(tagWithData.Data, PeripheralDeviceTypes.DirectAccess); break; case MediaTagType.SCSI_MODESENSE_10: txtDecoded.Text = Modes.PrettifyModeHeader10(tagWithData.Data, PeripheralDeviceTypes.DirectAccess); break; case MediaTagType.Xbox_DMI: txtDecoded.Text = DMI.IsXbox360(tagWithData.Data) ? DMI.PrettifyXbox360(tagWithData.Data) : DMI.PrettifyXbox(tagWithData.Data); break; default: tabDecoded.Visible = false; break; } }
public ImageInfoViewModel(string imagePath, IFilter filter, IMediaImage imageFormat, Window view) { _imagePath = imagePath; _filter = filter; _imageFormat = imageFormat; IAssetLoader assets = AvaloniaLocator.Current.GetService <IAssetLoader>(); MediaTagsList = new ObservableCollection <string>(); SectorTagsList = new ObservableCollection <string>(); Sessions = new ObservableCollection <Session>(); Tracks = new ObservableCollection <Track>(); DumpHardwareList = new ObservableCollection <DumpHardwareModel>(); EntropyCommand = ReactiveCommand.Create(ExecuteEntropyCommand); VerifyCommand = ReactiveCommand.Create(ExecuteVerifyCommand); ChecksumCommand = ReactiveCommand.Create(ExecuteChecksumCommand); ConvertCommand = ReactiveCommand.Create(ExecuteConvertCommand); CreateSidecarCommand = ReactiveCommand.Create(ExecuteCreateSidecarCommand); ViewSectorsCommand = ReactiveCommand.Create(ExecuteViewSectorsCommand); DecodeMediaTagCommand = ReactiveCommand.Create(ExecuteDecodeMediaTagCommand); var genericHddIcon = new Bitmap(assets.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-harddisk.png"))); var genericOpticalIcon = new Bitmap(assets.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-optical.png"))); var genericFolderIcon = new Bitmap(assets.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/inode-directory.png"))); var mediaResource = new Uri($"avares://Aaru.Gui/Assets/Logos/Media/{imageFormat.Info.MediaType}.png"); MediaLogo = assets.Exists(mediaResource) ? new Bitmap(assets.Open(mediaResource)) : imageFormat.Info.XmlMediaType == XmlMediaType.BlockMedia ? genericHddIcon : imageFormat.Info.XmlMediaType == XmlMediaType.OpticalDisc ? genericOpticalIcon : genericFolderIcon; ImagePathText = $"Path: {imagePath}"; FilterText = $"Filter: {filter.Name}"; ImageIdentifiedText = $"Image format identified by {imageFormat.Name} ({imageFormat.Id})."; ImageFormatText = !string.IsNullOrWhiteSpace(imageFormat.Info.Version) ? $"Format: {imageFormat.Format} version {imageFormat.Info.Version}" : $"Format: {imageFormat.Format}"; ImageSizeText = $"Image without headers is {imageFormat.Info.ImageSize} bytes long"; SectorsText = $"Contains a media of {imageFormat.Info.Sectors} sectors with a maximum sector size of {imageFormat.Info.SectorSize} bytes (if all sectors are of the same size this would be {imageFormat.Info.Sectors * imageFormat.Info.SectorSize} bytes)"; MediaTypeText = $"Contains a media of type {imageFormat.Info.MediaType} and XML type {imageFormat.Info.XmlMediaType}"; HasPartitionsText = $"{(imageFormat.Info.HasPartitions ? "Has" : "Doesn't have")} partitions"; HasSessionsText = $"{(imageFormat.Info.HasSessions ? "Has" : "Doesn't have")} sessions"; if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application)) { ApplicationText = !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion) ? $"Was created with {imageFormat.Info.Application} version {imageFormat.Info.ApplicationVersion}" : $"Was created with {imageFormat.Info.Application}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.Creator)) { CreatorText = $"Created by: {imageFormat.Info.Creator}"; } if (imageFormat.Info.CreationTime != DateTime.MinValue) { CreationTimeText = $"Created on {imageFormat.Info.CreationTime}"; } if (imageFormat.Info.LastModificationTime != DateTime.MinValue) { LastModificationTimeText = $"Last modified on {imageFormat.Info.LastModificationTime}"; } if (imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0) { MediaSequenceText = $"Media is number {imageFormat.Info.MediaSequence} on a set of {imageFormat.Info.LastMediaSequence} medias"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle)) { MediaTitleText = $"Media title: {imageFormat.Info.MediaTitle}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer)) { MediaManufacturerText = $"Media manufacturer: {imageFormat.Info.MediaManufacturer}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel)) { MediaModelText = $"Media model: {imageFormat.Info.MediaModel}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber)) { MediaSerialNumberText = $"Media serial number: {imageFormat.Info.MediaSerialNumber}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode)) { MediaBarcodeText = $"Media barcode: {imageFormat.Info.MediaBarcode}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber)) { MediaPartNumberText = $"Media part number: {imageFormat.Info.MediaPartNumber}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer)) { DriveManufacturerText = $"Drive manufacturer: {imageFormat.Info.DriveManufacturer}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel)) { DriveModelText = $"Drive model: {imageFormat.Info.DriveModel}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber)) { DriveSerialNumberText = $"Drive serial number: {imageFormat.Info.DriveSerialNumber}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision)) { DriveFirmwareRevisionText = $"Drive firmware info: {imageFormat.Info.DriveFirmwareRevision}"; } if (imageFormat.Info.Cylinders > 0 && imageFormat.Info.Heads > 0 && imageFormat.Info.SectorsPerTrack > 0 && imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc && (!(imageFormat is ITapeImage tapeImage) || !tapeImage.IsTape)) { MediaGeometryText = $"Media geometry: {imageFormat.Info.Cylinders} cylinders, {imageFormat.Info.Heads} heads, {imageFormat.Info.SectorsPerTrack} sectors per track"; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Count > 0) { foreach (MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t)) { MediaTagsList.Add(tag.ToString()); } } if (imageFormat.Info.ReadableSectorTags != null && imageFormat.Info.ReadableSectorTags.Count > 0) { foreach (SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t)) { SectorTagsList.Add(tag.ToString()); } } PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess; byte[] scsiInquiryData = null; Inquiry?scsiInquiry = null; Modes.DecodedMode?scsiMode = null; byte[] scsiModeSense6 = null; byte[] scsiModeSense10 = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SCSI_INQUIRY) == true) { scsiInquiryData = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY); scsiDeviceType = (PeripheralDeviceTypes)(scsiInquiryData[0] & 0x1F); scsiInquiry = Inquiry.Decode(scsiInquiryData); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SCSI_MODESENSE_6) == true) { scsiModeSense6 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6); scsiMode = Modes.DecodeMode6(scsiModeSense6, scsiDeviceType); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SCSI_MODESENSE_10) == true) { scsiModeSense10 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10); scsiMode = Modes.DecodeMode10(scsiModeSense10, scsiDeviceType); } ScsiInfo = new ScsiInfo { DataContext = new ScsiInfoViewModel(scsiInquiryData, scsiInquiry, null, scsiMode, scsiDeviceType, scsiModeSense6, scsiModeSense10, null, view) }; byte[] ataIdentify = null; byte[] atapiIdentify = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.ATA_IDENTIFY) == true) { ataIdentify = imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.ATAPI_IDENTIFY) == true) { atapiIdentify = imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY); } AtaInfo = new AtaInfo { DataContext = new AtaInfoViewModel(ataIdentify, atapiIdentify, null, view) }; byte[] toc = null; TOC.CDTOC? decodedToc = null; byte[] fullToc = null; FullTOC.CDFullTOC? decodedFullToc = null; byte[] pma = null; byte[] atip = null; ATIP.CDATIP decodedAtip = null; byte[] cdtext = null; CDTextOnLeadIn.CDText?decodedCdText = null; string mediaCatalogueNumber = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_TOC) == true) { toc = imageFormat.ReadDiskTag(MediaTagType.CD_TOC); if (toc.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0)); if (dataLen + 2 != toc.Length) { byte[] tmp = new byte[toc.Length + 2]; Array.Copy(toc, 0, tmp, 2, toc.Length); tmp[0] = (byte)((toc.Length & 0xFF00) >> 8); tmp[1] = (byte)(toc.Length & 0xFF); toc = tmp; } decodedToc = TOC.Decode(toc); } } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_FullTOC) == true) { fullToc = imageFormat.ReadDiskTag(MediaTagType.CD_FullTOC); if (fullToc.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(fullToc, 0)); if (dataLen + 2 != fullToc.Length) { byte[] tmp = new byte[fullToc.Length + 2]; Array.Copy(fullToc, 0, tmp, 2, fullToc.Length); tmp[0] = (byte)((fullToc.Length & 0xFF00) >> 8); tmp[1] = (byte)(fullToc.Length & 0xFF); fullToc = tmp; } decodedFullToc = FullTOC.Decode(fullToc); } } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_PMA) == true) { pma = imageFormat.ReadDiskTag(MediaTagType.CD_PMA); if (pma.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0)); if (dataLen + 2 != pma.Length) { byte[] tmp = new byte[pma.Length + 2]; Array.Copy(pma, 0, tmp, 2, pma.Length); tmp[0] = (byte)((pma.Length & 0xFF00) >> 8); tmp[1] = (byte)(pma.Length & 0xFF); pma = tmp; } } } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_ATIP) == true) { atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0)); if (dataLen + 4 != atip.Length) { byte[] tmp = new byte[atip.Length + 4]; Array.Copy(atip, 0, tmp, 4, atip.Length); tmp[0] = (byte)((atip.Length & 0xFF000000) >> 24); tmp[1] = (byte)((atip.Length & 0xFF0000) >> 16); tmp[2] = (byte)((atip.Length & 0xFF00) >> 8); tmp[3] = (byte)(atip.Length & 0xFF); atip = tmp; } decodedAtip = ATIP.Decode(atip); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_TEXT) == true) { cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0)); if (dataLen + 4 != cdtext.Length) { byte[] tmp = new byte[cdtext.Length + 4]; Array.Copy(cdtext, 0, tmp, 4, cdtext.Length); tmp[0] = (byte)((cdtext.Length & 0xFF000000) >> 24); tmp[1] = (byte)((cdtext.Length & 0xFF0000) >> 16); tmp[2] = (byte)((cdtext.Length & 0xFF00) >> 8); tmp[3] = (byte)(cdtext.Length & 0xFF); cdtext = tmp; } decodedCdText = CDTextOnLeadIn.Decode(cdtext); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_MCN) == true) { byte[] mcn = imageFormat.ReadDiskTag(MediaTagType.CD_MCN); mediaCatalogueNumber = Encoding.UTF8.GetString(mcn); } CompactDiscInfo = new CompactDiscInfo { DataContext = new CompactDiscInfoViewModel(toc, atip, null, null, fullToc, pma, cdtext, decodedToc, decodedAtip, null, decodedFullToc, decodedCdText, null, mediaCatalogueNumber, null, view) }; byte[] dvdPfi = null; byte[] dvdDmi = null; byte[] dvdCmi = null; byte[] hddvdCopyrightInformation = null; byte[] dvdBca = null; PFI.PhysicalFormatInformation?decodedPfi = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVD_PFI) == true) { dvdPfi = imageFormat.ReadDiskTag(MediaTagType.DVD_PFI); decodedPfi = PFI.Decode(dvdPfi); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVD_DMI) == true) { dvdDmi = imageFormat.ReadDiskTag(MediaTagType.DVD_DMI); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVD_CMI) == true) { dvdCmi = imageFormat.ReadDiskTag(MediaTagType.DVD_CMI); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.HDDVD_CPI) == true) { hddvdCopyrightInformation = imageFormat.ReadDiskTag(MediaTagType.HDDVD_CPI); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVD_BCA) == true) { dvdBca = imageFormat.ReadDiskTag(MediaTagType.DVD_BCA); } DvdInfo = new DvdInfo { DataContext = new DvdInfoViewModel(imageFormat.Info.MediaType, dvdPfi, dvdDmi, dvdCmi, hddvdCopyrightInformation, dvdBca, null, decodedPfi, view) }; byte[] dvdRamDds = null; byte[] dvdRamCartridgeStatus = null; byte[] dvdRamSpareArea = null; byte[] lastBorderOutRmd = null; byte[] dvdPreRecordedInfo = null; byte[] dvdrMediaIdentifier = null; byte[] dvdrPhysicalInformation = null; byte[] hddvdrMediumStatus = null; byte[] dvdrLayerCapacity = null; byte[] dvdrDlMiddleZoneStart = null; byte[] dvdrDlJumpIntervalSize = null; byte[] dvdrDlManualLayerJumpStartLba = null; byte[] dvdPlusAdip = null; byte[] dvdPlusDcb = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDRAM_DDS) == true) { dvdRamDds = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_DDS); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDRAM_MediumStatus) == true) { dvdRamCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_MediumStatus); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDRAM_SpareArea) == true) { dvdRamSpareArea = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_SpareArea); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDR_RMD) == true) { lastBorderOutRmd = imageFormat.ReadDiskTag(MediaTagType.DVDR_RMD); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDR_PreRecordedInfo) == true) { dvdPreRecordedInfo = imageFormat.ReadDiskTag(MediaTagType.DVDR_PreRecordedInfo); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDR_MediaIdentifier) == true) { dvdrMediaIdentifier = imageFormat.ReadDiskTag(MediaTagType.DVDR_MediaIdentifier); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDR_PFI) == true) { dvdrPhysicalInformation = imageFormat.ReadDiskTag(MediaTagType.DVDR_PFI); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.HDDVD_MediumStatus) == true) { hddvdrMediumStatus = imageFormat.ReadDiskTag(MediaTagType.HDDVD_MediumStatus); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDDL_LayerCapacity) == true) { dvdrLayerCapacity = imageFormat.ReadDiskTag(MediaTagType.DVDDL_LayerCapacity); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDDL_MiddleZoneAddress) == true) { dvdrDlMiddleZoneStart = imageFormat.ReadDiskTag(MediaTagType.DVDDL_MiddleZoneAddress); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDDL_JumpIntervalSize) == true) { dvdrDlJumpIntervalSize = imageFormat.ReadDiskTag(MediaTagType.DVDDL_JumpIntervalSize); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDDL_ManualLayerJumpLBA) == true) { dvdrDlManualLayerJumpStartLba = imageFormat.ReadDiskTag(MediaTagType.DVDDL_ManualLayerJumpLBA); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVD_ADIP) == true) { dvdPlusAdip = imageFormat.ReadDiskTag(MediaTagType.DVD_ADIP); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DCB) == true) { dvdPlusDcb = imageFormat.ReadDiskTag(MediaTagType.DCB); } DvdWritableInfo = new DvdWritableInfo { DataContext = new DvdWritableInfoViewModel(imageFormat.Info.MediaType, dvdRamDds, dvdRamCartridgeStatus, dvdRamSpareArea, lastBorderOutRmd, dvdPreRecordedInfo, dvdrMediaIdentifier, dvdrPhysicalInformation, hddvdrMediumStatus, null, dvdrLayerCapacity, dvdrDlMiddleZoneStart, dvdrDlJumpIntervalSize, dvdrDlManualLayerJumpStartLba, null, dvdPlusAdip, dvdPlusDcb, view) }; byte[] blurayBurstCuttingArea = null; byte[] blurayCartridgeStatus = null; byte[] blurayDds = null; byte[] blurayDiscInformation = null; byte[] blurayPowResources = null; byte[] bluraySpareAreaInformation = null; byte[] blurayTrackResources = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.BD_BCA) == true) { blurayBurstCuttingArea = imageFormat.ReadDiskTag(MediaTagType.BD_BCA); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.BD_CartridgeStatus) == true) { blurayCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.BD_CartridgeStatus); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.BD_DDS) == true) { blurayDds = imageFormat.ReadDiskTag(MediaTagType.BD_DDS); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.BD_DI) == true) { blurayDiscInformation = imageFormat.ReadDiskTag(MediaTagType.BD_DI); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_POWResourcesInformation) == true) { blurayPowResources = imageFormat.ReadDiskTag(MediaTagType.MMC_POWResourcesInformation); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.BD_SpareArea) == true) { bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.BD_SpareArea); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_TrackResourcesInformation) == true) { bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.MMC_TrackResourcesInformation); } BlurayInfo = new BlurayInfo { DataContext = new BlurayInfoViewModel(blurayDiscInformation, blurayBurstCuttingArea, blurayDds, blurayCartridgeStatus, bluraySpareAreaInformation, blurayPowResources, blurayTrackResources, null, null, view) }; byte[] xboxDmi = null; byte[] xboxSecuritySector = null; SS.SecuritySector?decodedXboxSecuritySector = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.Xbox_DMI) == true) { xboxDmi = imageFormat.ReadDiskTag(MediaTagType.Xbox_DMI); } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.Xbox_SecuritySector) == true) { xboxSecuritySector = imageFormat.ReadDiskTag(MediaTagType.Xbox_SecuritySector); decodedXboxSecuritySector = SS.Decode(xboxSecuritySector); } XboxInfo = new XboxInfo { DataContext = new XboxInfoViewModel(null, xboxDmi, xboxSecuritySector, decodedXboxSecuritySector, view) }; byte[] pcmciaCis = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.PCMCIA_CIS) == true) { pcmciaCis = imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS); } PcmciaInfo = new PcmciaInfo { DataContext = new PcmciaInfoViewModel(pcmciaCis, view) }; DeviceType deviceType = DeviceType.Unknown; byte[] cid = null; byte[] csd = null; byte[] ocr = null; byte[] extendedCsd = null; byte[] scr = null; if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_CID) == true) { cid = imageFormat.ReadDiskTag(MediaTagType.SD_CID); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_CSD) == true) { csd = imageFormat.ReadDiskTag(MediaTagType.SD_CSD); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_OCR) == true) { ocr = imageFormat.ReadDiskTag(MediaTagType.SD_OCR); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_SCR) == true) { scr = imageFormat.ReadDiskTag(MediaTagType.SD_SCR); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_CID) == true) { cid = imageFormat.ReadDiskTag(MediaTagType.MMC_CID); deviceType = DeviceType.MMC; } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_CSD) == true) { csd = imageFormat.ReadDiskTag(MediaTagType.MMC_CSD); deviceType = DeviceType.MMC; } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_OCR) == true) { ocr = imageFormat.ReadDiskTag(MediaTagType.MMC_OCR); deviceType = DeviceType.MMC; } if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_ExtendedCSD) == true) { extendedCsd = imageFormat.ReadDiskTag(MediaTagType.MMC_ExtendedCSD); deviceType = DeviceType.MMC; } SdMmcInfo = new SdMmcInfo { DataContext = new SdMmcInfoViewModel(deviceType, cid, csd, ocr, extendedCsd, scr) }; if (imageFormat is IOpticalMediaImage opticalMediaImage) { try { if (opticalMediaImage.Sessions != null && opticalMediaImage.Sessions.Count > 0) { foreach (Session session in opticalMediaImage.Sessions) { Sessions.Add(session); } } } catch { // ignored } try { if (opticalMediaImage.Tracks != null && opticalMediaImage.Tracks.Count > 0) { foreach (Track track in opticalMediaImage.Tracks) { Tracks.Add(track); } } } catch { // ignored } } if (imageFormat.DumpHardware is null) { return; } foreach (DumpHardwareType dump in imageFormat.DumpHardware) { foreach (ExtentType extent in dump.Extents) { DumpHardwareList.Add(new DumpHardwareModel { Manufacturer = dump.Manufacturer, Model = dump.Model, Serial = dump.Serial, SoftwareName = dump.Software.Name, SoftwareVersion = dump.Software.Version, OperatingSystem = dump.Software.OperatingSystem, Start = extent.Start, End = extent.End }); } } }
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(); }
ScanResults Scsi() { var results = new ScanResults(); MhddLog mhddLog; IbgLog ibgLog; byte[] senseBuf; bool sense = false; results.Blocks = 0; uint blockSize = 0; ushort currentProfile = 0x0001; if (dev.IsRemovable) { sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); if (sense) { InitProgress?.Invoke(); FixedSense?decSense = Sense.DecodeFixed(senseBuf); if (decSense.HasValue) { if (decSense.Value.ASC == 0x3A) { int leftRetries = 5; while (leftRetries > 0) { PulseProgress?.Invoke("Waiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); if (!sense) { break; } leftRetries--; } if (sense) { StoppingErrorMessage?.Invoke("Please insert media in drive"); return(results); } } else if (decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01) { int leftRetries = 10; while (leftRetries > 0) { PulseProgress?.Invoke("Waiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); if (!sense) { break; } leftRetries--; } if (sense) { StoppingErrorMessage?. Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); return(results); } } // These should be trapped by the OS but seems in some cases they're not else if (decSense.Value.ASC == 0x28) { int leftRetries = 10; while (leftRetries > 0) { PulseProgress?.Invoke("Waiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); if (!sense) { break; } leftRetries--; } if (sense) { StoppingErrorMessage?. Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); return(results); } } else { StoppingErrorMessage?. Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); return(results); } } else { StoppingErrorMessage?.Invoke("Unknown testing unit was ready."); return(results); } EndProgress?.Invoke(); } } Reader scsiReader = null; switch (dev.ScsiType) { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: case PeripheralDeviceTypes.OCRWDevice: case PeripheralDeviceTypes.OpticalDevice: case PeripheralDeviceTypes.SimplifiedDevice: case PeripheralDeviceTypes.WriteOnceDevice: scsiReader = new Reader(dev, dev.Timeout, null); results.Blocks = scsiReader.GetDeviceBlocks(); if (scsiReader.FindReadCommand()) { StoppingErrorMessage?.Invoke("Unable to read medium."); return(results); } blockSize = scsiReader.LogicalBlockSize; if (results.Blocks != 0 && blockSize != 0) { results.Blocks++; UpdateStatus?. Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {results.Blocks * (ulong)blockSize} bytes)"); } break; case PeripheralDeviceTypes.SequentialAccess: StoppingErrorMessage?.Invoke("Scanning will never be supported on SCSI Streaming Devices." + Environment.NewLine + "It has no sense to do it, and it will put too much strain on the tape."); return(results); } if (results.Blocks == 0) { StoppingErrorMessage?.Invoke("Unable to read medium or empty medium present..."); return(results); } bool compactDisc = true; FullTOC.CDFullTOC?toc = null; if (dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) { sense = dev.GetConfiguration(out byte[] cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out _); if (!sense) { Features.SeparatedFeatures ftr = Features.Separate(cmdBuf); currentProfile = ftr.CurrentProfile; switch (ftr.CurrentProfile) { case 0x0005: case 0x0008: case 0x0009: case 0x000A: case 0x0020: case 0x0021: case 0x0022: break; default: compactDisc = false; break; } } if (compactDisc) { currentProfile = 0x0008; // We discarded all discs that falsify a TOC before requesting a real TOC // No TOC, no CD (or an empty one) bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _); if (!tocSense) { toc = FullTOC.Decode(cmdBuf); } } } else { compactDisc = false; } uint blocksToRead = 64; results.A = 0; // <3ms results.B = 0; // >=3ms, <10ms results.C = 0; // >=10ms, <50ms results.D = 0; // >=50ms, <150ms results.E = 0; // >=150ms, <500ms results.F = 0; // >=500ms results.Errored = 0; DateTime start; DateTime end; results.ProcessingTime = 0; results.TotalTime = 0; double currentSpeed = 0; results.MaxSpeed = double.MinValue; results.MinSpeed = double.MaxValue; results.UnreadableSectors = new List <ulong>(); if (compactDisc) { if (toc == null) { StoppingErrorMessage?.Invoke("Error trying to decode TOC..."); return(results); } bool readcd = !dev.ReadCd(out _, out senseBuf, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); if (readcd) { UpdateStatus?.Invoke("Using MMC READ CD command."); } start = DateTime.UtcNow; while (true) { if (readcd) { sense = dev.ReadCd(out _, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); if (dev.Error) { blocksToRead /= 2; } } if (!dev.Error || blocksToRead == 1) { break; } } if (dev.Error) { StoppingErrorMessage?. Invoke($"Device error {dev.LastError} trying to guess ideal transfer length."); return(results); } UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time."); InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, currentProfile); mhddLog = new MhddLog(mhddLogPath, dev, results.Blocks, blockSize, blocksToRead, false); ibgLog = new IbgLog(ibgLogPath, currentProfile); DateTime timeSpeedStart = DateTime.UtcNow; ulong sectorSpeedStart = 0; InitProgress?.Invoke(); for (ulong i = 0; i < results.Blocks; i += blocksToRead) { if (aborted) { break; } double cmdDuration = 0; if (results.Blocks - i < blocksToRead) { blocksToRead = (uint)(results.Blocks - i); } #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator if (currentSpeed > results.MaxSpeed && currentSpeed != 0) { results.MaxSpeed = currentSpeed; } if (currentSpeed < results.MinSpeed && currentSpeed != 0) { results.MinSpeed = currentSpeed; } #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)", (long)i, (long)results.Blocks); if (readcd) { sense = dev.ReadCd(out _, out senseBuf, (uint)i, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration); results.ProcessingTime += cmdDuration; } if (!sense) { if (cmdDuration >= 500) { results.F += blocksToRead; } else if (cmdDuration >= 150) { results.E += blocksToRead; } else if (cmdDuration >= 50) { results.D += blocksToRead; } else if (cmdDuration >= 10) { results.C += blocksToRead; } else if (cmdDuration >= 3) { results.B += blocksToRead; } else { results.A += blocksToRead; } ScanTime?.Invoke(i, cmdDuration); mhddLog.Write(i, cmdDuration); ibgLog.Write(i, currentSpeed * 1024); } else { AaruConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}", Sense.PrettifySense(senseBuf)); FixedSense?senseDecoded = Sense.DecodeFixed(senseBuf); if (senseDecoded.HasValue) { // TODO: This error happens when changing from track type afaik. Need to solve that more cleanly // LOGICAL BLOCK ADDRESS OUT OF RANGE if ((senseDecoded.Value.ASC != 0x21 || senseDecoded.Value.ASCQ != 0x00) && // ILLEGAL MODE FOR THIS TRACK (requesting sectors as-is, this is a firmware misconception when audio sectors // are in a track where subchannel indicates data) (senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00)) { results.Errored += blocksToRead; for (ulong b = i; b < i + blocksToRead; b++) { results.UnreadableSectors.Add(b); } ScanUnreadable?.Invoke(i); mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(i, 0); } } else { ScanUnreadable?.Invoke(i); results.Errored += blocksToRead; for (ulong b = i; b < i + blocksToRead; b++) { results.UnreadableSectors.Add(b); } mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(i, 0); } } sectorSpeedStart += blocksToRead; double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds; if (elapsed < 1) { continue; } currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed); ScanSpeed?.Invoke(i, currentSpeed * 1024); sectorSpeedStart = 0; timeSpeedStart = DateTime.UtcNow; } end = DateTime.UtcNow; EndProgress?.Invoke(); mhddLog.Close(); ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000), devicePath); } else { start = DateTime.UtcNow; UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time."); InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, currentProfile); mhddLog = new MhddLog(mhddLogPath, dev, results.Blocks, blockSize, blocksToRead, false); ibgLog = new IbgLog(ibgLogPath, currentProfile); DateTime timeSpeedStart = DateTime.UtcNow; ulong sectorSpeedStart = 0; InitProgress?.Invoke(); for (ulong i = 0; i < results.Blocks; i += blocksToRead) { if (aborted) { break; } if (results.Blocks - i < blocksToRead) { blocksToRead = (uint)(results.Blocks - i); } #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator if (currentSpeed > results.MaxSpeed && currentSpeed != 0) { results.MaxSpeed = currentSpeed; } if (currentSpeed < results.MinSpeed && currentSpeed != 0) { results.MinSpeed = currentSpeed; } #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)", (long)i, (long)results.Blocks); sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration); results.ProcessingTime += cmdDuration; if (!sense && !dev.Error) { if (cmdDuration >= 500) { results.F += blocksToRead; } else if (cmdDuration >= 150) { results.E += blocksToRead; } else if (cmdDuration >= 50) { results.D += blocksToRead; } else if (cmdDuration >= 10) { results.C += blocksToRead; } else if (cmdDuration >= 3) { results.B += blocksToRead; } else { results.A += blocksToRead; } ScanTime?.Invoke(i, cmdDuration); mhddLog.Write(i, cmdDuration); ibgLog.Write(i, currentSpeed * 1024); } // TODO: Separate errors on kind of errors. else { ScanUnreadable?.Invoke(i); results.Errored += blocksToRead; for (ulong b = i; b < i + blocksToRead; b++) { results.UnreadableSectors.Add(b); } mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(i, 0); } sectorSpeedStart += blocksToRead; double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds; if (elapsed < 1) { continue; } currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed); ScanSpeed?.Invoke(i, currentSpeed * 1024); sectorSpeedStart = 0; timeSpeedStart = DateTime.UtcNow; } end = DateTime.UtcNow; EndProgress?.Invoke(); mhddLog.Close(); ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000), devicePath); } results.SeekMax = double.MinValue; results.SeekMin = double.MaxValue; results.SeekTotal = 0; const int SEEK_TIMES = 1000; var rnd = new Random(); InitProgress?.Invoke(); for (int i = 0; i < SEEK_TIMES; i++) { if (aborted) { break; } uint seekPos = (uint)rnd.Next((int)results.Blocks); PulseProgress?.Invoke($"Seeking to sector {seekPos}...\t\t"); double seekCur; if (scsiReader.CanSeek) { scsiReader.Seek(seekPos, out seekCur); } else { scsiReader.ReadBlock(out _, seekPos, out seekCur); } #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator if (seekCur > results.SeekMax && seekCur != 0) { results.SeekMax = seekCur; } if (seekCur < results.SeekMin && seekCur != 0) { results.SeekMin = seekCur; } #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator results.SeekTotal += seekCur; GC.Collect(); } EndProgress?.Invoke(); results.ProcessingTime /= 1000; results.TotalTime = (end - start).TotalSeconds; results.AvgSpeed = (blockSize * (double)(results.Blocks + 1)) / 1048576 / results.ProcessingTime; results.SeekTimes = SEEK_TIMES; return(results); }
internal void LoadData(byte[] toc, byte[] atip, byte[] compactDiscInformation, byte[] session, byte[] rawToc, byte[] pma, byte[] cdTextLeadIn, TOC.CDTOC?decodedToc, ATIP.CDATIP?decodedAtip, Session.CDSessionInfo?decodedSession, FullTOC.CDFullTOC?fullToc, CDTextOnLeadIn.CDText?decodedCdTextLeadIn, DiscInformation.StandardDiscInformation?decodedCompactDiscInformation, string mcn, Dictionary <byte, string> isrcs) { tocData = toc; atipData = atip; compactDiscInformationData = compactDiscInformation; sessionData = session; rawTocData = rawToc; pmaData = pma; cdTextLeadInData = cdTextLeadIn; if (decodedCompactDiscInformation.HasValue) { tabCdInformation.Visible = true; txtCdInformation.Text = DiscInformation.Prettify000b(decodedCompactDiscInformation); btnCdInformation.Visible = compactDiscInformation != null; } if (decodedToc.HasValue) { tabCdToc.Visible = true; txtCdToc.Text = TOC.Prettify(decodedToc); btnCdToc.Visible = toc != null; } if (fullToc.HasValue) { tabCdFullToc.Visible = true; txtCdFullToc.Text = FullTOC.Prettify(fullToc); btnCdFullToc.Visible = rawToc != null; } if (decodedSession.HasValue) { tabCdSession.Visible = true; txtCdSession.Text = Session.Prettify(decodedSession); btnCdSession.Visible = session != null; } if (decodedCdTextLeadIn.HasValue) { tabCdText.Visible = true; txtCdText.Text = CDTextOnLeadIn.Prettify(decodedCdTextLeadIn); btnCdText.Visible = cdTextLeadIn != null; } if (decodedAtip.HasValue) { tabCdAtip.Visible = true; txtCdAtip.Text = ATIP.Prettify(atip); btnCdAtip.Visible = atip != null; } if (!string.IsNullOrEmpty(mcn)) { stkMcn.Visible = true; txtMcn.Text = mcn; } if (isrcs != null && isrcs.Count > 0) { grpIsrcs.Visible = true; TreeGridItemCollection isrcsItems = new TreeGridItemCollection(); grdIsrcs.Columns.Add(new GridColumn { HeaderText = "ISRC", DataCell = new TextBoxCell(0) }); grdIsrcs.Columns.Add(new GridColumn { HeaderText = "Track", DataCell = new TextBoxCell(0) }); grdIsrcs.AllowMultipleSelection = false; grdIsrcs.ShowHeader = true; grdIsrcs.DataStore = isrcsItems; foreach (KeyValuePair <byte, string> isrc in isrcs) { isrcsItems.Add(new TreeGridItem { Values = new object[] { isrc.Key.ToString(), isrc.Value } }); } } btnCdPma.Visible = pma != null; tabCdMisc.Visible = stkMcn.Visible || grpIsrcs.Visible || btnCdPma.Visible; Visible = tabCdInformation.Visible || tabCdToc.Visible || tabCdFullToc.Visible || tabCdSession.Visible || tabCdText.Visible || tabCdAtip.Visible || stkMcn.Visible || grpIsrcs.Visible || btnCdPma.Visible; }
public pnlImageInfo(string imagePath, IFilter filter, IMediaImage imageFormat) { this.imagePath = imagePath; this.filter = filter; this.imageFormat = imageFormat; XamlReader.Load(this); Stream logo = ResourceHandler .GetResourceStream($"DiscImageChef.Gui.Assets.Logos.Media.{imageFormat.Info.MediaType}.svg"); /* if(logo != null) * { * svgMediaLogo.SvgStream = logo; * svgMediaLogo.Visible = true; * } * else * {*/ logo = ResourceHandler .GetResourceStream($"DiscImageChef.Gui.Assets.Logos.Media.{imageFormat.Info.MediaType}.png"); if (logo != null) { imgMediaLogo.Image = new Bitmap(logo); imgMediaLogo.Visible = true; } //} lblImagePath.Text = $"Path: {imagePath}"; lblFilter.Text = $"Filter: {filter.Name}"; lblImageFormat.Text = $"Image format identified by {imageFormat.Name} ({imageFormat.Id})."; lblImageFormat.Text = !string.IsNullOrWhiteSpace(imageFormat.Info.Version) ? $"Format: {imageFormat.Format} version {imageFormat.Info.Version}" : $"Format: {imageFormat.Format}"; lblImageSize.Text = $"Image without headers is {imageFormat.Info.ImageSize} bytes long"; lblSectors.Text = $"Contains a media of {imageFormat.Info.Sectors} sectors with a maximum sector size of {imageFormat.Info.SectorSize} bytes (if all sectors are of the same size this would be {imageFormat.Info.Sectors * imageFormat.Info.SectorSize} bytes)"; lblMediaType.Text = $"Contains a media of type {imageFormat.Info.MediaType} and XML type {imageFormat.Info.XmlMediaType}"; lblHasPartitions.Text = $"{(imageFormat.Info.HasPartitions ? "Has" : "Doesn't have")} partitions"; lblHasSessions.Text = $"{(imageFormat.Info.HasSessions ? "Has" : "Doesn't have")} sessions"; if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application)) { lblApplication.Visible = true; lblApplication.Text = !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion) ? $"Was created with {imageFormat.Info.Application} version {imageFormat.Info.ApplicationVersion}" : $"Was created with {imageFormat.Info.Application}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.Creator)) { lblCreator.Visible = true; lblCreator.Text = $"Created by: {imageFormat.Info.Creator}"; } if (imageFormat.Info.CreationTime != DateTime.MinValue) { lblCreationTime.Visible = true; lblCreationTime.Text = $"Created on {imageFormat.Info.CreationTime}"; } if (imageFormat.Info.LastModificationTime != DateTime.MinValue) { lblLastModificationTime.Visible = true; lblLastModificationTime.Text = $"Last modified on {imageFormat.Info.LastModificationTime}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.Comments)) { grpComments.Visible = true; txtComments.Text = imageFormat.Info.Comments; } if (imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0) { lblMediaSequence.Visible = true; lblMediaSequence.Text = $"Media is number {imageFormat.Info.MediaSequence} on a set of {imageFormat.Info.LastMediaSequence} medias"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle)) { lblMediaTitle.Visible = true; lblMediaTitle.Text = $"Media title: {imageFormat.Info.MediaTitle}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer)) { lblMediaManufacturer.Visible = true; lblMediaManufacturer.Text = $"Media manufacturer: {imageFormat.Info.MediaManufacturer}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel)) { lblMediaModel.Visible = true; lblMediaModel.Text = $"Media model: {imageFormat.Info.MediaModel}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber)) { lblMediaSerialNumber.Visible = true; lblMediaSerialNumber.Text = $"Media serial number: {imageFormat.Info.MediaSerialNumber}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode)) { lblMediaBarcode.Visible = true; lblMediaBarcode.Text = $"Media barcode: {imageFormat.Info.MediaBarcode}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber)) { lblMediaPartNumber.Visible = true; lblMediaPartNumber.Text = $"Media part number: {imageFormat.Info.MediaPartNumber}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer)) { lblDriveManufacturer.Visible = true; lblDriveManufacturer.Text = $"Drive manufacturer: {imageFormat.Info.DriveManufacturer}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel)) { lblDriveModel.Visible = true; lblDriveModel.Text = $"Drive model: {imageFormat.Info.DriveModel}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber)) { lblDriveSerialNumber.Visible = true; lblDriveSerialNumber.Text = $"Drive serial number: {imageFormat.Info.DriveSerialNumber}"; } if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision)) { lblDriveFirmwareRevision.Visible = true; lblDriveFirmwareRevision.Text = $"Drive firmware info: {imageFormat.Info.DriveFirmwareRevision}"; } if (imageFormat.Info.Cylinders > 0 && imageFormat.Info.Heads > 0 && imageFormat.Info.SectorsPerTrack > 0 && imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc && (!(imageFormat is ITapeImage tapeImage) || !tapeImage.IsTape)) { lblMediaGeometry.Visible = true; lblMediaGeometry.Text = $"Media geometry: {imageFormat.Info.Cylinders} cylinders, {imageFormat.Info.Heads} heads, {imageFormat.Info.SectorsPerTrack} sectors per track"; } grpMediaInfo.Visible = lblMediaSequence.Visible || lblMediaTitle.Visible || lblMediaManufacturer.Visible || lblMediaModel.Visible || lblMediaSerialNumber.Visible || lblMediaBarcode.Visible || lblMediaPartNumber.Visible; grpDriveInfo.Visible = lblDriveManufacturer.Visible || lblDriveModel.Visible || lblDriveSerialNumber.Visible || lblDriveFirmwareRevision.Visible || lblMediaGeometry.Visible; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Count > 0) { TreeGridItemCollection mediaTagList = new TreeGridItemCollection(); treeMediaTags.Columns.Add(new GridColumn { HeaderText = "Tag", DataCell = new TextBoxCell(0) }); treeMediaTags.AllowMultipleSelection = false; treeMediaTags.ShowHeader = false; treeMediaTags.DataStore = mediaTagList; foreach (MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t)) { mediaTagList.Add(new TreeGridItem { Values = new object[] { tag.ToString() } }); } grpMediaTags.Visible = true; } if (imageFormat.Info.ReadableSectorTags != null && imageFormat.Info.ReadableSectorTags.Count > 0) { TreeGridItemCollection sectorTagList = new TreeGridItemCollection(); treeSectorTags.Columns.Add(new GridColumn { HeaderText = "Tag", DataCell = new TextBoxCell(0) }); treeSectorTags.AllowMultipleSelection = false; treeSectorTags.ShowHeader = false; treeSectorTags.DataStore = sectorTagList; foreach (SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t)) { sectorTagList.Add(new TreeGridItem { Values = new object[] { tag.ToString() } }); } grpSectorTags.Visible = true; } PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess; byte[] scsiInquiryData = null; Inquiry.SCSIInquiry?scsiInquiry = null; Modes.DecodedMode? scsiMode = null; byte[] scsiModeSense6 = null; byte[] scsiModeSense10 = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_INQUIRY)) { scsiInquiryData = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY); scsiDeviceType = (PeripheralDeviceTypes)(scsiInquiryData[0] & 0x1F); scsiInquiry = Inquiry.Decode(scsiInquiryData); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_6)) { scsiModeSense6 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6); scsiMode = Modes.DecodeMode6(scsiModeSense6, scsiDeviceType); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_10)) { scsiModeSense10 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10); scsiMode = Modes.DecodeMode10(scsiModeSense10, scsiDeviceType); } tabScsiInfo tabScsiInfo = new tabScsiInfo(); tabScsiInfo.LoadData(scsiInquiryData, scsiInquiry, null, scsiMode, scsiDeviceType, scsiModeSense6, scsiModeSense10, null); tabInfos.Pages.Add(tabScsiInfo); byte[] ataIdentify = null; byte[] atapiIdentify = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) { ataIdentify = imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATAPI_IDENTIFY)) { atapiIdentify = imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY); } tabAtaInfo tabAtaInfo = new tabAtaInfo(); tabAtaInfo.LoadData(ataIdentify, atapiIdentify, null); tabInfos.Pages.Add(tabAtaInfo); byte[] toc = null; TOC.CDTOC? decodedToc = null; byte[] fullToc = null; FullTOC.CDFullTOC? decodedFullToc = null; byte[] pma = null; byte[] atip = null; ATIP.CDATIP? decodedAtip = null; byte[] cdtext = null; CDTextOnLeadIn.CDText?decodedCdText = null; string mediaCatalogueNumber = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_TOC)) { toc = imageFormat.ReadDiskTag(MediaTagType.CD_TOC); if (toc.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0)); if (dataLen + 2 != toc.Length) { byte[] tmp = new byte[toc.Length + 2]; Array.Copy(toc, 0, tmp, 2, toc.Length); tmp[0] = (byte)((toc.Length & 0xFF00) >> 8); tmp[1] = (byte)(toc.Length & 0xFF); toc = tmp; } decodedToc = TOC.Decode(toc); } } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_FullTOC)) { fullToc = imageFormat.ReadDiskTag(MediaTagType.CD_FullTOC); if (fullToc.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(fullToc, 0)); if (dataLen + 2 != fullToc.Length) { byte[] tmp = new byte[fullToc.Length + 2]; Array.Copy(fullToc, 0, tmp, 2, fullToc.Length); tmp[0] = (byte)((fullToc.Length & 0xFF00) >> 8); tmp[1] = (byte)(fullToc.Length & 0xFF); fullToc = tmp; } decodedFullToc = FullTOC.Decode(fullToc); } } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_PMA)) { pma = imageFormat.ReadDiskTag(MediaTagType.CD_PMA); if (pma.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0)); if (dataLen + 2 != pma.Length) { byte[] tmp = new byte[pma.Length + 2]; Array.Copy(pma, 0, tmp, 2, pma.Length); tmp[0] = (byte)((pma.Length & 0xFF00) >> 8); tmp[1] = (byte)(pma.Length & 0xFF); pma = tmp; } } } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_ATIP)) { atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0)); if (dataLen + 4 != atip.Length) { byte[] tmp = new byte[atip.Length + 4]; Array.Copy(atip, 0, tmp, 4, atip.Length); tmp[0] = (byte)((atip.Length & 0xFF000000) >> 24); tmp[1] = (byte)((atip.Length & 0xFF0000) >> 16); tmp[2] = (byte)((atip.Length & 0xFF00) >> 8); tmp[3] = (byte)(atip.Length & 0xFF); atip = tmp; } decodedAtip = ATIP.Decode(atip); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_TEXT)) { cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0)); if (dataLen + 4 != cdtext.Length) { byte[] tmp = new byte[cdtext.Length + 4]; Array.Copy(cdtext, 0, tmp, 4, cdtext.Length); tmp[0] = (byte)((cdtext.Length & 0xFF000000) >> 24); tmp[1] = (byte)((cdtext.Length & 0xFF0000) >> 16); tmp[2] = (byte)((cdtext.Length & 0xFF00) >> 8); tmp[3] = (byte)(cdtext.Length & 0xFF); cdtext = tmp; } decodedCdText = CDTextOnLeadIn.Decode(cdtext); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_MCN)) { byte[] mcn = imageFormat.ReadDiskTag(MediaTagType.CD_MCN); mediaCatalogueNumber = Encoding.UTF8.GetString(mcn); } tabCompactDiscInfo tabCompactDiscInfo = new tabCompactDiscInfo(); tabCompactDiscInfo.LoadData(toc, atip, null, null, fullToc, pma, cdtext, decodedToc, decodedAtip, null, decodedFullToc, decodedCdText, null, mediaCatalogueNumber, null); tabInfos.Pages.Add(tabCompactDiscInfo); byte[] dvdPfi = null; byte[] dvdDmi = null; byte[] dvdCmi = null; byte[] hddvdCopyrightInformation = null; byte[] dvdBca = null; PFI.PhysicalFormatInformation?decodedPfi = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_PFI)) { dvdPfi = imageFormat.ReadDiskTag(MediaTagType.DVD_PFI); decodedPfi = PFI.Decode(dvdPfi); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_DMI)) { dvdDmi = imageFormat.ReadDiskTag(MediaTagType.DVD_DMI); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_CMI)) { dvdCmi = imageFormat.ReadDiskTag(MediaTagType.DVD_CMI); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.HDDVD_CPI)) { hddvdCopyrightInformation = imageFormat.ReadDiskTag(MediaTagType.HDDVD_CPI); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_BCA)) { dvdBca = imageFormat.ReadDiskTag(MediaTagType.DVD_BCA); } tabDvdInfo tabDvdInfo = new tabDvdInfo(); tabDvdInfo.LoadData(imageFormat.Info.MediaType, dvdPfi, dvdDmi, dvdCmi, hddvdCopyrightInformation, dvdBca, null, decodedPfi); tabInfos.Pages.Add(tabDvdInfo); byte[] dvdRamDds = null; byte[] dvdRamCartridgeStatus = null; byte[] dvdRamSpareArea = null; byte[] lastBorderOutRmd = null; byte[] dvdPreRecordedInfo = null; byte[] dvdrMediaIdentifier = null; byte[] dvdrPhysicalInformation = null; byte[] hddvdrMediumStatus = null; byte[] dvdrLayerCapacity = null; byte[] dvdrDlMiddleZoneStart = null; byte[] dvdrDlJumpIntervalSize = null; byte[] dvdrDlManualLayerJumpStartLba = null; byte[] dvdPlusAdip = null; byte[] dvdPlusDcb = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_DDS)) { dvdRamDds = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_DDS); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_MediumStatus)) { dvdRamCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_MediumStatus); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_SpareArea)) { dvdRamSpareArea = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_SpareArea); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_RMD)) { lastBorderOutRmd = imageFormat.ReadDiskTag(MediaTagType.DVDR_RMD); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_PreRecordedInfo)) { dvdPreRecordedInfo = imageFormat.ReadDiskTag(MediaTagType.DVDR_PreRecordedInfo); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_MediaIdentifier)) { dvdrMediaIdentifier = imageFormat.ReadDiskTag(MediaTagType.DVDR_MediaIdentifier); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_PFI)) { dvdrPhysicalInformation = imageFormat.ReadDiskTag(MediaTagType.DVDR_PFI); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.HDDVD_MediumStatus)) { hddvdrMediumStatus = imageFormat.ReadDiskTag(MediaTagType.HDDVD_MediumStatus); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_LayerCapacity)) { dvdrLayerCapacity = imageFormat.ReadDiskTag(MediaTagType.DVDDL_LayerCapacity); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_MiddleZoneAddress)) { dvdrDlMiddleZoneStart = imageFormat.ReadDiskTag(MediaTagType.DVDDL_MiddleZoneAddress); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_JumpIntervalSize)) { dvdrDlJumpIntervalSize = imageFormat.ReadDiskTag(MediaTagType.DVDDL_JumpIntervalSize); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_ManualLayerJumpLBA)) { dvdrDlManualLayerJumpStartLba = imageFormat.ReadDiskTag(MediaTagType.DVDDL_ManualLayerJumpLBA); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_ADIP)) { dvdPlusAdip = imageFormat.ReadDiskTag(MediaTagType.DVD_ADIP); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DCB)) { dvdPlusDcb = imageFormat.ReadDiskTag(MediaTagType.DCB); } tabDvdWritableInfo tabDvdWritableInfo = new tabDvdWritableInfo(); tabDvdWritableInfo.LoadData(imageFormat.Info.MediaType, dvdRamDds, dvdRamCartridgeStatus, dvdRamSpareArea, lastBorderOutRmd, dvdPreRecordedInfo, dvdrMediaIdentifier, dvdrPhysicalInformation, hddvdrMediumStatus, null, dvdrLayerCapacity, dvdrDlMiddleZoneStart, dvdrDlJumpIntervalSize, dvdrDlManualLayerJumpStartLba, null, dvdPlusAdip, dvdPlusDcb); tabInfos.Pages.Add(tabDvdWritableInfo); byte[] blurayBurstCuttingArea = null; byte[] blurayCartridgeStatus = null; byte[] blurayDds = null; byte[] blurayDiscInformation = null; byte[] blurayPowResources = null; byte[] bluraySpareAreaInformation = null; byte[] blurayTrackResources = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_BCA)) { blurayBurstCuttingArea = imageFormat.ReadDiskTag(MediaTagType.BD_BCA); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_CartridgeStatus)) { blurayCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.BD_CartridgeStatus); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DDS)) { blurayDds = imageFormat.ReadDiskTag(MediaTagType.BD_DDS); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DI)) { blurayDiscInformation = imageFormat.ReadDiskTag(MediaTagType.BD_DI); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_POWResourcesInformation)) { blurayPowResources = imageFormat.ReadDiskTag(MediaTagType.MMC_POWResourcesInformation); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_SpareArea)) { bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.BD_SpareArea); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_TrackResourcesInformation)) { bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.MMC_TrackResourcesInformation); } tabBlurayInfo tabBlurayInfo = new tabBlurayInfo(); tabBlurayInfo.LoadData(blurayDiscInformation, blurayBurstCuttingArea, blurayDds, blurayCartridgeStatus, bluraySpareAreaInformation, blurayPowResources, blurayTrackResources, null, null); tabInfos.Pages.Add(tabBlurayInfo); byte[] xboxDmi = null; byte[] xboxSecuritySector = null; SS.SecuritySector?decodedXboxSecuritySector = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_DMI)) { xboxDmi = imageFormat.ReadDiskTag(MediaTagType.Xbox_DMI); } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_SecuritySector)) { xboxSecuritySector = imageFormat.ReadDiskTag(MediaTagType.Xbox_SecuritySector); decodedXboxSecuritySector = SS.Decode(xboxSecuritySector); } tabXboxInfo tabXboxInfo = new tabXboxInfo(); tabXboxInfo.LoadData(null, xboxDmi, xboxSecuritySector, decodedXboxSecuritySector); tabInfos.Pages.Add(tabXboxInfo); byte[] pcmciaCis = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS)) { pcmciaCis = imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS); } tabPcmciaInfo tabPcmciaInfo = new tabPcmciaInfo(); tabPcmciaInfo.LoadData(pcmciaCis); tabInfos.Pages.Add(tabPcmciaInfo); DeviceType deviceType = DeviceType.Unknown; byte[] cid = null; byte[] csd = null; byte[] ocr = null; byte[] extendedCsd = null; byte[] scr = null; if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CID)) { cid = imageFormat.ReadDiskTag(MediaTagType.SD_CID); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CSD)) { csd = imageFormat.ReadDiskTag(MediaTagType.SD_CSD); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_OCR)) { ocr = imageFormat.ReadDiskTag(MediaTagType.SD_OCR); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_SCR)) { scr = imageFormat.ReadDiskTag(MediaTagType.SD_SCR); deviceType = DeviceType.SecureDigital; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CID)) { cid = imageFormat.ReadDiskTag(MediaTagType.MMC_CID); deviceType = DeviceType.MMC; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CSD)) { csd = imageFormat.ReadDiskTag(MediaTagType.MMC_CSD); deviceType = DeviceType.MMC; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_OCR)) { ocr = imageFormat.ReadDiskTag(MediaTagType.MMC_OCR); deviceType = DeviceType.MMC; } if (imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_ExtendedCSD)) { extendedCsd = imageFormat.ReadDiskTag(MediaTagType.MMC_ExtendedCSD); deviceType = DeviceType.MMC; } tabSdMmcInfo tabSdMmcInfo = new tabSdMmcInfo(); tabSdMmcInfo.LoadData(deviceType, cid, csd, ocr, extendedCsd, scr); tabInfos.Pages.Add(tabSdMmcInfo); if (imageFormat is IOpticalMediaImage opticalMediaImage) { try { if (opticalMediaImage.Sessions != null && opticalMediaImage.Sessions.Count > 0) { TreeGridItemCollection sessionList = new TreeGridItemCollection(); treeSessions.Columns.Add(new GridColumn { HeaderText = "Session", DataCell = new TextBoxCell(0) }); treeSessions.Columns.Add(new GridColumn { HeaderText = "First track", DataCell = new TextBoxCell(1) }); treeSessions.Columns.Add(new GridColumn { HeaderText = "Last track", DataCell = new TextBoxCell(2) }); treeSessions.Columns.Add(new GridColumn { HeaderText = "Start", DataCell = new TextBoxCell(3) }); treeSessions.Columns.Add(new GridColumn { HeaderText = "End", DataCell = new TextBoxCell(4) }); treeSessions.AllowMultipleSelection = false; treeSessions.ShowHeader = true; treeSessions.DataStore = sessionList; foreach (Session session in opticalMediaImage.Sessions) { sessionList.Add(new TreeGridItem { Values = new object[] { session.SessionSequence, session.StartTrack, session.EndTrack, session.StartSector, session.EndSector } }); } tabSessions.Visible = true; } } catch { // ignored } try { if (opticalMediaImage.Tracks != null && opticalMediaImage.Tracks.Count > 0) { TreeGridItemCollection tracksList = new TreeGridItemCollection(); treeTracks.Columns.Add(new GridColumn { HeaderText = "Track", DataCell = new TextBoxCell(0) }); treeTracks.Columns.Add(new GridColumn { HeaderText = "Type", DataCell = new TextBoxCell(1) }); treeTracks.Columns.Add(new GridColumn { HeaderText = "Bps", DataCell = new TextBoxCell(2) }); treeTracks.Columns.Add(new GridColumn { HeaderText = "Raw bps", DataCell = new TextBoxCell(3) }); treeTracks.Columns.Add(new GridColumn { HeaderText = "Subchannel", DataCell = new TextBoxCell(4) }); treeTracks.Columns.Add(new GridColumn { HeaderText = "Pregap", DataCell = new TextBoxCell(5) }); treeTracks.Columns.Add(new GridColumn { HeaderText = "Start", DataCell = new TextBoxCell(6) }); treeTracks.Columns.Add(new GridColumn { HeaderText = "End", DataCell = new TextBoxCell(7) }); treeTracks.AllowMultipleSelection = false; treeTracks.ShowHeader = true; treeTracks.DataStore = tracksList; foreach (Track track in opticalMediaImage.Tracks) { tracksList.Add(new TreeGridItem { Values = new object[] { track.TrackSequence, track.TrackType, track.TrackBytesPerSector, track.TrackRawBytesPerSector, track.TrackSubchannelType, track.TrackPregap, track.TrackStartSector, track.TrackEndSector } }); } tabTracks.Visible = true; } } catch { // ignored } } if (imageFormat.DumpHardware == null) { return; } TreeGridItemCollection dumpHardwareList = new TreeGridItemCollection(); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "Manufacturer", DataCell = new TextBoxCell(0) }); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "Model", DataCell = new TextBoxCell(1) }); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "Serial", DataCell = new TextBoxCell(2) }); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "Software", DataCell = new TextBoxCell(3) }); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "Version", DataCell = new TextBoxCell(4) }); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "Operating system", DataCell = new TextBoxCell(5) }); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "Start", DataCell = new TextBoxCell(6) }); treeDumpHardware.Columns.Add(new GridColumn { HeaderText = "End", DataCell = new TextBoxCell(7) }); treeDumpHardware.AllowMultipleSelection = false; treeDumpHardware.ShowHeader = true; treeDumpHardware.DataStore = dumpHardwareList; foreach (DumpHardwareType dump in imageFormat.DumpHardware) { foreach (ExtentType extent in dump.Extents) { dumpHardwareList.Add(new TreeGridItem { Values = new object[] { dump.Manufacturer, dump.Model, dump.Serial, dump.Software.Name, dump.Software.Version, dump.Software.OperatingSystem, extent.Start, extent.End } }); } } tabDumpHardware.Visible = true; }
static void DoScsiMediaInfo(bool debug, string outputPrefix, Devices.Device dev) { var scsiInfo = new ScsiInfo(dev); if (!scsiInfo.MediaInserted) { return; } if (scsiInfo.DeviceInfo.ScsiModeSense6 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense6.bin", "SCSI MODE SENSE (6)", scsiInfo.DeviceInfo.ScsiModeSense6); } if (scsiInfo.DeviceInfo.ScsiModeSense10 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense10.bin", "SCSI MODE SENSE (10)", scsiInfo.DeviceInfo.ScsiModeSense10); } switch (dev.ScsiType) { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: case PeripheralDeviceTypes.OCRWDevice: case PeripheralDeviceTypes.OpticalDevice: case PeripheralDeviceTypes.SimplifiedDevice: case PeripheralDeviceTypes.WriteOnceDevice: case PeripheralDeviceTypes.BridgingExpander when dev.Model.StartsWith("MDM", StringComparison.Ordinal) || dev.Model.StartsWith("MDH", StringComparison.Ordinal): if (scsiInfo.ReadCapacity != null) DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity.bin", "SCSI READ CAPACITY", scsiInfo.ReadCapacity); if (scsiInfo.ReadCapacity16 != null) DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity16.bin", "SCSI READ CAPACITY(16)", scsiInfo.ReadCapacity16); if (scsiInfo.Blocks != 0 && scsiInfo.BlockSize != 0) { ulong totalSize = scsiInfo.Blocks * scsiInfo.BlockSize; if (totalSize > 1099511627776) { AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} TiB)", scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1099511627776d); } else if (totalSize > 1073741824) { AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} GiB)", scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1073741824d); } else if (totalSize > 1048576) { AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} MiB)", scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1048576d); } else if (totalSize > 1024) { AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} KiB)", scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1024d); } else { AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", scsiInfo.Blocks, scsiInfo.BlockSize, totalSize); } } break; case PeripheralDeviceTypes.SequentialAccess: if (scsiInfo.DensitySupport != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_ssc_reportdensitysupport_media.bin", "SSC REPORT DENSITY SUPPORT (MEDIA)", scsiInfo.DensitySupport); if (scsiInfo.DensitySupportHeader.HasValue) { AaruConsole.WriteLine("Densities supported by currently inserted media:"); AaruConsole.WriteLine(DensitySupport.PrettifyDensity(scsiInfo.DensitySupportHeader)); } } if (scsiInfo.MediaTypeSupport != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_ssc_reportdensitysupport_medium_media.bin", "SSC REPORT DENSITY SUPPORT (MEDIUM & MEDIA)", scsiInfo.MediaTypeSupport); if (scsiInfo.MediaTypeSupportHeader.HasValue) { AaruConsole.WriteLine("Medium types currently inserted in device:"); AaruConsole.WriteLine(DensitySupport.PrettifyMediumType(scsiInfo.MediaTypeSupportHeader)); } AaruConsole.WriteLine(DensitySupport.PrettifyMediumType(scsiInfo.MediaTypeSupport)); } break; } if (dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) { if (scsiInfo.MmcConfiguration != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_getconfiguration_current.bin", "SCSI GET CONFIGURATION", scsiInfo.MmcConfiguration); } if (scsiInfo.RecognizedFormatLayers != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_formatlayers.bin", "SCSI READ DISC STRUCTURE", scsiInfo.RecognizedFormatLayers); } if (scsiInfo.WriteProtectionStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_writeprotection.bin", "SCSI READ DISC STRUCTURE", scsiInfo.WriteProtectionStatus); } if (scsiInfo.DvdPfi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_pfi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPfi); if (scsiInfo.DecodedPfi.HasValue) { AaruConsole.WriteLine("PFI:\n{0}", PFI.Prettify(scsiInfo.DecodedPfi)); } } if (scsiInfo.DvdDmi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_dmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdDmi); if (DMI.IsXbox(scsiInfo.DvdDmi)) { AaruConsole.WriteLine("Xbox DMI:\n{0}", DMI.PrettifyXbox(scsiInfo.DvdDmi)); } else if (DMI.IsXbox360(scsiInfo.DvdDmi)) { AaruConsole.WriteLine("Xbox 360 DMI:\n{0}", DMI.PrettifyXbox360(scsiInfo.DvdDmi)); } } if (scsiInfo.DvdCmi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_cmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdCmi); AaruConsole.WriteLine("Lead-In CMI:\n{0}", CSS_CPRM.PrettifyLeadInCopyright(scsiInfo.DvdCmi)); } if (scsiInfo.DvdDiscKey != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_disckey.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdDiscKey); } if (scsiInfo.DvdSectorCmi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_sectorcmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdSectorCmi); } if (scsiInfo.DvdBca != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_bca.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdBca); } if (scsiInfo.DvdAacs != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_aacs.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdAacs); } if (scsiInfo.DvdRamDds != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_dds.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamDds); AaruConsole.WriteLine("Disc Definition Structure:\n{0}", DDS.Prettify(scsiInfo.DvdRamDds)); } if (scsiInfo.DvdRamCartridgeStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_status.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamCartridgeStatus); AaruConsole.WriteLine("Medium Status:\n{0}", Cartridge.Prettify(scsiInfo.DvdRamCartridgeStatus)); } if (scsiInfo.DvdRamSpareArea != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_spare.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamSpareArea); AaruConsole.WriteLine("Spare Area Information:\n{0}", Spare.Prettify(scsiInfo.DvdRamSpareArea)); } if (scsiInfo.LastBorderOutRmd != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_lastrmd.bin", "SCSI READ DISC STRUCTURE", scsiInfo.LastBorderOutRmd); } if (scsiInfo.DvdPreRecordedInfo != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_pri.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPreRecordedInfo); if (scsiInfo.DecodedDvdPrePitInformation.HasValue) { AaruConsole.WriteLine("DVD-R(W) Pre-Recorded Information:\n{0}", PRI.Prettify(scsiInfo.DecodedDvdPrePitInformation)); } } if (scsiInfo.DvdrMediaIdentifier != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_mediaid.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrMediaIdentifier); } if (scsiInfo.DvdrPhysicalInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_pfi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrPhysicalInformation); if (scsiInfo.DecodedDvdrPfi.HasValue) { AaruConsole.WriteLine("DVD-R(W) PFI:\n{0}", PFI.Prettify(scsiInfo.DecodedDvdrPfi)); } } if (scsiInfo.DvdPlusAdip != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd+_adip.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPlusAdip); } if (scsiInfo.DvdPlusDcb != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd+_dcb.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPlusDcb); } if (scsiInfo.HddvdCopyrightInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvd_cmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdCopyrightInformation); } if (scsiInfo.HddvdrMediumStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvdr_status.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdrMediumStatus); } if (scsiInfo.HddvdrLastRmd != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvdr_lastrmd.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdrLastRmd); } if (scsiInfo.DvdrLayerCapacity != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_layercap.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrLayerCapacity); } if (scsiInfo.DvdrDlMiddleZoneStart != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_mzs.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlMiddleZoneStart); } if (scsiInfo.DvdrDlJumpIntervalSize != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_jis.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlJumpIntervalSize); } if (scsiInfo.DvdrDlManualLayerJumpStartLba != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_manuallj.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlManualLayerJumpStartLba); } if (scsiInfo.DvdrDlRemapAnchorPoint != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_remapanchor.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlRemapAnchorPoint); } if (scsiInfo.BlurayDiscInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_di.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayDiscInformation); AaruConsole.WriteLine("Blu-ray Disc Information:\n{0}", DI.Prettify(scsiInfo.BlurayDiscInformation)); } if (scsiInfo.BlurayPac != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_pac.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayPac); } if (scsiInfo.BlurayBurstCuttingArea != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_bca.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayBurstCuttingArea); AaruConsole.WriteLine("Blu-ray Burst Cutting Area:\n{0}", BCA.Prettify(scsiInfo.BlurayBurstCuttingArea)); } if (scsiInfo.BlurayDds != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_dds.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayDds); AaruConsole.WriteLine("Blu-ray Disc Definition Structure:\n{0}", Decoders.Bluray.DDS.Prettify(scsiInfo.BlurayDds)); } if (scsiInfo.BlurayCartridgeStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_cartstatus.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayCartridgeStatus); AaruConsole.WriteLine("Blu-ray Cartridge Status:\n{0}", Decoders.Bluray.Cartridge.Prettify(scsiInfo.BlurayCartridgeStatus)); } if (scsiInfo.BluraySpareAreaInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_spare.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BluraySpareAreaInformation); AaruConsole.WriteLine("Blu-ray Spare Area Information:\n{0}", Decoders.Bluray.Spare.Prettify(scsiInfo.BluraySpareAreaInformation)); } if (scsiInfo.BlurayRawDfl != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_dfl.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayRawDfl); } if (scsiInfo.BlurayTrackResources != null) { AaruConsole.WriteLine("Track Resources Information:\n{0}", DiscInformation.Prettify(scsiInfo.BlurayTrackResources)); DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_001b.bin", "SCSI READ DISC INFORMATION", scsiInfo.BlurayTrackResources); } if (scsiInfo.BlurayPowResources != null) { AaruConsole.WriteLine("POW Resources Information:\n{0}", DiscInformation.Prettify(scsiInfo.BlurayPowResources)); DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_010b.bin", "SCSI READ DISC INFORMATION", scsiInfo.BlurayPowResources); } if (scsiInfo.Toc != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_toc.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Toc); if (scsiInfo.DecodedToc.HasValue) { AaruConsole.WriteLine("TOC:\n{0}", TOC.Prettify(scsiInfo.DecodedToc)); } } if (scsiInfo.Atip != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_atip.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Atip); if (scsiInfo.DecodedAtip != null) { AaruConsole.WriteLine("ATIP:\n{0}", ATIP.Prettify(scsiInfo.DecodedAtip)); } } if (scsiInfo.DiscInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_000b.bin", "SCSI READ DISC INFORMATION", scsiInfo.DiscInformation); if (scsiInfo.DecodedDiscInformation.HasValue) { AaruConsole.WriteLine("Standard Disc Information:\n{0}", DiscInformation.Prettify000b(scsiInfo.DecodedDiscInformation)); } } if (scsiInfo.Session != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_session.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Session); if (scsiInfo.DecodedSession.HasValue) { AaruConsole.WriteLine("Session information:\n{0}", Session.Prettify(scsiInfo.DecodedSession)); } } if (scsiInfo.RawToc != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_rawtoc.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.RawToc); if (scsiInfo.FullToc.HasValue) { AaruConsole.WriteLine("Raw TOC:\n{0}", FullTOC.Prettify(scsiInfo.RawToc)); } } if (scsiInfo.Pma != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_pma.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Pma); AaruConsole.WriteLine("PMA:\n{0}", PMA.Prettify(scsiInfo.Pma)); } if (scsiInfo.CdTextLeadIn != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_cdtext.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.CdTextLeadIn); if (scsiInfo.DecodedCdTextLeadIn.HasValue) { AaruConsole.WriteLine("CD-TEXT on Lead-In:\n{0}", CDTextOnLeadIn.Prettify(scsiInfo.DecodedCdTextLeadIn)); } } if (!string.IsNullOrEmpty(scsiInfo.Mcn)) { AaruConsole.WriteLine("MCN: {0}", scsiInfo.Mcn); } if (scsiInfo.Isrcs != null) { foreach (KeyValuePair <byte, string> isrc in scsiInfo.Isrcs) { AaruConsole.WriteLine("Track's {0} ISRC: {1}", isrc.Key, isrc.Value); } } if (scsiInfo.XboxSecuritySector != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_xbox_ss.bin", "KREON EXTRACT SS", scsiInfo.XboxSecuritySector); } if (scsiInfo.DecodedXboxSecuritySector.HasValue) { AaruConsole.WriteLine("Xbox Security Sector:\n{0}", SS.Prettify(scsiInfo.DecodedXboxSecuritySector)); } if (scsiInfo.XgdInfo != null) { AaruConsole.WriteLine("Video layer 0 size: {0} sectors", scsiInfo.XgdInfo.L0Video); AaruConsole.WriteLine("Video layer 1 size: {0} sectors", scsiInfo.XgdInfo.L1Video); AaruConsole.WriteLine("Middle zone size: {0} sectors", scsiInfo.XgdInfo.MiddleZone); AaruConsole.WriteLine("Game data size: {0} sectors", scsiInfo.XgdInfo.GameSize); AaruConsole.WriteLine("Total size: {0} sectors", scsiInfo.XgdInfo.TotalSize); AaruConsole.WriteLine("Real layer break: {0}", scsiInfo.XgdInfo.LayerBreak); AaruConsole.WriteLine(); } } if (scsiInfo.MediaSerialNumber != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_mediaserialnumber.bin", "SCSI READ MEDIA SERIAL NUMBER", scsiInfo.MediaSerialNumber); AaruConsole.Write("Media Serial Number: "); for (int i = 4; i < scsiInfo.MediaSerialNumber.Length; i++) { AaruConsole.Write("{0:X2}", scsiInfo.MediaSerialNumber[i]); } AaruConsole.WriteLine(); } AaruConsole.WriteLine("Media identified as {0}", scsiInfo.MediaType); Statistics.AddMedia(scsiInfo.MediaType, true); if (scsiInfo.Toc != null || scsiInfo.RawToc != null) { Track[] tracks = Dump.GetCdTracks(dev, null, false, out long lastSector, null, null, null, out _, null, null); if (tracks != null) { uint firstLba = (uint)tracks.Min(t => t.TrackStartSector); bool supportsPqSubchannel = Dump.SupportsPqSubchannel(dev, null, null, firstLba); bool supportsRwSubchannel = Dump.SupportsRwSubchannel(dev, null, null, firstLba); // Open main database var ctx = AaruContext.Create(Settings.Settings.MainDbPath); // Search for device in main database Aaru.Database.Models.Device dbDev = ctx.Devices.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model && d.Revision == dev.FirmwareRevision); Dump.SolveTrackPregaps(dev, null, null, tracks, supportsPqSubchannel, supportsRwSubchannel, dbDev, out bool inexactPositioning, false); for (int t = 1; t < tracks.Length; t++) { tracks[t - 1].TrackEndSector = tracks[t].TrackStartSector - 1; } tracks[^ 1].TrackEndSector = (ulong)lastSector;
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); }
/// <summary>Reads the TOC, processes it, returns the track list and last sector</summary> /// <param name="blockSize">Size of the read sector in bytes</param> /// <param name="dev">Device</param> /// <param name="dskType">Disc type</param> /// <param name="dumpLog">Dump log</param> /// <param name="force">Force dump enabled</param> /// <param name="lastSector">Last sector number</param> /// <param name="leadOutStarts">Lead-out starts</param> /// <param name="mediaTags">Media tags</param> /// <param name="stoppingErrorMessage">Stopping error message handler</param> /// <param name="subType">Track subchannel type</param> /// <param name="toc">Full CD TOC</param> /// <param name="trackFlags">Track flags</param> /// <param name="updateStatus">Update status handler</param> /// <returns>List of tracks</returns> public static Track[] GetCdTracks(ref uint blockSize, Device dev, MediaType dskType, DumpLog dumpLog, bool force, out long lastSector, Dictionary <int, long> leadOutStarts, Dictionary <MediaTagType, byte[]> mediaTags, ErrorMessageHandler stoppingErrorMessage, TrackSubchannelType subType, out FullTOC.CDFullTOC?toc, Dictionary <byte, byte> trackFlags, UpdateStatusHandler updateStatus) { byte[] cmdBuf = null; // Data buffer const uint sectorSize = 2352; // Full sector size bool sense = true; // Sense indicator List <Track> trackList = new List <Track>(); // Tracks in disc byte[] tmpBuf; // Temporary buffer toc = null; lastSector = 0; TrackType leadoutTrackType = TrackType.Audio; // We discarded all discs that falsify a TOC before requesting a real TOC // No TOC, no CD (or an empty one) dumpLog?.WriteLine("Reading full TOC"); updateStatus?.Invoke("Reading full TOC"); sense = dev.ReadRawToc(out cmdBuf, out _, 0, dev.Timeout, out _); if (!sense) { toc = FullTOC.Decode(cmdBuf); if (toc.HasValue) { tmpBuf = new byte[cmdBuf.Length - 2]; Array.Copy(cmdBuf, 2, tmpBuf, 0, cmdBuf.Length - 2); mediaTags?.Add(MediaTagType.CD_FullTOC, tmpBuf); } } updateStatus?.Invoke("Building track map..."); dumpLog?.WriteLine("Building track map..."); if (toc.HasValue) { FullTOC.TrackDataDescriptor[] sortedTracks = toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray(); foreach (FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => trk.ADR == 1 || trk.ADR == 4)) { if (trk.POINT >= 0x01 && trk.POINT <= 0x63) { trackList.Add(new Track { TrackSequence = trk.POINT, TrackSession = trk.SessionNumber, TrackType = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data : TrackType.Audio, TrackStartSector = (ulong)(((trk.PHOUR * 3600 * 75) + (trk.PMIN * 60 * 75) + (trk.PSEC * 75) + trk.PFRAME) - 150), TrackBytesPerSector = (int)sectorSize, TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType }); trackFlags?.Add(trk.POINT, trk.CONTROL); } else if (trk.POINT == 0xA2) { int phour, pmin, psec, pframe; if (trk.PFRAME == 0) { pframe = 74; if (trk.PSEC == 0) { psec = 59; if (trk.PMIN == 0) { pmin = 59; phour = trk.PHOUR - 1; } else { pmin = trk.PMIN - 1; phour = trk.PHOUR; } } else { psec = trk.PSEC - 1; pmin = trk.PMIN; phour = trk.PHOUR; } } else { pframe = trk.PFRAME - 1; psec = trk.PSEC; pmin = trk.PMIN; phour = trk.PHOUR; } lastSector = ((phour * 3600 * 75) + (pmin * 60 * 75) + (psec * 75) + pframe) - 150; leadOutStarts?.Add(trk.SessionNumber, lastSector + 1); } else if (trk.POINT == 0xA0 && trk.ADR == 1) { leadoutTrackType = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data : TrackType.Audio; } } } else { updateStatus?.Invoke("Cannot read RAW TOC, requesting processed one..."); dumpLog?.WriteLine("Cannot read RAW TOC, requesting processed one..."); sense = dev.ReadToc(out cmdBuf, out _, false, 0, dev.Timeout, out _); TOC.CDTOC?oldToc = TOC.Decode(cmdBuf); if ((sense || !oldToc.HasValue) && !force) { dumpLog?.WriteLine("Could not read TOC, if you want to continue, use force, and will try from LBA 0 to 360000..."); stoppingErrorMessage?. Invoke("Could not read TOC, if you want to continue, use force, and will try from LBA 0 to 360000..."); return(null); } foreach (TOC.CDTOCTrackDataDescriptor trk in oldToc. Value.TrackDescriptors.OrderBy(t => t.TrackNumber). Where(trk => trk.ADR == 1 || trk.ADR == 4)) { if (trk.TrackNumber >= 0x01 && trk.TrackNumber <= 0x63) { trackList.Add(new Track { TrackSequence = trk.TrackNumber, TrackSession = 1, TrackType = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data : TrackType.Audio, TrackStartSector = trk.TrackStartAddress, TrackBytesPerSector = (int)sectorSize, TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType }); trackFlags?.Add(trk.TrackNumber, trk.CONTROL); } else if (trk.TrackNumber == 0xAA) { leadoutTrackType = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data : TrackType.Audio; lastSector = trk.TrackStartAddress - 1; } } } if (trackList.Count == 0) { updateStatus?.Invoke("No tracks found, adding a single track from 0 to Lead-Out"); dumpLog?.WriteLine("No tracks found, adding a single track from 0 to Lead-Out"); trackList.Add(new Track { TrackSequence = 1, TrackSession = 1, TrackType = leadoutTrackType, TrackStartSector = 0, TrackBytesPerSector = (int)sectorSize, TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType }); trackFlags?.Add(1, (byte)(leadoutTrackType == TrackType.Audio ? 0 : 4)); } if (lastSector == 0) { sense = dev.ReadCapacity16(out cmdBuf, out _, dev.Timeout, out _); if (!sense) { byte[] temp = new byte[8]; Array.Copy(cmdBuf, 0, temp, 0, 8); Array.Reverse(temp); lastSector = (long)BitConverter.ToUInt64(temp, 0); blockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); } else { sense = dev.ReadCapacity(out cmdBuf, out _, dev.Timeout, out _); if (!sense) { lastSector = (cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]; blockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); } } if (lastSector <= 0) { if (!force) { stoppingErrorMessage?. Invoke("Could not find Lead-Out, if you want to continue use force option and will continue until 360000 sectors..."); dumpLog?. WriteLine("Could not find Lead-Out, if you want to continue use force option and will continue until 360000 sectors..."); return(null); } updateStatus?. Invoke("WARNING: Could not find Lead-Out start, will try to read up to 360000 sectors, probably will fail before..."); dumpLog?.WriteLine("WARNING: Could not find Lead-Out start, will try to read up to 360000 sectors, probably will fail before..."); lastSector = 360000; } } return(trackList.ToArray()); }
public CompactDiscInfoViewModel(byte[] toc, byte[] atip, byte[] compactDiscInformation, byte[] session, byte[] rawToc, byte[] pma, byte[] cdTextLeadIn, TOC.CDTOC?decodedToc, ATIP.CDATIP?decodedAtip, Session.CDSessionInfo?decodedSession, FullTOC.CDFullTOC?fullToc, CDTextOnLeadIn.CDText?decodedCdTextLeadIn, DiscInformation.StandardDiscInformation?decodedCompactDiscInformation, string mcn, Dictionary <byte, string> isrcs, Window view) { _tocData = toc; _atipData = atip; _compactDiscInformationData = compactDiscInformation; _sessionData = session; _rawTocData = rawToc; _pmaData = pma; _cdTextLeadInData = cdTextLeadIn; _view = view; IsrcList = new ObservableCollection <IsrcModel>(); SaveCdInformationCommand = ReactiveCommand.Create(ExecuteSaveCdInformationCommand); SaveCdTocCommand = ReactiveCommand.Create(ExecuteSaveCdTocCommand); SaveCdFullTocCommand = ReactiveCommand.Create(ExecuteSaveCdFullTocCommand); SaveCdSessionCommand = ReactiveCommand.Create(ExecuteSaveCdSessionCommand); SaveCdTextCommand = ReactiveCommand.Create(ExecuteSaveCdTextCommand); SaveCdAtipCommand = ReactiveCommand.Create(ExecuteSaveCdAtipCommand); SaveCdPmaCommand = ReactiveCommand.Create(ExecuteSaveCdPmaCommand); if (decodedCompactDiscInformation.HasValue) { CdInformationText = DiscInformation.Prettify000b(decodedCompactDiscInformation); } if (decodedToc.HasValue) { CdTocText = TOC.Prettify(decodedToc); } if (fullToc.HasValue) { CdFullTocText = FullTOC.Prettify(fullToc); } if (decodedSession.HasValue) { CdSessionText = Session.Prettify(decodedSession); } if (decodedCdTextLeadIn.HasValue) { CdTextText = CDTextOnLeadIn.Prettify(decodedCdTextLeadIn); } if (decodedAtip.HasValue) { CdAtipText = ATIP.Prettify(atip); } if (!string.IsNullOrEmpty(mcn)) { McnText = mcn; } if (isrcs != null && isrcs.Count > 0) { foreach (KeyValuePair <byte, string> isrc in isrcs) { IsrcList.Add(new IsrcModel { Track = isrc.Key.ToString(), Isrc = isrc.Value }); } } MiscellaneousVisible = McnText != null || isrcs?.Count > 0 || pma != null; CdPmaVisible = pma != null; }
static void DoScsiMediaInfo(string outputPrefix, Device dev) { ScsiInfo scsiInfo = new ScsiInfo(dev); if (!scsiInfo.MediaInserted) { return; } if (scsiInfo.DeviceInfo.ScsiModeSense6 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense6.bin", "SCSI MODE SENSE (6)", scsiInfo.DeviceInfo.ScsiModeSense6); } if (scsiInfo.DeviceInfo.ScsiModeSense10 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense10.bin", "SCSI MODE SENSE (10)", scsiInfo.DeviceInfo.ScsiModeSense10); } switch (dev.ScsiType) { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: case PeripheralDeviceTypes.OCRWDevice: case PeripheralDeviceTypes.OpticalDevice: case PeripheralDeviceTypes.SimplifiedDevice: case PeripheralDeviceTypes.WriteOnceDevice: if (scsiInfo.ReadCapacity != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity.bin", "SCSI READ CAPACITY", scsiInfo.ReadCapacity); } if (scsiInfo.ReadCapacity16 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity16.bin", "SCSI READ CAPACITY(16)", scsiInfo.ReadCapacity16); } if (scsiInfo.Blocks != 0 && scsiInfo.BlockSize != 0) { DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", scsiInfo.Blocks, scsiInfo.BlockSize, scsiInfo.Blocks * scsiInfo.BlockSize); } break; case PeripheralDeviceTypes.SequentialAccess: if (scsiInfo.DensitySupport != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_ssc_reportdensitysupport_media.bin", "SSC REPORT DENSITY SUPPORT (MEDIA)", scsiInfo.DensitySupport); if (scsiInfo.DensitySupportHeader.HasValue) { DicConsole.WriteLine("Densities supported by currently inserted media:"); DicConsole.WriteLine(DensitySupport.PrettifyDensity(scsiInfo.DensitySupportHeader)); } } if (scsiInfo.MediaTypeSupport != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_ssc_reportdensitysupport_medium_media.bin", "SSC REPORT DENSITY SUPPORT (MEDIUM & MEDIA)", scsiInfo.MediaTypeSupport); if (scsiInfo.MediaTypeSupportHeader.HasValue) { DicConsole.WriteLine("Medium types currently inserted in device:"); DicConsole.WriteLine(DensitySupport.PrettifyMediumType(scsiInfo.MediaTypeSupportHeader)); } DicConsole.WriteLine(DensitySupport.PrettifyMediumType(scsiInfo.MediaTypeSupport)); } break; } if (dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) { if (scsiInfo.MmcConfiguration != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_getconfiguration_current.bin", "SCSI GET CONFIGURATION", scsiInfo.MmcConfiguration); } if (scsiInfo.RecognizedFormatLayers != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_formatlayers.bin", "SCSI READ DISC STRUCTURE", scsiInfo.RecognizedFormatLayers); } if (scsiInfo.WriteProtectionStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_writeprotection.bin", "SCSI READ DISC STRUCTURE", scsiInfo.WriteProtectionStatus); } if (scsiInfo.DvdPfi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_pfi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPfi); if (scsiInfo.DecodedPfi.HasValue) { DicConsole.WriteLine("PFI:\n{0}", PFI.Prettify(scsiInfo.DecodedPfi)); } } if (scsiInfo.DvdDmi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_dmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdDmi); if (DMI.IsXbox(scsiInfo.DvdDmi)) { DicConsole.WriteLine("Xbox DMI:\n{0}", DMI.PrettifyXbox(scsiInfo.DvdDmi)); } else if (DMI.IsXbox360(scsiInfo.DvdDmi)) { DicConsole.WriteLine("Xbox 360 DMI:\n{0}", DMI.PrettifyXbox360(scsiInfo.DvdDmi)); } } if (scsiInfo.DvdCmi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_cmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdCmi); DicConsole.WriteLine("Lead-In CMI:\n{0}", CSS_CPRM.PrettifyLeadInCopyright(scsiInfo.DvdCmi)); } if (scsiInfo.DvdBca != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_bca.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdBca); } if (scsiInfo.DvdAacs != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_aacs.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdAacs); } if (scsiInfo.DvdRamDds != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_dds.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamDds); DicConsole.WriteLine("Disc Definition Structure:\n{0}", DDS.Prettify(scsiInfo.DvdRamDds)); } if (scsiInfo.DvdRamCartridgeStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_status.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamCartridgeStatus); DicConsole.WriteLine("Medium Status:\n{0}", Cartridge.Prettify(scsiInfo.DvdRamCartridgeStatus)); } if (scsiInfo.DvdRamSpareArea != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_spare.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamSpareArea); DicConsole.WriteLine("Spare Area Information:\n{0}", Spare.Prettify(scsiInfo.DvdRamSpareArea)); } if (scsiInfo.LastBorderOutRmd != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_lastrmd.bin", "SCSI READ DISC STRUCTURE", scsiInfo.LastBorderOutRmd); } if (scsiInfo.DvdPreRecordedInfo != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_pri.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPreRecordedInfo); } if (scsiInfo.DvdrMediaIdentifier != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_mediaid.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrMediaIdentifier); } if (scsiInfo.DvdrPhysicalInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_pfi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrPhysicalInformation); } if (scsiInfo.DvdPlusAdip != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd+_adip.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPlusAdip); } if (scsiInfo.DvdPlusDcb != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd+_dcb.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPlusDcb); } if (scsiInfo.HddvdCopyrightInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvd_cmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdCopyrightInformation); } if (scsiInfo.HddvdrMediumStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvdr_status.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdrMediumStatus); } if (scsiInfo.HddvdrLastRmd != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvdr_lastrmd.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdrLastRmd); } if (scsiInfo.DvdrLayerCapacity != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_layercap.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrLayerCapacity); } if (scsiInfo.DvdrDlMiddleZoneStart != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_mzs.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlMiddleZoneStart); } if (scsiInfo.DvdrDlJumpIntervalSize != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_jis.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlJumpIntervalSize); } if (scsiInfo.DvdrDlManualLayerJumpStartLba != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_manuallj.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlManualLayerJumpStartLba); } if (scsiInfo.DvdrDlRemapAnchorPoint != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_remapanchor.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlRemapAnchorPoint); } if (scsiInfo.BlurayDiscInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_di.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayDiscInformation); DicConsole.WriteLine("Blu-ray Disc Information:\n{0}", DI.Prettify(scsiInfo.BlurayDiscInformation)); } if (scsiInfo.BlurayPac != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_pac.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayPac); } if (scsiInfo.BlurayBurstCuttingArea != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_bca.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayBurstCuttingArea); DicConsole.WriteLine("Blu-ray Burst Cutting Area:\n{0}", BCA.Prettify(scsiInfo.BlurayBurstCuttingArea)); } if (scsiInfo.BlurayDds != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_dds.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayDds); DicConsole.WriteLine("Blu-ray Disc Definition Structure:\n{0}", Decoders.Bluray.DDS.Prettify(scsiInfo.BlurayDds)); } if (scsiInfo.BlurayCartridgeStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_cartstatus.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayCartridgeStatus); DicConsole.WriteLine("Blu-ray Cartridge Status:\n{0}", Decoders.Bluray.Cartridge.Prettify(scsiInfo.BlurayCartridgeStatus)); } if (scsiInfo.BluraySpareAreaInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_spare.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BluraySpareAreaInformation); DicConsole.WriteLine("Blu-ray Spare Area Information:\n{0}", Decoders.Bluray.Spare.Prettify(scsiInfo.BluraySpareAreaInformation)); } if (scsiInfo.BlurayRawDfl != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_dfl.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayRawDfl); } if (scsiInfo.BlurayTrackResources != null) { DicConsole.WriteLine("Track Resources Information:\n{0}", DiscInformation.Prettify(scsiInfo.BlurayTrackResources)); DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_001b.bin", "SCSI READ DISC INFORMATION", scsiInfo.BlurayTrackResources); } if (scsiInfo.BlurayPowResources != null) { DicConsole.WriteLine("POW Resources Information:\n{0}", DiscInformation.Prettify(scsiInfo.BlurayPowResources)); DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_010b.bin", "SCSI READ DISC INFORMATION", scsiInfo.BlurayPowResources); } if (scsiInfo.Toc != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_toc.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Toc); if (scsiInfo.DecodedToc.HasValue) { DicConsole.WriteLine("TOC:\n{0}", TOC.Prettify(scsiInfo.DecodedToc)); } } if (scsiInfo.Atip != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_atip.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Atip); if (scsiInfo.DecodedAtip.HasValue) { DicConsole.WriteLine("ATIP:\n{0}", ATIP.Prettify(scsiInfo.DecodedAtip)); } } if (scsiInfo.CompactDiscInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_000b.bin", "SCSI READ DISC INFORMATION", scsiInfo.CompactDiscInformation); if (scsiInfo.DecodedCompactDiscInformation.HasValue) { DicConsole.WriteLine("Standard Disc Information:\n{0}", DiscInformation.Prettify000b(scsiInfo.DecodedCompactDiscInformation)); } } if (scsiInfo.Session != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_session.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Session); if (scsiInfo.DecodedSession.HasValue) { DicConsole.WriteLine("Session information:\n{0}", Session.Prettify(scsiInfo.DecodedSession)); } } if (scsiInfo.RawToc != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_rawtoc.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.RawToc); if (scsiInfo.FullToc.HasValue) { DicConsole.WriteLine("Raw TOC:\n{0}", FullTOC.Prettify(scsiInfo.RawToc)); } } if (scsiInfo.Pma != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_pma.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Pma); DicConsole.WriteLine("PMA:\n{0}", PMA.Prettify(scsiInfo.Pma)); } if (scsiInfo.CdTextLeadIn != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_cdtext.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.CdTextLeadIn); if (scsiInfo.DecodedCdTextLeadIn.HasValue) { DicConsole.WriteLine("CD-TEXT on Lead-In:\n{0}", CDTextOnLeadIn.Prettify(scsiInfo.DecodedCdTextLeadIn)); } } if (!string.IsNullOrEmpty(scsiInfo.Mcn)) { DicConsole.WriteLine("MCN: {0}", scsiInfo.Mcn); } if (scsiInfo.Isrcs != null) { foreach (KeyValuePair <byte, string> isrc in scsiInfo.Isrcs) { DicConsole.WriteLine("Track's {0} ISRC: {1}", isrc.Key, isrc.Value); } } if (scsiInfo.XboxSecuritySector != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_xbox_ss.bin", "KREON EXTRACT SS", scsiInfo.XboxSecuritySector); } if (scsiInfo.DecodedXboxSecuritySector.HasValue) { DicConsole.WriteLine("Xbox Security Sector:\n{0}", SS.Prettify(scsiInfo.DecodedXboxSecuritySector)); } if (scsiInfo.XgdInfo != null) { DicConsole.WriteLine("Video layer 0 size: {0} sectors", scsiInfo.XgdInfo.L0Video); DicConsole.WriteLine("Video layer 1 size: {0} sectors", scsiInfo.XgdInfo.L1Video); DicConsole.WriteLine("Middle zone size: {0} sectors", scsiInfo.XgdInfo.MiddleZone); DicConsole.WriteLine("Game data size: {0} sectors", scsiInfo.XgdInfo.GameSize); DicConsole.WriteLine("Total size: {0} sectors", scsiInfo.XgdInfo.TotalSize); DicConsole.WriteLine("Real layer break: {0}", scsiInfo.XgdInfo.LayerBreak); DicConsole.WriteLine(); } } if (scsiInfo.MediaSerialNumber != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_mediaserialnumber.bin", "SCSI READ MEDIA SERIAL NUMBER", scsiInfo.MediaSerialNumber); DicConsole.Write("Media Serial Number: "); for (int i = 4; i < scsiInfo.MediaSerialNumber.Length; i++) { DicConsole.Write("{0:X2}", scsiInfo.MediaSerialNumber[i]); } DicConsole.WriteLine(); } DicConsole.WriteLine("Media identified as {0}", scsiInfo.MediaType); Statistics.AddMedia(scsiInfo.MediaType, true); dev.Close(); }
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; } }
static void DoScsiMediaInfo(bool debug, bool verbose, string outputPrefix, Devices.Device dev) { var scsiInfo = new ScsiInfo(dev); if (!scsiInfo.MediaInserted) { return; } if (scsiInfo.DeviceInfo.ScsiModeSense6 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense6.bin", "SCSI MODE SENSE (6)", scsiInfo.DeviceInfo.ScsiModeSense6); } if (scsiInfo.DeviceInfo.ScsiModeSense10 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense10.bin", "SCSI MODE SENSE (10)", scsiInfo.DeviceInfo.ScsiModeSense10); } switch (dev.ScsiType) { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: case PeripheralDeviceTypes.OCRWDevice: case PeripheralDeviceTypes.OpticalDevice: case PeripheralDeviceTypes.SimplifiedDevice: case PeripheralDeviceTypes.WriteOnceDevice: if (scsiInfo.ReadCapacity != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity.bin", "SCSI READ CAPACITY", scsiInfo.ReadCapacity); } if (scsiInfo.ReadCapacity16 != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity16.bin", "SCSI READ CAPACITY(16)", scsiInfo.ReadCapacity16); } if (scsiInfo.Blocks != 0 && scsiInfo.BlockSize != 0) { DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", scsiInfo.Blocks, scsiInfo.BlockSize, scsiInfo.Blocks * scsiInfo.BlockSize); } break; case PeripheralDeviceTypes.SequentialAccess: if (scsiInfo.DensitySupport != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_ssc_reportdensitysupport_media.bin", "SSC REPORT DENSITY SUPPORT (MEDIA)", scsiInfo.DensitySupport); if (scsiInfo.DensitySupportHeader.HasValue) { DicConsole.WriteLine("Densities supported by currently inserted media:"); DicConsole.WriteLine(DensitySupport.PrettifyDensity(scsiInfo.DensitySupportHeader)); } } if (scsiInfo.MediaTypeSupport != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_ssc_reportdensitysupport_medium_media.bin", "SSC REPORT DENSITY SUPPORT (MEDIUM & MEDIA)", scsiInfo.MediaTypeSupport); if (scsiInfo.MediaTypeSupportHeader.HasValue) { DicConsole.WriteLine("Medium types currently inserted in device:"); DicConsole.WriteLine(DensitySupport.PrettifyMediumType(scsiInfo.MediaTypeSupportHeader)); } DicConsole.WriteLine(DensitySupport.PrettifyMediumType(scsiInfo.MediaTypeSupport)); } break; } if (dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) { if (scsiInfo.MmcConfiguration != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_getconfiguration_current.bin", "SCSI GET CONFIGURATION", scsiInfo.MmcConfiguration); } if (scsiInfo.RecognizedFormatLayers != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_formatlayers.bin", "SCSI READ DISC STRUCTURE", scsiInfo.RecognizedFormatLayers); } if (scsiInfo.WriteProtectionStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_writeprotection.bin", "SCSI READ DISC STRUCTURE", scsiInfo.WriteProtectionStatus); } if (scsiInfo.DvdPfi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_pfi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPfi); if (scsiInfo.DecodedPfi.HasValue) { DicConsole.WriteLine("PFI:\n{0}", PFI.Prettify(scsiInfo.DecodedPfi)); } } if (scsiInfo.DvdDmi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_dmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdDmi); if (DMI.IsXbox(scsiInfo.DvdDmi)) { DicConsole.WriteLine("Xbox DMI:\n{0}", DMI.PrettifyXbox(scsiInfo.DvdDmi)); } else if (DMI.IsXbox360(scsiInfo.DvdDmi)) { DicConsole.WriteLine("Xbox 360 DMI:\n{0}", DMI.PrettifyXbox360(scsiInfo.DvdDmi)); } } if (scsiInfo.DvdCmi != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_cmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdCmi); DicConsole.WriteLine("Lead-In CMI:\n{0}", CSS_CPRM.PrettifyLeadInCopyright(scsiInfo.DvdCmi)); } if (scsiInfo.DvdBca != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_bca.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdBca); } if (scsiInfo.DvdAacs != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_aacs.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdAacs); } if (scsiInfo.DvdRamDds != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_dds.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamDds); DicConsole.WriteLine("Disc Definition Structure:\n{0}", DDS.Prettify(scsiInfo.DvdRamDds)); } if (scsiInfo.DvdRamCartridgeStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_status.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamCartridgeStatus); DicConsole.WriteLine("Medium Status:\n{0}", Cartridge.Prettify(scsiInfo.DvdRamCartridgeStatus)); } if (scsiInfo.DvdRamSpareArea != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdram_spare.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdRamSpareArea); DicConsole.WriteLine("Spare Area Information:\n{0}", Spare.Prettify(scsiInfo.DvdRamSpareArea)); } if (scsiInfo.LastBorderOutRmd != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_lastrmd.bin", "SCSI READ DISC STRUCTURE", scsiInfo.LastBorderOutRmd); } if (scsiInfo.DvdPreRecordedInfo != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_pri.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPreRecordedInfo); } if (scsiInfo.DvdrMediaIdentifier != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_mediaid.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrMediaIdentifier); } if (scsiInfo.DvdrPhysicalInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_pfi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrPhysicalInformation); } if (scsiInfo.DvdPlusAdip != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd+_adip.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPlusAdip); } if (scsiInfo.DvdPlusDcb != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd+_dcb.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdPlusDcb); } if (scsiInfo.HddvdCopyrightInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvd_cmi.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdCopyrightInformation); } if (scsiInfo.HddvdrMediumStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvdr_status.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdrMediumStatus); } if (scsiInfo.HddvdrLastRmd != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_hddvdr_lastrmd.bin", "SCSI READ DISC STRUCTURE", scsiInfo.HddvdrLastRmd); } if (scsiInfo.DvdrLayerCapacity != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvdr_layercap.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrLayerCapacity); } if (scsiInfo.DvdrDlMiddleZoneStart != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_mzs.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlMiddleZoneStart); } if (scsiInfo.DvdrDlJumpIntervalSize != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_jis.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlJumpIntervalSize); } if (scsiInfo.DvdrDlManualLayerJumpStartLba != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_manuallj.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlManualLayerJumpStartLba); } if (scsiInfo.DvdrDlRemapAnchorPoint != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_dvd_remapanchor.bin", "SCSI READ DISC STRUCTURE", scsiInfo.DvdrDlRemapAnchorPoint); } if (scsiInfo.BlurayDiscInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_di.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayDiscInformation); DicConsole.WriteLine("Blu-ray Disc Information:\n{0}", DI.Prettify(scsiInfo.BlurayDiscInformation)); } if (scsiInfo.BlurayPac != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_pac.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayPac); } if (scsiInfo.BlurayBurstCuttingArea != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_bca.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayBurstCuttingArea); DicConsole.WriteLine("Blu-ray Burst Cutting Area:\n{0}", BCA.Prettify(scsiInfo.BlurayBurstCuttingArea)); } if (scsiInfo.BlurayDds != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_dds.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayDds); DicConsole.WriteLine("Blu-ray Disc Definition Structure:\n{0}", Decoders.Bluray.DDS.Prettify(scsiInfo.BlurayDds)); } if (scsiInfo.BlurayCartridgeStatus != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_cartstatus.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayCartridgeStatus); DicConsole.WriteLine("Blu-ray Cartridge Status:\n{0}", Decoders.Bluray.Cartridge.Prettify(scsiInfo.BlurayCartridgeStatus)); } if (scsiInfo.BluraySpareAreaInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_spare.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BluraySpareAreaInformation); DicConsole.WriteLine("Blu-ray Spare Area Information:\n{0}", Decoders.Bluray.Spare.Prettify(scsiInfo.BluraySpareAreaInformation)); } if (scsiInfo.BlurayRawDfl != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_bd_dfl.bin", "SCSI READ DISC STRUCTURE", scsiInfo.BlurayRawDfl); } if (scsiInfo.BlurayTrackResources != null) { DicConsole.WriteLine("Track Resources Information:\n{0}", DiscInformation.Prettify(scsiInfo.BlurayTrackResources)); DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_001b.bin", "SCSI READ DISC INFORMATION", scsiInfo.BlurayTrackResources); } if (scsiInfo.BlurayPowResources != null) { DicConsole.WriteLine("POW Resources Information:\n{0}", DiscInformation.Prettify(scsiInfo.BlurayPowResources)); DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_010b.bin", "SCSI READ DISC INFORMATION", scsiInfo.BlurayPowResources); } if (scsiInfo.Toc != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_toc.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Toc); if (scsiInfo.DecodedToc.HasValue) { DicConsole.WriteLine("TOC:\n{0}", TOC.Prettify(scsiInfo.DecodedToc)); } } if (scsiInfo.Atip != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_atip.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Atip); if (scsiInfo.DecodedAtip.HasValue) { DicConsole.WriteLine("ATIP:\n{0}", ATIP.Prettify(scsiInfo.DecodedAtip)); } } if (scsiInfo.CompactDiscInformation != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_000b.bin", "SCSI READ DISC INFORMATION", scsiInfo.CompactDiscInformation); if (scsiInfo.DecodedCompactDiscInformation.HasValue) { DicConsole.WriteLine("Standard Disc Information:\n{0}", DiscInformation.Prettify000b(scsiInfo.DecodedCompactDiscInformation)); } } if (scsiInfo.Session != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_session.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Session); if (scsiInfo.DecodedSession.HasValue) { DicConsole.WriteLine("Session information:\n{0}", Session.Prettify(scsiInfo.DecodedSession)); } } if (scsiInfo.RawToc != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_rawtoc.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.RawToc); if (scsiInfo.FullToc.HasValue) { DicConsole.WriteLine("Raw TOC:\n{0}", FullTOC.Prettify(scsiInfo.RawToc)); } } if (scsiInfo.Pma != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_pma.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.Pma); DicConsole.WriteLine("PMA:\n{0}", PMA.Prettify(scsiInfo.Pma)); } if (scsiInfo.CdTextLeadIn != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_cdtext.bin", "SCSI READ TOC/PMA/ATIP", scsiInfo.CdTextLeadIn); if (scsiInfo.DecodedCdTextLeadIn.HasValue) { DicConsole.WriteLine("CD-TEXT on Lead-In:\n{0}", CDTextOnLeadIn.Prettify(scsiInfo.DecodedCdTextLeadIn)); } } if (!string.IsNullOrEmpty(scsiInfo.Mcn)) { DicConsole.WriteLine("MCN: {0}", scsiInfo.Mcn); } if (scsiInfo.Isrcs != null) { foreach (KeyValuePair <byte, string> isrc in scsiInfo.Isrcs) { DicConsole.WriteLine("Track's {0} ISRC: {1}", isrc.Key, isrc.Value); } } if (scsiInfo.XboxSecuritySector != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_xbox_ss.bin", "KREON EXTRACT SS", scsiInfo.XboxSecuritySector); } if (scsiInfo.DecodedXboxSecuritySector.HasValue) { DicConsole.WriteLine("Xbox Security Sector:\n{0}", SS.Prettify(scsiInfo.DecodedXboxSecuritySector)); } if (scsiInfo.XgdInfo != null) { DicConsole.WriteLine("Video layer 0 size: {0} sectors", scsiInfo.XgdInfo.L0Video); DicConsole.WriteLine("Video layer 1 size: {0} sectors", scsiInfo.XgdInfo.L1Video); DicConsole.WriteLine("Middle zone size: {0} sectors", scsiInfo.XgdInfo.MiddleZone); DicConsole.WriteLine("Game data size: {0} sectors", scsiInfo.XgdInfo.GameSize); DicConsole.WriteLine("Total size: {0} sectors", scsiInfo.XgdInfo.TotalSize); DicConsole.WriteLine("Real layer break: {0}", scsiInfo.XgdInfo.LayerBreak); DicConsole.WriteLine(); } } if (scsiInfo.MediaSerialNumber != null) { DataFile.WriteTo("Media-Info command", outputPrefix, "_mediaserialnumber.bin", "SCSI READ MEDIA SERIAL NUMBER", scsiInfo.MediaSerialNumber); DicConsole.Write("Media Serial Number: "); for (int i = 4; i < scsiInfo.MediaSerialNumber.Length; i++) { DicConsole.Write("{0:X2}", scsiInfo.MediaSerialNumber[i]); } DicConsole.WriteLine(); } DicConsole.WriteLine("Media identified as {0}", scsiInfo.MediaType); Statistics.AddMedia(scsiInfo.MediaType, true); if (scsiInfo.Toc != null || scsiInfo.RawToc != null) { uint blockSize = 2352; Track[] tracks = Dump.GetCdTracks(ref blockSize, dev, scsiInfo.MediaType, null, false, out long lastSector, null, null, null, TrackSubchannelType.None, out _, null, null); if (tracks != null) { bool supportsPqSubchannel = Dump.SupportsPqSubchannel(dev, null, null); bool supportsRwSubchannel = Dump.SupportsRwSubchannel(dev, null, null); // Open master database var ctx = DicContext.Create(Settings.Settings.MasterDbPath); // Search for device in master database Database.Models.Device dbDev = ctx.Devices.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model && d.Revision == dev.FirmwareRevision); Dump.SolveTrackPregaps(dev, null, null, tracks, supportsPqSubchannel, supportsRwSubchannel, dbDev, out bool inexactPositioning); for (int t = 1; t < tracks.Length; t++) { tracks[t - 1].TrackEndSector = tracks[t].TrackStartSector - 1; } tracks[tracks.Length - 1].TrackEndSector = (ulong)lastSector; DicConsole.WriteLine(); DicConsole.WriteLine("Track calculations:"); if (inexactPositioning) { DicConsole. WriteLine("WARNING: The drive has returned incorrect Q positioning when calculating pregaps. A best effort has been tried but they may be incorrect."); } foreach (Track track in tracks) { DicConsole. WriteLine("Track {0} starts at LBA {1}, ends at LBA {2}, has a pregap of {3} sectors and is of type {4}", track.TrackSequence, track.TrackStartSector, track.TrackEndSector, track.TrackPregap, track.TrackType); } DicConsole.WriteLine(); DicConsole.WriteLine("Offsets:"); CdOffset cdOffset = null; // Search for read offset in master database cdOffset = ctx.CdOffsets.FirstOrDefault(d => d.Manufacturer == dev.Manufacturer && d.Model == dev.Model); CompactDisc.GetOffset(cdOffset, dbDev, debug, dev, scsiInfo.MediaType, null, tracks, null, out int?driveOffset, out int?combinedOffset); if (combinedOffset is null) { if (driveOffset is null) { DicConsole.WriteLine("Drive reading offset not found in database."); DicConsole.WriteLine("Disc offset cannot be calculated."); } else { DicConsole. WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples)."); DicConsole.WriteLine("Disc write offset is unknown."); } } else { int offsetBytes = combinedOffset.Value; if (driveOffset is null) { DicConsole.WriteLine("Drive reading offset not found in database."); DicConsole. WriteLine($"Combined disc and drive offset are {offsetBytes} bytes ({offsetBytes / 4} samples)."); } else { DicConsole. WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples)."); DicConsole.WriteLine($"Combined offset is {offsetBytes} bytes ({offsetBytes / 4} samples)"); int?discOffset = offsetBytes - driveOffset; DicConsole.WriteLine($"Disc offset is {discOffset} bytes ({discOffset / 4} samples)"); } } } } dev.Close(); }
public static int Invoke(bool verbose, bool debug, bool diskTags, string imagePath, string length, bool sectorTags, ulong startSector) { MainClass.PrintCopyright(); if (debug) { DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; } if (verbose) { DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; } Statistics.AddCommand("decode"); DicConsole.DebugWriteLine("Decode command", "--debug={0}", debug); DicConsole.DebugWriteLine("Decode command", "--disk-tags={0}", diskTags); DicConsole.DebugWriteLine("Decode command", "--input={0}", imagePath); DicConsole.DebugWriteLine("Decode command", "--length={0}", length); DicConsole.DebugWriteLine("Decode command", "--sector-tags={0}", sectorTags); DicConsole.DebugWriteLine("Decode command", "--start={0}", startSector); DicConsole.DebugWriteLine("Decode command", "--verbose={0}", verbose); var filtersList = new FiltersList(); IFilter inputFilter = filtersList.GetFilter(imagePath); if (inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); return((int)ErrorNumber.CannotOpenFile); } IMediaImage inputFormat = ImageFormat.Detect(inputFilter); if (inputFormat == null) { DicConsole.ErrorWriteLine("Unable to recognize image format, not decoding"); return((int)ErrorNumber.UnrecognizedFormat); } inputFormat.Open(inputFilter); Statistics.AddMediaFormat(inputFormat.Format); Statistics.AddMedia(inputFormat.Info.MediaType, false); Statistics.AddFilter(inputFilter.Name); if (diskTags) { if (inputFormat.Info.ReadableMediaTags.Count == 0) { DicConsole.WriteLine("There are no disk tags in chosen disc image."); } else { foreach (MediaTagType tag in inputFormat.Info.ReadableMediaTags) { switch (tag) { case MediaTagType.SCSI_INQUIRY: { byte[] inquiry = inputFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY); if (inquiry == null) { DicConsole.WriteLine("Error reading SCSI INQUIRY response from disc image"); } else { DicConsole.WriteLine("SCSI INQUIRY command response:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(Inquiry.Prettify(inquiry)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.ATA_IDENTIFY: { byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY); if (identify == null) { DicConsole.WriteLine("Error reading ATA IDENTIFY DEVICE response from disc image"); } else { DicConsole.WriteLine("ATA IDENTIFY DEVICE command response:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(Identify.Prettify(identify)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.ATAPI_IDENTIFY: { byte[] identify = inputFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY); if (identify == null) { DicConsole. WriteLine("Error reading ATA IDENTIFY PACKET DEVICE response from disc image"); } else { DicConsole.WriteLine("ATA IDENTIFY PACKET DEVICE command response:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(Identify.Prettify(identify)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.CD_ATIP: { byte[] atip = inputFormat.ReadDiskTag(MediaTagType.CD_ATIP); if (atip == null) { DicConsole.WriteLine("Error reading CD ATIP from disc image"); } else { DicConsole.WriteLine("CD ATIP:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(ATIP.Prettify(atip)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.CD_FullTOC: { byte[] fullToc = inputFormat.ReadDiskTag(MediaTagType.CD_FullTOC); if (fullToc == null) { DicConsole.WriteLine("Error reading CD full TOC from disc image"); } else { DicConsole.WriteLine("CD full TOC:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(FullTOC.Prettify(fullToc)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.CD_PMA: { byte[] pma = inputFormat.ReadDiskTag(MediaTagType.CD_PMA); if (pma == null) { DicConsole.WriteLine("Error reading CD PMA from disc image"); } else { DicConsole.WriteLine("CD PMA:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(PMA.Prettify(pma)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.CD_SessionInfo: { byte[] sessionInfo = inputFormat.ReadDiskTag(MediaTagType.CD_SessionInfo); if (sessionInfo == null) { DicConsole.WriteLine("Error reading CD session information from disc image"); } else { DicConsole.WriteLine("CD session information:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(Session.Prettify(sessionInfo)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.CD_TEXT: { byte[] cdText = inputFormat.ReadDiskTag(MediaTagType.CD_TEXT); if (cdText == null) { DicConsole.WriteLine("Error reading CD-TEXT from disc image"); } else { DicConsole.WriteLine("CD-TEXT:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(CDTextOnLeadIn.Prettify(cdText)); DicConsole. WriteLine("================================================================================"); } break; } case MediaTagType.CD_TOC: { byte[] toc = inputFormat.ReadDiskTag(MediaTagType.CD_TOC); if (toc == null) { DicConsole.WriteLine("Error reading CD TOC from disc image"); } else { DicConsole.WriteLine("CD TOC:"); DicConsole. WriteLine("================================================================================"); DicConsole.WriteLine(TOC.Prettify(toc)); DicConsole. WriteLine("================================================================================"); } break; } default: DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.", tag); break; } } } } if (sectorTags) { if (length.ToLowerInvariant() == "all") { } else { if (!ulong.TryParse(length, out ulong _)) { DicConsole.WriteLine("Value \"{0}\" is not a valid number for length.", length); DicConsole.WriteLine("Not decoding sectors tags"); return(3); } } if (inputFormat.Info.ReadableSectorTags.Count == 0) { DicConsole.WriteLine("There are no sector tags in chosen disc image."); } else { foreach (SectorTagType tag in inputFormat.Info.ReadableSectorTags) { switch (tag) { default: DicConsole.WriteLine("Decoder for disk tag type \"{0}\" not yet implemented, sorry.", tag); break; } } } // TODO: Not implemented } return((int)ErrorNumber.NoError); }
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; } FixedSense?decodedSense = Sense.DecodeFixed(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; } FixedSense?decodedSense = Sense.DecodeFixed(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; } }