Beispiel #1
0
        public void Read()
        {
            byte[] buffer = new byte[0];
            Errno  error  = _fs.Read("Content/0000000000000000/FFFE07DF/00040000", 0, 0, ref buffer);

            Assert.AreEqual(Errno.IsDirectory, error);

            error = _fs.Read("Content/0000000000000000/FFFE07DF/00040000/ContentCache", 0, 0, ref buffer);
            Assert.AreEqual(Errno.NoSuchFile, error);

            error = _fs.Read("Content/0000000000000000/FFFE07DF/00040000/ContentCache.pkg", 0, 0, ref buffer);
            Assert.AreEqual(Errno.NoError, error);
            Assert.AreEqual(0, buffer.Length);

            Assert.AreEqual("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
                            Sha256Context.Data(buffer, out _));

            error = _fs.Read("Content/0000000000000000/FFFE07DF/00040000/ContentCache.pkg", 1, 16, ref buffer);
            Assert.AreEqual(Errno.NoError, error);
            Assert.AreEqual(16, buffer.Length);

            Assert.AreEqual("f73a941675b8df16b0fc908f242c3c51382c5b159e709e0f9ffc1e5aac35f77d",
                            Sha256Context.Data(buffer, out _));

            error = _fs.Read("Content/0000000000000000/FFFE07DF/00040000/ContentCache.pkg", 248, 131072, ref buffer);
            Assert.AreEqual(Errno.NoError, error);
            Assert.AreEqual(85768, buffer.Length);

            Assert.AreEqual("19caf1365e1b7d5446ca0c2518d15e94c3ab0faaf2f8f3b31c9e1656dff57bd9",
                            Sha256Context.Data(buffer, out _));

            error = _fs.Read("Content/0000000000000000/FFFE07DF/00040000/ContentCache.pkg", 131072, 0, ref buffer);
            Assert.AreEqual(Errno.InvalidArgument, error);
        }
Beispiel #2
0
        public void Read()
        {
            byte[] buffer = new byte[0];
            Errno  error  = _fs.Read("49470015", 0, 0, ref buffer);

            Assert.AreEqual(Errno.IsDirectory, error);

            error = _fs.Read("49470015/TitleImage", 0, 0, ref buffer);
            Assert.AreEqual(Errno.NoSuchFile, error);

            error = _fs.Read("49470015/7AC2FE88C908/savedata.dat", 0, 0, ref buffer);
            Assert.AreEqual(Errno.NoError, error);
            Assert.AreEqual(0, buffer.Length);

            Assert.AreEqual("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
                            Sha256Context.Data(buffer, out _));

            error = _fs.Read("49470015/7AC2FE88C908/savedata.dat", 1, 16, ref buffer);
            Assert.AreEqual(Errno.NoError, error);
            Assert.AreEqual(16, buffer.Length);

            Assert.AreEqual("ff82559d2d0c610ac25b78dcb53a8312e32b56192044deb1f01540581bd54e80",
                            Sha256Context.Data(buffer, out _));

            error = _fs.Read("49470015/7AC2FE88C908/savedata.dat", 248, 131072, ref buffer);
            Assert.AreEqual(Errno.NoError, error);
            Assert.AreEqual(61996, buffer.Length);

            Assert.AreEqual("2eb0d62a96ad28473ce0dd67052efdfae31f371992e1d8309beeeff6f2b46a59",
                            Sha256Context.Data(buffer, out _));

            error = _fs.Read("49470015/7AC2FE88C908/savedata.dat", 131072, 0, ref buffer);
            Assert.AreEqual(Errno.InvalidArgument, error);
        }
Beispiel #3
0
        public void Sha256RandomData()
        {
            byte[]     data = new byte[1048576];
            FileStream fs   = new FileStream(Path.Combine(Consts.TestFilesRoot, "checksums", "random"), FileMode.Open,
                                             FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            Sha256Context.Data(data, out byte[] result);
            Assert.AreEqual(ExpectedRandom, result);
        }
Beispiel #4
0
        public void Sha256RandomData()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "random"),
                                    FileMode.Open, FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            Sha256Context.Data(data, out byte[] result);
            Assert.AreEqual(_expectedRandom, result);
        }
