Add option to fix subchannels.

This commit is contained in:
2020-06-13 23:38:35 +01:00
parent e085e1e024
commit b108eedfc6
5 changed files with 721 additions and 19 deletions

View File

@@ -96,7 +96,8 @@ namespace Aaru.Core.Devices.Dumping
// Check subchannel // Check subchannel
for(int subPos = 0; subPos < deSub.Length; subPos += 96) for(int subPos = 0; subPos < deSub.Length; subPos += 96)
{ {
byte[] q = new byte[12]; bool @fixed = false;
byte[] q = new byte[12];
Array.Copy(deSub, subPos + 12, q, 0, 12); Array.Copy(deSub, subPos + 12, q, 0, 12);
CRC16CCITTContext.Data(q, 10, out byte[] crc); CRC16CCITTContext.Data(q, 10, out byte[] crc);
@@ -124,12 +125,15 @@ namespace Aaru.Core.Devices.Dumping
if(deSub[rw] != 0) if(deSub[rw] != 0)
rwOk = false; rwOk = false;
bool rwPacket = false;
bool cdtextPacket = false;
if(!rwOk) if(!rwOk)
{ {
byte[] sectorSub = new byte[96]; byte[] sectorSub = new byte[96];
Array.Copy(sub, subPos, sectorSub, 0, 96); Array.Copy(sub, subPos, sectorSub, 0, 96);
DetectRwPackets(sectorSub, out _, out bool rwPacket, out bool cdtextPacket); DetectRwPackets(sectorSub, out _, out rwPacket, out cdtextPacket);
// TODO: CD+G reed solomon // TODO: CD+G reed solomon
if(rwPacket && !cdtextPacket) if(rwPacket && !cdtextPacket)
@@ -139,30 +143,103 @@ namespace Aaru.Core.Devices.Dumping
rwOk = CheckCdTextPackets(sectorSub); rwOk = CheckCdTextPackets(sectorSub);
} }
// TODO: Fix if(!pOk && _fixSubchannel)
{
if(pWeight >= 48)
for(int p = subPos; p < subPos + 12; p++)
deSub[p] = 255;
else
for(int p = subPos; p < subPos + 12; p++)
deSub[p] = 0;
pOk = true;
@fixed = true;
subLog.WritePFix();
}
if(!rwOk &&
!rwPacket &&
!cdtextPacket &&
_fixSubchannel)
{
for(int rw = subPos + 24; rw < subPos + 96; rw++)
deSub[rw] = 0;
rwOk = true;
@fixed = true;
subLog.WriteRwFix();
}
byte smin, ssec, sframe, amin, asec, aframe, pmin, psec, pframe;
byte rmin, rsec, rframe;
int aPos;
if(!crcOk &&
_fixSubchannel &&
subPos > 0 &&
subPos < deSub.Length - 96)
{
crcOk = FixQSubchannel(deSub, q, subPos, sectorAddress, _fixSubchannelCrc, out bool fixedAdr,
out bool controlFix, out bool fixedZero, out bool fixedTno,
out bool fixedIndex, out bool fixedRelPos, out bool fixedAbsPos,
out bool fixedCrc);
if(crcOk)
{
Array.Copy(q, 0, deSub, subPos + 12, 12);
@fixed = true;
if(fixedAdr)
subLog.WriteQAdrFix();
if(controlFix)
subLog.WriteQCtrlFix();
if(fixedZero)
subLog.WriteQZeroFix();
if(fixedTno)
subLog.WriteQTnoFix();
if(fixedIndex)
subLog.WriteQIndexFix();
if(fixedRelPos)
subLog.WriteQRelPosFix();
if(fixedAbsPos)
subLog.WriteQAbsPosFix();
if(fixedCrc)
subLog.WriteQCrcFix();
}
}
if(!pOk || if(!pOk ||
!crcOk || !crcOk ||
!rwOk) !rwOk)
continue; continue;
int aPos = int.MinValue; aPos = int.MinValue;
byte aframe = (byte)(((q[9] / 16) * 10) + (q[9] & 0x0F)); aframe = (byte)(((q[9] / 16) * 10) + (q[9] & 0x0F));
if((q[0] & 0x3) == 1) if((q[0] & 0x3) == 1)
{ {
byte amin = (byte)(((q[7] / 16) * 10) + (q[7] & 0x0F)); amin = (byte)(((q[7] / 16) * 10) + (q[7] & 0x0F));
byte asec = (byte)(((q[8] / 16) * 10) + (q[8] & 0x0F)); asec = (byte)(((q[8] / 16) * 10) + (q[8] & 0x0F));
aPos = ((amin * 60 * 75) + (asec * 75) + aframe) - 150; aPos = ((amin * 60 * 75) + (asec * 75) + aframe) - 150;
} }
else else
{ {
ulong expectedSectorAddress = sectorAddress + (ulong)(subPos / 96) + 150; ulong expectedSectorAddress = sectorAddress + (ulong)(subPos / 96) + 150;
byte smin = (byte)(expectedSectorAddress / 60 / 75); smin = (byte)(expectedSectorAddress / 60 / 75);
expectedSectorAddress -= (ulong)(smin * 60 * 75); expectedSectorAddress -= (ulong)(smin * 60 * 75);
byte ssec = (byte)(expectedSectorAddress / 75); ssec = (byte)(expectedSectorAddress / 75);
expectedSectorAddress -= (ulong)(smin * 75); expectedSectorAddress -= (ulong)(smin * 75);
byte sframe = (byte)(expectedSectorAddress - ((ulong)ssec * 75)); sframe = (byte)(expectedSectorAddress - ((ulong)ssec * 75));
aPos = ((smin * 60 * 75) + (ssec * 75) + aframe) - 150; aPos = ((smin * 60 * 75) + (ssec * 75) + aframe) - 150;
@@ -183,6 +260,10 @@ namespace Aaru.Core.Devices.Dumping
_outputPlugin.WriteSectorTag(posSub, (ulong)aPos, SectorTagType.CdSectorSubchannel); _outputPlugin.WriteSectorTag(posSub, (ulong)aPos, SectorTagType.CdSectorSubchannel);
subchannelExtents.Remove(aPos); subchannelExtents.Remove(aPos);
if(@fixed)
subLog?.WriteEntry(posSub, supportedSubchannel == MmcSubchannel.Raw,
(long)sectorAddress + (subPos / 96), 1);
} }
return indexesChanged; return indexesChanged;
@@ -635,5 +716,529 @@ namespace Aaru.Core.Devices.Dumping
return false; return false;
} }
bool FixQSubchannel(byte[] deSub, byte[] q, int subPos, ulong sectorAddress, bool fixCrc, out bool fixedAdr,
out bool controlFix, out bool fixedZero, out bool fixedTno, out bool fixedIndex,
out bool fixedRelPos, out bool fixedAbsPos, out bool fixedCrc)
{
byte smin, ssec, sframe, amin, asec, aframe, pmin, psec, pframe;
byte rmin, rsec, rframe;
int aPos, rPos, pPos, dPos;
controlFix = false;
fixedZero = false;
fixedTno = false;
fixedIndex = false;
fixedRelPos = false;
fixedAbsPos = false;
fixedCrc = false;
ulong expectedSectorAddress = sectorAddress + (ulong)(subPos / 96) + 150;
smin = (byte)(expectedSectorAddress / 60 / 75);
expectedSectorAddress -= (ulong)(smin * 60 * 75);
ssec = (byte)(expectedSectorAddress / 75);
expectedSectorAddress -= (ulong)(smin * 75);
sframe = (byte)(expectedSectorAddress - ((ulong)ssec * 75));
byte[] preQ = new byte[12];
byte[] nextQ = new byte[12];
Array.Copy(deSub, (subPos + 12) - 96, preQ, 0, 12);
Array.Copy(deSub, subPos + 12 + 96, nextQ, 0, 12);
bool status;
CRC16CCITTContext.Data(preQ, 10, out byte[] preCrc);
bool preCrcOk = preCrc[0] == preQ[10] && preCrc[1] == preQ[11];
CRC16CCITTContext.Data(nextQ, 10, out byte[] nextCrc);
bool nextCrcOk = nextCrc[0] == nextQ[10] && nextCrc[1] == nextQ[11];
fixedAdr = false;
// Extraneous bits in ADR
if((q[0] & 0xC) != 0)
{
q[0] &= 0xF3;
fixedAdr = true;
}
CRC16CCITTContext.Data(q, 10, out byte[] qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(fixedAdr && status)
return true;
int oldAdr = q[0] & 0x3;
// Try Q-Mode 1
q[0] = (byte)((q[0] & 0xF0) + 1);
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
{
fixedAdr = true;
return true;
}
// Try Q-Mode 2
q[0] = (byte)((q[0] & 0xF0) + 2);
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
{
fixedAdr = true;
return true;
}
// Try Q-Mode 3
q[0] = (byte)((q[0] & 0xF0) + 3);
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
{
fixedAdr = true;
return true;
}
q[0] = (byte)((q[0] & 0xF0) + oldAdr);
oldAdr = q[0];
// Try using previous control
if(preCrcOk && (q[0] & 0xF0) != (preQ[0] & 0xF0))
{
q[0] = (byte)((q[0] & 0x03) + (preQ[0] & 0xF0));
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
{
controlFix = true;
return true;
}
q[0] = (byte)oldAdr;
}
// Try using next control
if(nextCrcOk && (q[0] & 0xF0) != (nextQ[0] & 0xF0))
{
q[0] = (byte)((q[0] & 0x03) + (nextQ[0] & 0xF0));
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
{
controlFix = true;
return true;
}
q[0] = (byte)oldAdr;
}
if(preCrcOk &&
nextCrcOk &&
(nextQ[0] & 0xF0) == (preQ[0] & 0xF0) &&
(q[0] & 0xF0) != (nextQ[0] & 0xF0))
{
q[0] = (byte)((q[0] & 0x03) + (nextQ[0] & 0xF0));
controlFix = true;
}
if((q[0] & 0x3) == 1)
{
// ZERO not zero
if(q[6] != 0)
{
q[6] = 0;
fixedZero = true;
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
return true;
}
if(preCrcOk && nextCrcOk)
{
if(preQ[1] == nextQ[1] &&
preQ[1] != q[1])
{
q[1] = preQ[1];
fixedTno = true;
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
return true;
}
}
if(preCrcOk && nextCrcOk)
{
if(preQ[2] == nextQ[2] &&
preQ[2] != q[2])
{
q[2] = preQ[2];
fixedIndex = true;
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
return true;
}
}
amin = (byte)(((q[7] / 16) * 10) + (q[7] & 0x0F));
asec = (byte)(((q[8] / 16) * 10) + (q[8] & 0x0F));
aframe = (byte)(((q[9] / 16) * 10) + (q[9] & 0x0F));
aPos = ((amin * 60 * 75) + (asec * 75) + aframe) - 150;
pmin = (byte)(((q[3] / 16) * 10) + (q[3] & 0x0F));
psec = (byte)(((q[4] / 16) * 10) + (q[4] & 0x0F));
pframe = (byte)(((q[5] / 16) * 10) + (q[5] & 0x0F));
pPos = (pmin * 60 * 75) + (psec * 75) + pframe;
// TODO: pregap
// Not pregap
if(q[2] > 0)
{
// Previous was not pregap either
if(preQ[2] > 0 && preCrcOk)
{
rmin = (byte)(((preQ[3] / 16) * 10) + (preQ[3] & 0x0F));
rsec = (byte)(((preQ[4] / 16) * 10) + (preQ[4] & 0x0F));
rframe = (byte)(((preQ[5] / 16) * 10) + (preQ[5] & 0x0F));
rPos = (rmin * 60 * 75) + (rsec * 75) + rframe;
dPos = pPos - rPos;
if(dPos != 1)
{
q[3] = preQ[3];
q[4] = preQ[4];
q[5] = preQ[5];
// BCD add 1, so 0x39 becomes 0x40
if((q[5] & 0xF) == 9)
q[5] += 7;
else
q[5]++;
// 74 frames, so from 0x00 to 0x74, BCD
if(q[5] >= 0x74)
{
// 0 frames
q[5] = 0;
// Add 1 second
if((q[4] & 0xF) == 9)
q[4] += 7;
else
q[4]++;
// 60 seconds, so from 0x00 to 0x59, BCD
if(q[4] >= 0x59)
{
// 0 seconds
q[4] = 0;
// Add 1 minute
q[3]++;
}
}
fixedRelPos = true;
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
return true;
}
}
// Next is not pregap and we didn't fix relative position with previous
if(nextQ[2] > 0 &&
nextCrcOk &&
!fixedRelPos)
{
rmin = (byte)(((nextQ[3] / 16) * 10) + (nextQ[3] & 0x0F));
rsec = (byte)(((nextQ[4] / 16) * 10) + (nextQ[4] & 0x0F));
rframe = (byte)(((nextQ[5] / 16) * 10) + (nextQ[5] & 0x0F));
rPos = (rmin * 60 * 75) + (rsec * 75) + rframe;
dPos = rPos - pPos;
if(dPos != 1)
{
q[3] = nextQ[3];
q[4] = nextQ[4];
q[5] = nextQ[5];
// If frames is 0
if(q[5] == 0)
{
// If seconds is 0
if(q[4] == 0)
{
// BCD decrease minutes
if((q[3] & 0xF) == 0)
q[3] = (byte)((q[3] & 0xF0) - 0x10);
else
q[3]--;
q[4] = 0x59;
q[5] = 0x73;
}
else
{
// BCD decrease seconds
if((q[4] & 0xF) == 0)
q[4] = (byte)((q[4] & 0xF0) - 0x10);
else
q[4]--;
q[5] = 0x73;
}
}
// BCD decrease frames
else if((q[5] & 0xF) == 0)
q[5] = (byte)((q[5] & 0xF0) - 0x10);
else
q[5]--;
fixedRelPos = true;
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
return true;
}
}
}
if(preCrcOk)
{
rmin = (byte)(((preQ[7] / 16) * 10) + (preQ[7] & 0x0F));
rsec = (byte)(((preQ[8] / 16) * 10) + (preQ[8] & 0x0F));
rframe = (byte)(((preQ[9] / 16) * 10) + (preQ[9] & 0x0F));
rPos = ((rmin * 60 * 75) + (rsec * 75) + rframe) - 150;
dPos = aPos - rPos;
if(dPos != 1)
{
q[7] = preQ[7];
q[8] = preQ[8];
q[9] = preQ[9];
// BCD add 1, so 0x39 becomes 0x40
if((q[9] & 0xF) == 9)
q[9] += 7;
else
q[9]++;
// 74 frames, so from 0x00 to 0x74, BCD
if(q[9] >= 0x74)
{
// 0 frames
q[9] = 0;
// Add 1 second
if((q[8] & 0xF) == 9)
q[8] += 7;
else
q[8]++;
// 60 seconds, so from 0x00 to 0x59, BCD
if(q[8] >= 0x59)
{
// 0 seconds
q[8] = 0;
// Add 1 minute
q[7]++;
}
}
fixedAbsPos = true;
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
return true;
}
}
// Next is not pregap and we didn't fix relative position with previous
if(nextQ[2] > 0 &&
nextCrcOk &&
!fixedAbsPos)
{
rmin = (byte)(((nextQ[7] / 16) * 10) + (nextQ[7] & 0x0F));
rsec = (byte)(((nextQ[8] / 16) * 10) + (nextQ[8] & 0x0F));
rframe = (byte)(((nextQ[9] / 16) * 10) + (nextQ[9] & 0x0F));
rPos = ((rmin * 60 * 75) + (rsec * 75) + rframe) - 150;
dPos = rPos - pPos;
if(dPos != 1)
{
q[7] = nextQ[7];
q[8] = nextQ[8];
q[9] = nextQ[9];
// If frames is 0
if(q[9] == 0)
{
// If seconds is 0
if(q[8] == 0)
{
// BCD decrease minutes
if((q[7] & 0xF) == 0)
q[7] = (byte)((q[7] & 0xF0) - 0x10);
else
q[7]--;
q[8] = 0x59;
q[9] = 0x73;
}
else
{
// BCD decrease seconds
if((q[8] & 0xF) == 0)
q[8] = (byte)((q[8] & 0xF0) - 0x10);
else
q[8]--;
q[9] = 0x73;
}
}
// BCD decrease frames
else if((q[9] & 0xF) == 0)
q[9] = (byte)((q[9] & 0xF0) - 0x10);
else
q[9]--;
fixedAbsPos = true;
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
if(status)
return true;
}
}
CRC16CCITTContext.Data(q, 10, out qCrc);
status = qCrc[0] == q[10] && qCrc[1] == q[11];
// Game Over
if(!fixCrc || status)
return false;
if(preCrcOk)
{
rmin = (byte)(((preQ[7] / 16) * 10) + (preQ[7] & 0x0F));
rsec = (byte)(((preQ[8] / 16) * 10) + (preQ[8] & 0x0F));
rframe = (byte)(((preQ[9] / 16) * 10) + (preQ[9] & 0x0F));
rPos = ((rmin * 60 * 75) + (rsec * 75) + rframe) - 150;
dPos = aPos - rPos;
bool absOk = dPos == 1;
rmin = (byte)(((preQ[3] / 16) * 10) + (preQ[3] & 0x0F));
rsec = (byte)(((preQ[4] / 16) * 10) + (preQ[4] & 0x0F));
rframe = (byte)(((preQ[5] / 16) * 10) + (preQ[5] & 0x0F));
rPos = (rmin * 60 * 75) + (rsec * 75) + rframe;
dPos = pPos - rPos;
bool relOk = dPos == 1;
if(q[0] != preQ[0] ||
q[1] != preQ[1] ||
q[2] != preQ[2] ||
q[6] != 0 ||
!absOk ||
!relOk)
return false;
CRC16CCITTContext.Data(q, 10, out qCrc);
q[10] = qCrc[0];
q[11] = qCrc[1];
fixedCrc = true;
return true;
}
else if(nextCrcOk)
{
rmin = (byte)(((nextQ[7] / 16) * 10) + (nextQ[7] & 0x0F));
rsec = (byte)(((nextQ[8] / 16) * 10) + (nextQ[8] & 0x0F));
rframe = (byte)(((nextQ[9] / 16) * 10) + (nextQ[9] & 0x0F));
rPos = ((rmin * 60 * 75) + (rsec * 75) + rframe) - 150;
dPos = rPos - aPos;
bool absOk = dPos == 1;
rmin = (byte)(((nextQ[3] / 16) * 10) + (nextQ[3] & 0x0F));
rsec = (byte)(((nextQ[4] / 16) * 10) + (nextQ[4] & 0x0F));
rframe = (byte)(((nextQ[5] / 16) * 10) + (nextQ[5] & 0x0F));
rPos = (rmin * 60 * 75) + (rsec * 75) + rframe;
dPos = rPos - pPos;
bool relOk = dPos == 1;
if(q[0] != nextQ[0] ||
q[1] != nextQ[1] ||
q[2] != nextQ[2] ||
q[6] != 0 ||
!absOk ||
!relOk)
return false;
CRC16CCITTContext.Data(q, 10, out qCrc);
q[10] = qCrc[0];
q[11] = qCrc[1];
fixedCrc = true;
return true;
}
// Ok if previous and next are both BAD I won't rewrite the CRC at all
}
else if((q[0] & 0x3) == 2)
{
// TODO: MCN
}
else if((q[0] & 0x3) == 3)
{
// TODO: ISRC
}
return false;
}
} }
} }

