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); }
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); }
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); }
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); }
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); }
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; } }