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>
/// Implement dumping Compact Discs
/// </summary>
// TODO: ISRC, MCN and pregaps
// TODO: Barcode and pregaps
static class CompactDisc
{
/// <summary>
@@ -757,6 +757,29 @@ namespace DiscImageChef.Core.Devices.Dumping
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);
double imageWriteDuration = 0;

View File

@@ -31,6 +31,7 @@
// ****************************************************************************/
using System;
using System.Text;
using DiscImageChef.Console;
namespace DiscImageChef.Devices
@@ -127,7 +128,8 @@ namespace DiscImageChef.Devices
/// <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>
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,
byte agid,
uint timeout, out double duration)
{
senseBuffer = new byte[32];
@@ -353,7 +355,8 @@ namespace DiscImageChef.Devices
/// <param name="dataType">Which disc information to read</param>
/// <param name="timeout">Timeout in seconds.</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,
MmcDiscInformationDataTypes dataType,
uint timeout, out double duration)
{
senseBuffer = new byte[32];
@@ -398,7 +401,8 @@ namespace DiscImageChef.Devices
/// <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="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,
uint transferLength,
MmcSectorTypes expectedSectorType, bool dap, bool relAddr, bool sync,
MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error,
MmcSubchannel subchannel, uint timeout, out double duration)
@@ -454,9 +458,12 @@ namespace DiscImageChef.Devices
/// <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="subchannel">Subchannel selection.</param>
public bool ReadCdMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf, uint endMsf, uint blockSize,
MmcSectorTypes expectedSectorType, bool dap, bool sync, MmcHeaderCodes headerCodes,
bool userData, bool edcEcc, MmcErrorField c2Error, MmcSubchannel subchannel, uint timeout,
public bool ReadCdMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf,
uint endMsf, uint blockSize,
MmcSectorTypes expectedSectorType, bool dap, bool sync,
MmcHeaderCodes headerCodes,
bool userData, bool edcEcc, MmcErrorField c2Error,
MmcSubchannel subchannel, uint timeout,
out double duration)
{
senseBuffer = new byte[32];
@@ -542,7 +549,8 @@ namespace DiscImageChef.Devices
}
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];
byte[] cdb = new byte[6];
@@ -560,6 +568,7 @@ namespace DiscImageChef.Devices
if(loadEject) cdb[4] += 0x02;
if(start) cdb[4] += 0x01;
}
cdb[4] += (byte)((powerConditions & 0x0F) << 4);
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
@@ -570,5 +579,60 @@ namespace DiscImageChef.Devices
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