View File

@@ -72,6 +72,7 @@ namespace Aaru.Core.Devices.Dumping
readonly CICMMetadataType _preSidecar; readonly CICMMetadataType _preSidecar;
readonly bool _private; readonly bool _private;
readonly ushort _retryPasses; readonly ushort _retryPasses;
readonly bool _retrySubchannel;
readonly bool _stopOnError; readonly bool _stopOnError;
readonly DumpSubchannel _subchannel; readonly DumpSubchannel _subchannel;
readonly bool _trim; readonly bool _trim;
@@ -80,9 +81,10 @@ namespace Aaru.Core.Devices.Dumping
Database.Models.Device _dbDev; // Device database entry Database.Models.Device _dbDev; // Device database entry
bool _dumpFirstTrackPregap; bool _dumpFirstTrackPregap;
bool _fixOffset; bool _fixOffset;
readonly bool _fixSubchannel;
readonly bool _fixSubchannelCrc;
uint _maximumReadable; // Maximum number of sectors drive can read at once uint _maximumReadable; // Maximum number of sectors drive can read at once
Resume _resume; Resume _resume;
readonly bool _retrySubchannel;
Sidecar _sidecarClass; Sidecar _sidecarClass;
uint _skip; uint _skip;
int _speed; int _speed;
@@ -115,7 +117,7 @@ namespace Aaru.Core.Devices.Dumping
Encoding encoding, string outputPrefix, string outputPath, Dictionary<string, string> formatOptions, Encoding encoding, string outputPrefix, string outputPath, Dictionary<string, string> formatOptions,
CICMMetadataType preSidecar, uint skip, bool metadata, bool trim, bool dumpFirstTrackPregap, CICMMetadataType preSidecar, uint skip, bool metadata, bool trim, bool dumpFirstTrackPregap,
bool fixOffset, bool debug, DumpSubchannel subchannel, int speed, bool @private, bool fixOffset, bool debug, DumpSubchannel subchannel, int speed, bool @private,
bool fixSubchannelPosition, bool retrySubchannel) bool fixSubchannelPosition, bool retrySubchannel, bool fixSubchannel, bool fixSubchannelCrc)
{ {
_doResume = doResume; _doResume = doResume;
_dev = dev; _dev = dev;
@@ -147,6 +149,8 @@ namespace Aaru.Core.Devices.Dumping
_private = @private; _private = @private;
_fixSubchannelPosition = fixSubchannelPosition; _fixSubchannelPosition = fixSubchannelPosition;
_retrySubchannel = retrySubchannel; _retrySubchannel = retrySubchannel;
_fixSubchannel = fixSubchannel;
_fixSubchannelCrc = fixSubchannelCrc;
} }
/// <summary>Starts dumping with the stablished fields and autodetecting the device type</summary> /// <summary>Starts dumping with the stablished fields and autodetecting the device type</summary>

