Add support for dumping ISRC and MCN.

This commit is contained in:
2018-02-04 22:43:37 +00:00
parent a14476671f
commit 4818765c5d
3 changed files with 274 additions and 159 deletions

View File

@@ -57,7 +57,7 @@ namespace DiscImageChef.Core.Devices.Dumping
/// <summary> /// <summary>
/// Implement dumping Compact Discs /// Implement dumping Compact Discs
/// </summary> /// </summary>
// TODO: ISRC, MCN and pregaps // TODO: Barcode and pregaps
static class CompactDisc static class CompactDisc
{ {
/// <summary> /// <summary>
@@ -757,6 +757,29 @@ namespace DiscImageChef.Core.Devices.Dumping
outputPlugin.WriteSectorTag(new[] {kvp.Value}, track.TrackStartSector, SectorTagType.CdTrackFlags); outputPlugin.WriteSectorTag(new[] {kvp.Value}, track.TrackStartSector, SectorTagType.CdTrackFlags);
} }
// Set MCN
sense = dev.ReadMcn(out string mcn, out _, out _, dev.Timeout, out _);
if(!sense && mcn != null && mcn != "0000000000000")
if(outputPlugin.WriteMediaTag(Encoding.ASCII.GetBytes(mcn), MediaTagType.CD_MCN))
{
DicConsole.WriteLine("Setting disc Media Catalogue Number to {0}", mcn);
dumpLog.WriteLine("Setting disc Media Catalogue Number to {0}", mcn);
}
// Set ISRCs
foreach(Track trk in tracks)
{
sense = dev.ReadIsrc((byte)trk.TrackSequence, out string isrc, out _, out _, dev.Timeout, out _);
if(sense || isrc == null || isrc == "000000000000") continue;
if(outputPlugin.WriteSectorTag(Encoding.ASCII.GetBytes(isrc), trk.TrackStartSector,
SectorTagType.CdTrackIsrc))
{
DicConsole.WriteLine("Setting ISRC for track {0} to {1}", trk.TrackSequence, isrc);
dumpLog.WriteLine("Setting ISRC for track {0} to {1}", trk.TrackSequence, isrc);
}
}
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock); if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
double imageWriteDuration = 0; double imageWriteDuration = 0;

View File