@@ -280,6 +280,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)",
blocks, blockSize, blocks * blockSize);
}
break;
case PeripheralDeviceTypes.SequentialAccess:
byte[] medBuf;
@@ -318,6 +319,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Medium types currently inserted in device:");
DicConsole.WriteLine(DensitySupport.PrettifyMediumType(meds));
}
DicConsole.WriteLine(DensitySupport.PrettifyMediumType(seqBuf));
}
}
@@ -628,6 +630,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Disc Definition Structure:\n{0}", DDS.Prettify(cmdBuf));
}
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0,
MmcDiscStructureFormat.DvdramMediumStatus, 0, dev.Timeout, out _);
if(sense)
@@ -639,6 +642,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Medium Status:\n{0}", Cartridge.Prettify(cmdBuf));
}
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0,
MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout,
out _);
@@ -651,6 +655,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Spare Area Information:\n{0}", Spare.Prettify(cmdBuf));
}
break;
case MediaType.DVDR:
case MediaType.HDDVDR:
@@ -914,6 +919,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Disc Information:\n{0}", DI.Prettify(cmdBuf));
}
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.Pac, 0, dev.Timeout, out _);
if(sense)
@@ -941,6 +947,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Burst Cutting Area:\n{0}", BCA.Prettify(cmdBuf));
}
break;
#endregion BD-ROM only
@@ -961,6 +968,7 @@ namespace DiscImageChef.Commands
DicConsole.WriteLine("Blu-ray Disc Definition Structure:\n{0}",
Decoders.Bluray.DDS.Prettify(cmdBuf));
}
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.CartridgeStatus, 0, dev.Timeout, out _);
if(sense)
@@ -973,6 +981,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Cartridge Status:\n{0}", DI.Prettify(cmdBuf));
}
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout,
out _);
@@ -986,6 +995,7 @@ namespace DiscImageChef.Commands
"SCSI READ DISC STRUCTURE", cmdBuf);
DicConsole.WriteLine("Blu-ray Spare Area Information:\n{0}", DI.Prettify(cmdBuf));
}
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Bd, 0, 0,
MmcDiscStructureFormat.RawDfl, 0, dev.Timeout, out _);
if(sense)
@@ -1005,6 +1015,7 @@ namespace DiscImageChef.Commands
DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_001b.bin",
"SCSI READ DISC INFORMATION", cmdBuf);
}
sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf,
MmcDiscInformationDataTypes.PowResources, dev.Timeout, out _);
if(sense)
@@ -1016,6 +1027,7 @@ namespace DiscImageChef.Commands
DataFile.WriteTo("Media-Info command", outputPrefix, "_readdiscinformation_010b.bin",
"SCSI READ DISC INFORMATION", cmdBuf);
}
break;
#endregion Writable Blu-ray only
@@ -1127,8 +1139,10 @@ namespace DiscImageChef.Commands
foreach(TOC.CDTOCTrackDataDescriptor track in toc.Value.TrackDescriptors)
{
if(track.TrackNumber == 1 &&
((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
(TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrackIncremental))
((TocControl)(track.CONTROL & 0x0D) ==
TocControl.DataTrack ||
(TocControl)(track.CONTROL & 0x0D) ==
TocControl.DataTrackIncremental))
allFirstSessionTracksAreAudio &= firstTrackLastSession != 1;
if((TocControl)(track.CONTROL & 0x0D) == TocControl.DataTrack ||
@@ -1163,9 +1177,9 @@ namespace DiscImageChef.Commands
if(fullToc.HasValue)
{
FullTOC.TrackDataDescriptor a0Track =
fullToc.Value.TrackDescriptors.FirstOrDefault(t => t.POINT == 0xA0 && t.ADR == 1);
fullToc.Value.TrackDescriptors
.FirstOrDefault(t => t.POINT == 0xA0 && t.ADR == 1);
if(a0Track.POINT == 0xA0)
{
switch(a0Track.PSEC)
{
case 0x10:
@@ -1177,7 +1191,7 @@ namespace DiscImageChef.Commands
}
}
}
}
sense = dev.ReadPma(out cmdBuf, out senseBuf, dev.Timeout, out _);
if(sense)
DicConsole.DebugWriteLine("Media-Info command", "READ TOC/PMA/ATIP: PMA\n{0}",
@@ -1200,6 +1214,16 @@ namespace DiscImageChef.Commands
if(CDTextOnLeadIn.Decode(cmdBuf).HasValue)
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;
@@ -1294,7 +1318,8 @@ namespace DiscImageChef.Commands
}
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,
0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _);
if(sense)
{
@@ -1346,7 +1371,8 @@ namespace DiscImageChef.Commands
}
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,
0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out _);
if(sense)
{
@@ -1357,8 +1383,10 @@ namespace DiscImageChef.Commands
DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors",
totalSize);
middleZone =
totalSize - (PFI.Decode(cmdBuf).Value.Layer0EndPSN -
PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1) - gameSize + 1;
totalSize -
(PFI.Decode(cmdBuf).Value.Layer0EndPSN -
PFI.Decode(cmdBuf).Value.DataAreaStartPSN + 1) -
gameSize + 1;
totalSize = l0Video + l1Video + middleZone * 2 + gameSize;
layerBreak = l0Video + middleZone + gameSize / 2;