Beispiel #5
0
        public void EmptyData()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"), FileMode.Open,
                                    FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            Sha256Context.Data(data, out byte[] result);
            result.Should().BeEquivalentTo(_expectedEmpty);
        }
Beispiel #6
0
        public static void DetectDiscType(ref MediaType mediaType, int sessions, FullTOC.CDFullTOC?decodedToc,
                                          Device dev, out bool hiddenTrack, out bool hiddenData,
                                          int firstTrackLastSession)
        {
            uint startOfFirstDataTrack = uint.MaxValue;

            byte[] cmdBuf;
            bool   sense;
            byte   secondSessionFirstTrack = 0;

            byte[] sector0;
            byte[] sector1                      = null;
            byte[] ps2BootSectors               = null;
            byte[] playdia1                     = null;
            byte[] playdia2                     = null;
            byte[] firstDataSectorNotZero       = null;
            byte[] secondDataSectorNotZero      = null;
            byte[] firstTrackSecondSession      = null;
            byte[] firstTrackSecondSessionAudio = null;
            byte[] videoNowColorFrame;
            hiddenTrack = false;
            hiddenData  = false;

            if (decodedToc.HasValue)
            {
                if (decodedToc.Value.TrackDescriptors.Any(t => t.SessionNumber == 2))
                {
                    secondSessionFirstTrack =
                        decodedToc.Value.TrackDescriptors.Where(t => t.SessionNumber == 2).Min(t => t.POINT);
                }
            }

            if (mediaType == MediaType.CD ||
                mediaType == MediaType.CDROMXA)
            {
                bool hasDataTrack  = false;
                bool hasAudioTrack = false;
                bool allFirstSessionTracksAreAudio = true;
                bool hasVideoTrack = false;

                if (decodedToc.HasValue)
                {
                    foreach (FullTOC.TrackDataDescriptor track in decodedToc.Value.TrackDescriptors)
                    {
                        if (track.TNO == 1 &&
                            ((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
                             (TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental))
                        {
                            allFirstSessionTracksAreAudio &= firstTrackLastSession != 1;
                        }

                        if ((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
                            (TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental)
                        {
                            uint startAddress =
                                (uint)(((track.PHOUR * 3600 * 75) + (track.PMIN * 60 * 75) + (track.PSEC * 75) +
                                        track.PFRAME) - 150);

                            if (startAddress < startOfFirstDataTrack)
                            {
                                startOfFirstDataTrack = startAddress;
                            }

                            hasDataTrack = true;
                            allFirstSessionTracksAreAudio &= track.POINT >= firstTrackLastSession;
                        }
                        else
                        {
                            hasAudioTrack = true;
                        }

                        hasVideoTrack |= track.ADR == 4;
                    }
                }

                if (hasDataTrack &&
                    hasAudioTrack &&
                    allFirstSessionTracksAreAudio &&
                    sessions == 2)
                {
                    mediaType = MediaType.CDPLUS;
                }

                if (!hasDataTrack &&
                    hasAudioTrack &&
                    sessions == 1)
                {
                    mediaType = MediaType.CDDA;
                }

                if (hasDataTrack &&
                    !hasAudioTrack &&
                    sessions == 1)
                {
                    mediaType = MediaType.CDROM;
                }

                if (hasVideoTrack &&
                    !hasDataTrack &&
                    sessions == 1)
                {
                    mediaType = MediaType.CDV;
                }
            }

            if (secondSessionFirstTrack != 0 &&
                decodedToc.HasValue &&
                decodedToc.Value.TrackDescriptors.Any(t => t.POINT == secondSessionFirstTrack))
            {
                FullTOC.TrackDataDescriptor secondSessionFirstTrackTrack =
                    decodedToc.Value.TrackDescriptors.First(t => t.POINT == secondSessionFirstTrack);

                uint firstSectorSecondSessionFirstTrack =
                    (uint)(((secondSessionFirstTrackTrack.PHOUR * 3600 * 75) +
                            (secondSessionFirstTrackTrack.PMIN * 60 * 75) +
                            (secondSessionFirstTrackTrack.PSEC * 75) +
                            secondSessionFirstTrackTrack.PFRAME) - 150);

                sense = dev.ReadCd(out cmdBuf, out _, firstSectorSecondSessionFirstTrack, 2352, 1,
                                   MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true,
                                   MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                if (!sense &&
                    !dev.Error)
                {
                    firstTrackSecondSession = cmdBuf;
                }
                else
                {
                    sense = dev.ReadCd(out cmdBuf, out _, firstSectorSecondSessionFirstTrack, 2352, 1,
                                       MmcSectorTypes.Cdda, false, false, true, MmcHeaderCodes.None, true, true,
                                       MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        firstTrackSecondSession = cmdBuf;
                    }
                }

                sense = dev.ReadCd(out cmdBuf, out _, firstSectorSecondSessionFirstTrack - 1, 2352, 3,
                                   MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true,
                                   MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                if (!sense &&
                    !dev.Error)
                {
                    firstTrackSecondSessionAudio = cmdBuf;
                }
                else
                {
                    sense = dev.ReadCd(out cmdBuf, out _, firstSectorSecondSessionFirstTrack - 1, 2352, 3,
                                       MmcSectorTypes.Cdda, false, false, true, MmcHeaderCodes.None, true, true,
                                       MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        firstTrackSecondSessionAudio = cmdBuf;
                    }
                }
            }

            videoNowColorFrame = new byte[9 * 2352];

            for (int i = 0; i < 9; i++)
            {
                sense = dev.ReadCd(out cmdBuf, out _, (uint)i, 2352, 1, MmcSectorTypes.AllTypes, false, false, true,
                                   MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None,
                                   dev.Timeout, out _);

                if (sense || dev.Error)
                {
                    sense = dev.ReadCd(out cmdBuf, out _, (uint)i, 2352, 1, MmcSectorTypes.Cdda, false, false, true,
                                       MmcHeaderCodes.None, true, true, MmcErrorField.None, MmcSubchannel.None,
                                       dev.Timeout, out _);

                    if (sense || !dev.Error)
                    {
                        videoNowColorFrame = null;

                        break;
                    }
                }

                Array.Copy(cmdBuf, 0, videoNowColorFrame, i * 2352, 2352);
            }

            if (decodedToc.HasValue)
            {
                FullTOC.TrackDataDescriptor firstTrack =
                    decodedToc.Value.TrackDescriptors.FirstOrDefault(t => t.POINT == 1);

                if (firstTrack.POINT == 1)
                {
                    uint firstTrackSector = (uint)(((firstTrack.PHOUR * 3600 * 75) + (firstTrack.PMIN * 60 * 75) +
                                                    (firstTrack.PSEC * 75) + firstTrack.PFRAME) - 150);

                    // Check for hidden data before start of track 1
                    if (firstTrackSector > 0)
                    {
                        sense = dev.ReadCd(out sector0, out _, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true,
                                           MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
                                           MmcSubchannel.None, dev.Timeout, out _);

                        if (!dev.Error &&
                            !sense)
                        {
                            hiddenTrack = true;

                            hiddenData = IsData(sector0);

                            if (hiddenData)
                            {
                                sense = dev.ReadCd(out byte[] sector16, out _, 16, 2352, 1, MmcSectorTypes.AllTypes,
                                                   false, false, true, MmcHeaderCodes.AllHeaders, true, true,
                                                   MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                                if (IsCdi(sector0, sector16))
                                {
                                    mediaType = MediaType.CDIREADY;
                                }
                            }
                        }
                    }
                }
            }

            sector0 = null;

            switch (mediaType)
            {
            case MediaType.CD:
            case MediaType.CDDA:
            case MediaType.CDPLUS:
            case MediaType.CDROM:
            case MediaType.CDROMXA:
            {
                sense = dev.ReadCd(out cmdBuf, out _, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true,
                                   MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None,
                                   dev.Timeout, out _);

                if (!sense &&
                    !dev.Error)
                {
                    sector0 = new byte[2048];
                    Array.Copy(cmdBuf, 16, sector0, 0, 2048);

                    sense = dev.ReadCd(out cmdBuf, out _, 1, 2352, 1, MmcSectorTypes.AllTypes, false, false, true,
                                       MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
                                       MmcSubchannel.None, dev.Timeout, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        sector1 = new byte[2048];
                        Array.Copy(cmdBuf, 16, sector1, 0, 2048);
                    }

                    sense = dev.ReadCd(out cmdBuf, out _, 4200, 2352, 1, MmcSectorTypes.AllTypes, false, false,
                                       true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
                                       MmcSubchannel.None, dev.Timeout, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        playdia1 = new byte[2048];
                        Array.Copy(cmdBuf, 24, playdia1, 0, 2048);
                    }

                    sense = dev.ReadCd(out cmdBuf, out _, 4201, 2352, 1, MmcSectorTypes.AllTypes, false, false,
                                       true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
                                       MmcSubchannel.None, dev.Timeout, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        playdia2 = new byte[2048];
                        Array.Copy(cmdBuf, 24, playdia2, 0, 2048);
                    }

                    if (startOfFirstDataTrack != uint.MaxValue)
                    {
                        sense = dev.ReadCd(out cmdBuf, out _, startOfFirstDataTrack, 2352, 1,
                                           MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
                                           true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            firstDataSectorNotZero = new byte[2048];
                            Array.Copy(cmdBuf, 16, firstDataSectorNotZero, 0, 2048);
                        }

                        sense = dev.ReadCd(out cmdBuf, out _, startOfFirstDataTrack + 1, 2352, 1,
                                           MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
                                           true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            secondDataSectorNotZero = new byte[2048];
                            Array.Copy(cmdBuf, 16, secondDataSectorNotZero, 0, 2048);
                        }
                    }

                    var ps2Ms = new MemoryStream();

                    for (uint p = 0; p < 12; p++)
                    {
                        sense = dev.ReadCd(out cmdBuf, out _, p, 2352, 1, MmcSectorTypes.AllTypes, false, false,
                                           true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
                                           MmcSubchannel.None, dev.Timeout, out _);

                        if (sense || dev.Error)
                        {
                            break;
                        }

                        ps2Ms.Write(cmdBuf, cmdBuf[0x0F] == 0x02 ? 24 : 16, 2048);
                    }

                    if (ps2Ms.Length == 0x6000)
                    {
                        ps2BootSectors = ps2Ms.ToArray();
                    }
                }
                else
                {
                    sense = dev.ReadCd(out cmdBuf, out _, 0, 2324, 1, MmcSectorTypes.Mode2, false, false, true,
                                       MmcHeaderCodes.None, true, true, MmcErrorField.None, MmcSubchannel.None,
                                       dev.Timeout, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        sector0 = new byte[2048];
                        Array.Copy(cmdBuf, 0, sector0, 0, 2048);

                        sense = dev.ReadCd(out cmdBuf, out _, 1, 2324, 1, MmcSectorTypes.Mode2, false, false, true,
                                           MmcHeaderCodes.None, true, true, MmcErrorField.None, MmcSubchannel.None,
                                           dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            sector1 = new byte[2048];
                            Array.Copy(cmdBuf, 1, sector0, 0, 2048);
                        }

                        sense = dev.ReadCd(out cmdBuf, out _, 4200, 2324, 1, MmcSectorTypes.Mode2, false, false,
                                           true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
                                           MmcSubchannel.None, dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            playdia1 = new byte[2048];
                            Array.Copy(cmdBuf, 0, playdia1, 0, 2048);
                        }

                        sense = dev.ReadCd(out cmdBuf, out _, 4201, 2324, 1, MmcSectorTypes.Mode2, false, false,
                                           true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
                                           MmcSubchannel.None, dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            playdia2 = new byte[2048];
                            Array.Copy(cmdBuf, 0, playdia2, 0, 2048);
                        }

                        if (startOfFirstDataTrack != uint.MaxValue)
                        {
                            sense = dev.ReadCd(out cmdBuf, out _, startOfFirstDataTrack, 2324, 1,
                                               MmcSectorTypes.Mode2, false, false, true, MmcHeaderCodes.None, true,
                                               true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                            if (!sense &&
                                !dev.Error)
                            {
                                firstDataSectorNotZero = new byte[2048];
                                Array.Copy(cmdBuf, 0, firstDataSectorNotZero, 0, 2048);
                            }

                            sense = dev.ReadCd(out cmdBuf, out _, startOfFirstDataTrack + 1, 2324, 1,
                                               MmcSectorTypes.Mode2, false, false, true, MmcHeaderCodes.None, true,
                                               true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _);

                            if (!sense &&
                                !dev.Error)
                            {
                                secondDataSectorNotZero = new byte[2048];
                                Array.Copy(cmdBuf, 0, secondDataSectorNotZero, 0, 2048);
                            }
                        }

                        var ps2Ms = new MemoryStream();

                        for (uint p = 0; p < 12; p++)
                        {
                            sense = dev.ReadCd(out cmdBuf, out _, p, 2324, 1, MmcSectorTypes.Mode2, false, false,
                                               true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
                                               MmcSubchannel.None, dev.Timeout, out _);

                            if (sense || dev.Error)
                            {
                                break;
                            }

                            ps2Ms.Write(cmdBuf, 0, 2048);
                        }

                        if (ps2Ms.Length == 0x6000)
                        {
                            ps2BootSectors = ps2Ms.ToArray();
                        }
                    }
                    else
                    {
                        sense = dev.ReadCd(out cmdBuf, out _, 0, 2048, 1, MmcSectorTypes.Mode1, false, false, true,
                                           MmcHeaderCodes.None, true, true, MmcErrorField.None, MmcSubchannel.None,
                                           dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            sector0 = cmdBuf;

                            sense = dev.ReadCd(out cmdBuf, out _, 0, 2048, 1, MmcSectorTypes.Mode1, false, false,
                                               true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
                                               MmcSubchannel.None, dev.Timeout, out _);

                            if (!sense &&
                                !dev.Error)
                            {
                                sector1 = cmdBuf;
                            }

                            sense = dev.ReadCd(out cmdBuf, out _, 0, 2048, 12, MmcSectorTypes.Mode1, false, false,
                                               true, MmcHeaderCodes.None, true, true, MmcErrorField.None,
                                               MmcSubchannel.None, dev.Timeout, out _);

                            if (!sense &&
                                !dev.Error)
                            {
                                ps2BootSectors = cmdBuf;
                            }

                            if (startOfFirstDataTrack != uint.MaxValue)
                            {
                                sense = dev.ReadCd(out cmdBuf, out _, startOfFirstDataTrack, 2048, 1,
                                                   MmcSectorTypes.Mode1, false, false, true, MmcHeaderCodes.None,
                                                   true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout,
                                                   out _);

                                if (!sense &&
                                    !dev.Error)
                                {
                                    firstDataSectorNotZero = cmdBuf;
                                }

                                sense = dev.ReadCd(out cmdBuf, out _, startOfFirstDataTrack + 1, 2048, 1,
                                                   MmcSectorTypes.Mode1, false, false, true, MmcHeaderCodes.None,
                                                   true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout,
                                                   out _);

                                if (!sense &&
                                    !dev.Error)
                                {
                                    secondDataSectorNotZero = cmdBuf;
                                }
                            }
                        }
                        else
                        {
                            goto case MediaType.DVDROM;
                        }
                    }
                }

                break;
            }

            // TODO: Check for CD-i Ready
            case MediaType.CDI: break;

            case MediaType.DVDROM:
            case MediaType.HDDVDROM:
            case MediaType.BDROM:
            case MediaType.Unknown:
                sense = dev.Read16(out cmdBuf, out _, 0, false, true, false, 0, 2048, 0, 1, false, dev.Timeout,
                                   out _);

                if (!sense &&
                    !dev.Error)
                {
                    sector0 = cmdBuf;

                    sense = dev.Read16(out cmdBuf, out _, 0, false, true, false, 1, 2048, 0, 1, false, dev.Timeout,
                                       out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        sector1 = cmdBuf;
                    }

                    sense = dev.Read16(out cmdBuf, out _, 0, false, true, false, 0, 2048, 0, 12, false, dev.Timeout,
                                       out _);

                    if (!sense &&
                        !dev.Error &&
                        cmdBuf.Length == 0x6000)
                    {
                        ps2BootSectors = cmdBuf;
                    }
                }
                else
                {
                    sense = dev.Read12(out cmdBuf, out _, 0, false, true, false, false, 0, 2048, 0, 1, false,
                                       dev.Timeout, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        sector0 = cmdBuf;

                        sense = dev.Read12(out cmdBuf, out _, 0, false, true, false, false, 1, 2048, 0, 1, false,
                                           dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            sector1 = cmdBuf;
                        }

                        sense = dev.Read12(out cmdBuf, out _, 0, false, true, false, false, 0, 2048, 0, 12, false,
                                           dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error &&
                            cmdBuf.Length == 0x6000)
                        {
                            ps2BootSectors = cmdBuf;
                        }
                    }
                    else
                    {
                        sense = dev.Read10(out cmdBuf, out _, 0, false, true, false, false, 0, 2048, 0, 1,
                                           dev.Timeout, out _);

                        if (!sense &&
                            !dev.Error)
                        {
                            sector0 = cmdBuf;

                            sense = dev.Read10(out cmdBuf, out _, 0, false, true, false, false, 1, 2048, 0, 1,
                                               dev.Timeout, out _);

                            if (!sense &&
                                !dev.Error)
                            {
                                sector1 = cmdBuf;
                            }

                            sense = dev.Read10(out cmdBuf, out _, 0, false, true, false, false, 0, 2048, 0, 12,
                                               dev.Timeout, out _);

                            if (!sense &&
                                !dev.Error &&
                                cmdBuf.Length == 0x6000)
                            {
                                ps2BootSectors = cmdBuf;
                            }
                        }
                        else
                        {
                            sense = dev.Read6(out cmdBuf, out _, 0, 2048, 1, dev.Timeout, out _);

                            if (!sense &&
                                !dev.Error)
                            {
                                sector0 = cmdBuf;

                                sense = dev.Read6(out cmdBuf, out _, 1, 2048, 1, dev.Timeout, out _);

                                if (!sense &&
                                    !dev.Error)
                                {
                                    sector1 = cmdBuf;
                                }

                                sense = dev.Read6(out cmdBuf, out _, 0, 2048, 12, dev.Timeout, out _);

                                if (!sense &&
                                    !dev.Error &&
                                    cmdBuf.Length == 0x6000)
                                {
                                    ps2BootSectors = cmdBuf;
                                }
                            }
                        }
                    }
                }

                break;

            // Recordables will not be checked
            case MediaType.CDR:
            case MediaType.CDRW:
            case MediaType.CDMRW:
            case MediaType.DDCDR:
            case MediaType.DDCDRW:
            case MediaType.DVDR:
            case MediaType.DVDRW:
            case MediaType.DVDPR:
            case MediaType.DVDPRW:
            case MediaType.DVDPRWDL:
            case MediaType.DVDRDL:
            case MediaType.DVDPRDL:
            case MediaType.DVDRAM:
            case MediaType.DVDRWDL:
            case MediaType.DVDDownload:
            case MediaType.HDDVDRAM:
            case MediaType.HDDVDR:
            case MediaType.HDDVDRW:
            case MediaType.HDDVDRDL:
            case MediaType.HDDVDRWDL:
            case MediaType.BDR:
            case MediaType.BDRE:
            case MediaType.BDRXL:
            case MediaType.BDREXL: return;
            }

            if (sector0 == null)
            {
                return;
            }

            switch (mediaType)
            {
            case MediaType.CD:
            case MediaType.CDDA:
            case MediaType.CDPLUS:
            case MediaType.CDROM:
            case MediaType.CDROMXA:
                // TODO: CDTV requires reading the filesystem, searching for a file called "/CDTV.TM"
                // TODO: CD32 requires reading the filesystem, searching for a file called "/CD32.TM"
                // TODO: Neo-Geo CD requires reading the filesystem and checking that the file "/IPL.TXT" is correct
                // TODO: Pippin requires interpreting Apple Partition Map, reading HFS and checking for Pippin signatures
            {
                if (CD.DecodeIPBin(sector0).HasValue)
                {
                    mediaType = MediaType.MEGACD;

                    return;
                }

                if (Saturn.DecodeIPBin(sector0).HasValue)
                {
                    mediaType = MediaType.SATURNCD;
                }

                // Are GDR detectable ???
                if (Dreamcast.DecodeIPBin(sector0).HasValue)
                {
                    mediaType = MediaType.GDROM;
                }

                if (ps2BootSectors != null &&
                    ps2BootSectors.Length == 0x6000)
                {
                    // The decryption key is applied as XOR. As first byte is originally always NULL, it gives us the key :)
                    byte decryptByte = ps2BootSectors[0];

                    for (int i = 0; i < 0x6000; i++)
                    {
                        ps2BootSectors[i] ^= decryptByte;
                    }

                    string ps2BootSectorsHash = Sha256Context.Data(ps2BootSectors, out _);

                    DicConsole.DebugWriteLine("Media-info Command", "PlayStation 2 boot sectors SHA256: {0}",
                                              ps2BootSectorsHash);

                    if (ps2BootSectorsHash == PS2_PAL_HASH ||
                        ps2BootSectorsHash == PS2_NTSC_HASH ||
                        ps2BootSectorsHash == PS2_JAPANESE_HASH)
                    {
                        mediaType = MediaType.PS2CD;
                    }
                }

                if (sector0 != null)
                {
                    byte[] syncBytes = new byte[7];
                    Array.Copy(sector0, 0, syncBytes, 0, 7);

                    if (_operaId.SequenceEqual(syncBytes))
                    {
                        mediaType = MediaType.ThreeDO;
                    }

                    if (_fmTownsBootId.SequenceEqual(syncBytes))
                    {
                        mediaType = MediaType.FMTOWNS;
                    }
                }

                if (playdia1 != null &&
                    playdia2 != null)
                {
                    byte[] pd1 = new byte[_playdiaCopyright.Length];
                    byte[] pd2 = new byte[_playdiaCopyright.Length];

                    Array.Copy(playdia1, 38, pd1, 0, pd1.Length);
                    Array.Copy(playdia2, 0, pd2, 0, pd1.Length);

                    if (_playdiaCopyright.SequenceEqual(pd1) &&
                        _playdiaCopyright.SequenceEqual(pd2))
                    {
                        mediaType = MediaType.Playdia;
                    }
                }

                if (secondDataSectorNotZero != null)
                {
                    byte[] pce = new byte[_pcEngineSignature.Length];
                    Array.Copy(secondDataSectorNotZero, 32, pce, 0, pce.Length);

                    if (_pcEngineSignature.SequenceEqual(pce))
                    {
                        mediaType = MediaType.SuperCDROM2;
                    }
                }

                if (firstDataSectorNotZero != null)
                {
                    byte[] pcfx = new byte[_pcFxSignature.Length];
                    Array.Copy(firstDataSectorNotZero, 0, pcfx, 0, pcfx.Length);

                    if (_pcFxSignature.SequenceEqual(pcfx))
                    {
                        mediaType = MediaType.PCFX;
                    }
                }

                if (firstTrackSecondSessionAudio != null)
                {
                    byte[] jaguar = new byte[_atariSignature.Length];

                    for (int i = 0; i + jaguar.Length <= firstTrackSecondSessionAudio.Length; i += 2)
                    {
                        Array.Copy(firstTrackSecondSessionAudio, i, jaguar, 0, jaguar.Length);

                        if (!_atariSignature.SequenceEqual(jaguar))
                        {
                            continue;
                        }

                        mediaType = MediaType.JaguarCD;

                        break;
                    }
                }

                if (firstTrackSecondSession != null)
                {
                    if (firstTrackSecondSession.Length >= 2336)
                    {
                        byte[] milcd = new byte[2048];
                        Array.Copy(firstTrackSecondSession, 24, milcd, 0, 2048);

                        if (Dreamcast.DecodeIPBin(milcd).HasValue)
                        {
                            mediaType = MediaType.MilCD;
                        }
                    }
                }

                // TODO: Detect black and white VideoNow
                // TODO: Detect VideoNow XP
                if (IsVideoNowColor(videoNowColorFrame))
                {
                    mediaType = MediaType.VideoNowColor;
                }

                break;
            }

            // TODO: Check for CD-i Ready
            case MediaType.CDI: break;

            case MediaType.DVDROM:
            case MediaType.HDDVDROM:
            case MediaType.BDROM:
            case MediaType.Unknown:
                // TODO: Nuon requires reading the filesystem, searching for a file called "/NUON/NUON.RUN"
                if (ps2BootSectors != null &&
                    ps2BootSectors.Length == 0x6000)
                {
                    // The decryption key is applied as XOR. As first byte is originally always NULL, it gives us the key :)
                    byte decryptByte = ps2BootSectors[0];

                    for (int i = 0; i < 0x6000; i++)
                    {
                        ps2BootSectors[i] ^= decryptByte;
                    }

                    string ps2BootSectorsHash = Sha256Context.Data(ps2BootSectors, out _);

                    DicConsole.DebugWriteLine("Media-info Command", "PlayStation 2 boot sectors SHA256: {0}",
                                              ps2BootSectorsHash);

                    if (ps2BootSectorsHash == PS2_PAL_HASH ||
                        ps2BootSectorsHash == PS2_NTSC_HASH ||
                        ps2BootSectorsHash == PS2_JAPANESE_HASH)
                    {
                        mediaType = MediaType.PS2DVD;
                    }
                }

                if (sector1 != null)
                {
                    byte[] tmp = new byte[_ps3Id.Length];
                    Array.Copy(sector1, 0, tmp, 0, tmp.Length);

                    if (tmp.SequenceEqual(_ps3Id))
                    {
                        switch (mediaType)
                        {
                        case MediaType.BDROM:
                            mediaType = MediaType.PS3BD;

                            break;

                        case MediaType.DVDROM:
                            mediaType = MediaType.PS3DVD;

                            break;
                        }
                    }

                    tmp = new byte[_ps4Id.Length];
                    Array.Copy(sector1, 512, tmp, 0, tmp.Length);

                    if (tmp.SequenceEqual(_ps4Id) &&
                        mediaType == MediaType.BDROM)
                    {
                        mediaType = MediaType.PS4BD;
                    }
                }

                // TODO: Identify discs that require reading tracks (PC-FX, PlayStation, Sega, etc)
                break;
            }
        }