View File

@@ -185,5 +185,75 @@ namespace Aaru.Core.Logging
_logSw.Flush(); _logSw.Flush();
} }
public void WritePFix()
{
_logSw.WriteLine("Fixed P subchannel using weight average.");
_logSw.Flush();
}
public void WriteRwFix()
{
_logSw.WriteLine("Fixed R-W subchannels writing empty data.");
_logSw.Flush();
}
public void WriteQAdrFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct ADR.");
_logSw.Flush();
}
public void WriteQCtrlFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct CONTROL.");
_logSw.Flush();
}
public void WriteQZeroFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct ZERO.");
_logSw.Flush();
}
public void WriteQTnoFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct TNO.");
_logSw.Flush();
}
public void WriteQIndexFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct INDEX.");
_logSw.Flush();
}
public void WriteQRelPosFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct RELATIVE POSITION.");
_logSw.Flush();
}
public void WriteQAbsPosFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct ABSOLUTE POSITION.");
_logSw.Flush();
}
public void WriteQCrcFix()
{
_logSw.WriteLine("Fixed Q subchannel with correct CRC.");
_logSw.Flush();
}
} }
} }

View File

@@ -800,7 +800,7 @@ namespace Aaru.Gui.ViewModels.Windows
_dumper = new Dump(Resume, _dev, _devicePath, SelectedPlugin.Plugin, (ushort)Retries, Force, false, _dumper = new Dump(Resume, _dev, _devicePath, SelectedPlugin.Plugin, (ushort)Retries, Force, false,
Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination, Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination,
parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false, parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false,
Track1Pregap, true, false, DumpSubchannel.Any, 0, false, false, false); Track1Pregap, true, false, DumpSubchannel.Any, 0, false, false, false, false, false);
new Thread(DoWork).Start(); new Thread(DoWork).Start();
} }

