diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs index d605d2932..47265c078 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -79,6 +79,7 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime dumpStart = DateTime.UtcNow; // Time of dump start DateTime end; // Time of operation end ExtentsULong extents = null; // Extents + bool hiddenData; // Hidden track is data IbgLog ibgLog; // IMGBurn log double imageWriteDuration = 0; // Duration of image write long lastSector; // Last sector number @@ -98,8 +99,8 @@ namespace DiscImageChef.Core.Devices.Dumping const uint sectorSize = 2352; // Full sector size int sectorsForOffset = 0; // Sectors needed to fix offset ulong sectorSpeedStart = 0; // Used to calculate correct speed - bool sense=true; // Sense indicator - byte[] senseBuf = null; // Sense buffer + bool sense = true; // Sense indicator + byte[] senseBuf = null; // Sense buffer int sessions; // Number of sessions in disc DateTime start; // Start of operation uint subSize; // Subchannel size in bytes @@ -113,16 +114,14 @@ namespace DiscImageChef.Core.Devices.Dumping Dictionary trackFlags = new Dictionary(); // Track flags Track[] tracks; // Tracks in disc - bool nextData; // Next cluster of sectors is all data; + int firstTrackLastSession; // Number of first track in last session + bool hiddenTrack; // Disc has a hidden track before track 1 + bool nextData; // Next cluster of sectors is all data; + MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel + DateTime timeSpeedStart; // Time of start for speed calculation Dictionary mediaTags = new Dictionary(); // Media tags - int firstTrackLastSession; // Number of first track in last session - - MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel - - DateTime timeSpeedStart; // Time of start for speed calculation - dskType = MediaType.CD; if(_dumpRaw) @@ -428,157 +427,31 @@ namespace DiscImageChef.Core.Devices.Dumping leadOutExtents.Add(dataExtentsArray[i].Item2 + 1, dataExtentsArray[i + 1].Item1 - 1); } - // Check for hidden data before start of track 1 - if(tracks.First(t => t.TrackSequence == 1).TrackStartSector > 0 && readcd) + _dumpLog.WriteLine("Detecting disc type..."); + UpdateStatus?.Invoke("Detecting disc type..."); + + MMC.DetectDiscType(ref dskType, sessions, toc, _dev, out hiddenTrack, out hiddenData, + firstTrackLastSession); + + if(hiddenTrack) { - _dumpLog.WriteLine("First track starts after sector 0, checking for a hidden track..."); - UpdateStatus?.Invoke("First track starts after sector 0, checking for a hidden track..."); + _dumpLog.WriteLine("Disc contains a hidden track..."); + UpdateStatus?.Invoke("Disc contains a hidden track..."); - sense = _dev.ReadCd(out cmdBuf, out senseBuf, 0, blockSize, 1, MmcSectorTypes.AllTypes, false, false, - true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, - supportedSubchannel, _dev.Timeout, out _); - - if(_dev.Error || sense) + List trkList = new List { - _dumpLog.WriteLine("Could not read sector 0, continuing..."); - UpdateStatus?.Invoke("Could not read sector 0, continuing..."); - } - else - { - byte[] syncMark = + new Track { - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 - }; - - byte[] cdiMark = - { - 0x01, 0x43, 0x44, 0x2D - }; - - byte[] testMark = new byte[12]; - Array.Copy(cmdBuf, 0, testMark, 0, 12); - - bool hiddenData = syncMark.SequenceEqual(testMark) && - (cmdBuf[0xF] == 0 || cmdBuf[0xF] == 1 || cmdBuf[0xF] == 2); - - if(hiddenData && cmdBuf[0xF] == 2) - { - sense = _dev.ReadCd(out cmdBuf, out senseBuf, 16, blockSize, 1, MmcSectorTypes.AllTypes, false, - false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, - supportedSubchannel, _dev.Timeout, out _); - - if(!_dev.Error && - !sense) - { - testMark = new byte[4]; - Array.Copy(cmdBuf, 24, testMark, 0, 4); - - if(cdiMark.SequenceEqual(testMark)) - dskType = MediaType.CDIREADY; - } - - List trkList = new List - { - new Track - { - TrackSequence = 0, - TrackSession = 1, - TrackType = hiddenData ? TrackType.Data : TrackType.Audio, - TrackStartSector = 0, - TrackBytesPerSector = (int)sectorSize, - TrackRawBytesPerSector = (int)sectorSize, - TrackSubchannelType = subType, - TrackEndSector = tracks.First(t => t.TrackSequence == 1).TrackStartSector - 1 - } - }; - - trkList.AddRange(tracks); - tracks = trkList.ToArray(); + TrackSequence = 0, TrackSession = 1, + TrackType = hiddenData ? TrackType.Data : TrackType.Audio, + TrackStartSector = 0, TrackBytesPerSector = (int)sectorSize, + TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType, + TrackEndSector = tracks.First(t => t.TrackSequence == 1).TrackStartSector - 1 } - } - } + }; - if(dskType == MediaType.CD || - dskType == MediaType.CDROMXA) - { - // TODO: Add other detectors here - _dumpLog.WriteLine("Detecting disc type..."); - UpdateStatus?.Invoke("Detecting disc type..."); - - bool hasDataTrack = false; - bool hasAudioTrack = false; - bool allFirstSessionTracksAreAudio = true; - bool hasVideoTrack = false; - - foreach(FullTOC.TrackDataDescriptor track in toc.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) - { - hasDataTrack = true; - allFirstSessionTracksAreAudio &= track.POINT >= firstTrackLastSession; - } - else - { - hasAudioTrack = true; - } - - hasVideoTrack |= track.ADR == 4; - } - - if(hasDataTrack && - hasAudioTrack && - allFirstSessionTracksAreAudio && - sessions == 2) - dskType = MediaType.CDPLUS; - - if(!hasDataTrack && - hasAudioTrack && - sessions == 1) - dskType = MediaType.CDDA; - - if(hasDataTrack && - !hasAudioTrack && - sessions == 1) - dskType = MediaType.CDROM; - - if(hasVideoTrack && - !hasDataTrack && - sessions == 1) - dskType = MediaType.CDV; - - byte[] videoNowColorFrame = new byte[9 * sectorSize]; - - for(int i = 0; i < 9; i++) - { - sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)i, sectorSize, 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 senseBuf, (uint)i, sectorSize, 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 * sectorSize, sectorSize); - } - - if(MMC.IsVideoNowColor(videoNowColorFrame)) - dskType = MediaType.VideoNowColor; + trkList.AddRange(tracks); + tracks = trkList.ToArray(); } // Check mode for tracks diff --git a/DiscImageChef.Core/Media/Detection/MMC.cs b/DiscImageChef.Core/Media/Detection/MMC.cs index e26553819..896c91020 100644 --- a/DiscImageChef.Core/Media/Detection/MMC.cs +++ b/DiscImageChef.Core/Media/Detection/MMC.cs @@ -31,14 +31,79 @@ // ****************************************************************************/ using System; +using System.IO; using System.Linq; +using DiscImageChef.Checksums; +using DiscImageChef.CommonTypes; +using DiscImageChef.Console; +using DiscImageChef.Decoders.CD; +using DiscImageChef.Decoders.Sega; +using DiscImageChef.Devices; +// ReSharper disable JoinDeclarationAndInitializer namespace DiscImageChef.Core.Media.Detection { public static class MMC { + /// SHA256 of PlayStation 2 boot sectors, seen in PAL discs + const string PS2_PAL_HASH = "5d04ff236613e1d8adcf9c201874acd6f6deed1e04306558b86f91cfb626f39d"; + + /// SHA256 of PlayStation 2 boot sectors, seen in Japanese, American, Malaysian and Korean discs + const string PS2_NTSC_HASH = "0bada1426e2c0351b872ef2a9ad2e5a0ac3918f4c53aa53329cb2911a8e16c23"; + + /// SHA256 of PlayStation 2 boot sectors, seen in Japanese discs + const string PS2_JAPANESE_HASH = "b82bffb809070d61fe050b7e1545df53d8f3cc648257cdff7502bc0ba6b38870"; + + static readonly byte[] _ps3Id = + { + 0x50, 0x6C, 0x61, 0x79, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x33, 0x00, 0x00, 0x00, 0x00 + }; + + static readonly byte[] _ps4Id = + { + 0x50, 0x6C, 0x61, 0x79, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x34, 0x00, 0x00, 0x00, 0x00 + }; + + static readonly byte[] _operaId = + { + 0x01, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x01 + }; + + // Only present on bootable CDs, but those make more than 99% of all available + static readonly byte[] _fmTownsBootId = + { + 0x49, 0x50, 0x4C, 0x34, 0xEB, 0x55, 0x06 + }; + + /// Present on first two seconds of second track, says "COPYRIGHT BANDAI" + static readonly byte[] _playdiaCopyright = + { + 0x43, 0x4F, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, 0x42, 0x41, 0x4E, 0x44, 0x41, 0x49 + }; + + static readonly byte[] _pcEngineSignature = + { + 0x50, 0x43, 0x20, 0x45, 0x6E, 0x67, 0x69, 0x6E, 0x65, 0x20, 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 0x20, 0x53, + 0x59, 0x53, 0x54, 0x45, 0x4D + }; + + static readonly byte[] _pcFxSignature = + { + 0x50, 0x43, 0x2D, 0x46, 0x58, 0x3A, 0x48, 0x75, 0x5F, 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D + }; + + static readonly byte[] _atariSignature = + { + 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, + 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, + 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, + 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x52, 0x41, 0x20, 0x49, 0x50, 0x41, + 0x52, 0x50, 0x56, 0x4F, 0x44, 0x45, 0x44, 0x20, 0x54, 0x41, 0x20, 0x41, 0x45, 0x48, 0x44, 0x41, 0x52, 0x45, + 0x41, 0x20, 0x52, 0x54 + }; + /// This is some kind of header. Every 10 bytes there's an audio byte. - static readonly byte[] VideoNowColorFrameMarker = + static readonly byte[] _videoNowColorFrameMarker = { 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, 0x81, 0xE3, 0xC7, 0x00, 0x81, 0xE3, 0xE3, 0xC7, 0xC7, 0x81, @@ -65,14 +130,9 @@ namespace DiscImageChef.Core.Media.Detection 0xFF, 0xFF, 0xFF, 0x00 }; - /// Checks if the media corresponds to CD-i. - /// Contents of LBA 0, with all headers. - /// Contents of LBA 0, with all headers. - /// true if it corresponds to a CD-i, falseotherwise. - public static bool IsCdi(byte[] sector0, byte[] sector16) + static bool IsData(byte[] sector) { - if(sector0?.Length != 2352 || - sector16?.Length != 2352) + if(sector?.Length != 2352) return false; byte[] syncMark = @@ -80,34 +140,45 @@ namespace DiscImageChef.Core.Media.Detection 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }; + byte[] testMark = new byte[12]; + Array.Copy(sector, 0, testMark, 0, 12); + + return syncMark.SequenceEqual(testMark) && (sector[0xF] == 0 || sector[0xF] == 1 || sector[0xF] == 2); + } + + /// Checks if the media corresponds to CD-i. + /// Contents of LBA 0, with all headers. + /// Contents of LBA 0, with all headers. + /// true if it corresponds to a CD-i, falseotherwise. + static bool IsCdi(byte[] sector0, byte[] sector16) + { + if(sector16?.Length != 2352) + return false; + byte[] cdiMark = { 0x01, 0x43, 0x44, 0x2D }; - byte[] testMark = new byte[12]; - Array.Copy(sector0, 0, testMark, 0, 12); + bool isData = IsData(sector0); - bool hiddenData = syncMark.SequenceEqual(testMark) && - (sector0[0xF] == 0 || sector0[0xF] == 1 || sector0[0xF] == 2); - - if(!hiddenData || + if(!isData || sector0[0xF] != 2) return false; - testMark = new byte[4]; + byte[] testMark = new byte[4]; Array.Copy(sector16, 24, testMark, 0, 4); return cdiMark.SequenceEqual(testMark); } - public static bool IsVideoNowColor(byte[] videoFrame) + static bool IsVideoNowColor(byte[] videoFrame) { if(videoFrame is null || - videoFrame.Length < VideoNowColorFrameMarker.Length) + videoFrame.Length < _videoNowColorFrameMarker.Length) return false; - byte[] buffer = new byte[VideoNowColorFrameMarker.Length]; + byte[] buffer = new byte[_videoNowColorFrameMarker.Length]; for(int framePosition = 0; framePosition + buffer.Length < videoFrame.Length; framePosition++) { @@ -116,7 +187,7 @@ namespace DiscImageChef.Core.Media.Detection for(int ab = 9; ab < buffer.Length; ab += 10) buffer[ab] = 0; - if(!VideoNowColorFrameMarker.SequenceEqual(buffer)) + if(!_videoNowColorFrameMarker.SequenceEqual(buffer)) continue; return true; @@ -127,7 +198,7 @@ namespace DiscImageChef.Core.Media.Detection public static int GetVideoNowColorOffset(byte[] data) { - byte[] buffer = new byte[VideoNowColorFrameMarker.Length]; + byte[] buffer = new byte[_videoNowColorFrameMarker.Length]; for(int framePosition = 0; framePosition + buffer.Length < data.Length; framePosition++) { @@ -136,7 +207,7 @@ namespace DiscImageChef.Core.Media.Detection for(int ab = 9; ab < buffer.Length; ab += 10) buffer[ab] = 0; - if(!VideoNowColorFrameMarker.SequenceEqual(buffer)) + if(!_videoNowColorFrameMarker.SequenceEqual(buffer)) continue; return 18032 - framePosition; @@ -144,5 +215,765 @@ namespace DiscImageChef.Core.Media.Detection return 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.First(t => t.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; + } + } } } \ No newline at end of file diff --git a/DiscImageChef.Core/Media/Info/ScsiInfo.cs b/DiscImageChef.Core/Media/Info/ScsiInfo.cs index 7e257cf5a..22165b009 100644 --- a/DiscImageChef.Core/Media/Info/ScsiInfo.cs +++ b/DiscImageChef.Core/Media/Info/ScsiInfo.cs @@ -32,10 +32,8 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading; -using DiscImageChef.Checksums; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; @@ -45,7 +43,6 @@ using DiscImageChef.Decoders.DVD; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI.MMC; using DiscImageChef.Decoders.SCSI.SSC; -using DiscImageChef.Decoders.Sega; using DiscImageChef.Decoders.Xbox; using DiscImageChef.Devices; using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo; @@ -55,136 +52,102 @@ namespace DiscImageChef.Core.Media.Info { public class ScsiInfo { - /// SHA256 of PlayStation 2 boot sectors, seen in PAL discs - private const string PS2_PAL_HASH = "5d04ff236613e1d8adcf9c201874acd6f6deed1e04306558b86f91cfb626f39d"; - - /// SHA256 of PlayStation 2 boot sectors, seen in Japanese, American, Malaysian and Korean discs - private const string PS2_NTSC_HASH = "0bada1426e2c0351b872ef2a9ad2e5a0ac3918f4c53aa53329cb2911a8e16c23"; - - /// SHA256 of PlayStation 2 boot sectors, seen in Japanese discs - private const string PS2_JAPANESE_HASH = "b82bffb809070d61fe050b7e1545df53d8f3cc648257cdff7502bc0ba6b38870"; - - private static readonly byte[] Ps3Id = - { - 0x50, 0x6C, 0x61, 0x79, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x33, 0x00, 0x00, 0x00, 0x00 - }; - - private static readonly byte[] Ps4Id = - { - 0x50, 0x6C, 0x61, 0x79, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x34, 0x00, 0x00, 0x00, 0x00 - }; - - private static readonly byte[] OperaId = {0x01, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x01}; - - // Only present on bootable CDs, but those make more than 99% of all available - private static readonly byte[] FmTownsBootId = {0x49, 0x50, 0x4C, 0x34, 0xEB, 0x55, 0x06}; - - /// Present on first two seconds of second track, says "COPYRIGHT BANDAI" - private static readonly byte[] PlaydiaCopyright = - { - 0x43, 0x4F, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, 0x42, 0x41, 0x4E, 0x44, 0x41, 0x49 - }; - - private static readonly byte[] PcEngineSignature = - { - 0x50, 0x43, 0x20, 0x45, 0x6E, 0x67, 0x69, 0x6E, 0x65, 0x20, 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 0x20, - 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D - }; - - private static readonly byte[] PcFxSignature = - { - 0x50, 0x43, 0x2D, 0x46, 0x58, 0x3A, 0x48, 0x75, 0x5F, 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D - }; - - private static readonly byte[] AtariSignature = - { - 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, - 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, - 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, - 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x49, 0x52, 0x54, 0x41, 0x52, 0x41, - 0x20, 0x49, 0x50, 0x41, 0x52, 0x50, 0x56, 0x4F, 0x44, 0x45, 0x44, 0x20, 0x54, 0x41, 0x20, 0x41, 0x45, - 0x48, 0x44, 0x41, 0x52, 0x45, 0x41, 0x20, 0x52, 0x54 - }; - public ScsiInfo(Device dev) { - if (dev.Type != DeviceType.SCSI && dev.Type != DeviceType.ATAPI) return; + if(dev.Type != DeviceType.SCSI && + dev.Type != DeviceType.ATAPI) + return; - MediaType = MediaType.Unknown; + MediaType = MediaType.Unknown; MediaInserted = false; - var resets = 0; - var startOfFirstDataTrack = uint.MaxValue; - bool sense; + int resets = 0; + bool sense; byte[] cmdBuf; byte[] senseBuf; - bool containsFloppyPage; - byte secondSessionFirstTrack = 0; + bool containsFloppyPage = false; + int sessions = 1; + int firstTrackLastSession = 1; - if (dev.IsRemovable) + if(dev.IsRemovable) { deviceGotReset: sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { - var decSense = Sense.DecodeFixed(senseBuf); - if (decSense.HasValue) + FixedSense? decSense = Sense.DecodeFixed(senseBuf); + + if(decSense.HasValue) { // Just retry, for 5 times - if (decSense.Value.ASC == 0x29) + if(decSense.Value.ASC == 0x29) { resets++; - if (resets < 5) goto deviceGotReset; + + if(resets < 5) + goto deviceGotReset; } - if (decSense.Value.ASC == 0x3A) + if(decSense.Value.ASC == 0x3A) { - var leftRetries = 5; - while (leftRetries > 0) + int leftRetries = 5; + + while(leftRetries > 0) { //DicConsole.WriteLine("\rWaiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); - if (!sense) break; + + if(!sense) + break; leftRetries--; } - if (sense) + if(sense) { DicConsole.ErrorWriteLine("Please insert media in drive"); + return; } } - else if (decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01) + else if(decSense.Value.ASC == 0x04 && + decSense.Value.ASCQ == 0x01) { - var leftRetries = 10; - while (leftRetries > 0) + int leftRetries = 10; + + while(leftRetries > 0) { //DicConsole.WriteLine("\rWaiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); - if (!sense) break; + + if(!sense) + break; leftRetries--; } - if (sense) + if(sense) { DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); + return; } } else { DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); + return; } } else { DicConsole.ErrorWriteLine("Unknown testing unit was ready."); + return; } } @@ -194,28 +157,25 @@ namespace DiscImageChef.Core.Media.Info DeviceInfo = new DeviceInfo(dev); - byte scsiMediumType = 0; + byte scsiMediumType = 0; byte scsiDensityCode = 0; - containsFloppyPage = false; - if (DeviceInfo.ScsiMode.HasValue) + if(DeviceInfo.ScsiMode.HasValue) { - scsiMediumType = (byte) DeviceInfo.ScsiMode.Value.Header.MediumType; - if (DeviceInfo.ScsiMode.Value.Header.BlockDescriptors != null && - DeviceInfo.ScsiMode.Value.Header.BlockDescriptors.Length >= 1) - scsiDensityCode = (byte) DeviceInfo.ScsiMode.Value.Header.BlockDescriptors[0].Density; + scsiMediumType = (byte)DeviceInfo.ScsiMode.Value.Header.MediumType; - if (DeviceInfo.ScsiMode.Value.Pages != null) - containsFloppyPage = - DeviceInfo.ScsiMode.Value.Pages.Aggregate(containsFloppyPage, - (current, modePage) => - current | (modePage.Page == 0x05)); + if(DeviceInfo.ScsiMode.Value.Header.BlockDescriptors != null && + DeviceInfo.ScsiMode.Value.Header.BlockDescriptors.Length >= 1) + scsiDensityCode = (byte)DeviceInfo.ScsiMode.Value.Header.BlockDescriptors[0].Density; + + if(DeviceInfo.ScsiMode.Value.Pages != null) + containsFloppyPage = DeviceInfo.ScsiMode.Value.Pages.Any(p => p.Page == 0x05); } - Blocks = 0; + Blocks = 0; BlockSize = 0; - switch (dev.ScsiType) + switch(dev.ScsiType) { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: @@ -224,62 +184,74 @@ namespace DiscImageChef.Core.Media.Info case PeripheralDeviceTypes.SimplifiedDevice: case PeripheralDeviceTypes.WriteOnceDevice: sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (!sense) + + if(!sense) { ReadCapacity = cmdBuf; - Blocks = (ulong) ((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); - BlockSize = (uint) ((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); + Blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); + BlockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); } sense = dev.ReadCapacity16(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (!sense) ReadCapacity16 = cmdBuf; - if (ReadCapacity == null || Blocks == 0xFFFFFFFF || Blocks == 0) + if(!sense) + ReadCapacity16 = cmdBuf; + + if(ReadCapacity == null || + Blocks == 0xFFFFFFFF || + Blocks == 0) { - if (ReadCapacity16 == null && Blocks == 0) - if (dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice) + if(ReadCapacity16 == null && + Blocks == 0) + if(dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice) { DicConsole.ErrorWriteLine("Unable to get media capacity"); DicConsole.ErrorWriteLine("{0}", Sense.PrettifySense(senseBuf)); } - if (ReadCapacity16 != null) + if(ReadCapacity16 != null) { - var temp = new byte[8]; + byte[] temp = new byte[8]; Array.Copy(cmdBuf, 0, temp, 0, 8); Array.Reverse(temp); - Blocks = BitConverter.ToUInt64(temp, 0); - BlockSize = (uint) ((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); + Blocks = BitConverter.ToUInt64(temp, 0); + BlockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); } } - if (Blocks != 0 && BlockSize != 0) Blocks++; + if(Blocks != 0 && + BlockSize != 0) + Blocks++; break; case PeripheralDeviceTypes.SequentialAccess: byte[] medBuf; - sense = dev.ReportDensitySupport(out var seqBuf, out senseBuf, false, dev.Timeout, out _); - if (!sense) + sense = dev.ReportDensitySupport(out byte[] seqBuf, out senseBuf, false, dev.Timeout, out _); + + if(!sense) { sense = dev.ReportDensitySupport(out medBuf, out senseBuf, true, dev.Timeout, out _); - if (!sense && !seqBuf.SequenceEqual(medBuf)) + if(!sense && + !seqBuf.SequenceEqual(medBuf)) { - DensitySupport = seqBuf; + DensitySupport = seqBuf; DensitySupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(seqBuf); } } sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, true, false, dev.Timeout, out _); - if (!sense) + + if(!sense) { sense = dev.ReportDensitySupport(out medBuf, out senseBuf, true, true, dev.Timeout, out _); - if (!sense && !seqBuf.SequenceEqual(medBuf)) + if(!sense && + !seqBuf.SequenceEqual(medBuf)) { - MediaTypeSupport = medBuf; + MediaTypeSupport = medBuf; MediaTypeSupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(seqBuf); } } @@ -297,159 +269,199 @@ namespace DiscImageChef.Core.Media.Info break; } - if (dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) + if(dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) { sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, - out _); - if (sense) + out _); + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ GET CONFIGURATION:\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { MmcConfiguration = cmdBuf; - var ftr = Features.Separate(cmdBuf); + Features.SeparatedFeatures ftr = Features.Separate(cmdBuf); DicConsole.DebugWriteLine("Media-Info command", "GET CONFIGURATION current profile is {0:X4}h", - ftr.CurrentProfile); + ftr.CurrentProfile); - switch (ftr.CurrentProfile) + switch(ftr.CurrentProfile) { case 0x0001: MediaType = MediaType.GENERIC_HDD; + break; case 0x0002: - switch (scsiMediumType) + switch(scsiMediumType) { case 0x01: MediaType = MediaType.PD650; + break; case 0x41: - switch (Blocks) + switch(Blocks) { case 58620544: MediaType = MediaType.REV120; + break; case 17090880: MediaType = MediaType.REV35; + break; default: // TODO: Unknown value MediaType = MediaType.REV70; + break; } break; default: MediaType = MediaType.Unknown; + break; } break; case 0x0005: MediaType = MediaType.CDMO; + break; case 0x0008: MediaType = MediaType.CD; + break; case 0x0009: MediaType = MediaType.CDR; + break; case 0x000A: MediaType = MediaType.CDRW; + break; case 0x0010: MediaType = MediaType.DVDROM; + break; case 0x0011: MediaType = MediaType.DVDR; + break; case 0x0012: MediaType = MediaType.DVDRAM; + break; case 0x0013: case 0x0014: MediaType = MediaType.DVDRW; + break; case 0x0015: case 0x0016: MediaType = MediaType.DVDRDL; + break; case 0x0017: MediaType = MediaType.DVDRWDL; + break; case 0x0018: MediaType = MediaType.DVDDownload; + break; case 0x001A: MediaType = MediaType.DVDPRW; + break; case 0x001B: MediaType = MediaType.DVDPR; + break; case 0x0020: MediaType = MediaType.DDCD; + break; case 0x0021: MediaType = MediaType.DDCDR; + break; case 0x0022: MediaType = MediaType.DDCDRW; + break; case 0x002A: MediaType = MediaType.DVDPRWDL; + break; case 0x002B: MediaType = MediaType.DVDPRDL; + break; case 0x0040: MediaType = MediaType.BDROM; + break; case 0x0041: case 0x0042: MediaType = MediaType.BDR; + break; case 0x0043: MediaType = MediaType.BDRE; + break; case 0x0050: MediaType = MediaType.HDDVDROM; + break; case 0x0051: MediaType = MediaType.HDDVDR; + break; case 0x0052: MediaType = MediaType.HDDVDRAM; + break; case 0x0053: MediaType = MediaType.HDDVDRW; + break; case 0x0058: MediaType = MediaType.HDDVDRDL; + break; case 0x005A: MediaType = MediaType.HDDVDRWDL; + break; } } - if (MediaType == MediaType.PD650 && Blocks == 1281856) MediaType = MediaType.PD650_WORM; + if(MediaType == MediaType.PD650 && + Blocks == 1281856) + MediaType = MediaType.PD650_WORM; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.RecognizedFormatLayers, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.RecognizedFormatLayers, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Recognized Format Layers\n{0}", - Sense.PrettifySense(senseBuf)); - else RecognizedFormatLayers = cmdBuf; + "READ DISC STRUCTURE: Recognized Format Layers\n{0}", + Sense.PrettifySense(senseBuf)); + else + RecognizedFormatLayers = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.WriteProtectionStatus, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.WriteProtectionStatus, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Write Protection Status\n{0}", - Sense.PrettifySense(senseBuf)); - else WriteProtectionStatus = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + WriteProtectionStatus = cmdBuf; // More like a drive information /* @@ -461,200 +473,228 @@ namespace DiscImageChef.Core.Media.Info */ #region All DVD and HD DVD types - - if (MediaType == MediaType.DVDDownload || MediaType == MediaType.DVDPR || - MediaType == MediaType.DVDPRDL || MediaType == MediaType.DVDPRW || - MediaType == MediaType.DVDPRWDL || - MediaType == MediaType.DVDR || MediaType == MediaType.DVDRAM || - MediaType == MediaType.DVDRDL || - MediaType == MediaType.DVDROM || MediaType == MediaType.DVDRW || - MediaType == MediaType.DVDRWDL || - MediaType == MediaType.HDDVDR || MediaType == MediaType.HDDVDRAM || - MediaType == MediaType.HDDVDRDL || MediaType == MediaType.HDDVDROM || - MediaType == MediaType.HDDVDRW || MediaType == MediaType.HDDVDRWDL) + if(MediaType == MediaType.DVDDownload || + MediaType == MediaType.DVDPR || + MediaType == MediaType.DVDPRDL || + MediaType == MediaType.DVDPRW || + MediaType == MediaType.DVDPRWDL || + MediaType == MediaType.DVDR || + MediaType == MediaType.DVDRAM || + MediaType == MediaType.DVDRDL || + MediaType == MediaType.DVDROM || + MediaType == MediaType.DVDRW || + MediaType == MediaType.DVDRWDL || + MediaType == MediaType.HDDVDR || + MediaType == MediaType.HDDVDRAM || + MediaType == MediaType.HDDVDRDL || + MediaType == MediaType.HDDVDROM || + MediaType == MediaType.HDDVDRW || + MediaType == MediaType.HDDVDRWDL) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: PFI\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { - DvdPfi = cmdBuf; + DvdPfi = cmdBuf; DecodedPfi = PFI.Decode(cmdBuf); - if (DecodedPfi.HasValue) - if (MediaType == MediaType.DVDROM) - switch (DecodedPfi.Value.DiskCategory) + + if(DecodedPfi.HasValue) + if(MediaType == MediaType.DVDROM) + switch(DecodedPfi.Value.DiskCategory) { case DiskCategory.DVDPR: MediaType = MediaType.DVDPR; + break; case DiskCategory.DVDPRDL: MediaType = MediaType.DVDPRDL; + break; case DiskCategory.DVDPRW: MediaType = MediaType.DVDPRW; + break; case DiskCategory.DVDPRWDL: MediaType = MediaType.DVDPRWDL; + break; case DiskCategory.DVDR: - MediaType = DecodedPfi.Value.PartVersion == 6 - ? MediaType.DVDRDL - : MediaType.DVDR; + MediaType = DecodedPfi.Value.PartVersion == 6 ? MediaType.DVDRDL + : MediaType.DVDR; + break; case DiskCategory.DVDRAM: MediaType = MediaType.DVDRAM; + break; default: MediaType = MediaType.DVDROM; + break; case DiskCategory.DVDRW: - MediaType = DecodedPfi.Value.PartVersion == 3 - ? MediaType.DVDRWDL - : MediaType.DVDRW; + MediaType = DecodedPfi.Value.PartVersion == 3 ? MediaType.DVDRWDL + : MediaType.DVDRW; + break; case DiskCategory.HDDVDR: MediaType = MediaType.HDDVDR; + break; case DiskCategory.HDDVDRAM: MediaType = MediaType.HDDVDRAM; + break; case DiskCategory.HDDVDROM: MediaType = MediaType.HDDVDROM; + break; case DiskCategory.HDDVDRW: MediaType = MediaType.HDDVDRW; + break; case DiskCategory.Nintendo: - MediaType = DecodedPfi.Value.DiscSize == DVDSize.Eighty - ? MediaType.GOD - : MediaType.WOD; + MediaType = DecodedPfi.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD + : MediaType.WOD; + break; case DiskCategory.UMD: MediaType = MediaType.UMD; + break; } } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, - out _); - if (sense) + MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, + out _); + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DMI\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { DvdDmi = cmdBuf; - if (DMI.IsXbox(cmdBuf)) + + if(DMI.IsXbox(cmdBuf)) { MediaType = MediaType.XGD; } - else if (DMI.IsXbox360(cmdBuf)) + else if(DMI.IsXbox360(cmdBuf)) { MediaType = MediaType.XGD2; // All XGD3 all have the same number of blocks - if (Blocks == 25063 || // Locked (or non compatible drive) - Blocks == 4229664 || // Xtreme unlock - Blocks == 4246304) // Wxripper unlock + if(Blocks == 25063 || // Locked (or non compatible drive) + Blocks == 4229664 || // Xtreme unlock + Blocks == 4246304) // Wxripper unlock MediaType = MediaType.XGD3; } } } - #endregion All DVD and HD DVD types #region DVD-ROM - - if (MediaType == MediaType.DVDDownload || MediaType == MediaType.DVDROM) + if(MediaType == MediaType.DVDDownload || + MediaType == MediaType.DVDROM) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: CMI\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdCmi = cmdBuf; - } + MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: CMI\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdCmi = cmdBuf; + } #endregion DVD-ROM - switch (MediaType) + switch(MediaType) { #region DVD-ROM and HD DVD-ROM - case MediaType.DVDDownload: case MediaType.DVDROM: case MediaType.HDDVDROM: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: BCA\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdBca = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + DvdBca = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdAacs, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DVD AACS\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdAacs = cmdBuf; - break; + MmcDiscStructureFormat.DvdAacs, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DVD AACS\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdAacs = cmdBuf; + + break; #endregion DVD-ROM and HD DVD-ROM #region DVD-RAM and HD DVD-RAM - case MediaType.DVDRAM: case MediaType.HDDVDRAM: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DDS\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdRamDds = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + DvdRamDds = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdramMediumStatus, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.DvdramMediumStatus, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Medium Status\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdRamCartridgeStatus = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + DvdRamCartridgeStatus = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout, - out _); - if (sense) + MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout, + out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: SAI\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdRamSpareArea = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + DvdRamSpareArea = cmdBuf; break; - #endregion DVD-RAM and HD DVD-RAM #region DVD-R and HD DVD-R - case MediaType.DVDR: case MediaType.HDDVDR: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.LastBorderOutRmd, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Last-Out Border RMD\n{0}", - Sense.PrettifySense(senseBuf)); - else LastBorderOutRmd = cmdBuf; - break; + MmcDiscStructureFormat.LastBorderOutRmd, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", + "READ DISC STRUCTURE: Last-Out Border RMD\n{0}", + Sense.PrettifySense(senseBuf)); + else + LastBorderOutRmd = cmdBuf; + + break; #endregion DVD-R and HD DVD-R } #region Require drive authentication, won't work - /* sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscKey, 0, dev.Timeout, out _); if(sense) @@ -712,259 +752,293 @@ namespace DiscImageChef.Core.Media.Info else DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscstructure_aacsdatakeys.bin", "SCSI READ DISC STRUCTURE", cmdBuf); */ - #endregion Require drive authentication, won't work #region DVD-R and DVD-RW - - if (MediaType == MediaType.DVDR || MediaType == MediaType.DVDRW) + if(MediaType == MediaType.DVDR || + MediaType == MediaType.DVDRW) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Pre-Recorded Info\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdPreRecordedInfo = cmdBuf; - } + MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Pre-Recorded Info\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdPreRecordedInfo = cmdBuf; + } #endregion DVD-R and DVD-RW - switch (MediaType) + switch(MediaType) { #region DVD-R, DVD-RW and HD DVD-R - case MediaType.DVDR: case MediaType.DVDRW: case MediaType.HDDVDR: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdrMediaIdentifier, 0, dev.Timeout, - out _); - if (sense) + MmcDiscStructureFormat.DvdrMediaIdentifier, 0, dev.Timeout, + out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DVD-R Media ID\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdrMediaIdentifier = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + DvdrMediaIdentifier = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdrPhysicalInformation, 0, dev.Timeout, - out _); - if (sense) + MmcDiscStructureFormat.DvdrPhysicalInformation, 0, dev.Timeout, + out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DVD-R PFI\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdrPhysicalInformation = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + DvdrPhysicalInformation = cmdBuf; break; - #endregion DVD-R, DVD-RW and HD DVD-R #region All DVD+ - case MediaType.DVDPR: case MediaType.DVDPRDL: case MediaType.DVDPRW: case MediaType.DVDPRWDL: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.Adip, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.Adip, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: ADIP\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdPlusAdip = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + DvdPlusAdip = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.Dcb, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DCB\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdPlusDcb = cmdBuf; - break; + MmcDiscStructureFormat.Dcb, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DCB\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdPlusDcb = cmdBuf; + + break; #endregion All DVD+ #region HD DVD-ROM - case MediaType.HDDVDROM: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.HddvdCopyrightInformation, 0, dev.Timeout, - out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: HDDVD CMI\n{0}", - Sense.PrettifySense(senseBuf)); - else HddvdCopyrightInformation = cmdBuf; - break; + MmcDiscStructureFormat.HddvdCopyrightInformation, 0, dev.Timeout, + out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: HD DVD CMI\n{0}", + Sense.PrettifySense(senseBuf)); + else + HddvdCopyrightInformation = cmdBuf; + + break; #endregion HD DVD-ROM } #region HD DVD-R - - if (MediaType == MediaType.HDDVDR) + if(MediaType == MediaType.HDDVDR) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.HddvdrMediumStatus, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: HDDVD-R Medium Status\n{0}", - Sense.PrettifySense(senseBuf)); - else HddvdrMediumStatus = cmdBuf; - sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.HddvdrLastRmd, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Last RMD\n{0}", - Sense.PrettifySense(senseBuf)); - else HddvdrLastRmd = cmdBuf; - } + MmcDiscStructureFormat.HddvdrMediumStatus, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", + "READ DISC STRUCTURE: HD DVD-R Medium Status\n{0}", + Sense.PrettifySense(senseBuf)); + else + HddvdrMediumStatus = cmdBuf; + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, + MmcDiscStructureFormat.HddvdrLastRmd, 0, dev.Timeout, out _); + + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Last RMD\n{0}", + Sense.PrettifySense(senseBuf)); + else + HddvdrLastRmd = cmdBuf; + } #endregion HD DVD-R #region DVD-R DL, DVD-RW DL, DVD+R DL, DVD+RW DL - - if (MediaType == MediaType.DVDPRDL || MediaType == MediaType.DVDRDL || MediaType == MediaType.DVDRWDL || - MediaType == MediaType.DVDPRWDL) + if(MediaType == MediaType.DVDPRDL || + MediaType == MediaType.DVDRDL || + MediaType == MediaType.DVDRWDL || + MediaType == MediaType.DVDPRWDL) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdrLayerCapacity, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Layer Capacity\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdrLayerCapacity = cmdBuf; - } + MmcDiscStructureFormat.DvdrLayerCapacity, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Layer Capacity\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdrLayerCapacity = cmdBuf; + } #endregion DVD-R DL, DVD-RW DL, DVD+R DL, DVD+RW DL - switch (MediaType) + switch(MediaType) { #region DVD-R DL - case MediaType.DVDRDL: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.MiddleZoneStart, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Middle Zone Start\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdrDlMiddleZoneStart = cmdBuf; - sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.JumpIntervalSize, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Jump Interval Size\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdrDlJumpIntervalSize = cmdBuf; - sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.ManualLayerJumpStartLba, 0, dev.Timeout, - out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Manual Layer Jump Start LBA\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdrDlManualLayerJumpStartLba = cmdBuf; - sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.RemapAnchorPoint, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Remap Anchor Point\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdrDlRemapAnchorPoint = cmdBuf; - break; + MmcDiscStructureFormat.MiddleZoneStart, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", + "READ DISC STRUCTURE: Middle Zone Start\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdrDlMiddleZoneStart = cmdBuf; + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, + MmcDiscStructureFormat.JumpIntervalSize, 0, dev.Timeout, out _); + + if(sense) + DicConsole.DebugWriteLine("Media-Info command", + "READ DISC STRUCTURE: Jump Interval Size\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdrDlJumpIntervalSize = cmdBuf; + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, + MmcDiscStructureFormat.ManualLayerJumpStartLba, 0, dev.Timeout, + out _); + + if(sense) + DicConsole.DebugWriteLine("Media-Info command", + "READ DISC STRUCTURE: Manual Layer Jump Start LBA\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdrDlManualLayerJumpStartLba = cmdBuf; + + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, + MmcDiscStructureFormat.RemapAnchorPoint, 0, dev.Timeout, out _); + + if(sense) + DicConsole.DebugWriteLine("Media-Info command", + "READ DISC STRUCTURE: Remap Anchor Point\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdrDlRemapAnchorPoint = cmdBuf; + + break; #endregion DVD-R DL #region All Blu-ray - case MediaType.BDR: case MediaType.BDRE: case MediaType.BDROM: case MediaType.BDRXL: case MediaType.BDREXL: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DI\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayDiscInformation = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + BlurayDiscInformation = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.Pac, 0, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: PAC\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayPac = cmdBuf; - break; + MmcDiscStructureFormat.Pac, 0, dev.Timeout, out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: PAC\n{0}", + Sense.PrettifySense(senseBuf)); + else + BlurayPac = cmdBuf; + + break; #endregion All Blu-ray } - switch (MediaType) + switch(MediaType) { #region BD-ROM only - case MediaType.BDROM: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.BdBurstCuttingArea, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.BdBurstCuttingArea, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: BCA\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayBurstCuttingArea = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + BlurayBurstCuttingArea = cmdBuf; break; - #endregion BD-ROM only #region Writable Blu-ray only - case MediaType.BDR: case MediaType.BDRE: case MediaType.BDRXL: case MediaType.BDREXL: sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.BdDds, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.BdDds, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DDS\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayDds = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + BlurayDds = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.CartridgeStatus, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.CartridgeStatus, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Cartridge Status\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayCartridgeStatus = cmdBuf; + "READ DISC STRUCTURE: Cartridge Status\n{0}", + Sense.PrettifySense(senseBuf)); + else + BlurayCartridgeStatus = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, - out _); - if (sense) + MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, + out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", - "READ DISC STRUCTURE: Spare Area Information\n{0}", - Sense.PrettifySense(senseBuf)); - else BluraySpareAreaInformation = cmdBuf; + "READ DISC STRUCTURE: Spare Area Information\n{0}", + Sense.PrettifySense(senseBuf)); + else + BluraySpareAreaInformation = cmdBuf; sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.RawDfl, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.RawDfl, 0, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: Raw DFL\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayRawDfl = cmdBuf; - sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, - MmcDiscInformationDataTypes.TrackResources, dev.Timeout, out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC INFORMATION 001b\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayTrackResources = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + BlurayRawDfl = cmdBuf; sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, - MmcDiscInformationDataTypes.PowResources, dev.Timeout, out _); - if (sense) + MmcDiscInformationDataTypes.TrackResources, dev.Timeout, out _); + + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC INFORMATION 001b\n{0}", + Sense.PrettifySense(senseBuf)); + else + BlurayTrackResources = cmdBuf; + + sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, + MmcDiscInformationDataTypes.PowResources, dev.Timeout, out _); + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ DISC INFORMATION 010b\n{0}", - Sense.PrettifySense(senseBuf)); - else BlurayPowResources = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + BlurayPowResources = cmdBuf; break; - #endregion Writable Blu-ray only #region CDs - case MediaType.CD: case MediaType.CDR: case MediaType.CDROM: @@ -972,1018 +1046,471 @@ namespace DiscImageChef.Core.Media.Info case MediaType.Unknown: // We discarded all discs that falsify a TOC before requesting a real TOC // No TOC, no CD (or an empty one) - var tocSense = dev.ReadTocPmaAtip(out cmdBuf, out senseBuf, false, 0, 0, dev.Timeout, out _); - if (tocSense) + bool tocSense = dev.ReadTocPmaAtip(out cmdBuf, out senseBuf, false, 0, 0, dev.Timeout, out _); + + if(tocSense) { DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: TOC\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { - Toc = cmdBuf; + Toc = cmdBuf; DecodedToc = TOC.Decode(cmdBuf); // As we have a TOC we know it is a CD - if (MediaType == MediaType.Unknown) MediaType = MediaType.CD; + if(MediaType == MediaType.Unknown) + MediaType = MediaType.CD; } // ATIP exists on blank CDs sense = dev.ReadAtip(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: ATIP\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { - Atip = cmdBuf; + Atip = cmdBuf; DecodedAtip = ATIP.Decode(cmdBuf); - if (DecodedAtip.HasValue) + + if(DecodedAtip.HasValue) + // Only CD-R and CD-RW have ATIP MediaType = DecodedAtip.Value.DiscType ? MediaType.CDRW : MediaType.CDR; } // We got a TOC, get information about a recorded/mastered CD - if (!tocSense) + if(!tocSense) { sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, - MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, - out _); - if (sense) + MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, + out _); + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ DISC INFORMATION 000b\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { - CompactDiscInformation = cmdBuf; + CompactDiscInformation = cmdBuf; DecodedCompactDiscInformation = DiscInformation.Decode000b(cmdBuf); - if (DecodedCompactDiscInformation.HasValue) - if (MediaType == MediaType.CD) - switch (DecodedCompactDiscInformation.Value.DiscType) + + if(DecodedCompactDiscInformation.HasValue) + if(MediaType == MediaType.CD) + switch(DecodedCompactDiscInformation.Value.DiscType) { case 0x10: MediaType = MediaType.CDI; + break; case 0x20: MediaType = MediaType.CDROMXA; + break; } } - var sessions = 1; - var firstTrackLastSession = 0; - sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: Session info\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { - Session = cmdBuf; + Session = cmdBuf; DecodedSession = Decoders.CD.Session.Decode(cmdBuf); - if (DecodedSession.HasValue) + + if(DecodedSession.HasValue) { - sessions = DecodedSession.Value.LastCompleteSession; + sessions = DecodedSession.Value.LastCompleteSession; firstTrackLastSession = DecodedSession.Value.TrackDescriptors[0].TrackNumber; } } - if (MediaType == MediaType.CD) - { - var hasDataTrack = false; - var hasAudioTrack = false; - var allFirstSessionTracksAreAudio = true; - var hasVideoTrack = false; - - if (DecodedToc.HasValue) - foreach (var track in DecodedToc.Value.TrackDescriptors) - { - if (track.TrackNumber == 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) - { - if (track.TrackStartAddress < startOfFirstDataTrack) - startOfFirstDataTrack = track.TrackStartAddress; - hasDataTrack = true; - allFirstSessionTracksAreAudio &= track.TrackNumber >= 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; - } - sense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: Raw TOC\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { RawToc = cmdBuf; FullToc = FullTOC.Decode(cmdBuf); - if (FullToc.HasValue) + + if(FullToc.HasValue) { - var a0Track = - FullToc.Value.TrackDescriptors - .FirstOrDefault(t => t.POINT == 0xA0 && t.ADR == 1); - if (a0Track.POINT == 0xA0) - switch (a0Track.PSEC) + FullTOC.TrackDataDescriptor a0Track = + FullToc.Value.TrackDescriptors. + FirstOrDefault(t => t.POINT == 0xA0 && t.ADR == 1); + + if(a0Track.POINT == 0xA0) + switch(a0Track.PSEC) { case 0x10: MediaType = MediaType.CDI; + break; case 0x20: MediaType = MediaType.CDROMXA; + break; } - - if (FullToc.Value.TrackDescriptors.Any(t => t.SessionNumber == 2)) - secondSessionFirstTrack = FullToc - .Value.TrackDescriptors - .Where(t => t.SessionNumber == 2).Min(t => t.POINT); } } sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: PMA\n{0}", - Sense.PrettifySense(senseBuf)); - else Pma = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + Pma = cmdBuf; sense = dev.ReadCdText(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: CD-TEXT\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { - CdTextLeadIn = cmdBuf; + CdTextLeadIn = cmdBuf; DecodedCdTextLeadIn = CDTextOnLeadIn.Decode(cmdBuf); } - sense = dev.ReadMcn(out var mcn, out _, out _, dev.Timeout, out _); - if (!sense && mcn != null && mcn != "0000000000000") Mcn = mcn; + sense = dev.ReadMcn(out string mcn, out _, out _, dev.Timeout, out _); + + if(!sense && + mcn != null && + mcn != "0000000000000") + Mcn = mcn; Isrcs = new Dictionary(); - for (var i = DecodedToc.Value.FirstTrack; i <= DecodedToc.Value.LastTrack; i++) + + for(byte i = DecodedToc.Value.FirstTrack; i <= DecodedToc.Value.LastTrack; i++) { - sense = dev.ReadIsrc(i, out var isrc, out _, out _, dev.Timeout, out _); - if (!sense && isrc != null && isrc != "000000000000") Isrcs.Add(i, isrc); + sense = dev.ReadIsrc(i, out string isrc, out _, out _, dev.Timeout, out _); + + if(!sense && + isrc != null && + isrc != "000000000000") + Isrcs.Add(i, isrc); } - if (Isrcs.Count == 0) Isrcs = null; + if(Isrcs.Count == 0) + Isrcs = null; } break; - #endregion CDs } #region Nintendo - - if (MediaType == MediaType.Unknown && Blocks > 0) + if(MediaType == MediaType.Unknown && + Blocks > 0) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); - if (sense) + MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: PFI\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { DvdPfi = cmdBuf; - var nintendoPfi = PFI.Decode(cmdBuf); - if (nintendoPfi != null) + PFI.PhysicalFormatInformation? nintendoPfi = PFI.Decode(cmdBuf); + + if(nintendoPfi != null) { DicConsole.WriteLine("PFI:\n{0}", PFI.Prettify(cmdBuf)); - if (nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo && - nintendoPfi.Value.PartVersion == 15) - switch (nintendoPfi.Value.DiscSize) + + if(nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo && + nintendoPfi.Value.PartVersion == 15) + switch(nintendoPfi.Value.DiscSize) { case DVDSize.Eighty: MediaType = MediaType.GOD; + break; case DVDSize.OneTwenty: MediaType = MediaType.WOD; + break; } } } sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, - out _); - if (sense) - DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DMI\n{0}", - Sense.PrettifySense(senseBuf)); - else DvdDmi = cmdBuf; - } + MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, + out _); + if(sense) + DicConsole.DebugWriteLine("Media-Info command", "READ DISC STRUCTURE: DMI\n{0}", + Sense.PrettifySense(senseBuf)); + else + DvdDmi = cmdBuf; + } #endregion Nintendo } sense = dev.ReadMediaSerialNumber(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.DebugWriteLine("Media-Info command", "READ MEDIA SERIAL NUMBER\n{0}", - Sense.PrettifySense(senseBuf)); + Sense.PrettifySense(senseBuf)); } else { - if (cmdBuf.Length >= 4) MediaSerialNumber = cmdBuf; + if(cmdBuf.Length >= 4) + MediaSerialNumber = cmdBuf; } - switch (MediaType) + switch(MediaType) { #region Xbox - case MediaType.XGD: case MediaType.XGD2: case MediaType.XGD3: // We need to get INQUIRY to know if it is a Kreon drive - sense = dev.ScsiInquiry(out var inqBuffer, out senseBuf); - if (!sense) + sense = dev.ScsiInquiry(out byte[] inqBuffer, out senseBuf); + + if(!sense) { - var inq = Inquiry.Decode(inqBuffer); - if (inq.HasValue && inq.Value.KreonPresent) + Inquiry.SCSIInquiry? inq = Inquiry.Decode(inqBuffer); + + if(inq.HasValue && + inq.Value.KreonPresent) { sense = dev.KreonExtractSs(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) DicConsole.DebugWriteLine("Media-Info command", "KREON EXTRACT SS:\n{0}", - Sense.PrettifySense(senseBuf)); - else XboxSecuritySector = cmdBuf; + Sense.PrettifySense(senseBuf)); + else + XboxSecuritySector = cmdBuf; DecodedXboxSecuritySector = SS.Decode(cmdBuf); // Get video partition size DicConsole.DebugWriteLine("Dump-media command", "Getting video partition size"); sense = dev.KreonLock(out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.ErrorWriteLine("Cannot lock drive, not continuing."); + return; } sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.ErrorWriteLine("Cannot get disc capacity."); + return; } - var totalSize = - (ulong) ((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); + ulong totalSize = + (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); - if (sense) + MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); + + if(sense) { DicConsole.ErrorWriteLine("Cannot get PFI."); + return; } DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", - totalSize); - ulong l0Video = PFI.Decode(cmdBuf).Value.Layer0EndPSN - - PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1; - var l1Video = totalSize - l0Video + 1; + totalSize); + + ulong l0Video = (PFI.Decode(cmdBuf).Value.Layer0EndPSN - + PFI.Decode(cmdBuf).Value.DataAreaStartPSN) + 1; + + ulong l1Video = (totalSize - l0Video) + 1; // Get game partition size DicConsole.DebugWriteLine("Dump-media command", "Getting game partition size"); sense = dev.KreonUnlockXtreme(out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing."); + return; } sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.ErrorWriteLine("Cannot get disc capacity."); + return; } - var gameSize = - (ulong) ((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) + 1; + ulong gameSize = + (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) + 1; + DicConsole.DebugWriteLine("Dump-media command", "Game partition total size: {0} sectors", - gameSize); + gameSize); // Get middle zone size DicConsole.DebugWriteLine("Dump-media command", "Getting middle zone size"); sense = dev.KreonUnlockWxripper(out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing."); + return; } sense = dev.ReadCapacity(out cmdBuf, out senseBuf, dev.Timeout, out _); - if (sense) + + if(sense) { DicConsole.ErrorWriteLine("Cannot get disc capacity."); + return; } - totalSize = (ulong) ((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); + totalSize = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); + sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); - if (sense) + MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); + + if(sense) { DicConsole.ErrorWriteLine("Cannot get PFI."); + return; } DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors", - totalSize); - var middleZone = - totalSize - - (PFI.Decode(cmdBuf).Value.Layer0EndPSN - - PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1) - gameSize + 1; + totalSize); - totalSize = l0Video + l1Video + middleZone * 2 + gameSize; - var layerBreak = l0Video + middleZone + gameSize / 2; + ulong middleZone = + (totalSize - + ((PFI.Decode(cmdBuf).Value.Layer0EndPSN - + PFI.Decode(cmdBuf).Value.DataAreaStartPSN) + 1) - gameSize) + 1; + + totalSize = l0Video + l1Video + (middleZone * 2) + gameSize; + ulong layerBreak = l0Video + middleZone + (gameSize / 2); XgdInfo = new XgdInfo { - L0Video = l0Video, - L1Video = l1Video, - MiddleZone = middleZone, - GameSize = gameSize, - TotalSize = totalSize, - LayerBreak = layerBreak + L0Video = l0Video, L1Video = l1Video, MiddleZone = middleZone, + GameSize = gameSize, + TotalSize = totalSize, LayerBreak = layerBreak }; } } break; - #endregion Xbox case MediaType.Unknown: - MediaType = MediaTypeFromScsi.Get((byte) dev.ScsiType, dev.Manufacturer, dev.Model, scsiMediumType, - scsiDensityCode, Blocks, BlockSize); + MediaType = MediaTypeFromScsi.Get((byte)dev.ScsiType, dev.Manufacturer, dev.Model, scsiMediumType, + scsiDensityCode, Blocks, BlockSize); + break; } - if (MediaType == MediaType.Unknown && dev.IsUsb && containsFloppyPage) MediaType = MediaType.FlashDrive; + if(MediaType == MediaType.Unknown && + dev.IsUsb && + containsFloppyPage) + MediaType = MediaType.FlashDrive; - if (DeviceInfo.ScsiType != PeripheralDeviceTypes.MultiMediaDevice) return; + if(DeviceInfo.ScsiType != PeripheralDeviceTypes.MultiMediaDevice) + return; - byte[] sector0 = null; - 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 = null; + MediaType tmpType = MediaType; + MMC.DetectDiscType(ref tmpType, sessions, FullToc, dev, out _, out _, firstTrackLastSession); - if (secondSessionFirstTrack != 0 && DecodedToc.HasValue && - DecodedToc.Value.TrackDescriptors.Any(t => t.TrackNumber == secondSessionFirstTrack)) - { - var firstSectorSecondSessionFirstTrack = DecodedToc - .Value.TrackDescriptors - .First(t => t.TrackNumber == secondSessionFirstTrack) - .TrackStartAddress; - - sense = dev.ReadCd(out cmdBuf, out senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 (var i = 0; i < 9; i++) - { - sense = dev.ReadCd(out cmdBuf, out senseBuf, (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 senseBuf, (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); - } - - // Check for hidden data before start of track 1 - if (DecodedToc.HasValue && - DecodedToc.Value.TrackDescriptors.FirstOrDefault(t => t.TrackNumber == 1).TrackStartAddress > 0) - { - sense = dev.ReadCd(out cmdBuf, out senseBuf, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, - MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, - dev.Timeout, out _); - - if (!dev.Error && !sense) - { - sector0 = cmdBuf; - - sense = dev.ReadCd(out cmdBuf, out senseBuf, 16, 2352, 1, MmcSectorTypes.AllTypes, false, false, - true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, - MmcSubchannel.None, dev.Timeout, out _); - - if (!dev.Error && !sense) - if (MMC.IsCdi(sector0, cmdBuf)) - 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 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 senseBuf, 0, false, true, false, 0, BlockSize, 0, 1, false, - dev.Timeout, out _); - - if (!sense && !dev.Error) - { - sector0 = cmdBuf; - - sense = dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, 1, BlockSize, 0, 1, false, - dev.Timeout, out _); - - if (!sense && !dev.Error) sector1 = cmdBuf; - - sense = dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, 0, BlockSize, 0, 12, false, - dev.Timeout, out _); - - if (!sense && !dev.Error && cmdBuf.Length == 0x6000) ps2BootSectors = cmdBuf; - } - else - { - sense = dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, BlockSize, 0, 1, - false, dev.Timeout, out _); - - if (!sense && !dev.Error) - { - sector0 = cmdBuf; - - sense = dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, 1, BlockSize, 0, - 1, false, dev.Timeout, out _); - - if (!sense && !dev.Error) sector1 = cmdBuf; - - sense = dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, BlockSize, 0, - 12, false, dev.Timeout, out _); - - if (!sense && !dev.Error && cmdBuf.Length == 0x6000) ps2BootSectors = cmdBuf; - } - else - { - sense = dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, BlockSize, 0, - 1, dev.Timeout, out _); - - if (!sense && !dev.Error) - { - sector0 = cmdBuf; - - sense = dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, 1, BlockSize, - 0, 1, dev.Timeout, out _); - - if (!sense && !dev.Error) sector1 = cmdBuf; - - sense = dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, 0, BlockSize, - 0, 12, dev.Timeout, out _); - - if (!sense && !dev.Error && cmdBuf.Length == 0x6000) ps2BootSectors = cmdBuf; - } - else - { - sense = dev.Read6(out cmdBuf, out senseBuf, 0, BlockSize, 1, dev.Timeout, out _); - - if (!sense && !dev.Error) - { - sector0 = cmdBuf; - - sense = dev.Read6(out cmdBuf, out senseBuf, 1, BlockSize, 1, dev.Timeout, out _); - - if (!sense && !dev.Error) sector1 = cmdBuf; - - sense = dev.Read6(out cmdBuf, out senseBuf, 0, BlockSize, 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 :) - var decryptByte = ps2BootSectors[0]; - for (var i = 0; i < 0x6000; i++) ps2BootSectors[i] ^= decryptByte; - - var 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) - { - var 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) - { - var pd1 = new byte[PlaydiaCopyright.Length]; - var 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) - { - var pce = new byte[PcEngineSignature.Length]; - Array.Copy(secondDataSectorNotZero, 32, pce, 0, pce.Length); - - if (PcEngineSignature.SequenceEqual(pce)) MediaType = MediaType.SuperCDROM2; - } - - if (firstDataSectorNotZero != null) - { - var pcfx = new byte[PcFxSignature.Length]; - Array.Copy(firstDataSectorNotZero, 0, pcfx, 0, pcfx.Length); - - if (PcFxSignature.SequenceEqual(pcfx)) MediaType = MediaType.PCFX; - } - - if (firstTrackSecondSessionAudio != null) - { - var jaguar = new byte[AtariSignature.Length]; - for (var 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) - { - var 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 (MMC.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 :) - var decryptByte = ps2BootSectors[0]; - for (var i = 0; i < 0x6000; i++) ps2BootSectors[i] ^= decryptByte; - - var 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) - { - var 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; - } + MediaType = tmpType; } - public byte[] MediaSerialNumber { get; } - public byte[] XboxSecuritySector { get; } - public SS.SecuritySector? DecodedXboxSecuritySector { get; } - public XgdInfo XgdInfo { get; } - public byte[] MmcConfiguration { get; } - public byte[] RecognizedFormatLayers { get; } - public byte[] WriteProtectionStatus { get; } - public byte[] DvdPfi { get; } - public PFI.PhysicalFormatInformation? DecodedPfi { get; } - public byte[] DvdDmi { get; } - public byte[] DvdCmi { get; } - public byte[] DvdBca { get; } - public byte[] DvdAacs { get; } - public byte[] DvdRamDds { get; } - public byte[] DvdRamCartridgeStatus { get; } - public byte[] DvdRamSpareArea { get; } - public byte[] LastBorderOutRmd { get; } - public byte[] DvdPreRecordedInfo { get; } - public byte[] DvdrMediaIdentifier { get; } - public byte[] DvdrPhysicalInformation { get; } - public byte[] DvdPlusAdip { get; } - public byte[] DvdPlusDcb { get; } - public byte[] HddvdCopyrightInformation { get; } - public byte[] HddvdrMediumStatus { get; } - public byte[] HddvdrLastRmd { get; } - public byte[] DvdrLayerCapacity { get; } - public byte[] DvdrDlMiddleZoneStart { get; } - public byte[] DvdrDlJumpIntervalSize { get; } - public byte[] DvdrDlManualLayerJumpStartLba { get; } - public byte[] DvdrDlRemapAnchorPoint { get; } - public byte[] BlurayDiscInformation { get; } - public byte[] BlurayPac { get; } - public byte[] BlurayBurstCuttingArea { get; } - public byte[] BlurayDds { get; } - public byte[] BlurayCartridgeStatus { get; } - public byte[] BluraySpareAreaInformation { get; } - public byte[] BlurayRawDfl { get; } - public byte[] BlurayPowResources { get; } - public byte[] Toc { get; } - public byte[] Atip { get; } - public byte[] CompactDiscInformation { get; } - public byte[] Session { get; } - public byte[] RawToc { get; } - public byte[] Pma { get; } - public byte[] CdTextLeadIn { get; } - public TOC.CDTOC? DecodedToc { get; } - public ATIP.CDATIP? DecodedAtip { get; } - public Session.CDSessionInfo? DecodedSession { get; } - public FullTOC.CDFullTOC? FullToc { get; } - public CDTextOnLeadIn.CDText? DecodedCdTextLeadIn { get; } - public byte[] BlurayTrackResources { get; } + public byte[] MediaSerialNumber { get; } + public byte[] XboxSecuritySector { get; } + public SS.SecuritySector? DecodedXboxSecuritySector { get; } + public XgdInfo XgdInfo { get; } + public byte[] MmcConfiguration { get; } + public byte[] RecognizedFormatLayers { get; } + public byte[] WriteProtectionStatus { get; } + public byte[] DvdPfi { get; } + public PFI.PhysicalFormatInformation? DecodedPfi { get; } + public byte[] DvdDmi { get; } + public byte[] DvdCmi { get; } + public byte[] DvdBca { get; } + public byte[] DvdAacs { get; } + public byte[] DvdRamDds { get; } + public byte[] DvdRamCartridgeStatus { get; } + public byte[] DvdRamSpareArea { get; } + public byte[] LastBorderOutRmd { get; } + public byte[] DvdPreRecordedInfo { get; } + public byte[] DvdrMediaIdentifier { get; } + public byte[] DvdrPhysicalInformation { get; } + public byte[] DvdPlusAdip { get; } + public byte[] DvdPlusDcb { get; } + public byte[] HddvdCopyrightInformation { get; } + public byte[] HddvdrMediumStatus { get; } + public byte[] HddvdrLastRmd { get; } + public byte[] DvdrLayerCapacity { get; } + public byte[] DvdrDlMiddleZoneStart { get; } + public byte[] DvdrDlJumpIntervalSize { get; } + public byte[] DvdrDlManualLayerJumpStartLba { get; } + public byte[] DvdrDlRemapAnchorPoint { get; } + public byte[] BlurayDiscInformation { get; } + public byte[] BlurayPac { get; } + public byte[] BlurayBurstCuttingArea { get; } + public byte[] BlurayDds { get; } + public byte[] BlurayCartridgeStatus { get; } + public byte[] BluraySpareAreaInformation { get; } + public byte[] BlurayRawDfl { get; } + public byte[] BlurayPowResources { get; } + public byte[] Toc { get; } + public byte[] Atip { get; } + public byte[] CompactDiscInformation { get; } + public byte[] Session { get; } + public byte[] RawToc { get; } + public byte[] Pma { get; } + public byte[] CdTextLeadIn { get; } + public TOC.CDTOC? DecodedToc { get; } + public ATIP.CDATIP? DecodedAtip { get; } + public Session.CDSessionInfo? DecodedSession { get; } + public FullTOC.CDFullTOC? FullToc { get; } + public CDTextOnLeadIn.CDText? DecodedCdTextLeadIn { get; } + public byte[] BlurayTrackResources { get; } public DiscInformation.StandardDiscInformation? DecodedCompactDiscInformation { get; } - public string Mcn { get; } - public Dictionary Isrcs { get; } - public bool MediaInserted { get; } - public MediaType MediaType { get; } - public DeviceInfo DeviceInfo { get; } - public byte[] ReadCapacity { get; } - public ulong Blocks { get; } - public uint BlockSize { get; } - public byte[] ReadCapacity16 { get; } - public byte[] DensitySupport { get; } - public DensitySupport.DensitySupportHeader? DensitySupportHeader { get; } - public byte[] MediaTypeSupport { get; } - public DensitySupport.MediaTypeSupportHeader? MediaTypeSupportHeader { get; } + public string Mcn { get; } + public Dictionary Isrcs { get; } + public bool MediaInserted { get; } + public MediaType MediaType { get; } + public DeviceInfo DeviceInfo { get; } + public byte[] ReadCapacity { get; } + public ulong Blocks { get; } + public uint BlockSize { get; } + public byte[] ReadCapacity16 { get; } + public byte[] DensitySupport { get; } + public DensitySupport.DensitySupportHeader? DensitySupportHeader { get; } + public byte[] MediaTypeSupport { get; } + public DensitySupport.MediaTypeSupportHeader? MediaTypeSupportHeader { get; } } } \ No newline at end of file diff --git a/DiscImageChef.sln.DotSettings b/DiscImageChef.sln.DotSettings index 45f3e0a61..bb467e150 100644 --- a/DiscImageChef.sln.DotSettings +++ b/DiscImageChef.sln.DotSettings @@ -185,8 +185,10 @@ True True True + True True True + True True True True @@ -203,13 +205,17 @@ True True True + True True True + True + True True True True True True + True True True True @@ -217,6 +223,7 @@ True True True + True True True True