mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Use subchannel, if available, to set ISRC.
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Aaru.CommonTypes.Enums;
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.CommonTypes.Extents;
|
using Aaru.CommonTypes.Extents;
|
||||||
@@ -83,7 +84,8 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
ref double minSpeed, out bool newTrim, bool nextData, int offsetBytes, bool read6, bool read10,
|
ref double minSpeed, out bool newTrim, bool nextData, int offsetBytes, bool read6, bool read10,
|
||||||
bool read12, bool read16, bool readcd, int sectorsForOffset, uint subSize,
|
bool read12, bool read16, bool readcd, int sectorsForOffset, uint subSize,
|
||||||
MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration,
|
MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration,
|
||||||
Track[] tracks, SubchannelLog subLog, MmcSubchannel desiredSubchannel)
|
Track[] tracks, SubchannelLog subLog, MmcSubchannel desiredSubchannel,
|
||||||
|
Dictionary<byte, string> isrcs)
|
||||||
{
|
{
|
||||||
ulong sectorSpeedStart = 0; // Used to calculate correct speed
|
ulong sectorSpeedStart = 0; // Used to calculate correct speed
|
||||||
DateTime timeSpeedStart = DateTime.UtcNow; // Time of start for speed calculation
|
DateTime timeSpeedStart = DateTime.UtcNow; // Time of start for speed calculation
|
||||||
@@ -385,15 +387,8 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
|
|
||||||
_outputPlugin.WriteSectorsLong(data, i + r, 1);
|
_outputPlugin.WriteSectorsLong(data, i + r, 1);
|
||||||
|
|
||||||
if(desiredSubchannel != MmcSubchannel.None)
|
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i + r, 1, subLog,
|
||||||
{
|
isrcs, (byte)track.TrackSequence);
|
||||||
if(supportedSubchannel == MmcSubchannel.Q16)
|
|
||||||
sub = Subchannel.ConvertQToRaw(sub);
|
|
||||||
|
|
||||||
_outputPlugin.WriteSectorsTag(sub, i + r, 1, SectorTagType.CdSectorSubchannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)(i + r), 1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -506,15 +501,8 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
|
|
||||||
_outputPlugin.WriteSectorsLong(data, i, blocksToRead);
|
_outputPlugin.WriteSectorsLong(data, i, blocksToRead);
|
||||||
|
|
||||||
if(desiredSubchannel != MmcSubchannel.None)
|
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i, blocksToRead, subLog,
|
||||||
{
|
isrcs, (byte)track.TrackSequence);
|
||||||
if(supportedSubchannel == MmcSubchannel.Q16)
|
|
||||||
sub = Subchannel.ConvertQToRaw(sub);
|
|
||||||
|
|
||||||
_outputPlugin.WriteSectorsTag(sub, i, blocksToRead, SectorTagType.CdSectorSubchannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)i, blocksToRead);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,55 +64,56 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
/// <summary>Dumps a compact disc</summary>
|
/// <summary>Dumps a compact disc</summary>
|
||||||
void CompactDisc()
|
void CompactDisc()
|
||||||
{
|
{
|
||||||
ExtentsULong audioExtents; // Extents with audio sectors
|
ExtentsULong audioExtents; // Extents with audio sectors
|
||||||
ulong blocks; // Total number of positive sectors
|
ulong blocks; // Total number of positive sectors
|
||||||
uint blockSize; // Size of the read sector in bytes
|
uint blockSize; // Size of the read sector in bytes
|
||||||
CdOffset cdOffset; // Read offset from database
|
CdOffset cdOffset; // Read offset from database
|
||||||
byte[] cmdBuf; // Data buffer
|
byte[] cmdBuf; // Data buffer
|
||||||
DumpHardwareType currentTry = null; // Current dump hardware try
|
DumpHardwareType currentTry = null; // Current dump hardware try
|
||||||
double currentSpeed = 0; // Current read speed
|
double currentSpeed = 0; // Current read speed
|
||||||
int? discOffset = null; // Disc write offset
|
int? discOffset = null; // Disc write offset
|
||||||
DateTime dumpStart = DateTime.UtcNow; // Time of dump start
|
DateTime dumpStart = DateTime.UtcNow; // Time of dump start
|
||||||
DateTime end; // Time of operation end
|
DateTime end; // Time of operation end
|
||||||
ExtentsULong extents = null; // Extents
|
ExtentsULong extents = null; // Extents
|
||||||
bool hiddenData; // Hidden track is data
|
bool hiddenData; // Hidden track is data
|
||||||
IbgLog ibgLog; // IMGBurn log
|
IbgLog ibgLog; // IMGBurn log
|
||||||
double imageWriteDuration = 0; // Duration of image write
|
double imageWriteDuration = 0; // Duration of image write
|
||||||
long lastSector; // Last sector number
|
long lastSector; // Last sector number
|
||||||
var leadOutExtents = new ExtentsULong(); // Lead-out extents
|
var leadOutExtents = new ExtentsULong(); // Lead-out extents
|
||||||
Dictionary<int, long> leadOutStarts = new Dictionary<int, long>(); // Lead-out starts
|
Dictionary<int, long> leadOutStarts = new Dictionary<int, long>(); // Lead-out starts
|
||||||
double maxSpeed = double.MinValue; // Maximum speed
|
double maxSpeed = double.MinValue; // Maximum speed
|
||||||
MhddLog mhddLog; // MHDD log
|
MhddLog mhddLog; // MHDD log
|
||||||
double minSpeed = double.MaxValue; // Minimum speed
|
double minSpeed = double.MaxValue; // Minimum speed
|
||||||
bool newTrim; // Is trim a new one?
|
bool newTrim; // Is trim a new one?
|
||||||
int offsetBytes = 0; // Read offset
|
int offsetBytes = 0; // Read offset
|
||||||
bool read6 = false; // Device supports READ(6)
|
bool read6 = false; // Device supports READ(6)
|
||||||
bool read10 = false; // Device supports READ(10)
|
bool read10 = false; // Device supports READ(10)
|
||||||
bool read12 = false; // Device supports READ(12)
|
bool read12 = false; // Device supports READ(12)
|
||||||
bool read16 = false; // Device supports READ(16)
|
bool read16 = false; // Device supports READ(16)
|
||||||
bool readcd; // Device supports READ CD
|
bool readcd; // Device supports READ CD
|
||||||
bool ret; // Image writing return status
|
bool ret; // Image writing return status
|
||||||
const uint sectorSize = 2352; // Full sector size
|
const uint sectorSize = 2352; // Full sector size
|
||||||
int sectorsForOffset = 0; // Sectors needed to fix offset
|
int sectorsForOffset = 0; // Sectors needed to fix offset
|
||||||
bool sense = true; // Sense indicator
|
bool sense = true; // Sense indicator
|
||||||
int sessions; // Number of sessions in disc
|
int sessions; // Number of sessions in disc
|
||||||
DateTime start; // Start of operation
|
DateTime start; // Start of operation
|
||||||
SubchannelLog subLog = null; // Subchannel log
|
SubchannelLog subLog = null; // Subchannel log
|
||||||
uint subSize; // Subchannel size in bytes
|
uint subSize; // Subchannel size in bytes
|
||||||
TrackSubchannelType subType; // Track subchannel type
|
TrackSubchannelType subType; // Track subchannel type
|
||||||
bool supportsLongSectors = true; // Supports reading EDC and ECC
|
bool supportsLongSectors = true; // Supports reading EDC and ECC
|
||||||
bool supportsPqSubchannel; // Supports reading PQ subchannel
|
bool supportsPqSubchannel; // Supports reading PQ subchannel
|
||||||
bool supportsRwSubchannel; // Supports reading RW subchannel
|
bool supportsRwSubchannel; // Supports reading RW subchannel
|
||||||
byte[] tmpBuf; // Temporary buffer
|
byte[] tmpBuf; // Temporary buffer
|
||||||
FullTOC.CDFullTOC? toc; // Full CD TOC
|
FullTOC.CDFullTOC? toc; // Full CD TOC
|
||||||
double totalDuration = 0; // Total commands duration
|
double totalDuration = 0; // Total commands duration
|
||||||
Dictionary<byte, byte> trackFlags = new Dictionary<byte, byte>(); // Track flags
|
Dictionary<byte, byte> trackFlags = new Dictionary<byte, byte>(); // Track flags
|
||||||
Track[] tracks; // Tracks in disc
|
Track[] tracks; // Tracks in disc
|
||||||
int firstTrackLastSession; // Number of first track in last session
|
int firstTrackLastSession; // Number of first track in last session
|
||||||
bool hiddenTrack; // Disc has a hidden track before track 1
|
bool hiddenTrack; // Disc has a hidden track before track 1
|
||||||
MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel
|
MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel
|
||||||
MmcSubchannel desiredSubchannel; // User requested subchannel
|
MmcSubchannel desiredSubchannel; // User requested subchannel
|
||||||
bool bcdSubchannel = false; // Subchannel positioning is in BCD
|
bool bcdSubchannel = false; // Subchannel positioning is in BCD
|
||||||
|
Dictionary<byte, string> isrcs = new Dictionary<byte, string>();
|
||||||
|
|
||||||
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>(); // Media tags
|
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>(); // Media tags
|
||||||
|
|
||||||
@@ -834,23 +835,18 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set ISRCs
|
// Set ISRCs
|
||||||
// TODO: Use subchannels
|
if(supportedSubchannel == MmcSubchannel.None)
|
||||||
foreach(Track trk in tracks)
|
foreach(Track trk in tracks)
|
||||||
{
|
{
|
||||||
sense = _dev.ReadIsrc((byte)trk.TrackSequence, out string isrc, out _, out _, _dev.Timeout, out _);
|
sense = _dev.ReadIsrc((byte)trk.TrackSequence, out string isrc, out _, out _, _dev.Timeout, out _);
|
||||||
|
|
||||||
if(sense ||
|
if(sense ||
|
||||||
isrc == null ||
|
isrc == null ||
|
||||||
isrc == "000000000000")
|
isrc == "000000000000")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(!_outputPlugin.WriteSectorTag(Encoding.ASCII.GetBytes(isrc), trk.TrackStartSector,
|
isrcs[(byte)trk.TrackSequence] = isrc;
|
||||||
SectorTagType.CdTrackIsrc))
|
}
|
||||||
continue;
|
|
||||||
|
|
||||||
UpdateStatus?.Invoke($"Setting ISRC for track {trk.TrackSequence} to {isrc}");
|
|
||||||
_dumpLog.WriteLine("Setting ISRC for track {0} to {1}", trk.TrackSequence, isrc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_resume.NextBlock > 0)
|
if(_resume.NextBlock > 0)
|
||||||
{
|
{
|
||||||
@@ -1019,13 +1015,13 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
ref imageWriteDuration, lastSector, leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed,
|
ref imageWriteDuration, lastSector, leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed,
|
||||||
out newTrim, tracks[0].TrackType != TrackType.Audio, offsetBytes, read6, read10, read12, read16,
|
out newTrim, tracks[0].TrackType != TrackType.Audio, offsetBytes, read6, read10, read12, read16,
|
||||||
readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors, ref totalDuration,
|
readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors, ref totalDuration,
|
||||||
tracks, subLog, desiredSubchannel);
|
tracks, subLog, desiredSubchannel, isrcs);
|
||||||
|
|
||||||
// TODO: Enable when underlying images support lead-outs
|
// TODO: Enable when underlying images support lead-outs
|
||||||
/*
|
/*
|
||||||
DumpCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration,
|
DumpCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration,
|
||||||
leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd,
|
leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd,
|
||||||
supportedSubchannel, subSize, ref totalDuration, subLog, desiredSubchannel);
|
supportedSubchannel, subSize, ref totalDuration, subLog, desiredSubchannel, isrcs);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
@@ -1052,10 +1048,10 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
|
|
||||||
TrimCdUserData(audioExtents, blockSize, currentTry, extents, newTrim, offsetBytes, read6, read10, read12,
|
TrimCdUserData(audioExtents, blockSize, currentTry, extents, newTrim, offsetBytes, read6, read10, read12,
|
||||||
read16, readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors,
|
read16, readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors,
|
||||||
ref totalDuration, subLog, desiredSubchannel);
|
ref totalDuration, subLog, desiredSubchannel, tracks, isrcs);
|
||||||
|
|
||||||
RetryCdUserData(audioExtents, blockSize, currentTry, extents, offsetBytes, readcd, sectorsForOffset,
|
RetryCdUserData(audioExtents, blockSize, currentTry, extents, offsetBytes, readcd, sectorsForOffset,
|
||||||
subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel);
|
subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel, tracks, isrcs);
|
||||||
|
|
||||||
// Write media tags to image
|
// Write media tags to image
|
||||||
if(!_aborted)
|
if(!_aborted)
|
||||||
@@ -1102,6 +1098,19 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
if(_preSidecar != null)
|
if(_preSidecar != null)
|
||||||
_outputPlugin.SetCicmMetadata(_preSidecar);
|
_outputPlugin.SetCicmMetadata(_preSidecar);
|
||||||
|
|
||||||
|
foreach(KeyValuePair<byte, string> isrc in isrcs)
|
||||||
|
{
|
||||||
|
// TODO: Track tags
|
||||||
|
Track track = tracks.First(t => t.TrackSequence == isrc.Key);
|
||||||
|
|
||||||
|
if(!_outputPlugin.WriteSectorTag(Encoding.ASCII.GetBytes(isrc.Value), track.TrackStartSector,
|
||||||
|
SectorTagType.CdTrackIsrc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
UpdateStatus?.Invoke($"Setting ISRC for track {isrc.Key} to {isrc.Value}");
|
||||||
|
_dumpLog.WriteLine("Setting ISRC for track {0} to {1}", isrc.Key, isrc.Value);
|
||||||
|
}
|
||||||
|
|
||||||
_dumpLog.WriteLine("Closing output file.");
|
_dumpLog.WriteLine("Closing output file.");
|
||||||
UpdateStatus?.Invoke("Closing output file.");
|
UpdateStatus?.Invoke("Closing output file.");
|
||||||
DateTime closeStart = DateTime.Now;
|
DateTime closeStart = DateTime.Now;
|
||||||
|
|||||||
@@ -32,12 +32,12 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Aaru.CommonTypes.Enums;
|
using System.Linq;
|
||||||
using Aaru.CommonTypes.Extents;
|
using Aaru.CommonTypes.Extents;
|
||||||
|
using Aaru.CommonTypes.Structs;
|
||||||
using Aaru.CommonTypes.Structs.Devices.SCSI;
|
using Aaru.CommonTypes.Structs.Devices.SCSI;
|
||||||
using Aaru.Console;
|
using Aaru.Console;
|
||||||
using Aaru.Core.Logging;
|
using Aaru.Core.Logging;
|
||||||
using Aaru.Decoders.CD;
|
|
||||||
using Aaru.Decoders.SCSI;
|
using Aaru.Decoders.SCSI;
|
||||||
using Aaru.Devices;
|
using Aaru.Devices;
|
||||||
using Schemas;
|
using Schemas;
|
||||||
@@ -53,7 +53,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
void RetryCdUserData(ExtentsULong audioExtents, uint blockSize, DumpHardwareType currentTry,
|
void RetryCdUserData(ExtentsULong audioExtents, uint blockSize, DumpHardwareType currentTry,
|
||||||
ExtentsULong extents, int offsetBytes, bool readcd, int sectorsForOffset, uint subSize,
|
ExtentsULong extents, int offsetBytes, bool readcd, int sectorsForOffset, uint subSize,
|
||||||
MmcSubchannel supportedSubchannel, ref double totalDuration, SubchannelLog subLog,
|
MmcSubchannel supportedSubchannel, ref double totalDuration, SubchannelLog subLog,
|
||||||
MmcSubchannel desiredSubchannel)
|
MmcSubchannel desiredSubchannel, Track[] tracks, Dictionary<byte, string> isrcs)
|
||||||
{
|
{
|
||||||
bool sense = true; // Sense indicator
|
bool sense = true; // Sense indicator
|
||||||
byte[] cmdBuf = null; // Data buffer
|
byte[] cmdBuf = null; // Data buffer
|
||||||
@@ -207,6 +207,9 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
forward ? "forward" : "reverse",
|
forward ? "forward" : "reverse",
|
||||||
runningPersistent ? "recovering partial data, " : ""));
|
runningPersistent ? "recovering partial data, " : ""));
|
||||||
|
|
||||||
|
Track track = tracks.OrderBy(t => t.TrackStartSector).
|
||||||
|
LastOrDefault(t => badSector >= t.TrackStartSector);
|
||||||
|
|
||||||
byte sectorsToReRead = 1;
|
byte sectorsToReRead = 1;
|
||||||
uint badSectorToReRead = (uint)badSector;
|
uint badSectorToReRead = (uint)badSector;
|
||||||
|
|
||||||
@@ -281,15 +284,8 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
|
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
|
||||||
_outputPlugin.WriteSectorLong(data, badSector);
|
_outputPlugin.WriteSectorLong(data, badSector);
|
||||||
|
|
||||||
if(desiredSubchannel != MmcSubchannel.None)
|
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog, isrcs,
|
||||||
{
|
(byte)track.TrackSequence);
|
||||||
if(supportedSubchannel == MmcSubchannel.Q16)
|
|
||||||
sub = Subchannel.ConvertQToRaw(sub);
|
|
||||||
|
|
||||||
_outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)badSector, 1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -364,6 +360,9 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
|
|
||||||
PulseProgress?.Invoke($"Trying to get partial data for sector {badSector}");
|
PulseProgress?.Invoke($"Trying to get partial data for sector {badSector}");
|
||||||
|
|
||||||
|
Track track = tracks.OrderBy(t => t.TrackStartSector).
|
||||||
|
LastOrDefault(t => badSector >= t.TrackStartSector);
|
||||||
|
|
||||||
if(readcd)
|
if(readcd)
|
||||||
{
|
{
|
||||||
sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1,
|
sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1,
|
||||||
@@ -387,15 +386,8 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
|
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
|
||||||
_outputPlugin.WriteSectorLong(data, badSector);
|
_outputPlugin.WriteSectorLong(data, badSector);
|
||||||
|
|
||||||
if(desiredSubchannel != MmcSubchannel.None)
|
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog,
|
||||||
{
|
isrcs, (byte)track.TrackSequence);
|
||||||
if(supportedSubchannel == MmcSubchannel.Q16)
|
|
||||||
sub = Subchannel.ConvertQToRaw(sub);
|
|
||||||
|
|
||||||
_outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)badSector, 1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Aaru.CommonTypes.Enums;
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.CommonTypes.Extents;
|
using Aaru.CommonTypes.Extents;
|
||||||
using Aaru.Core.Logging;
|
using Aaru.Core.Logging;
|
||||||
@@ -225,7 +226,7 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
ExtentsULong leadOutExtents, ref double maxSpeed, MhddLog mhddLog, ref double minSpeed,
|
ExtentsULong leadOutExtents, ref double maxSpeed, MhddLog mhddLog, ref double minSpeed,
|
||||||
bool read6, bool read10, bool read12, bool read16, bool readcd,
|
bool read6, bool read10, bool read12, bool read16, bool readcd,
|
||||||
MmcSubchannel supportedSubchannel, uint subSize, ref double totalDuration,
|
MmcSubchannel supportedSubchannel, uint subSize, ref double totalDuration,
|
||||||
SubchannelLog subLog, MmcSubchannel desiredSubchannel)
|
SubchannelLog subLog, MmcSubchannel desiredSubchannel, Dictionary<byte, string> isrcs)
|
||||||
{
|
{
|
||||||
byte[] cmdBuf = null; // Data buffer
|
byte[] cmdBuf = null; // Data buffer
|
||||||
const uint sectorSize = 2352; // Full sector size
|
const uint sectorSize = 2352; // Full sector size
|
||||||
@@ -308,6 +309,9 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
|
|
||||||
_outputPlugin.WriteSectorsLong(data, i, _maximumReadable);
|
_outputPlugin.WriteSectorsLong(data, i, _maximumReadable);
|
||||||
|
|
||||||
|
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i, _maximumReadable,
|
||||||
|
subLog, isrcs, 0xAA);
|
||||||
|
|
||||||
if(desiredSubchannel != MmcSubchannel.None)
|
if(desiredSubchannel != MmcSubchannel.None)
|
||||||
{
|
{
|
||||||
if(supportedSubchannel == MmcSubchannel.Q16)
|
if(supportedSubchannel == MmcSubchannel.Q16)
|
||||||
|
|||||||
@@ -30,7 +30,12 @@
|
|||||||
// Copyright © 2011-2020 Natalia Portillo
|
// Copyright © 2011-2020 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Aaru.Checksums;
|
||||||
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.Core.Logging;
|
using Aaru.Core.Logging;
|
||||||
|
using Aaru.Decoders.CD;
|
||||||
using Aaru.Devices;
|
using Aaru.Devices;
|
||||||
|
|
||||||
// ReSharper disable JoinDeclarationAndInitializer
|
// ReSharper disable JoinDeclarationAndInitializer
|
||||||
@@ -60,5 +65,60 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16,
|
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16,
|
||||||
dev.Timeout, out _);
|
dev.Timeout, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WriteSubchannelToImage(MmcSubchannel supportedSubchannel, MmcSubchannel desiredSubchannel, byte[] sub,
|
||||||
|
ulong sectorAddress, uint length, SubchannelLog subLog,
|
||||||
|
Dictionary<byte, string> isrcs, byte currentTrack)
|
||||||
|
{
|
||||||
|
if(supportedSubchannel == MmcSubchannel.Q16)
|
||||||
|
sub = Subchannel.ConvertQToRaw(sub);
|
||||||
|
|
||||||
|
if(desiredSubchannel != MmcSubchannel.None)
|
||||||
|
_outputPlugin.WriteSectorsTag(sub, sectorAddress, 1, SectorTagType.CdSectorSubchannel);
|
||||||
|
|
||||||
|
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)sectorAddress, 1);
|
||||||
|
|
||||||
|
byte[] deSub = Subchannel.Deinterleave(sub);
|
||||||
|
|
||||||
|
// Check subchannel
|
||||||
|
for(int subPos = 0; subPos < deSub.Length; subPos += 96)
|
||||||
|
{
|
||||||
|
// ISRC
|
||||||
|
if((deSub[subPos + 12] & 0x3) == 3)
|
||||||
|
{
|
||||||
|
byte[] q = new byte[12];
|
||||||
|
Array.Copy(deSub, subPos + 12, q, 0, 12);
|
||||||
|
string isrc = Subchannel.DecodeIsrc(q);
|
||||||
|
|
||||||
|
if(isrc == null ||
|
||||||
|
isrc == "000000000000")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!isrcs.ContainsKey(currentTrack))
|
||||||
|
{
|
||||||
|
_dumpLog?.WriteLine($"Found new ISRC {isrc} for track {currentTrack}.");
|
||||||
|
UpdateStatus?.Invoke($"Found new ISRC {isrc} for track {currentTrack}.");
|
||||||
|
}
|
||||||
|
else if(isrcs[currentTrack] != isrc)
|
||||||
|
{
|
||||||
|
CRC16CCITTContext.Data(q, 10, out byte[] crc);
|
||||||
|
|
||||||
|
if(crc[0] != q[10] ||
|
||||||
|
crc[1] != q[11])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dumpLog?.
|
||||||
|
WriteLine($"ISRC for track {currentTrack} changed from {isrcs[currentTrack]} to {isrc}.");
|
||||||
|
|
||||||
|
UpdateStatus?.
|
||||||
|
Invoke($"ISRC for track {currentTrack} changed from {isrcs[currentTrack]} to {isrc}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
isrcs[currentTrack] = isrc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,8 +31,11 @@
|
|||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Aaru.CommonTypes.Enums;
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.CommonTypes.Extents;
|
using Aaru.CommonTypes.Extents;
|
||||||
|
using Aaru.CommonTypes.Structs;
|
||||||
using Aaru.Core.Logging;
|
using Aaru.Core.Logging;
|
||||||
using Aaru.Decoders.CD;
|
using Aaru.Decoders.CD;
|
||||||
using Aaru.Devices;
|
using Aaru.Devices;
|
||||||
@@ -50,7 +53,8 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
ExtentsULong extents, bool newTrim, int offsetBytes, bool read6, bool read10, bool read12,
|
ExtentsULong extents, bool newTrim, int offsetBytes, bool read6, bool read10, bool read12,
|
||||||
bool read16, bool readcd, int sectorsForOffset, uint subSize,
|
bool read16, bool readcd, int sectorsForOffset, uint subSize,
|
||||||
MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration,
|
MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration,
|
||||||
SubchannelLog subLog, MmcSubchannel desiredSubchannel)
|
SubchannelLog subLog, MmcSubchannel desiredSubchannel, Track[] tracks,
|
||||||
|
Dictionary<byte, string> isrcs)
|
||||||
{
|
{
|
||||||
DateTime start;
|
DateTime start;
|
||||||
DateTime end;
|
DateTime end;
|
||||||
@@ -110,6 +114,9 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
|
|
||||||
PulseProgress?.Invoke($"Trimming sector {badSector}");
|
PulseProgress?.Invoke($"Trimming sector {badSector}");
|
||||||
|
|
||||||
|
Track track = tracks.OrderBy(t => t.TrackStartSector).
|
||||||
|
LastOrDefault(t => badSector >= t.TrackStartSector);
|
||||||
|
|
||||||
byte sectorsToTrim = 1;
|
byte sectorsToTrim = 1;
|
||||||
uint badSectorToRead = (uint)badSector;
|
uint badSectorToRead = (uint)badSector;
|
||||||
|
|
||||||
@@ -180,6 +187,9 @@ namespace Aaru.Core.Devices.Dumping
|
|||||||
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
|
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
|
||||||
_outputPlugin.WriteSectorLong(data, badSector);
|
_outputPlugin.WriteSectorLong(data, badSector);
|
||||||
|
|
||||||
|
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog, isrcs,
|
||||||
|
(byte)track.TrackSequence);
|
||||||
|
|
||||||
if(desiredSubchannel != MmcSubchannel.None)
|
if(desiredSubchannel != MmcSubchannel.None)
|
||||||
{
|
{
|
||||||
if(supportedSubchannel == MmcSubchannel.Q16)
|
if(supportedSubchannel == MmcSubchannel.Q16)
|
||||||
|
|||||||
Reference in New Issue
Block a user