Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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();
        }
Ejemplo n.º 4
0
        // 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;
            }
        }
Ejemplo n.º 5
0
        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
                    });
                }
            }
        }
Ejemplo n.º 6
0
        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();
        }
Ejemplo n.º 7
0
        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;
        }
Ejemplo n.º 9
0
        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;
        }
Ejemplo n.º 10
0
        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;
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        /// <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());
        }
Ejemplo n.º 13
0
        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;
        }
Ejemplo n.º 14
0
        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();
        }
Ejemplo n.º 15
0
        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;
            }
        }
Ejemplo n.º 16
0
        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();
        }
Ejemplo n.º 17
0
        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);
        }
Ejemplo n.º 18
0
Archivo: GdRom.cs Proyecto: paulyc/Aaru
        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;
            }
        }