View File

@@ -194,11 +194,27 @@ namespace Aaru.Commands.Media
Add(new Option(new[] Add(new Option(new[]
{ {
"--retry-subchannel" "--retry-subchannel"
}, "Retry subchannel. Implies fixing subchannel position..") }, "Retry subchannel. Implies fixing subchannel position.")
{ {
Argument = new Argument<bool>(() => true), Required = false Argument = new Argument<bool>(() => true), Required = false
}); });
Add(new Option(new[]
{
"--fix-subchannel"
}, "Try to fix subchannel. Implies fixing subchannel position.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Add(new Option(new[]
{
"--fix-subchannel-crc"
}, "If subchannel looks OK but CRC fails, rewrite it. Implies fixing subchannel.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke))); Handler = CommandHandler.Create(GetType().GetMethod(nameof(Invoke)));
} }
@@ -206,7 +222,8 @@ namespace Aaru.Commands.Media
string encoding, bool firstPregap, bool fixOffset, bool force, bool metadata, string encoding, bool firstPregap, bool fixOffset, bool force, bool metadata,
bool trim, string outputPath, string options, bool persistent, ushort retryPasses, bool trim, string outputPath, string options, bool persistent, ushort retryPasses,
uint skip, byte speed, bool stopOnError, string format, string subchannel, uint skip, byte speed, bool stopOnError, string format, string subchannel,
bool @private, bool fixSubchannelPosition, bool retrySubchannel) bool @private, bool fixSubchannelPosition, bool retrySubchannel, bool fixSubchannel,
bool fixSubchannelCrc)
{ {
MainClass.PrintCopyright(); MainClass.PrintCopyright();
@@ -216,7 +233,10 @@ namespace Aaru.Commands.Media
if(verbose) if(verbose)
AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine; AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(retrySubchannel) if(fixSubchannelCrc)
fixSubchannel = true;
if(retrySubchannel || fixSubchannel)
fixSubchannelPosition = true; fixSubchannelPosition = true;
Statistics.AddCommand("dump-media"); Statistics.AddCommand("dump-media");
@@ -243,6 +263,8 @@ namespace Aaru.Commands.Media
AaruConsole.DebugWriteLine("Dump-Media command", "--private={0}", @private); AaruConsole.DebugWriteLine("Dump-Media command", "--private={0}", @private);
AaruConsole.DebugWriteLine("Dump-Media command", "--fix-subchannel-position={0}", fixSubchannelPosition); AaruConsole.DebugWriteLine("Dump-Media command", "--fix-subchannel-position={0}", fixSubchannelPosition);
AaruConsole.DebugWriteLine("Dump-Media command", "--retry-subchannel={0}", retrySubchannel); AaruConsole.DebugWriteLine("Dump-Media command", "--retry-subchannel={0}", retrySubchannel);
AaruConsole.DebugWriteLine("Dump-Media command", "--fix-subchannel={0}", fixSubchannel);
AaruConsole.DebugWriteLine("Dump-Media command", "--fix-subchannel-crc={0}", fixSubchannelCrc);
// TODO: Disabled temporarily // TODO: Disabled temporarily
//AaruConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw); //AaruConsole.DebugWriteLine("Dump-Media command", "--raw={0}", raw);
@@ -441,7 +463,8 @@ namespace Aaru.Commands.Media
var dumper = new Dump(resume, dev, devicePath, outputFormat, retryPasses, force, false, persistent, var dumper = new Dump(resume, dev, devicePath, outputFormat, retryPasses, force, false, persistent,
stopOnError, resumeClass, dumpLog, encodingClass, outputPrefix, outputPath, stopOnError, resumeClass, dumpLog, encodingClass, outputPrefix, outputPath,
parsedOptions, sidecar, skip, metadata, trim, firstPregap, fixOffset, debug, parsedOptions, sidecar, skip, metadata, trim, firstPregap, fixOffset, debug,
wantedSubchannel, speed, @private, fixSubchannelPosition, retrySubchannel); wantedSubchannel, speed, @private, fixSubchannelPosition, retrySubchannel,
fixSubchannel, fixSubchannelCrc);
dumper.UpdateStatus += Progress.UpdateStatus; dumper.UpdateStatus += Progress.UpdateStatus;
dumper.ErrorMessage += Progress.ErrorMessage; dumper.ErrorMessage += Progress.ErrorMessage;