@@ -31,6 +31,7 @@
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Text;
using DiscImageChef.Console; using DiscImageChef.Console;
namespace DiscImageChef.Devices namespace DiscImageChef.Devices
@@ -60,11 +61,11 @@ namespace DiscImageChef.Devices
/// <param name="startingFeatureNumber">Feature number where the feature list should start from</param> /// <param name="startingFeatureNumber">Feature number where the feature list should start from</param>
/// <param name="timeout">Timeout in seconds.</param> /// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber, public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber,
uint timeout, out double duration) uint timeout, out double duration)
{ {
return GetConfiguration(out buffer, out senseBuffer, startingFeatureNumber, MmcGetConfigurationRt.All, return GetConfiguration(out buffer, out senseBuffer, startingFeatureNumber, MmcGetConfigurationRt.All,
timeout, out duration); timeout, out duration);
} }
/// <summary> /// <summary>
@@ -77,19 +78,19 @@ namespace DiscImageChef.Devices
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <param name="startingFeatureNumber">Starting Feature number.</param> /// <param name="startingFeatureNumber">Starting Feature number.</param>
/// <param name="rt">Return type, <see cref="MmcGetConfigurationRt" />.</param> /// <param name="rt">Return type, <see cref="MmcGetConfigurationRt" />.</param>
public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber, public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber,
MmcGetConfigurationRt rt, uint timeout, out double duration) MmcGetConfigurationRt rt, uint timeout, out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[10]; byte[] cdb = new byte[10];
buffer = new byte[8]; buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.GetConfiguration; cdb[0] = (byte)ScsiCommands.GetConfiguration;
cdb[1] = (byte)((byte)rt & 0x03); cdb[1] = (byte)((byte)rt & 0x03);
cdb[2] = (byte)((startingFeatureNumber & 0xFF00) >> 8); cdb[2] = (byte)((startingFeatureNumber & 0xFF00) >> 8);
cdb[3] = (byte)(startingFeatureNumber & 0xFF); cdb[3] = (byte)(startingFeatureNumber & 0xFF);
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[8] = (byte)(buffer.Length & 0xFF); cdb[8] = (byte)(buffer.Length & 0xFF);
cdb[9] = 0; cdb[9] = 0;
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
@@ -99,10 +100,10 @@ namespace DiscImageChef.Devices
if(sense) return true; if(sense) return true;
ushort confLength = (ushort)((buffer[2] << 8) + buffer[3] + 4); ushort confLength = (ushort)((buffer[2] << 8) + buffer[3] + 4);
buffer = new byte[confLength]; buffer = new byte[confLength];
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[8] = (byte)(buffer.Length & 0xFF); cdb[8] = (byte)(buffer.Length & 0xFF);
senseBuffer = new byte[32]; senseBuffer = new byte[32];
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out sense); out sense);
@@ -127,24 +128,25 @@ namespace DiscImageChef.Devices
/// <param name="agid">AGID used in medium copy protection</param> /// <param name="agid">AGID used in medium copy protection</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ReadDiscStructure(out byte[] buffer, out byte[] senseBuffer, MmcDiscStructureMediaType mediaType, public bool ReadDiscStructure(out byte[] buffer, out byte[] senseBuffer, MmcDiscStructureMediaType mediaType,
uint address, byte layerNumber, MmcDiscStructureFormat format, byte agid, uint address, byte layerNumber, MmcDiscStructureFormat format,
uint timeout, out double duration) byte agid,
uint timeout, out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[12]; byte[] cdb = new byte[12];
buffer = new byte[8]; buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.ReadDiscStructure; cdb[0] = (byte)ScsiCommands.ReadDiscStructure;
cdb[1] = (byte)((byte)mediaType & 0x0F); cdb[1] = (byte)((byte)mediaType & 0x0F);
cdb[2] = (byte)((address & 0xFF000000) >> 24); cdb[2] = (byte)((address & 0xFF000000) >> 24);
cdb[3] = (byte)((address & 0xFF0000) >> 16); cdb[3] = (byte)((address & 0xFF0000) >> 16);
cdb[4] = (byte)((address & 0xFF00) >> 8); cdb[4] = (byte)((address & 0xFF00) >> 8);
cdb[5] = (byte)(address & 0xFF); cdb[5] = (byte)(address & 0xFF);
cdb[6] = layerNumber; cdb[6] = layerNumber;
cdb[7] = (byte)format; cdb[7] = (byte)format;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((agid & 0x03) << 6); cdb[10] = (byte)((agid & 0x03) << 6);
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense); out bool sense);
@@ -153,10 +155,10 @@ namespace DiscImageChef.Devices
if(sense) return true; if(sense) return true;
ushort strctLength = (ushort)((buffer[0] << 8) + buffer[1] + 2); ushort strctLength = (ushort)((buffer[0] << 8) + buffer[1] + 2);
buffer = new byte[strctLength]; buffer = new byte[strctLength];
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
senseBuffer = new byte[32]; senseBuffer = new byte[32];
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out sense); out sense);
@@ -290,27 +292,27 @@ namespace DiscImageChef.Devices
/// <param name="trackSessionNumber">Track/Session number</param> /// <param name="trackSessionNumber">Track/Session number</param>
/// <param name="timeout">Timeout in seconds.</param> /// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ReadTocPmaAtip(out byte[] buffer, out byte[] senseBuffer, bool msf, byte format, public bool ReadTocPmaAtip(out byte[] buffer, out byte[] senseBuffer, bool msf, byte format,
byte trackSessionNumber, uint timeout, out double duration) byte trackSessionNumber, uint timeout, out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[10]; byte[] cdb = new byte[10];
byte[] tmpBuffer = (format & 0x0F) == 5 ? new byte[32768] : new byte[1024]; byte[] tmpBuffer = (format & 0x0F) == 5 ? new byte[32768] : new byte[1024];
cdb[0] = (byte)ScsiCommands.ReadTocPmaAtip; cdb[0] = (byte)ScsiCommands.ReadTocPmaAtip;
if(msf) cdb[1] = 0x02; if(msf) cdb[1] = 0x02;
cdb[2] = (byte)(format & 0x0F); cdb[2] = (byte)(format & 0x0F);
cdb[6] = trackSessionNumber; cdb[6] = trackSessionNumber;
cdb[7] = (byte)((tmpBuffer.Length & 0xFF00) >> 8); cdb[7] = (byte)((tmpBuffer.Length & 0xFF00) >> 8);
cdb[8] = (byte)(tmpBuffer.Length & 0xFF); cdb[8] = (byte)(tmpBuffer.Length & 0xFF);
LastError = SendScsiCommand(cdb, ref tmpBuffer, out senseBuffer, timeout, ScsiDirection.In, out duration, LastError = SendScsiCommand(cdb, ref tmpBuffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense); out bool sense);
Error = LastError != 0; Error = LastError != 0;
uint strctLength = (uint)((tmpBuffer[0] << 8) + tmpBuffer[1] + 2); uint strctLength = (uint)((tmpBuffer[0] << 8) + tmpBuffer[1] + 2);
buffer = new byte[strctLength]; buffer = new byte[strctLength];
if(buffer.Length <= tmpBuffer.Length) if(buffer.Length <= tmpBuffer.Length)
{ {
@@ -341,7 +343,7 @@ namespace DiscImageChef.Devices
public bool ReadDiscInformation(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration) public bool ReadDiscInformation(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
{ {
return ReadDiscInformation(out buffer, out senseBuffer, MmcDiscInformationDataTypes.DiscInformation, return ReadDiscInformation(out buffer, out senseBuffer, MmcDiscInformationDataTypes.DiscInformation,
timeout, out duration); timeout, out duration);
} }
/// <summary> /// <summary>
@@ -353,24 +355,25 @@ namespace DiscImageChef.Devices
/// <param name="dataType">Which disc information to read</param> /// <param name="dataType">Which disc information to read</param>
/// <param name="timeout">Timeout in seconds.</param> /// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ReadDiscInformation(out byte[] buffer, out byte[] senseBuffer, MmcDiscInformationDataTypes dataType, public bool ReadDiscInformation(out byte[] buffer, out byte[] senseBuffer,
uint timeout, out double duration) MmcDiscInformationDataTypes dataType,
uint timeout, out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[10]; byte[] cdb = new byte[10];
byte[] tmpBuffer = new byte[804]; byte[] tmpBuffer = new byte[804];
cdb[0] = (byte)ScsiCommands.ReadDiscInformation; cdb[0] = (byte)ScsiCommands.ReadDiscInformation;
cdb[1] = (byte)dataType; cdb[1] = (byte)dataType;
cdb[7] = (byte)((tmpBuffer.Length & 0xFF00) >> 8); cdb[7] = (byte)((tmpBuffer.Length & 0xFF00) >> 8);
cdb[8] = (byte)(tmpBuffer.Length & 0xFF); cdb[8] = (byte)(tmpBuffer.Length & 0xFF);
LastError = SendScsiCommand(cdb, ref tmpBuffer, out senseBuffer, timeout, ScsiDirection.In, out duration, LastError = SendScsiCommand(cdb, ref tmpBuffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense); out bool sense);
Error = LastError != 0; Error = LastError != 0;
uint strctLength = (uint)((tmpBuffer[0] << 8) + tmpBuffer[1] + 2); uint strctLength = (uint)((tmpBuffer[0] << 8) + tmpBuffer[1] + 2);
buffer = new byte[strctLength]; buffer = new byte[strctLength];
Array.Copy(tmpBuffer, 0, buffer, 0, buffer.Length); Array.Copy(tmpBuffer, 0, buffer, 0, buffer.Length);
DicConsole.DebugWriteLine("SCSI Device", "READ DISC INFORMATION took {0} ms.", duration); DicConsole.DebugWriteLine("SCSI Device", "READ DISC INFORMATION took {0} ms.", duration);
@@ -398,31 +401,32 @@ namespace DiscImageChef.Devices
/// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param> /// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param>
/// <param name="c2Error">C2 error options.</param> /// <param name="c2Error">C2 error options.</param>
/// <param name="subchannel">Subchannel selection.</param> /// <param name="subchannel">Subchannel selection.</param>
public bool ReadCd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint transferLength, public bool ReadCd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
MmcSectorTypes expectedSectorType, bool dap, bool relAddr, bool sync, uint transferLength,
MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error, MmcSectorTypes expectedSectorType, bool dap, bool relAddr, bool sync,
MmcSubchannel subchannel, uint timeout, out double duration) MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error,
MmcSubchannel subchannel, uint timeout, out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[12]; byte[] cdb = new byte[12];
cdb[0] = (byte)ScsiCommands.ReadCd; cdb[0] = (byte)ScsiCommands.ReadCd;
cdb[1] = (byte)((byte)expectedSectorType << 2); cdb[1] = (byte)((byte)expectedSectorType << 2);
if(dap) cdb[1] += 0x02; if(dap) cdb[1] += 0x02;
if(relAddr) cdb[1] += 0x01; if(relAddr) cdb[1] += 0x01;
cdb[2] = (byte)((lba & 0xFF000000) >> 24); cdb[2] = (byte)((lba & 0xFF000000) >> 24);
cdb[3] = (byte)((lba & 0xFF0000) >> 16); cdb[3] = (byte)((lba & 0xFF0000) >> 16);
cdb[4] = (byte)((lba & 0xFF00) >> 8); cdb[4] = (byte)((lba & 0xFF00) >> 8);
cdb[5] = (byte)(lba & 0xFF); cdb[5] = (byte)(lba & 0xFF);
cdb[6] = (byte)((transferLength & 0xFF0000) >> 16); cdb[6] = (byte)((transferLength & 0xFF0000) >> 16);
cdb[7] = (byte)((transferLength & 0xFF00) >> 8); cdb[7] = (byte)((transferLength & 0xFF00) >> 8);
cdb[8] = (byte)(transferLength & 0xFF); cdb[8] = (byte)(transferLength & 0xFF);
cdb[9] = (byte)((byte)c2Error << 1); cdb[9] = (byte)((byte)c2Error << 1);
cdb[9] += (byte)((byte)headerCodes << 5); cdb[9] += (byte)((byte)headerCodes << 5);
if(sync) cdb[9] += 0x80; if(sync) cdb[9] += 0x80;
if(userData) cdb[9] += 0x10; if(userData) cdb[9] += 0x10;
if(edcEcc) cdb[9] += 0x08; if(edcEcc) cdb[9] += 0x08;
cdb[10] = (byte)subchannel; cdb[10] = (byte)subchannel;
buffer = new byte[blockSize * transferLength]; buffer = new byte[blockSize * transferLength];
@@ -454,29 +458,32 @@ namespace DiscImageChef.Devices
/// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param> /// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param>
/// <param name="c2Error">C2 error options.</param> /// <param name="c2Error">C2 error options.</param>
/// <param name="subchannel">Subchannel selection.</param> /// <param name="subchannel">Subchannel selection.</param>
public bool ReadCdMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf, uint endMsf, uint blockSize, public bool ReadCdMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf,
MmcSectorTypes expectedSectorType, bool dap, bool sync, MmcHeaderCodes headerCodes, uint endMsf, uint blockSize,
bool userData, bool edcEcc, MmcErrorField c2Error, MmcSubchannel subchannel, uint timeout, MmcSectorTypes expectedSectorType, bool dap, bool sync,
out double duration) MmcHeaderCodes headerCodes,
bool userData, bool edcEcc, MmcErrorField c2Error,
MmcSubchannel subchannel, uint timeout,
out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[12]; byte[] cdb = new byte[12];
cdb[0] = (byte)ScsiCommands.ReadCdMsf; cdb[0] = (byte)ScsiCommands.ReadCdMsf;
cdb[1] = (byte)((byte)expectedSectorType << 2); cdb[1] = (byte)((byte)expectedSectorType << 2);
if(dap) cdb[1] += 0x02; if(dap) cdb[1] += 0x02;
cdb[3] = (byte)((startMsf & 0xFF0000) >> 16); cdb[3] = (byte)((startMsf & 0xFF0000) >> 16);
cdb[4] = (byte)((startMsf & 0xFF00) >> 8); cdb[4] = (byte)((startMsf & 0xFF00) >> 8);
cdb[5] = (byte)(startMsf & 0xFF); cdb[5] = (byte)(startMsf & 0xFF);
cdb[6] = (byte)((endMsf & 0xFF0000) >> 16); cdb[6] = (byte)((endMsf & 0xFF0000) >> 16);
cdb[7] = (byte)((endMsf & 0xFF00) >> 8); cdb[7] = (byte)((endMsf & 0xFF00) >> 8);
cdb[8] = (byte)(endMsf & 0xFF); cdb[8] = (byte)(endMsf & 0xFF);
cdb[9] = (byte)((byte)c2Error << 1); cdb[9] = (byte)((byte)c2Error << 1);
cdb[9] += (byte)((byte)headerCodes << 5); cdb[9] += (byte)((byte)headerCodes << 5);
if(sync) cdb[9] += 0x80; if(sync) cdb[9] += 0x80;
if(userData) cdb[9] += 0x10; if(userData) cdb[9] += 0x10;
if(edcEcc) cdb[9] += 0x08; if(edcEcc) cdb[9] += 0x08;
cdb[10] = (byte)subchannel; cdb[10] = (byte)subchannel;
uint transferLength = (uint)((cdb[6] - cdb[3]) * 60 * 75 + (cdb[7] - cdb[4]) * 75 + (cdb[8] - cdb[5])); uint transferLength = (uint)((cdb[6] - cdb[3]) * 60 * 75 + (cdb[7] - cdb[4]) * 75 + (cdb[8] - cdb[5]));
@@ -504,12 +511,12 @@ namespace DiscImageChef.Devices
public bool PreventAllowMediumRemoval(out byte[] senseBuffer, bool persistent, bool prevent, uint timeout, public bool PreventAllowMediumRemoval(out byte[] senseBuffer, bool persistent, bool prevent, uint timeout,
out double duration) out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[6]; byte[] cdb = new byte[6];
byte[] buffer = new byte[0]; byte[] buffer = new byte[0];
cdb[0] = (byte)ScsiCommands.PreventAllowMediumRemoval; cdb[0] = (byte)ScsiCommands.PreventAllowMediumRemoval;
if(prevent) cdb[4] += 0x01; if(prevent) cdb[4] += 0x01;
if(persistent) cdb[4] += 0x02; if(persistent) cdb[4] += 0x02;
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
@@ -541,25 +548,27 @@ namespace DiscImageChef.Devices
return StartStopUnit(out senseBuffer, false, 0, 0, false, false, false, timeout, out duration); return StartStopUnit(out senseBuffer, false, 0, 0, false, false, false, timeout, out duration);
} }
public bool StartStopUnit(out byte[] senseBuffer, bool immediate, byte formatLayer, byte powerConditions, public bool StartStopUnit(out byte[] senseBuffer, bool immediate, byte formatLayer, byte powerConditions,
bool changeFormatLayer, bool loadEject, bool start, uint timeout, out double duration) bool changeFormatLayer, bool loadEject, bool start, uint timeout,
out double duration)
{ {
senseBuffer = new byte[32]; senseBuffer = new byte[32];
byte[] cdb = new byte[6]; byte[] cdb = new byte[6];
byte[] buffer = new byte[0]; byte[] buffer = new byte[0];
cdb[0] = (byte)ScsiCommands.StartStopUnit; cdb[0] = (byte)ScsiCommands.StartStopUnit;
if(immediate) cdb[1] += 0x01; if(immediate) cdb[1] += 0x01;
if(changeFormatLayer) if(changeFormatLayer)
{ {
cdb[3] = (byte)(formatLayer & 0x03); cdb[3] = (byte)(formatLayer & 0x03);
cdb[4] += 0x04; cdb[4] += 0x04;
} }
else else
{ {
if(loadEject) cdb[4] += 0x02; if(loadEject) cdb[4] += 0x02;
if(start) cdb[4] += 0x01; if(start) cdb[4] += 0x01;
} }
cdb[4] += (byte)((powerConditions & 0x0F) << 4); cdb[4] += (byte)((powerConditions & 0x0F) << 4);
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
@@ -570,5 +579,60 @@ namespace DiscImageChef.Devices
return sense; return sense;
} }
public bool ReadMcn(out string mcn, out byte[] buffer, out byte[] senseBuffer, uint timeout,
out double duration)
{
senseBuffer = new byte[32];
byte[] cdb = new byte[10];
mcn = null;
cdb[0] = (byte)ScsiCommands.ReadSubChannel;
cdb[1] = 0;
cdb[2] = 0x40;
cdb[3] = 0x02;
cdb[7] = (23 & 0xFF00) >> 8;
cdb[8] = 23 & 0xFF;
buffer = new byte[23];
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
Error = LastError != 0;
DicConsole.DebugWriteLine("SCSI Device", "READ READ SUB-CHANNEL (MCN) took {0} ms.", duration);
if(!sense && (buffer[8] & 0x80) == 0x80) mcn = Encoding.ASCII.GetString(buffer, 9, 13);
return sense;
}
public bool ReadIsrc(byte trackNumber, out string isrc, out byte[] buffer, out byte[] senseBuffer, uint timeout,
out double duration)
{
senseBuffer = new byte[32];
byte[] cdb = new byte[10];
isrc = null;
cdb[0] = (byte)ScsiCommands.ReadSubChannel;
cdb[1] = 0;
cdb[2] = 0x40;
cdb[3] = 0x03;
cdb[6] = trackNumber;
cdb[7] = (23 & 0xFF00) >> 8;
cdb[8] = 23 & 0xFF;
buffer = new byte[23];
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
Error = LastError != 0;
DicConsole.DebugWriteLine("SCSI Device", "READ READ SUB-CHANNEL (ISRC) took {0} ms.", duration);
if(!sense && (buffer[8] & 0x80) == 0x80) isrc = Encoding.ASCII.GetString(buffer, 9, 12);
return sense;
}
} }
} }

View File

@@ -56,9 +56,9 @@ namespace DiscImageChef.Commands
{ {
internal static void DoMediaInfo(MediaInfoOptions options) internal static void DoMediaInfo(MediaInfoOptions options)
{ {
DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", options.Debug); DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", options.Debug);
DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose); DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose);
DicConsole.DebugWriteLine("Media-Info command", "--device={0}", options.DevicePath); DicConsole.DebugWriteLine("Media-Info command", "--device={0}", options.DevicePath);
DicConsole.DebugWriteLine("Media-Info command", "--output-prefix={0}", options.OutputPrefix); DicConsole.DebugWriteLine("Media-Info command", "--output-prefix={0}", options.OutputPrefix);
if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' && if(options.DevicePath.Length == 2 && options.DevicePath[1] == ':' && options.DevicePath[0] != '/' &&
@@ -114,13 +114,13 @@ namespace DiscImageChef.Commands
static void DoScsiMediaInfo(string outputPrefix, Device dev) static void DoScsiMediaInfo(string outputPrefix, Device dev)
{ {
byte[] cmdBuf; byte[] cmdBuf;
byte[] senseBuf; byte[] senseBuf;
bool sense; bool sense;
MediaType dskType = MediaType.Unknown; MediaType dskType = MediaType.Unknown;
ulong blocks = 0; ulong blocks = 0;
uint blockSize = 0; uint blockSize = 0;
int resets = 0; int resets = 0;
if(dev.IsRemovable) if(dev.IsRemovable)
{ {
@@ -192,7 +192,7 @@ namespace DiscImageChef.Commands
} }
} }
Modes.DecodedMode? decMode = null; Modes.DecodedMode? decMode = null;
PeripheralDeviceTypes devType = dev.ScsiType; PeripheralDeviceTypes devType = dev.ScsiType;
sense = dev.ModeSense10(out byte[] modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, sense = dev.ModeSense10(out byte[] modeBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current,
@@ -218,8 +218,8 @@ namespace DiscImageChef.Commands
if(!sense) if(!sense)
DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense.bin", "SCSI MODE SENSE", modeBuf); DataFile.WriteTo("Media-Info command", outputPrefix, "_scsi_modesense.bin", "SCSI MODE SENSE", modeBuf);
byte scsiMediumType = 0; byte scsiMediumType = 0;
byte scsiDensityCode = 0; byte scsiDensityCode = 0;
bool containsFloppyPage = false; bool containsFloppyPage = false;
if(decMode.HasValue) if(decMode.HasValue)
@@ -246,15 +246,15 @@ namespace DiscImageChef.Commands
{ {
DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity.bin", "SCSI READ CAPACITY", DataFile.WriteTo("Media-Info command", outputPrefix, "_readcapacity.bin", "SCSI READ CAPACITY",
cmdBuf); cmdBuf);
blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); 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]); blockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]);
} }
if(sense || blocks == 0xFFFFFFFF) if(sense || blocks == 0xFFFFFFFF)
{ {
sense = dev.ReadCapacity16(out cmdBuf, out senseBuf, dev.Timeout, out _); sense = dev.ReadCapacity16(out cmdBuf, out senseBuf, dev.Timeout, out _);
if(sense && blocks == 0) if(sense && blocks == 0)
if(dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice) if(dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice)
{ {
DicConsole.ErrorWriteLine("Unable to get media capacity"); DicConsole.ErrorWriteLine("Unable to get media capacity");
@@ -269,7 +269,7 @@ namespace DiscImageChef.Commands
Array.Copy(cmdBuf, 0, temp, 0, 8); Array.Copy(cmdBuf, 0, temp, 0, 8);
Array.Reverse(temp); Array.Reverse(temp);
blocks = BitConverter.ToUInt64(temp, 0); blocks = BitConverter.ToUInt64(temp, 0);
blockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]); blockSize = (uint)((cmdBuf[5] << 24) + (cmdBuf[5] << 16) + (cmdBuf[6] << 8) + cmdBuf[7]);
} }
} }
@@ -280,6 +280,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)",
blocks, blockSize, blocks * blockSize); blocks, blockSize, blocks * blockSize);
} }
break; break;
case PeripheralDeviceTypes.SequentialAccess: case PeripheralDeviceTypes.SequentialAccess:
byte[] medBuf; byte[] medBuf;
@@ -318,6 +319,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Medium types currently inserted in device:"); DicConsole.WriteLine("Medium types currently inserted in device:");
DicConsole.WriteLine(DensitySupport.PrettifyMediumType(meds)); DicConsole.WriteLine(DensitySupport.PrettifyMediumType(meds));
} }
DicConsole.WriteLine(DensitySupport.PrettifyMediumType(seqBuf)); DicConsole.WriteLine(DensitySupport.PrettifyMediumType(seqBuf));
} }
} }
@@ -472,12 +474,12 @@ namespace DiscImageChef.Commands
*/ */
#region All DVD and HD DVD types #region All DVD and HD DVD types
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL || if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL ||
dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL || dskType == MediaType.DVDR || dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL || dskType == MediaType.DVDR ||
dskType == MediaType.DVDRAM || dskType == MediaType.DVDRDL || dskType == MediaType.DVDROM || dskType == MediaType.DVDRAM || dskType == MediaType.DVDRDL || dskType == MediaType.DVDROM ||
dskType == MediaType.DVDRW || dskType == MediaType.DVDRWDL || dskType == MediaType.HDDVDR || dskType == MediaType.DVDRW || dskType == MediaType.DVDRWDL || dskType == MediaType.HDDVDR ||
dskType == MediaType.HDDVDRAM || dskType == MediaType.HDDVDRDL || dskType == MediaType.HDDVDROM || dskType == MediaType.HDDVDRAM || dskType == MediaType.HDDVDRDL || dskType == MediaType.HDDVDROM ||
dskType == MediaType.HDDVDRW || dskType == MediaType.HDDVDRWDL) dskType == MediaType.HDDVDRW || dskType == MediaType.HDDVDRWDL)
{ {
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _);
@@ -566,9 +568,9 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Xbox 360 DMI:\n{0}", DMI.PrettifyXbox360(cmdBuf)); DicConsole.WriteLine("Xbox 360 DMI:\n{0}", DMI.PrettifyXbox360(cmdBuf));
// All XGD3 all have the same number of blocks // All XGD3 all have the same number of blocks
if(blocks == 25063 || // Locked (or non compatible drive) if(blocks == 25063 || // Locked (or non compatible drive)
blocks == 4229664 || // Xtreme unlock blocks == 4229664 || // Xtreme unlock
blocks == 4246304) // Wxripper unlock blocks == 4246304) // Wxripper unlock
dskType = MediaType.XGD3; dskType = MediaType.XGD3;
} }
} }
@@ -628,6 +630,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf); "SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Disc Definition Structure:\n{0}", DDS.Prettify(cmdBuf)); DicConsole.WriteLine("Disc Definition Structure:\n{0}", DDS.Prettify(cmdBuf));
} }
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0,
MmcDiscStructureFormat.DvdramMediumStatus, 0, dev.Timeout, out _); MmcDiscStructureFormat.DvdramMediumStatus, 0, dev.Timeout, out _);
if(sense) if(sense)
@@ -639,6 +642,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf); "SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Medium Status:\n{0}", Cartridge.Prettify(cmdBuf)); DicConsole.WriteLine("Medium Status:\n{0}", Cartridge.Prettify(cmdBuf));
} }
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0,
MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout, MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout,
out _); out _);
@@ -651,6 +655,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf); "SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Spare Area Information:\n{0}", Spare.Prettify(cmdBuf)); DicConsole.WriteLine("Spare Area Information:\n{0}", Spare.Prettify(cmdBuf));
} }
break; break;
case MediaType.DVDR: case MediaType.DVDR:
case MediaType.HDDVDR: case MediaType.HDDVDR:
@@ -914,6 +919,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf); "SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Disc Information:\n{0}", DI.Prettify(cmdBuf)); DicConsole.WriteLine("Blu-ray Disc Information:\n{0}", DI.Prettify(cmdBuf));
} }
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.Pac, 0, dev.Timeout, out _); MmcDiscStructureFormat.Pac, 0, dev.Timeout, out _);
if(sense) if(sense)
@@ -941,6 +947,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf); "SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Burst Cutting Area:\n{0}", BCA.Prettify(cmdBuf)); DicConsole.WriteLine("Blu-ray Burst Cutting Area:\n{0}", BCA.Prettify(cmdBuf));
} }
break; break;
#endregion BD-ROM only #endregion BD-ROM only
@@ -961,6 +968,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Blu-ray Disc Definition Structure:\n{0}", DicConsole.WriteLine("Blu-ray Disc Definition Structure:\n{0}",
Decoders.Bluray.DDS.Prettify(cmdBuf)); Decoders.Bluray.DDS.Prettify(cmdBuf));
} }
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.CartridgeStatus, 0, dev.Timeout, out _); MmcDiscStructureFormat.CartridgeStatus, 0, dev.Timeout, out _);
if(sense) if(sense)
@@ -973,6 +981,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf); "SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Cartridge Status:\n{0}", DI.Prettify(cmdBuf)); DicConsole.WriteLine("Blu-ray Cartridge Status:\n{0}", DI.Prettify(cmdBuf));
} }
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout,
out _); out _);
@@ -986,6 +995,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf); "SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Spare Area Information:\n{0}", DI.Prettify(cmdBuf)); DicConsole.WriteLine("Blu-ray Spare Area Information:\n{0}", DI.Prettify(cmdBuf));
} }
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.RawDfl, 0, dev.Timeout, out _); MmcDiscStructureFormat.RawDfl, 0, dev.Timeout, out _);
if(sense) if(sense)
@@ -1005,6 +1015,7 @@ namespace DiscImageChef.Commands
DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_001b.bin", DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_001b.bin",
"SCSI READ DISC INFORMATION", cmdBuf); "SCSI READ DISC INFORMATION", cmdBuf);
} }
sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf,
MmcDiscInformationDataTypes.PowResources, dev.Timeout, out _); MmcDiscInformationDataTypes.PowResources, dev.Timeout, out _);
if(sense) if(sense)
@@ -1016,6 +1027,7 @@ namespace DiscImageChef.Commands
DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_010b.bin", DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_010b.bin",
"SCSI READ DISC INFORMATION", cmdBuf); "SCSI READ DISC INFORMATION", cmdBuf);
} }
break; break;
#endregion Writable Blu-ray only #endregion Writable Blu-ray only
@@ -1096,7 +1108,7 @@ namespace DiscImageChef.Commands
} }
} }
int sessions = 1; int sessions = 1;
int firstTrackLastSession = 0; int firstTrackLastSession = 0;
sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out _); sense = dev.ReadSessionInfo(out cmdBuf, out senseBuf, dev.Timeout, out _);
@@ -1111,30 +1123,32 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Session information:\n{0}", Session.Prettify(session)); DicConsole.WriteLine("Session information:\n{0}", Session.Prettify(session));
if(session.HasValue) if(session.HasValue)
{ {
sessions = session.Value.LastCompleteSession; sessions = session.Value.LastCompleteSession;
firstTrackLastSession = session.Value.TrackDescriptors[0].TrackNumber; firstTrackLastSession = session.Value.TrackDescriptors[0].TrackNumber;
} }
} }
if(dskType == MediaType.CD) if(dskType == MediaType.CD)
{ {
bool hasDataTrack = false; bool hasDataTrack = false;
bool hasAudioTrack = false; bool hasAudioTrack = false;
bool allFirstSessionTracksAreAudio = true; bool allFirstSessionTracksAreAudio = true;
bool hasVideoTrack = false; bool hasVideoTrack = false;
if(toc.HasValue) if(toc.HasValue)
foreach(TOC.CDTOCTrackDataDescriptor track in toc.Value.TrackDescriptors) foreach(TOC.CDTOCTrackDataDescriptor track in toc.Value.TrackDescriptors)
{ {
if(track.TrackNumber == 1 && if(track.TrackNumber == 1 &&
((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack || ((TocControl)(track.CONTROL & 0x0D) ==
(TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental)) TocControl.DataTrack ||
(TocControl)(track.CONTROL & 0x0D) ==
TocControl.DataTrackIncremental))
allFirstSessionTracksAreAudio &= firstTrackLastSession != 1; allFirstSessionTracksAreAudio &= firstTrackLastSession != 1;
if((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack || if((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
(TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental) (TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental)
{ {
hasDataTrack = true; hasDataTrack = true;
allFirstSessionTracksAreAudio &= track.TrackNumber >= firstTrackLastSession; allFirstSessionTracksAreAudio &= track.TrackNumber >= firstTrackLastSession;
} }
else hasAudioTrack = true; else hasAudioTrack = true;
@@ -1143,10 +1157,10 @@ namespace DiscImageChef.Commands
} }
if(hasDataTrack && hasAudioTrack && allFirstSessionTracksAreAudio && sessions == 2) if(hasDataTrack && hasAudioTrack && allFirstSessionTracksAreAudio && sessions == 2)
dskType = MediaType.CDPLUS; dskType = MediaType.CDPLUS;
if(!hasDataTrack && hasAudioTrack && sessions == 1) dskType = MediaType.CDDA; if(!hasDataTrack && hasAudioTrack && sessions == 1) dskType = MediaType.CDDA;
if(hasDataTrack && !hasAudioTrack && sessions == 1) dskType = MediaType.CDROM; if(hasDataTrack && !hasAudioTrack && sessions == 1) dskType = MediaType.CDROM;
if(hasVideoTrack && !hasDataTrack && sessions == 1) dskType = MediaType.CDV; if(hasVideoTrack && !hasDataTrack && sessions == 1) dskType = MediaType.CDV;
} }
sense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _); sense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _);
@@ -1163,9 +1177,9 @@ namespace DiscImageChef.Commands
if(fullToc.HasValue) if(fullToc.HasValue)
{ {
FullTOC.TrackDataDescriptor a0Track = FullTOC.TrackDataDescriptor a0Track =
fullToc.Value.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA0 && t.ADR == 1); fullToc.Value.TrackDescriptors
if(a0Track.POINT == 0xA0) .FirstOrDefault(t => t.POINT == 0xA0 && t.ADR == 1);
{ if(a0Track.POINT == 0xA0)
switch(a0Track.PSEC) switch(a0Track.PSEC)
{ {
case 0x10: case 0x10:
@@ -1175,9 +1189,9 @@ namespace DiscImageChef.Commands
dskType = MediaType.CDROMXA; dskType = MediaType.CDROMXA;
break; break;
} }
}
} }
} }
sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out _); 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}", DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: PMA\n{0}",
@@ -1200,6 +1214,16 @@ namespace DiscImageChef.Commands
if(CDTextOnLeadIn.Decode(cmdBuf).HasValue) if(CDTextOnLeadIn.Decode(cmdBuf).HasValue)
DicConsole.WriteLine("CD-TEXT on Lead-In:\n{0}", CDTextOnLeadIn.Prettify(cmdBuf)); DicConsole.WriteLine("CD-TEXT on Lead-In:\n{0}", CDTextOnLeadIn.Prettify(cmdBuf));
} }
sense = dev.ReadMcn(out string mcn, out _, out _, dev.Timeout, out _);
if(!sense && mcn != null && mcn != "0000000000000") DicConsole.WriteLine("MCN: {0}", mcn);
for(byte i = toc.Value.FirstTrack; i <= toc.Value.LastTrack; i++)
{
sense = dev.ReadIsrc(i, out string isrc, out _, out _, dev.Timeout, out _);
if(!sense && isrc != null && isrc != "000000000000")
DicConsole.WriteLine("Track's {0} ISRC: {1}", i, isrc);
}
} }
break; break;
@@ -1223,7 +1247,7 @@ namespace DiscImageChef.Commands
{ {
DicConsole.WriteLine("PFI:\n{0}", PFI.Prettify(cmdBuf)); DicConsole.WriteLine("PFI:\n{0}", PFI.Prettify(cmdBuf));
if(nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo && if(nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo &&
nintendoPfi.Value.PartVersion == 15) nintendoPfi.Value.PartVersion == 15)
switch(nintendoPfi.Value.DiscSize) switch(nintendoPfi.Value.DiscSize)
{ {
case DVDSize.Eighty: case DVDSize.Eighty:
@@ -1294,8 +1318,9 @@ namespace DiscImageChef.Commands
} }
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, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); 0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _);
if(sense) if(sense)
{ {
DicConsole.ErrorWriteLine("Cannot get PFI."); DicConsole.ErrorWriteLine("Cannot get PFI.");
@@ -1304,9 +1329,9 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors",
totalSize); totalSize);
l0Video = PFI.Decode(cmdBuf).Value.Layer0EndPSN - l0Video = PFI.Decode(cmdBuf).Value.Layer0EndPSN -
PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1; PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1;
l1Video = totalSize - l0Video + 1; l1Video = totalSize - l0Video + 1;
// Get game partition size // Get game partition size
DicConsole.DebugWriteLine("Dump-media command", "Getting game partition size"); DicConsole.DebugWriteLine("Dump-media command", "Getting game partition size");
@@ -1346,8 +1371,9 @@ namespace DiscImageChef.Commands
} }
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, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _); 0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _);
if(sense) if(sense)
{ {
DicConsole.ErrorWriteLine("Cannot get PFI."); DicConsole.ErrorWriteLine("Cannot get PFI.");
@@ -1357,18 +1383,20 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors", DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors",
totalSize); totalSize);
middleZone = middleZone =
totalSize - (PFI.Decode(cmdBuf).Value.Layer0EndPSN - totalSize -
PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1) - gameSize + 1; (PFI.Decode(cmdBuf).Value.Layer0EndPSN -
PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1) -
gameSize + 1;
totalSize = l0Video + l1Video + middleZone * 2 + gameSize; totalSize = l0Video + l1Video + middleZone * 2 + gameSize;
layerBreak = l0Video + middleZone + gameSize / 2; layerBreak = l0Video + middleZone + gameSize / 2;
DicConsole.WriteLine("Video layer 0 size: {0} sectors", l0Video); DicConsole.WriteLine("Video layer 0 size: {0} sectors", l0Video);
DicConsole.WriteLine("Video layer 1 size: {0} sectors", l1Video); DicConsole.WriteLine("Video layer 1 size: {0} sectors", l1Video);
DicConsole.WriteLine("Middle zone size: {0} sectors", middleZone); DicConsole.WriteLine("Middle zone size: {0} sectors", middleZone);
DicConsole.WriteLine("Game data size: {0} sectors", gameSize); DicConsole.WriteLine("Game data size: {0} sectors", gameSize);
DicConsole.WriteLine("Total size: {0} sectors", totalSize); DicConsole.WriteLine("Total size: {0} sectors", totalSize);
DicConsole.WriteLine("Real layer break: {0}", layerBreak); DicConsole.WriteLine("Real layer break: {0}", layerBreak);
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
} }