[Aaru.Core] Reformat and cleanup.

This commit is contained in:
2023-10-03 22:57:50 +01:00
parent 57853b0d2a
commit af659f3fcb
85 changed files with 3303 additions and 1961 deletions

View File

@@ -59,12 +59,9 @@ partial class Dump
if(sector?.Length != 2352)
return false;
byte[] syncMark =
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
};
byte[] syncMark = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
byte[] testMark = new byte[12];
var testMark = new byte[12];
Array.Copy(sector, 0, testMark, 0, 12);
return syncMark.SequenceEqual(testMark) && (sector[0xF] == 0 || sector[0xF] == 1 || sector[0xF] == 2);
@@ -82,19 +79,16 @@ partial class Dump
if(sector?.Length != 2352)
return false;
byte[] syncMark =
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
};
byte[] syncMark = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
byte[] testMark = new byte[12];
var testMark = new byte[12];
for(int i = 0; i <= 2336; i++)
for(var i = 0; i <= 2336; i++)
{
Array.Copy(sector, i, testMark, 0, 12);
if(!syncMark.SequenceEqual(testMark) ||
(sector[i + 0xF] != 0x60 && sector[i + 0xF] != 0x61 && sector[i + 0xF] != 0x62))
sector[i + 0xF] != 0x60 && sector[i + 0xF] != 0x61 && sector[i + 0xF] != 0x62)
continue;
// De-scramble M and S
@@ -103,17 +97,17 @@ partial class Dump
int frame = sector[i + 14];
// Convert to binary
minute = (minute / 16 * 10) + (minute & 0x0F);
second = (second / 16 * 10) + (second & 0x0F);
frame = (frame / 16 * 10) + (frame & 0x0F);
minute = minute / 16 * 10 + (minute & 0x0F);
second = second / 16 * 10 + (second & 0x0F);
frame = frame / 16 * 10 + (frame & 0x0F);
// Calculate the first found LBA
int lba = (minute * 60 * 75) + (second * 75) + frame - 150;
int lba = minute * 60 * 75 + second * 75 + frame - 150;
// Calculate the difference between the found LBA and the requested one
int diff = wantedLba - lba;
offset = i + (2352 * diff);
offset = i + 2352 * diff;
return true;
}
@@ -156,12 +150,12 @@ partial class Dump
bool cdiReadyReadAsAudio, int offsetBytes, int sectorsForOffset,
Dictionary<byte, int> smallestPregapLbaPerTrack)
{
ulong sectorSpeedStart = 0; // Used to calculate correct speed
bool sense; // Sense indicator
byte[] cmdBuf; // Data buffer
byte[] senseBuf; // Sense buffer
double cmdDuration; // Command execution time
const uint sectorSize = 2352; // Full sector size
ulong sectorSpeedStart = 0; // Used to calculate correct speed
bool sense; // Sense indicator
byte[] cmdBuf; // Data buffer
byte[] senseBuf; // Sense buffer
double cmdDuration; // Command execution time
const uint sectorSize = 2352; // Full sector size
Track firstTrack = tracks.FirstOrDefault();
uint blocksToRead; // How many sectors to read at once
var outputOptical = _outputPlugin as IWritableOpticalImage;
@@ -190,7 +184,7 @@ partial class Dump
break;
}
uint firstSectorToRead = (uint)i;
var firstSectorToRead = (uint)i;
blocksToRead = _maximumReadable;
@@ -198,6 +192,7 @@ partial class Dump
blocksToRead += (uint)sectorsForOffset;
if(cdiReadyReadAsAudio)
{
if(offsetBytes < 0)
{
if(i == 0)
@@ -205,6 +200,7 @@ partial class Dump
else
firstSectorToRead -= (uint)sectorsForOffset;
}
}
if(currentSpeed > maxSpeed &&
currentSpeed > 0)
@@ -215,8 +211,10 @@ partial class Dump
minSpeed = currentSpeed;
UpdateProgress?.
Invoke(string.Format(Localization.Core.Reading_sector_0_of_1_2, i, blocks, ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i, (long)blocks);
Invoke(
string.Format(Localization.Core.Reading_sector_0_of_1_2, i, blocks,
ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i, (long)blocks);
sense = _dev.ReadCd(out cmdBuf, out senseBuf, firstSectorToRead, blockSize, blocksToRead,
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true,
@@ -228,11 +226,14 @@ partial class Dump
// Overcome the track mode change drive error
if(sense)
{
for(uint r = 0; r < _maximumReadable; r++)
{
UpdateProgress?.
Invoke(string.Format(Localization.Core.Reading_sector_0_of_1_2, i + r, blocks, ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i + r, (long)blocks);
Invoke(
string.Format(Localization.Core.Reading_sector_0_of_1_2, i + r, blocks,
ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i + r, (long)blocks);
sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)(i + r), blockSize, (uint)sectorsForOffset + 1,
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
@@ -249,13 +250,15 @@ partial class Dump
_writeStopwatch.Restart();
if(cdiReadyReadAsAudio)
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel,
ref blocksToRead, subSize, ref cmdBuf, blockSize, false);
{
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel,
ref blocksToRead, subSize, ref cmdBuf, blockSize, false);
}
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize];
byte[] sub = new byte[subSize];
var data = new byte[sectorSize];
var sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
@@ -318,6 +321,7 @@ partial class Dump
sectorSpeedStart = 0;
_speedStopwatch.Restart();
}
}
_speedStopwatch.Restart();
@@ -325,8 +329,10 @@ partial class Dump
!_dev.Error)
{
if(cdiReadyReadAsAudio)
{
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel, ref blocksToRead,
subSize, ref cmdBuf, blockSize, false);
subSize, ref cmdBuf, blockSize, false);
}
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, currentSpeed * 1024);
@@ -335,31 +341,31 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize * blocksToRead];
byte[] sub = new byte[subSize * blocksToRead];
byte[] tmpData = new byte[sectorSize];
var data = new byte[sectorSize * blocksToRead];
var sub = new byte[subSize * blocksToRead];
var tmpData = new byte[sectorSize];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
if(cdiReadyReadAsAudio)
{
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), tmpData, 0, sectorSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), tmpData, 0, sectorSize);
tmpData = Sector.Scramble(tmpData);
Array.Copy(tmpData, 0, data, sectorSize * b, sectorSize);
}
else
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize);
Array.Copy(cmdBuf, (int)(sectorSize + b * blockSize), sub, subSize * b, subSize);
}
outputOptical.WriteSectorsLong(data, i, blocksToRead);
bool indexesChanged = Media.CompactDisc.WriteSubchannelToImage(supportedSubchannel,
desiredSubchannel, sub, i, blocksToRead, subLog, isrcs, 1, ref mcn, tracks,
subchannelExtents, _fixSubchannelPosition, outputOptical, _fixSubchannel,
_fixSubchannelCrc, _dumpLog, UpdateStatus, smallestPregapLbaPerTrack, true,
out List<ulong> newPregapSectors);
desiredSubchannel, sub, i, blocksToRead, subLog, isrcs, 1, ref mcn, tracks,
subchannelExtents, _fixSubchannelPosition, outputOptical, _fixSubchannel,
_fixSubchannelCrc, _dumpLog, UpdateStatus, smallestPregapLbaPerTrack, true,
out List<ulong> newPregapSectors);
// Set tracks and go back
if(indexesChanged)
@@ -384,10 +390,10 @@ partial class Dump
{
if(cdiReadyReadAsAudio)
{
byte[] tmpData = new byte[sectorSize];
byte[] data = new byte[sectorSize * blocksToRead];
var tmpData = new byte[sectorSize];
var data = new byte[sectorSize * blocksToRead];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(b * sectorSize), tmpData, 0, sectorSize);
tmpData = Sector.Scramble(tmpData);

View File

@@ -100,31 +100,31 @@ partial class Dump
Dictionary<byte, string> isrcs, ref string mcn, HashSet<int> subchannelExtents,
Dictionary<byte, int> smallestPregapLbaPerTrack)
{
ulong sectorSpeedStart = 0; // Used to calculate correct speed
uint blocksToRead; // How many sectors to read at once
bool sense = true; // Sense indicator
byte[] cmdBuf = null; // Data buffer
byte[] senseBuf = null; // Sense buffer
double cmdDuration = 0; // Command execution time
const uint sectorSize = 2352; // Full sector size
ulong sectorSpeedStart = 0; // Used to calculate correct speed
uint blocksToRead; // How many sectors to read at once
var sense = true; // Sense indicator
byte[] cmdBuf = null; // Data buffer
byte[] senseBuf = null; // Sense buffer
double cmdDuration = 0; // Command execution time
const uint sectorSize = 2352; // Full sector size
newTrim = false;
PlextorSubchannel supportedPlextorSubchannel;
var outputFormat = _outputPlugin as IWritableImage;
supportedPlextorSubchannel = supportedSubchannel switch
{
MmcSubchannel.None => PlextorSubchannel.None,
MmcSubchannel.Raw => PlextorSubchannel.Pack,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
_ => PlextorSubchannel.None
};
{
MmcSubchannel.None => PlextorSubchannel.None,
MmcSubchannel.Raw => PlextorSubchannel.Pack,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
_ => PlextorSubchannel.None
};
InitProgress?.Invoke();
int currentReadSpeed = _speed;
bool crossingLeadOut = false;
bool failedCrossingLeadOut = false;
bool skippingLead = false;
int currentReadSpeed = _speed;
var crossingLeadOut = false;
var failedCrossingLeadOut = false;
var skippingLead = false;
for(ulong i = _resume.NextBlock; (long)i <= lastSector; i += blocksToRead)
{
@@ -148,7 +148,7 @@ partial class Dump
if((long)i > lastSector)
break;
uint firstSectorToRead = (uint)i;
var firstSectorToRead = (uint)i;
Track track = tracks.OrderBy(t => t.StartSector).LastOrDefault(t => i >= t.StartSector);
@@ -213,6 +213,7 @@ partial class Dump
}
if(_fixOffset && !inData)
{
if(offsetBytes < 0)
{
if(i == 0)
@@ -223,6 +224,7 @@ partial class Dump
if(blocksToRead <= sectorsForOffset)
blocksToRead += (uint)sectorsForOffset;
}
}
switch(inData)
{
@@ -237,11 +239,13 @@ partial class Dump
break;
case true when currentReadSpeed != _speed:
{
_dumpLog.WriteLine(_speed == 0xFFFF ? Localization.Core.Setting_speed_to_MAX_for_data_reading
_dumpLog.WriteLine(_speed == 0xFFFF
? Localization.Core.Setting_speed_to_MAX_for_data_reading
: string.Format(Localization.Core.Setting_speed_to_0_x_for_data_reading,
_speed));
UpdateStatus?.Invoke(_speed == 0xFFFF ? Localization.Core.Setting_speed_to_MAX_for_data_reading
UpdateStatus?.Invoke(_speed == 0xFFFF
? Localization.Core.Setting_speed_to_MAX_for_data_reading
: string.Format(Localization.Core.Setting_speed_to_0_x_for_data_reading,
_speed));
@@ -274,8 +278,10 @@ partial class Dump
minSpeed = currentSpeed;
UpdateProgress?.
Invoke(string.Format(Localization.Core.Reading_sector_0_of_1_2, i, blocks, ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i, (long)blocks);
Invoke(
string.Format(Localization.Core.Reading_sector_0_of_1_2, i, blocks,
ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i, (long)blocks);
if(crossingLeadOut &&
failedCrossingLeadOut &&
@@ -304,10 +310,10 @@ partial class Dump
// Try to workaround firmware
if(decSense?.ASC == 0x64)
{
bool goBackTrackTypeChange = false;
var goBackTrackTypeChange = false;
// Go one for one as the drive does not tell us which one failed
for(int bi = 0; bi < blocksToRead; bi++)
for(var bi = 0; bi < blocksToRead; bi++)
{
sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)(firstSectorToRead + bi), blockSize,
1, MmcSectorTypes.AllTypes, false, false, true,
@@ -360,6 +366,7 @@ partial class Dump
if(sense)
// Try reading one less every time
{
for(uint bi = blocksToRead; bi > 0; bi--)
{
sense = _dev.ReadCd(out cmdBuf, out senseBuf, firstSectorToRead, blockSize, bi,
@@ -374,6 +381,7 @@ partial class Dump
break;
}
}
}
}
}
@@ -404,17 +412,25 @@ partial class Dump
totalDuration += cmdDuration;
}
else if(read16)
{
sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, false, false, firstSectorToRead, blockSize, 0,
blocksToRead, false, _dev.Timeout, out cmdDuration);
}
else if(read12)
{
sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, false, false, false, firstSectorToRead,
blockSize, 0, blocksToRead, false, _dev.Timeout, out cmdDuration);
}
else if(read10)
{
sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, false, false, false, firstSectorToRead,
blockSize, 0, (ushort)blocksToRead, _dev.Timeout, out cmdDuration);
}
else if(read6)
{
sense = _dev.Read6(out cmdBuf, out senseBuf, firstSectorToRead, blockSize, (byte)blocksToRead,
_dev.Timeout, out cmdDuration);
}
double elapsed;
@@ -428,12 +444,14 @@ partial class Dump
for(uint r = 0; r < blocksToRead; r++)
{
UpdateProgress?.
Invoke(string.Format(Localization.Core.Reading_sector_0_of_1_2, i + r, blocks, ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i + r, (long)blocks);
Invoke(
string.Format(Localization.Core.Reading_sector_0_of_1_2, i + r, blocks,
ByteSize.FromMegabytes(currentSpeed).Per(_oneSecond).Humanize()),
(long)i + r, (long)blocks);
if(_supportsPlextorD8)
{
int adjustment = 0;
var adjustment = 0;
if(offsetBytes < 0)
adjustment = -sectorsForOffset;
@@ -447,10 +465,10 @@ partial class Dump
if(!sense)
{
uint sectorsForFix = (uint)(1 + sectorsForOffset);
var sectorsForFix = (uint)(1 + sectorsForOffset);
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel,
ref sectorsForFix, subSize, ref cmdBuf, blockSize, false);
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel,
ref sectorsForFix, subSize, ref cmdBuf, blockSize, false);
// TODO: Implement sector validity
cmdBuf = Sector.Scramble(cmdBuf);
@@ -466,17 +484,25 @@ partial class Dump
totalDuration += cmdDuration;
}
else if(read16)
{
sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, i + r, blockSize, 0, 1,
false, _dev.Timeout, out cmdDuration);
}
else if(read12)
{
sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)(i + r),
blockSize, 0, 1, false, _dev.Timeout, out cmdDuration);
}
else if(read10)
{
sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)(i + r),
blockSize, 0, 1, _dev.Timeout, out cmdDuration);
}
else if(read6)
{
sense = _dev.Read6(out cmdBuf, out senseBuf, (uint)(i + r), blockSize, 1, _dev.Timeout,
out cmdDuration);
}
if(!sense &&
!_dev.Error)
@@ -488,8 +514,8 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize];
byte[] sub = new byte[subSize];
var data = new byte[sectorSize];
var sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
@@ -499,12 +525,12 @@ partial class Dump
outputFormat.WriteSectorsLong(data, i + r, 1);
else
{
var cooked = new MemoryStream();
byte[] sector = new byte[sectorSize];
var cooked = new MemoryStream();
var sector = new byte[sectorSize];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), sector, 0, sectorSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), sector, 0, sectorSize);
byte[] cookedSector = Sector.GetUserData(sector);
cooked.Write(cookedSector, 0, cookedSector.Length);
}
@@ -546,10 +572,10 @@ partial class Dump
outputFormat.WriteSectorsLong(cmdBuf, i + r, 1);
else
{
var cooked = new MemoryStream();
byte[] sector = new byte[sectorSize];
var cooked = new MemoryStream();
var sector = new byte[sectorSize];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(b * sectorSize), sector, 0, sectorSize);
byte[] cookedSector = Sector.GetUserData(sector);
@@ -576,8 +602,10 @@ partial class Dump
outputFormat.WriteSectorsLong(new byte[sectorSize], i + r, 1);
if(desiredSubchannel != MmcSubchannel.None)
{
outputFormat.WriteSectorsTag(new byte[subSize], i + r, 1,
SectorTagType.CdSectorSubchannel);
}
}
else
{
@@ -632,7 +660,7 @@ partial class Dump
{
if(crossingLeadOut && failedCrossingLeadOut)
{
byte[] tmp = new byte[cmdBuf.Length + blockSize];
var tmp = new byte[cmdBuf.Length + blockSize];
Array.Copy(cmdBuf, 0, tmp, 0, cmdBuf.Length);
}
@@ -640,8 +668,10 @@ partial class Dump
if(_fixOffset &&
!inData &&
offsetBytes != 0)
{
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel, ref blocksToRead,
subSize, ref cmdBuf, blockSize, failedCrossingLeadOut);
subSize, ref cmdBuf, blockSize, failedCrossingLeadOut);
}
mhddLog.Write(i, cmdDuration, blocksToRead);
ibgLog.Write(i, currentSpeed * 1024);
@@ -650,26 +680,26 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize * blocksToRead];
byte[] sub = new byte[subSize * blocksToRead];
var data = new byte[sectorSize * blocksToRead];
var sub = new byte[subSize * blocksToRead];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize);
Array.Copy(cmdBuf, (int)(sectorSize + b * blockSize), sub, subSize * b, subSize);
}
if(supportsLongSectors)
outputFormat.WriteSectorsLong(data, i, blocksToRead);
else
{
var cooked = new MemoryStream();
byte[] sector = new byte[sectorSize];
var cooked = new MemoryStream();
var sector = new byte[sectorSize];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), sector, 0, sectorSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), sector, 0, sectorSize);
byte[] cookedSector = Sector.GetUserData(sector);
cooked.Write(cookedSector, 0, cookedSector.Length);
}
@@ -678,10 +708,10 @@ partial class Dump
}
bool indexesChanged = Media.CompactDisc.WriteSubchannelToImage(supportedSubchannel,
desiredSubchannel, sub, i, blocksToRead, subLog, isrcs, (byte)track.Sequence, ref mcn,
tracks, subchannelExtents, _fixSubchannelPosition, outputFormat as IWritableOpticalImage,
_fixSubchannel, _fixSubchannelCrc, _dumpLog, UpdateStatus, smallestPregapLbaPerTrack, true,
out List<ulong> newPregapSectors);
desiredSubchannel, sub, i, blocksToRead, subLog, isrcs, (byte)track.Sequence, ref mcn,
tracks, subchannelExtents, _fixSubchannelPosition, outputFormat as IWritableOpticalImage,
_fixSubchannel, _fixSubchannelCrc, _dumpLog, UpdateStatus, smallestPregapLbaPerTrack, true,
out List<ulong> newPregapSectors);
// Set tracks and go back
if(indexesChanged)
@@ -711,10 +741,10 @@ partial class Dump
outputFormat.WriteSectorsLong(cmdBuf, i, blocksToRead);
else
{
var cooked = new MemoryStream();
byte[] sector = new byte[sectorSize];
var cooked = new MemoryStream();
var sector = new byte[sectorSize];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(b * sectorSize), sector, 0, sectorSize);
byte[] cookedSector = Sector.GetUserData(sector);
@@ -759,8 +789,10 @@ partial class Dump
outputFormat.WriteSectorsLong(new byte[sectorSize * _skip], i, _skip);
if(desiredSubchannel != MmcSubchannel.None)
{
outputFormat.WriteSectorsTag(new byte[subSize * _skip], i, _skip,
SectorTagType.CdSectorSubchannel);
}
}
else
{

View File

@@ -86,21 +86,21 @@ sealed partial class Dump
MhddLog mhddLog; // MHDD log
double minSpeed = double.MaxValue; // Minimum speed
bool newTrim; // Is trim a new one?
int offsetBytes = 0; // Read offset
bool read6 = false; // Device supports READ(6)
bool read10 = false; // Device supports READ(10)
bool read12 = false; // Device supports READ(12)
bool read16 = false; // Device supports READ(16)
bool readcd = true; // Device supports READ CD
var offsetBytes = 0; // Read offset
var read6 = false; // Device supports READ(6)
var read10 = false; // Device supports READ(10)
var read12 = false; // Device supports READ(12)
var read16 = false; // Device supports READ(16)
var readcd = true; // Device supports READ CD
bool ret; // Image writing return status
const uint sectorSize = 2352; // Full sector size
int sectorsForOffset = 0; // Sectors needed to fix offset
bool sense = true; // Sense indicator
var sectorsForOffset = 0; // Sectors needed to fix offset
var sense = true; // Sense indicator
int sessions; // Number of sessions in disc
SubchannelLog subLog = null; // Subchannel log
uint subSize = 0; // Subchannel size in bytes
TrackSubchannelType subType = TrackSubchannelType.None; // Track subchannel type
bool supportsLongSectors = true; // Supports reading EDC and ECC
var supportsLongSectors = true; // Supports reading EDC and ECC
bool supportsPqSubchannel; // Supports reading PQ subchannel
bool supportsRwSubchannel; // Supports reading RW subchannel
byte[] tmpBuf; // Temporary buffer
@@ -112,11 +112,11 @@ sealed partial class Dump
bool hiddenTrack; // Disc has a hidden track before track 1
MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel
MmcSubchannel desiredSubchannel; // User requested subchannel
bool bcdSubchannel = false; // Subchannel positioning is in BCD
var bcdSubchannel = false; // Subchannel positioning is in BCD
Dictionary<byte, string> isrcs = new();
string mcn = null;
HashSet<int> subchannelExtents = new();
bool cdiReadyReadAsAudio = false;
var cdiReadyReadAsAudio = false;
uint firstLba;
var outputOptical = _outputPlugin as IWritableOpticalImage;
@@ -133,7 +133,7 @@ sealed partial class Dump
return;
}
tracks = GetCdTracks(_dev, _dumpLog, _force, out lastSector, leadOutStarts, mediaTags, StoppingErrorMessage,
tracks = GetCdTracks(_dev, _dumpLog, _force, out lastSector, leadOutStarts, mediaTags, StoppingErrorMessage,
out toc, trackFlags, UpdateStatus);
if(tracks is null)
@@ -219,7 +219,8 @@ sealed partial class Dump
desiredSubchannel = MmcSubchannel.None;
break;
default: throw new ArgumentOutOfRangeException();
default:
throw new ArgumentOutOfRangeException();
}
if(desiredSubchannel == MmcSubchannel.Q16 && supportsPqSubchannel)
@@ -361,7 +362,7 @@ sealed partial class Dump
// Check if subchannel is BCD
if(supportedSubchannel != MmcSubchannel.None)
{
sense = _dev.ReadCd(out cmdBuf, out _, (((firstLba / 75) + 1) * 75) + 35, blockSize, 1,
sense = _dev.ReadCd(out cmdBuf, out _, (firstLba / 75 + 1) * 75 + 35, blockSize, 1,
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true,
MmcErrorField.None, supportedSubchannel, _dev.Timeout, out _);
@@ -454,7 +455,7 @@ sealed partial class Dump
ErrorMessage?.Invoke(Localization.Core.Output_format_does_not_support_pregaps_continuing);
}
for(int t = 1; t < tracks.Length; t++)
for(var t = 1; t < tracks.Length; t++)
tracks[t - 1].EndSector = tracks[t].StartSector - 1;
tracks[^1].EndSector = (ulong)lastSector;
@@ -502,6 +503,7 @@ sealed partial class Dump
// Check if output format supports all disc tags we have retrieved so far
foreach(MediaTagType tag in mediaTags.Keys.Where(tag => !outputOptical.SupportedMediaTags.Contains(tag)))
{
if(_force)
{
_dumpLog.WriteLine(Localization.Core.Output_format_does_not_support_0_continuing, tag);
@@ -516,15 +518,16 @@ sealed partial class Dump
return;
}
}
if(leadOutStarts.Any())
{
UpdateStatus?.Invoke(Localization.Core.Solving_lead_outs);
foreach(KeyValuePair<int, long> leadOuts in leadOutStarts)
foreach(Track trk in tracks.Where(trk => trk.Session == leadOuts.Key).
Where(trk => trk.EndSector >= (ulong)leadOuts.Value))
trk.EndSector = (ulong)leadOuts.Value - 1;
foreach(Track trk in tracks.Where(trk => trk.Session == leadOuts.Key).
Where(trk => trk.EndSector >= (ulong)leadOuts.Value))
trk.EndSector = (ulong)leadOuts.Value - 1;
var dataExtents = new ExtentsULong();
@@ -533,7 +536,7 @@ sealed partial class Dump
Tuple<ulong, ulong>[] dataExtentsArray = dataExtents.ToArray();
for(int i = 0; i < dataExtentsArray.Length - 1; i++)
for(var i = 0; i < dataExtentsArray.Length - 1; i++)
leadOutExtents.Add(dataExtentsArray[i].Item2 + 1, dataExtentsArray[i + 1].Item1 - 1);
}
@@ -610,7 +613,7 @@ sealed partial class Dump
continue;
}
int bufOffset = 0;
var bufOffset = 0;
while(cmdBuf[0 + bufOffset] != 0x00 ||
cmdBuf[1 + bufOffset] != 0xFF ||
@@ -716,6 +719,7 @@ sealed partial class Dump
// Check if something prevents from dumping the first track pregap
if(_dumpFirstTrackPregap && readcd)
{
if(!outputOptical.SupportedMediaTags.Contains(MediaTagType.CD_FirstTrackPregap))
{
if(_force)
@@ -739,6 +743,7 @@ sealed partial class Dump
_dumpFirstTrackPregap = false;
}
}
// Try how many blocks are readable at once
while(true)
@@ -798,7 +803,7 @@ sealed partial class Dump
_dev.LastError));
}
bool cdiWithHiddenTrack1 = false;
var cdiWithHiddenTrack1 = false;
if(dskType is MediaType.CDIREADY &&
tracks.Min(t => t.Sequence) == 1)
@@ -811,12 +816,12 @@ sealed partial class Dump
if(_dumpFirstTrackPregap && readcd)
ReadCdFirstTrackPregap(blockSize, ref currentSpeed, mediaTags, supportedSubchannel, ref totalDuration);
_dumpLog.WriteLine(Localization.Core.Reading_0_sectors_at_a_time, _maximumReadable);
_dumpLog.WriteLine(Localization.Core.Device_reports_0_blocks_1_bytes, blocks, blocks * blockSize);
_dumpLog.WriteLine(Localization.Core.Device_can_read_0_blocks_at_a_time, _maximumReadable);
_dumpLog.WriteLine(Localization.Core.Reading_0_sectors_at_a_time, _maximumReadable);
_dumpLog.WriteLine(Localization.Core.Device_reports_0_blocks_1_bytes, blocks, blocks * blockSize);
_dumpLog.WriteLine(Localization.Core.Device_can_read_0_blocks_at_a_time, _maximumReadable);
_dumpLog.WriteLine(Localization.Core.Device_reports_0_bytes_per_logical_block, blockSize);
_dumpLog.WriteLine(Localization.Core.SCSI_device_type_0, _dev.ScsiType);
_dumpLog.WriteLine(Localization.Core.Media_identified_as_0, dskType);
_dumpLog.WriteLine(Localization.Core.SCSI_device_type_0, _dev.ScsiType);
_dumpLog.WriteLine(Localization.Core.Media_identified_as_0, dskType);
UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_sectors_at_a_time, _maximumReadable));
@@ -849,6 +854,7 @@ sealed partial class Dump
mcn = Encoding.ASCII.GetString(mcnBytes);
if(outputOptical.Tracks != null)
{
foreach(Track imgTrack in outputOptical.Tracks)
{
errno = outputOptical.ReadSectorTag(imgTrack.Sequence, SectorTagType.CdTrackIsrc, out byte[] isrcBytes);
@@ -868,6 +874,7 @@ sealed partial class Dump
foreach(KeyValuePair<ushort, int> imgIdx in imgTrack.Indexes)
trk.Indexes[imgIdx.Key] = imgIdx.Value;
}
}
// Send track list to output plugin. This may fail if subchannel is set but unsupported.
ret = outputOptical.SetTracks(tracks.ToList());
@@ -923,10 +930,7 @@ sealed partial class Dump
_dumpLog.WriteLine(Localization.Core.Setting_flags_for_track_0, track.Sequence);
UpdateStatus?.Invoke(string.Format(Localization.Core.Setting_flags_for_track_0, track.Sequence));
outputOptical.WriteSectorTag(new[]
{
kvp.Value
}, kvp.Key, SectorTagType.CdTrackFlags);
outputOptical.WriteSectorTag(new[] { kvp.Value }, kvp.Key, SectorTagType.CdTrackFlags);
}
// Set MCN
@@ -947,6 +951,7 @@ sealed partial class Dump
// Set ISRCs
if(supportedSubchannel == MmcSubchannel.None)
{
foreach(Track trk in tracks)
{
sense = _dev.ReadIsrc((byte)trk.Sequence, out string isrc, out _, out _, _dev.Timeout, out _);
@@ -957,8 +962,9 @@ sealed partial class Dump
isrcs[(byte)trk.Sequence] = isrc;
UpdateStatus?.Invoke(string.Format(Localization.Core.Found_ISRC_for_track_0_1, trk.Sequence, isrc));
_dumpLog.WriteLine(string.Format(Localization.Core.Found_ISRC_for_track_0_1, trk.Sequence, isrc));
_dumpLog.WriteLine(string.Format(Localization.Core.Found_ISRC_for_track_0_1, trk.Sequence, isrc));
}
}
if(supportedSubchannel != MmcSubchannel.None &&
desiredSubchannel != MmcSubchannel.None)
@@ -971,8 +977,10 @@ sealed partial class Dump
subchannelExtents.Add(sub);
if(_resume.NextBlock < blocks)
{
for(ulong i = _resume.NextBlock; i < blocks; i++)
subchannelExtents.Add((int)i);
}
}
if(_resume.NextBlock > 0)
@@ -986,8 +994,10 @@ sealed partial class Dump
#if DEBUG
foreach(Track trk in tracks)
{
UpdateStatus?.Invoke(string.Format(Localization.Core.Track_0_starts_at_LBA_1_and_ends_at_LBA_2,
trk.Sequence, trk.StartSector, trk.EndSector));
}
#endif
// Check offset
@@ -1135,8 +1145,10 @@ sealed partial class Dump
_mediaGraph = new BlockMap((int)_dimensions, (int)_dimensions, blocks);
if(_mediaGraph is not null)
{
foreach(Tuple<ulong, ulong> e in extents.ToArray())
_mediaGraph?.PaintSectorsGood(e.Item1, (uint)(e.Item2 - e.Item1 + 2));
}
_mediaGraph?.PaintSectorsBad(_resume.BadBlocks);
}
@@ -1149,10 +1161,12 @@ sealed partial class Dump
// Set speed
if(_speedMultiplier >= 0)
{
_dumpLog.WriteLine(_speed == 0xFFFF ? Localization.Core.Setting_speed_to_MAX_for_data_reading
_dumpLog.WriteLine(_speed == 0xFFFF
? Localization.Core.Setting_speed_to_MAX_for_data_reading
: string.Format(Localization.Core.Setting_speed_to_0_x_for_data_reading, _speed));
UpdateStatus?.Invoke(_speed == 0xFFFF ? Localization.Core.Setting_speed_to_MAX_for_data_reading
UpdateStatus?.Invoke(_speed == 0xFFFF
? Localization.Core.Setting_speed_to_MAX_for_data_reading
: string.Format(Localization.Core.Setting_speed_to_0_x_for_data_reading, _speed));
_speed *= _speedMultiplier;
@@ -1266,10 +1280,12 @@ sealed partial class Dump
}
if(_skipCdireadyHole)
{
ReadCdiReady(blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration,
leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, subSize, supportedSubchannel,
ref totalDuration, tracks, subLog, desiredSubchannel, isrcs, ref mcn, subchannelExtents,
blocks, cdiReadyReadAsAudio, offsetBytes, sectorsForOffset, smallestPregapLbaPerTrack);
}
}
ReadCdData(audioExtents, blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog,
@@ -1314,33 +1330,40 @@ sealed partial class Dump
ByteSize.FromBytes(blockSize * (blocks + 1)).
Per(imageWriteDuration.Seconds())));
TrimCdUserData(audioExtents, blockSize, currentTry, extents, newTrim, offsetBytes, read6, read10, read12,
read16, readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors,
TrimCdUserData(audioExtents, blockSize, currentTry, extents, newTrim, offsetBytes, read6, read10, read12,
read16, readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors,
ref totalDuration, subLog, desiredSubchannel, tracks, isrcs, ref mcn, subchannelExtents,
smallestPregapLbaPerTrack);
if(dskType is MediaType.CDR or MediaType.CDRW &&
_resume.BadBlocks.Count > 0 &&
_ignoreCdrRunOuts > 0)
{
HandleCdrRunOutSectors(blocks, desiredSubchannel, extents, subchannelExtents, subLog, supportsLongSectors,
trackFlags, tracks);
}
RetryCdUserData(audioExtents, blockSize, currentTry, extents, offsetBytes, readcd, sectorsForOffset, subSize,
supportedSubchannel, ref totalDuration, subLog, desiredSubchannel, tracks, isrcs, ref mcn,
subchannelExtents, smallestPregapLbaPerTrack, supportsLongSectors);
foreach(Tuple<ulong, ulong> leadoutExtent in leadOutExtents.ToArray())
{
for(ulong e = leadoutExtent.Item1; e <= leadoutExtent.Item2; e++)
subchannelExtents.Remove((int)e);
}
if(subchannelExtents.Count > 0 &&
_retryPasses > 0 &&
_retrySubchannel)
{
RetrySubchannel(readcd, subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel, tracks,
isrcs, ref mcn, subchannelExtents, smallestPregapLbaPerTrack);
isrcs, ref mcn, subchannelExtents, smallestPregapLbaPerTrack);
}
// Write media tags to image
if(!_aborted)
{
foreach(KeyValuePair<MediaTagType, byte[]> tag in mediaTags)
{
if(tag.Value is null)
@@ -1361,6 +1384,7 @@ sealed partial class Dump
return;
}
}
_resume.BadBlocks.Sort();
@@ -1376,8 +1400,10 @@ sealed partial class Dump
if(_generateSubchannels &&
outputOptical.SupportedSectorTags.Contains(SectorTagType.CdSectorSubchannel) &&
!_aborted)
{
Media.CompactDisc.GenerateSubchannels(subchannelExtents, tracks, trackFlags, blocks, subLog, _dumpLog,
InitProgress, UpdateProgress, EndProgress, outputOptical);
}
// TODO: Disc ID
var metadata = new CommonTypes.Structs.ImageInfo
@@ -1387,8 +1413,10 @@ sealed partial class Dump
};
if(!outputOptical.SetImageInfo(metadata))
{
ErrorMessage?.Invoke(Localization.Core.Error_0_setting_metadata + Environment.NewLine +
outputOptical.ErrorMessage);
}
outputOptical.SetDumpHardware(_resume.Tries);
@@ -1455,31 +1483,38 @@ sealed partial class Dump
double totalChkDuration = 0;
if(_metadata)
{
WriteOpticalSidecar(blockSize, blocks, dskType, null, mediaTags, sessions, out totalChkDuration,
discOffset);
}
_dumpStopwatch.Stop();
UpdateStatus?.Invoke("");
UpdateStatus?.
Invoke(string.Format(Localization.Core.Took_a_total_of_0_1_processing_commands_2_checksumming_3_writing_4_closing,
_dumpStopwatch.Elapsed.Humanize(minUnit: TimeUnit.Second),
totalDuration.Milliseconds().Humanize(minUnit: TimeUnit.Second),
totalChkDuration.Milliseconds().Humanize(minUnit: TimeUnit.Second),
imageWriteDuration.Seconds().Humanize(minUnit: TimeUnit.Second),
_imageCloseStopwatch.Elapsed.Humanize(minUnit: TimeUnit.Second)));
Invoke(string.Format(
Localization.Core.Took_a_total_of_0_1_processing_commands_2_checksumming_3_writing_4_closing,
_dumpStopwatch.Elapsed.Humanize(minUnit: TimeUnit.Second),
totalDuration.Milliseconds().Humanize(minUnit: TimeUnit.Second),
totalChkDuration.Milliseconds().Humanize(minUnit: TimeUnit.Second),
imageWriteDuration.Seconds().Humanize(minUnit: TimeUnit.Second),
_imageCloseStopwatch.Elapsed.Humanize(minUnit: TimeUnit.Second)));
UpdateStatus?.Invoke(string.Format(Localization.Core.Average_speed_0,
ByteSize.FromBytes(blockSize * (blocks + 1)).
Per(totalDuration.Milliseconds()).Humanize()));
if(maxSpeed > 0)
{
UpdateStatus?.Invoke(string.Format(Localization.Core.Fastest_speed_burst_0,
ByteSize.FromMegabytes(maxSpeed).Per(_oneSecond).Humanize()));
}
if(minSpeed is > 0 and < double.MaxValue)
{
UpdateStatus?.Invoke(string.Format(Localization.Core.Slowest_speed_burst_0,
ByteSize.FromMegabytes(minSpeed).Per(_oneSecond).Humanize()));
}
UpdateStatus?.Invoke(string.Format(Localization.Core._0_sectors_could_not_be_read, _resume.BadBlocks.Count));

View File

@@ -79,7 +79,7 @@ partial class Dump
ref string mcn, HashSet<int> subchannelExtents,
Dictionary<byte, int> smallestPregapLbaPerTrack, bool supportsLongSectors)
{
bool sense = true; // Sense indicator
var sense = true; // Sense indicator
byte[] cmdBuf = null; // Data buffer
double cmdDuration; // Command execution time
const uint sectorSize = 2352; // Full sector size
@@ -88,21 +88,21 @@ partial class Dump
var outputOptical = _outputPlugin as IWritableOpticalImage;
supportedPlextorSubchannel = supportedSubchannel switch
{
MmcSubchannel.None => PlextorSubchannel.None,
MmcSubchannel.Raw => PlextorSubchannel.Pack,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
_ => PlextorSubchannel.None
};
{
MmcSubchannel.None => PlextorSubchannel.None,
MmcSubchannel.Raw => PlextorSubchannel.Pack,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
_ => PlextorSubchannel.None
};
if(_resume.BadBlocks.Count <= 0 ||
_aborted ||
_retryPasses <= 0)
return;
int pass = 1;
bool forward = true;
bool runningPersistent = false;
var pass = 1;
var forward = true;
var runningPersistent = false;
Modes.ModePage? currentModePage = null;
byte[] md6;
@@ -125,9 +125,11 @@ partial class Dump
Modes.DecodedMode? dcMode10 = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
if(dcMode10?.Pages != null)
{
foreach(Modes.ModePage modePage in dcMode10.Value.Pages.Where(modePage =>
modePage is { Page: 0x01, Subpage: 0x00 }))
currentModePage = modePage;
}
}
}
else
@@ -135,9 +137,11 @@ partial class Dump
Modes.DecodedMode? dcMode6 = Modes.DecodeMode6(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
if(dcMode6?.Pages != null)
{
foreach(Modes.ModePage modePage in dcMode6.Value.Pages.Where(modePage =>
modePage is { Page: 0x01, Subpage: 0x00 }))
currentModePage = modePage;
}
}
if(currentModePage == null)
@@ -203,11 +207,11 @@ partial class Dump
}
InitProgress?.Invoke();
cdRepeatRetry:
cdRepeatRetry:
ulong[] tmpArray = _resume.BadBlocks.ToArray();
List<ulong> sectorsNotEvenPartial = new();
for(int i = 0; i < tmpArray.Length; i++)
for(var i = 0; i < tmpArray.Length; i++)
{
ulong badSector = tmpArray[i];
@@ -220,24 +224,32 @@ partial class Dump
}
if(forward)
{
PulseProgress?.Invoke(runningPersistent
? string.
Format(Localization.Core.Retrying_sector_0_pass_1_recovering_partial_data_forward,
badSector, pass)
Format(
Localization.Core.
Retrying_sector_0_pass_1_recovering_partial_data_forward,
badSector, pass)
: string.Format(Localization.Core.Retrying_sector_0_pass_1_forward, badSector,
pass));
}
else
{
PulseProgress?.Invoke(runningPersistent
? string.
Format(Localization.Core.Retrying_sector_0_pass_1_recovering_partial_data_reverse,
badSector, pass)
Format(
Localization.Core.
Retrying_sector_0_pass_1_recovering_partial_data_reverse,
badSector, pass)
: string.Format(Localization.Core.Retrying_sector_0_pass_1_reverse, badSector,
pass));
}
Track track = tracks.OrderBy(t => t.StartSector).LastOrDefault(t => badSector >= t.StartSector);
byte sectorsToReRead = 1;
uint badSectorToReRead = (uint)badSector;
var badSectorToReRead = (uint)badSector;
if(_fixOffset &&
audioExtents.Contains(badSector) &&
@@ -256,7 +268,7 @@ partial class Dump
if(_supportsPlextorD8 && audioExtents.Contains(badSector))
{
sense = ReadPlextorWithSubchannel(out cmdBuf, out senseBuf, badSectorToReRead, blockSize,
sense = ReadPlextorWithSubchannel(out cmdBuf, out senseBuf, badSectorToReRead, blockSize,
sectorsToReRead, supportedPlextorSubchannel, out cmdDuration);
totalDuration += cmdDuration;
@@ -324,8 +336,10 @@ partial class Dump
// MEDIUM ERROR, retry with ignore error below
if(decSense is { ASC: 0x11 })
{
if(!sectorsNotEvenPartial.Contains(badSector))
sectorsNotEvenPartial.Add(badSector);
}
}
// Because one block has been partially used to fix the offset
@@ -336,7 +350,7 @@ partial class Dump
uint blocksToRead = sectorsToReRead;
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel, ref blocksToRead, subSize,
ref cmdBuf, blockSize, false);
ref cmdBuf, blockSize, false);
}
if(!sense &&
@@ -357,10 +371,10 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize];
byte[] sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
var data = new byte[sectorSize];
var sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
if(supportsLongSectors)
outputOptical.WriteSectorLong(data, badSector);
@@ -454,7 +468,7 @@ partial class Dump
InitProgress?.Invoke();
for(int i = 0; i < sectorsNotEvenPartial.Count; i++)
for(var i = 0; i < sectorsNotEvenPartial.Count; i++)
{
ulong badSector = sectorsNotEvenPartial[i];
@@ -492,10 +506,10 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize];
byte[] sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
var data = new byte[sectorSize];
var sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
if(supportsLongSectors)
outputOptical.WriteSectorLong(data, badSector);
@@ -532,10 +546,7 @@ partial class Dump
var md = new Modes.DecodedMode
{
Header = new Modes.ModeHeader(),
Pages = new[]
{
currentModePage.Value
}
Pages = new[] { currentModePage.Value }
};
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
@@ -568,7 +579,7 @@ partial class Dump
Dictionary<byte, string> isrcs, ref string mcn, HashSet<int> subchannelExtents,
Dictionary<byte, int> smallestPregapLbaPerTrack)
{
bool sense = true; // Sense indicator
var sense = true; // Sense indicator
byte[] cmdBuf = null; // Data buffer
double cmdDuration; // Command execution time
byte[] senseBuf = null; // Sense buffer
@@ -580,22 +591,22 @@ partial class Dump
return;
supportedPlextorSubchannel = supportedSubchannel switch
{
MmcSubchannel.Raw => PlextorSubchannel.All,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
MmcSubchannel.Rw => PlextorSubchannel.Pack,
_ => PlextorSubchannel.None
};
{
MmcSubchannel.Raw => PlextorSubchannel.All,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
MmcSubchannel.Rw => PlextorSubchannel.Pack,
_ => PlextorSubchannel.None
};
if(_aborted)
return;
int pass = 1;
bool forward = true;
var pass = 1;
var forward = true;
InitProgress?.Invoke();
cdRepeatRetry:
cdRepeatRetry:
_resume.BadSubchannels = new List<int>();
_resume.BadSubchannels.AddRange(subchannelExtents);
@@ -608,7 +619,7 @@ partial class Dump
foreach(int bs in tmpArray)
{
uint badSector = (uint)bs;
var badSector = (uint)bs;
Track track = tracks.OrderBy(t => t.StartSector).LastOrDefault(t => badSector >= t.StartSector);

View File

@@ -91,7 +91,7 @@ partial class Dump
{
byte[] cmdBuf = null; // Data buffer
const uint sectorSize = 2352; // Full sector size
bool sense = true; // Sense indicator
var sense = true; // Sense indicator
byte[] senseBuf = null;
var outputOptical = _outputPlugin as IWritableOpticalImage;
@@ -101,6 +101,7 @@ partial class Dump
InitProgress?.Invoke();
foreach((ulong item1, ulong item2) in leadOutExtents.ToArray())
{
for(ulong i = item1; i <= item2; i++)
{
if(_aborted)
@@ -133,14 +134,20 @@ partial class Dump
totalDuration += cmdDuration;
}
else if(read16)
{
sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, i, blockSize, 0, 1, false,
_dev.Timeout, out cmdDuration);
}
else if(read12)
{
sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize, 0,
1, false, _dev.Timeout, out cmdDuration);
}
else if(read10)
{
sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize, 0,
1, _dev.Timeout, out cmdDuration);
}
else if(read6)
sense = _dev.Read6(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, _dev.Timeout, out cmdDuration);
@@ -155,14 +162,14 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize * _maximumReadable];
byte[] sub = new byte[subSize * _maximumReadable];
var data = new byte[sectorSize * _maximumReadable];
var sub = new byte[subSize * _maximumReadable];
for(int b = 0; b < _maximumReadable; b++)
for(var b = 0; b < _maximumReadable; b++)
{
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize);
Array.Copy(cmdBuf, (int)(sectorSize + b * blockSize), sub, subSize * b, subSize);
}
outputOptical.WriteSectorsLong(data, i, _maximumReadable);
@@ -222,6 +229,7 @@ partial class Dump
_resume.NextBlock = i + 1;
}
}
EndProgress?.Invoke();
}
@@ -265,7 +273,7 @@ partial class Dump
{
byte[] cmdBuf = null; // Data buffer
const uint sectorSize = 2352; // Full sector size
bool sense = true; // Sense indicator
var sense = true; // Sense indicator
byte[] senseBuf = null;
var outputOptical = _outputPlugin as IWritableOpticalImage;
@@ -274,6 +282,7 @@ partial class Dump
InitProgress?.Invoke();
foreach((ulong item1, ulong item2) in leadOutExtents.ToArray())
{
for(ulong i = item1; i <= item2; i++)
{
if(_aborted)
@@ -306,14 +315,20 @@ partial class Dump
totalDuration += cmdDuration;
}
else if(read16)
{
sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, i, blockSize, 0, 1, false,
_dev.Timeout, out cmdDuration);
}
else if(read12)
{
sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize, 0,
1, false, _dev.Timeout, out cmdDuration);
}
else if(read10)
{
sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, blockSize, 0,
1, _dev.Timeout, out cmdDuration);
}
else if(read6)
sense = _dev.Read6(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, _dev.Timeout, out cmdDuration);
@@ -328,14 +343,14 @@ partial class Dump
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize * _maximumReadable];
byte[] sub = new byte[subSize * _maximumReadable];
var data = new byte[sectorSize * _maximumReadable];
var sub = new byte[subSize * _maximumReadable];
for(int b = 0; b < _maximumReadable; b++)
for(var b = 0; b < _maximumReadable; b++)
{
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize);
Array.Copy(cmdBuf, (int)(sectorSize + b * blockSize), sub, subSize * b, subSize);
}
outputOptical.WriteSectorsLong(data, i, _maximumReadable);
@@ -375,8 +390,10 @@ partial class Dump
outputOptical.WriteSectorsLong(new byte[sectorSize * _skip], i, 1);
if(desiredSubchannel != MmcSubchannel.None)
{
outputOptical.WriteSectorsTag(new byte[subSize * _skip], i, 1,
SectorTagType.CdSectorSubchannel);
}
}
else
outputOptical.WriteSectors(new byte[blockSize * _skip], i, 1);
@@ -394,6 +411,7 @@ partial class Dump
if(!double.IsInfinity(newSpeed))
currentSpeed = newSpeed;
}
}
EndProgress?.Invoke();
}

View File

@@ -58,20 +58,20 @@ partial class Dump
if(cmdBuf.Length == 0)
return;
int offsetFix = offsetBytes < 0 ? (int)((sectorSize * sectorsForOffset) + offsetBytes) : offsetBytes;
int offsetFix = offsetBytes < 0 ? (int)(sectorSize * sectorsForOffset + offsetBytes) : offsetBytes;
byte[] tmpBuf;
if(supportedSubchannel != MmcSubchannel.None)
{
// De-interleave subchannel
byte[] data = new byte[sectorSize * blocksToRead];
byte[] sub = new byte[subSize * blocksToRead];
var data = new byte[sectorSize * blocksToRead];
var sub = new byte[subSize * blocksToRead];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize);
Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, sectorSize * b, sectorSize);
Array.Copy(cmdBuf, (int)(sectorSize + b * blockSize), sub, subSize * b, subSize);
}
if(failedCrossingLeadOut)
@@ -95,10 +95,10 @@ partial class Dump
// Re-interleave subchannel
cmdBuf = new byte[blockSize * blocksToRead];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(data, sectorSize * b, cmdBuf, (int)(0 + (b * blockSize)), sectorSize);
Array.Copy(sub, subSize * b, cmdBuf, (int)(sectorSize + (b * blockSize)), subSize);
Array.Copy(data, sectorSize * b, cmdBuf, (int)(0 + b * blockSize), sectorSize);
Array.Copy(sub, subSize * b, cmdBuf, (int)(sectorSize + b * blockSize), subSize);
}
}
else

View File

@@ -46,8 +46,8 @@ partial class Dump
/// <param name="supportedPlextorSubchannel">Supported subchannel type</param>
/// <param name="cmdDuration">Time spent sending commands to the drive</param>
/// <returns><c>true</c> if an error occured, <c>false</c> otherwise</returns>
bool ReadPlextorWithSubchannel(out byte[] cmdBuf, out byte[] senseBuf, uint firstSectorToRead, uint blockSize,
uint blocksToRead, PlextorSubchannel supportedPlextorSubchannel,
bool ReadPlextorWithSubchannel(out byte[] cmdBuf, out byte[] senseBuf, uint firstSectorToRead, uint blockSize,
uint blocksToRead, PlextorSubchannel supportedPlextorSubchannel,
out double cmdDuration)
{
bool sense;
@@ -93,18 +93,19 @@ partial class Dump
return true;
sense = _dev.PlextorReadCdDa(out byte[] subBuf, out senseBuf, firstSectorToRead, subSize, blocksToRead,
supportedPlextorSubchannel == PlextorSubchannel.Pack ? PlextorSubchannel.All
supportedPlextorSubchannel == PlextorSubchannel.Pack
? PlextorSubchannel.All
: supportedPlextorSubchannel, 0, out cmdDuration);
if(sense)
return true;
cmdBuf = new byte[(2352 * blocksToRead) + (subSize * blocksToRead)];
cmdBuf = new byte[2352 * blocksToRead + subSize * blocksToRead];
for(int b = 0; b < blocksToRead; b++)
for(var b = 0; b < blocksToRead; b++)
{
Array.Copy(dataBuf, 2352 * b, cmdBuf, (2352 + subSize) * b, 2352);
Array.Copy(subBuf, subSize * b, cmdBuf, ((2352 + subSize) * b) + 2352, subSize);
Array.Copy(dataBuf, 2352 * b, cmdBuf, (2352 + subSize) * b, 2352);
Array.Copy(subBuf, subSize * b, cmdBuf, (2352 + subSize) * b + 2352, subSize);
}
return false;

View File

@@ -62,20 +62,21 @@ partial class Dump
void ReadCdFirstTrackPregap(uint blockSize, ref double currentSpeed, Dictionary<MediaTagType, byte[]> mediaTags,
MmcSubchannel supportedSubchannel, ref double totalDuration)
{
bool sense; // Sense indicator
byte[] cmdBuf; // Data buffer
double cmdDuration; // Command execution time
ulong sectorSpeedStart = 0; // Used to calculate correct speed
bool gotFirstTrackPregap = false;
int firstTrackPregapSectorsGood = 0;
var firstTrackPregapMs = new MemoryStream();
bool sense; // Sense indicator
byte[] cmdBuf; // Data buffer
double cmdDuration; // Command execution time
ulong sectorSpeedStart = 0; // Used to calculate correct speed
var gotFirstTrackPregap = false;
var firstTrackPregapSectorsGood = 0;
var firstTrackPregapMs = new MemoryStream();
_dumpLog.WriteLine(Localization.Core.Reading_first_track_pregap);
UpdateStatus?.Invoke(Localization.Core.Reading_first_track_pregap);
InitProgress?.Invoke();
_speedStopwatch.Restart();
for(int firstTrackPregapBlock = -150; firstTrackPregapBlock < 0 && _resume.NextBlock == 0;
for(int firstTrackPregapBlock = -150;
firstTrackPregapBlock < 0 && _resume.NextBlock == 0;
firstTrackPregapBlock++)
{
if(_aborted)
@@ -153,7 +154,7 @@ partial class Dump
bool supportsPqSubchannel, bool supportsRwSubchannel,
Database.Models.Device dbDev, out bool inexactPositioning, bool dumping)
{
bool sense = true; // Sense indicator
var sense = true; // Sense indicator
byte[] subBuf = null;
int posQ;
uint retries;
@@ -169,7 +170,8 @@ partial class Dump
// Check if subchannel is BCD
for(retries = 0; retries < 10; retries++)
{
sense = supportsRwSubchannel ? GetSectorForPregapRaw(dev, 11, dbDev, out subBuf, false)
sense = supportsRwSubchannel
? GetSectorForPregapRaw(dev, 11, dbDev, out subBuf, false)
: GetSectorForPregapQ16(dev, 11, out subBuf, false);
if(sense)
@@ -181,11 +183,11 @@ partial class Dump
}
AaruConsole.DebugWriteLine(PREGAP_MODULE_NAME, bcd switch
{
true => Localization.Core.Subchannel_is_BCD,
false => Localization.Core.Subchannel_is_not_BCD,
_ => Localization.Core.Could_not_detect_drive_subchannel_BCD
});
{
true => Localization.Core.Subchannel_is_BCD,
false => Localization.Core.Subchannel_is_not_BCD,
_ => Localization.Core.Could_not_detect_drive_subchannel_BCD
});
if(bcd is null)
{
@@ -202,10 +204,10 @@ partial class Dump
foreach(Track t in tracks)
pregaps[t.Sequence] = 0;
for(int t = 0; t < tracks.Length; t++)
for(var t = 0; t < tracks.Length; t++)
{
Track track = tracks[t];
int trackRetries = 0;
var trackRetries = 0;
// First track of each session has at least 150 sectors of pregap and is not always readable
if(tracks.Where(trk => trk.Session == track.Session).MinBy(trk => trk.Sequence).Sequence == track.Sequence)
@@ -239,14 +241,14 @@ partial class Dump
AaruConsole.DebugWriteLine(PREGAP_MODULE_NAME, Localization.Core.Track_0, track.Sequence);
int lba = (int)track.StartSector - 1;
bool pregapFound = false;
var pregapFound = false;
Track previousTrack = tracks.FirstOrDefault(trk => trk.Sequence == track.Sequence - 1);
bool goneBack = false;
bool goFront = false;
bool forward = false;
bool crcOk = false;
bool previousPregapIsPreviousTrack = false;
var goneBack = false;
var goFront = false;
var forward = false;
var crcOk = false;
var previousPregapIsPreviousTrack = false;
// Check if pregap is 0
for(retries = 0; retries < 10 && !pregapFound; retries++)
@@ -294,7 +296,7 @@ partial class Dump
subBuf[6] = 0;
// Fix BCD numbering
for(int i = 1; i < 10; i++)
for(var i = 1; i < 10; i++)
{
if((subBuf[i] & 0xF0) > 0xA0)
subBuf[i] &= 0x7F;
@@ -309,12 +311,14 @@ partial class Dump
crcOk = crc[0] == subBuf[10] && crc[1] == subBuf[11];
if(crcOk)
{
AaruConsole.DebugWriteLine(PREGAP_MODULE_NAME,
Localization.Core.
LBA_0_Try_1_Sense_2_Q_FIXED_3_4_5_6_7_8_9_10_11_12_CRC_13_14_Calculated_CRC_15_16,
lba, retries + 1, sense, subBuf[0], subBuf[1], subBuf[2], subBuf[3],
subBuf[4], subBuf[5], subBuf[6], subBuf[7], subBuf[8], subBuf[9],
subBuf[10], subBuf[11], crc[0], crc[1]);
}
else
continue;
}
@@ -325,7 +329,7 @@ partial class Dump
if((subBuf[0] & 0xF) != 1)
continue;
posQ = (subBuf[7] * 60 * 75) + (subBuf[8] * 75) + subBuf[9] - 150;
posQ = subBuf[7] * 60 * 75 + subBuf[8] * 75 + subBuf[9] - 150;
if(subBuf[1] != track.Sequence - 1 ||
subBuf[2] == 0 ||
@@ -348,10 +352,12 @@ partial class Dump
{
// Some drives crash if you try to read just before the previous read, so seek away first
if(!forward)
{
sense = supportsRwSubchannel
? GetSectorForPregapRaw(dev, (uint)lba - 10, dbDev, out subBuf,
track.Type == TrackType.Audio)
: GetSectorForPregapQ16(dev, (uint)lba - 10, out subBuf, track.Type == TrackType.Audio);
}
for(retries = 0; retries < 10; retries++)
{
@@ -394,7 +400,7 @@ partial class Dump
subBuf[6] = 0;
// Fix BCD numbering
for(int i = 1; i < 10; i++)
for(var i = 1; i < 10; i++)
{
if((subBuf[i] & 0xF0) > 0xA0)
subBuf[i] &= 0x7F;
@@ -435,8 +441,8 @@ partial class Dump
{
if(pregaps[track.Sequence] == 0)
{
if((previousTrack.Type == TrackType.Audio && track.Type != TrackType.Audio) ||
(previousTrack.Type != TrackType.Audio && track.Type == TrackType.Audio))
if(previousTrack.Type == TrackType.Audio && track.Type != TrackType.Audio ||
previousTrack.Type != TrackType.Audio && track.Type == TrackType.Audio)
{
dumpLog?.WriteLine(Localization.Core.
Could_not_read_subchannel_for_this_track_supposing_hundred_fifty_sectors);
@@ -457,13 +463,17 @@ partial class Dump
{
dumpLog?.
WriteLine(string.
Format(Localization.Core.Could_not_read_subchannel_for_this_track_supposing_0_sectors,
pregaps[track.Sequence]));
Format(
Localization.Core.
Could_not_read_subchannel_for_this_track_supposing_0_sectors,
pregaps[track.Sequence]));
updateStatus?.
Invoke(string.
Format(Localization.Core.Could_not_read_subchannel_for_this_track_supposing_0_sectors,
pregaps[track.Sequence]));
Format(
Localization.Core.
Could_not_read_subchannel_for_this_track_supposing_0_sectors,
pregaps[track.Sequence]));
}
break;
@@ -552,7 +562,7 @@ partial class Dump
previousPregapIsPreviousTrack = false;
// Pregap according to Q position
posQ = (subBuf[7] * 60 * 75) + (subBuf[8] * 75) + subBuf[9] - 150;
posQ = subBuf[7] * 60 * 75 + subBuf[8] * 75 + subBuf[9] - 150;
int diff = posQ - lba;
int pregapQ = (int)track.StartSector - lba;
@@ -614,7 +624,7 @@ partial class Dump
if(dumping)
{
// Minus five, to ensure dumping will fix if there is a pregap LBA 0
int red = 5;
var red = 5;
while(trk.Pregap > 0 &&
red > 0)
@@ -643,7 +653,7 @@ partial class Dump
/// <param name="audioTrack">Set if it is an audio track</param>
/// <returns><c>true</c> if read correctly, <c>false</c> otherwise</returns>
static bool GetSectorForPregapRaw(Device dev, uint lba, Database.Models.Device dbDev, out byte[] subBuf,
bool audioTrack)
bool audioTrack)
{
byte[] cmdBuf;
bool sense;
@@ -656,9 +666,11 @@ partial class Dump
out _);
if(sense)
{
sense = dev.ReadCd(out cmdBuf, out _, lba, 2448, 1, MmcSectorTypes.AllTypes, false, false, true,
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Raw,
dev.Timeout, out _);
}
}
else
{
@@ -667,14 +679,16 @@ partial class Dump
dev.Timeout, out _);
if(sense)
{
sense = dev.ReadCd(out cmdBuf, out _, lba, 2448, 1, MmcSectorTypes.Cdda, false, false, false,
MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout,
out _);
}
}
if(!sense)
{
byte[] tmpBuf = new byte[96];
var tmpBuf = new byte[96];
Array.Copy(cmdBuf, 2352, tmpBuf, 0, 96);
subBuf = DeinterleaveQ(tmpBuf);
}
@@ -685,9 +699,11 @@ partial class Dump
out _);
if(sense)
{
sense = dev.ReadCd(out cmdBuf, out _, lba, 96, 1, MmcSectorTypes.Cdda, false, false, false,
MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Raw,
dev.Timeout, out _);
}
if(!sense)
subBuf = DeinterleaveQ(cmdBuf);
@@ -724,9 +740,11 @@ partial class Dump
out _);
if(sense)
{
sense = dev.ReadCd(out cmdBuf, out _, lba, 2368, 1, MmcSectorTypes.AllTypes, false, false, true,
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16,
dev.Timeout, out _);
}
}
else
{
@@ -735,9 +753,11 @@ partial class Dump
dev.Timeout, out _);
if(sense)
{
sense = dev.ReadCd(out cmdBuf, out _, lba, 2368, 1, MmcSectorTypes.Cdda, false, false, false,
MmcHeaderCodes.None, true, false, MmcErrorField.None, MmcSubchannel.Q16, dev.Timeout,
out _);
}
}
if(!sense)
@@ -752,9 +772,11 @@ partial class Dump
out _);
if(sense)
{
sense = dev.ReadCd(out cmdBuf, out _, lba, 16, 1, MmcSectorTypes.Cdda, false, false, false,
MmcHeaderCodes.None, false, false, MmcErrorField.None, MmcSubchannel.Q16,
dev.Timeout, out _);
}
if(!sense)
subBuf = cmdBuf;
@@ -768,10 +790,10 @@ partial class Dump
/// <returns>De-interleaved Q subchannel</returns>
static byte[] DeinterleaveQ(byte[] subchannel)
{
int[] q = new int[subchannel.Length / 8];
var q = new int[subchannel.Length / 8];
// De-interlace Q subchannel
for(int iq = 0; iq < subchannel.Length; iq += 8)
for(var iq = 0; iq < subchannel.Length; iq += 8)
{
q[iq / 8] = (subchannel[iq] & 0x40) << 1;
q[iq / 8] += subchannel[iq + 1] & 0x40;
@@ -783,9 +805,9 @@ partial class Dump
q[iq / 8] += (subchannel[iq + 7] & 0x40) >> 6;
}
byte[] deQ = new byte[q.Length];
var deQ = new byte[q.Length];
for(int iq = 0; iq < q.Length; iq++)
for(var iq = 0; iq < q.Length; iq++)
deQ[iq] = (byte)q[iq];
return deQ;
@@ -795,29 +817,29 @@ partial class Dump
/// <param name="q">Q subchannel</param>
static void BinaryToBcdQ(byte[] q)
{
q[1] = (byte)(((q[1] / 10) << 4) + (q[1] % 10));
q[2] = (byte)(((q[2] / 10) << 4) + (q[2] % 10));
q[3] = (byte)(((q[3] / 10) << 4) + (q[3] % 10));
q[4] = (byte)(((q[4] / 10) << 4) + (q[4] % 10));
q[5] = (byte)(((q[5] / 10) << 4) + (q[5] % 10));
q[6] = (byte)(((q[6] / 10) << 4) + (q[6] % 10));
q[7] = (byte)(((q[7] / 10) << 4) + (q[7] % 10));
q[8] = (byte)(((q[8] / 10) << 4) + (q[8] % 10));
q[9] = (byte)(((q[9] / 10) << 4) + (q[9] % 10));
q[1] = (byte)((q[1] / 10 << 4) + q[1] % 10);
q[2] = (byte)((q[2] / 10 << 4) + q[2] % 10);
q[3] = (byte)((q[3] / 10 << 4) + q[3] % 10);
q[4] = (byte)((q[4] / 10 << 4) + q[4] % 10);
q[5] = (byte)((q[5] / 10 << 4) + q[5] % 10);
q[6] = (byte)((q[6] / 10 << 4) + q[6] % 10);
q[7] = (byte)((q[7] / 10 << 4) + q[7] % 10);
q[8] = (byte)((q[8] / 10 << 4) + q[8] % 10);
q[9] = (byte)((q[9] / 10 << 4) + q[9] % 10);
}
/// <summary>In place converts Q subchannel from BCD to binary numbering</summary>
/// <param name="q">Q subchannel</param>
static void BcdToBinaryQ(byte[] q)
{
q[1] = (byte)((q[1] / 16 * 10) + (q[1] & 0x0F));
q[2] = (byte)((q[2] / 16 * 10) + (q[2] & 0x0F));
q[3] = (byte)((q[3] / 16 * 10) + (q[3] & 0x0F));
q[4] = (byte)((q[4] / 16 * 10) + (q[4] & 0x0F));
q[5] = (byte)((q[5] / 16 * 10) + (q[5] & 0x0F));
q[6] = (byte)((q[6] / 16 * 10) + (q[6] & 0x0F));
q[7] = (byte)((q[7] / 16 * 10) + (q[7] & 0x0F));
q[8] = (byte)((q[8] / 16 * 10) + (q[8] & 0x0F));
q[9] = (byte)((q[9] / 16 * 10) + (q[9] & 0x0F));
q[1] = (byte)(q[1] / 16 * 10 + (q[1] & 0x0F));
q[2] = (byte)(q[2] / 16 * 10 + (q[2] & 0x0F));
q[3] = (byte)(q[3] / 16 * 10 + (q[3] & 0x0F));
q[4] = (byte)(q[4] / 16 * 10 + (q[4] & 0x0F));
q[5] = (byte)(q[5] / 16 * 10 + (q[5] & 0x0F));
q[6] = (byte)(q[6] / 16 * 10 + (q[6] & 0x0F));
q[7] = (byte)(q[7] / 16 * 10 + (q[7] & 0x0F));
q[8] = (byte)(q[8] / 16 * 10 + (q[8] & 0x0F));
q[9] = (byte)(q[9] / 16 * 10 + (q[9] & 0x0F));
}
}

View File

@@ -55,10 +55,12 @@ partial class Dump
// Count how many run end sectors are detected as bad blocks
for(ulong i = blocks - 1; i > blocks - 1 - _ignoreCdrRunOuts; i--)
{
if(_resume.BadBlocks.Contains(i))
runOutSectors.Add(i);
else
break;
}
if(runOutSectors.Count == 0)
return;
@@ -76,20 +78,26 @@ partial class Dump
if(track is null)
continue;
byte[] sector = new byte[2352];
var sector = new byte[2352];
switch(track.Type)
{
case TrackType.Audio: break;
case TrackType.Audio:
break;
case TrackType.Data:
sector = new byte[2048];
break;
case TrackType.CdMode1: break;
case TrackType.CdMode2Formless: break;
case TrackType.CdMode2Form1: break;
case TrackType.CdMode2Form2: break;
default: continue;
case TrackType.CdMode1:
break;
case TrackType.CdMode2Formless:
break;
case TrackType.CdMode2Form1:
break;
case TrackType.CdMode2Form2:
break;
default:
continue;
}
if(track.Type != TrackType.Audio &&

View File

@@ -52,7 +52,7 @@ partial class Dump
/// <param name="sessions">Sessions</param>
/// <param name="firstTrackLastSession">First track in last session</param>
void ReadCdTags(ref MediaType mediaType, Dictionary<MediaTagType, byte[]> mediaTags, out int sessions,
out int firstTrackLastSession)
out int firstTrackLastSession)
{
byte[] cmdBuf; // Data buffer
bool sense; // Sense indicator
@@ -93,12 +93,14 @@ partial class Dump
if(discInfo.HasValue &&
mediaType == MediaType.CD)
{
mediaType = discInfo.Value.DiscType switch
{
0x10 => MediaType.CDI,
0x20 => MediaType.CDROMXA,
_ => mediaType
};
{
0x10 => MediaType.CDI,
0x20 => MediaType.CDROMXA,
_ => mediaType
};
}
}
_dumpLog.WriteLine(Localization.Core.Reading_PMA);

View File

@@ -60,9 +60,9 @@ partial class Dump
/// <param name="trackFlags">Track flags</param>
/// <param name="updateStatus">Update status handler</param>
/// <returns>List of tracks</returns>
public static Track[] GetCdTracks(Device dev, DumpLog dumpLog, bool force, out long lastSector,
Dictionary<int, long> leadOutStarts, Dictionary<MediaTagType, byte[]> mediaTags,
ErrorMessageHandler stoppingErrorMessage, out FullTOC.CDFullTOC? toc,
public static Track[] GetCdTracks(Device dev, DumpLog dumpLog, bool force, out long lastSector,
Dictionary<int, long> leadOutStarts, Dictionary<MediaTagType, byte[]> mediaTags,
ErrorMessageHandler stoppingErrorMessage, out FullTOC.CDFullTOC? toc,
Dictionary<byte, byte> trackFlags, UpdateStatusHandler updateStatus)
{
byte[] cmdBuf; // Data buffer
@@ -101,6 +101,7 @@ partial class Dump
toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray();
foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => trk.ADR is 1 or 4))
{
switch(trk.POINT)
{
case >= 0x01 and <= 0x63:
@@ -109,10 +110,11 @@ partial class Dump
Sequence = trk.POINT,
Session = trk.SessionNumber,
Type = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental
? TrackType.Data
: TrackType.Audio,
StartSector =
(ulong)((trk.PHOUR * 3600 * 75) + (trk.PMIN * 60 * 75) + (trk.PSEC * 75) + trk.PFRAME -
(ulong)(trk.PHOUR * 3600 * 75 + trk.PMIN * 60 * 75 + trk.PSEC * 75 + trk.PFRAME -
150),
BytesPerSector = (int)sectorSize,
RawBytesPerSector = (int)sectorSize
@@ -159,7 +161,7 @@ partial class Dump
phour = trk.PHOUR;
}
lastSector = (phour * 3600 * 75) + (pmin * 60 * 75) + (psec * 75) + pframe - 150;
lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150;
leadOutStarts?.Add(trk.SessionNumber, lastSector + 1);
break;
@@ -167,11 +169,13 @@ partial class Dump
case 0xA0 when trk.ADR == 1:
leadoutTrackType =
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental
? TrackType.Data
: TrackType.Audio;
break;
}
}
}
else
{
@@ -194,8 +198,10 @@ partial class Dump
}
if(oldToc.HasValue)
{
foreach(TOC.CDTOCTrackDataDescriptor trk in oldToc.Value.TrackDescriptors.OrderBy(t => t.TrackNumber).
Where(trk => trk.ADR is 1 or 4))
{
switch(trk.TrackNumber)
{
case >= 0x01 and <= 0x63:
@@ -205,7 +211,8 @@ partial class Dump
Session = 1,
Type = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental
? TrackType.Data : TrackType.Audio,
? TrackType.Data
: TrackType.Audio,
StartSector = trk.TrackStartAddress,
BytesPerSector = (int)sectorSize,
RawBytesPerSector = (int)sectorSize
@@ -217,13 +224,16 @@ partial class Dump
case 0xAA:
leadoutTrackType =
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental
? TrackType.Data
: TrackType.Audio;
lastSector = trk.TrackStartAddress - 1;
break;
}
}
}
}
if(trackList.Count == 0)
@@ -251,7 +261,7 @@ partial class Dump
if(!sense)
{
byte[] temp = new byte[8];
var temp = new byte[8];
Array.Copy(cmdBuf, 0, temp, 0, 8);
Array.Reverse(temp);
@@ -262,7 +272,7 @@ partial class Dump
sense = dev.ReadCapacity(out cmdBuf, out _, dev.Timeout, out _);
if(!sense)
lastSector = ((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]) & 0xFFFFFFFF;
lastSector = (cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3] & 0xFFFFFFFF;
}
if(lastSector > 0)

View File

@@ -83,7 +83,7 @@ partial class Dump
Dictionary<byte, string> isrcs, ref string mcn, HashSet<int> subchannelExtents,
Dictionary<byte, int> smallestPregapLbaPerTrack)
{
bool sense = true; // Sense indicator
var sense = true; // Sense indicator
byte[] cmdBuf = null; // Data buffer
double cmdDuration = 0; // Command execution time
const uint sectorSize = 2352; // Full sector size
@@ -92,12 +92,12 @@ partial class Dump
var outputOptical = _outputPlugin as IWritableOpticalImage;
supportedPlextorSubchannel = supportedSubchannel switch
{
MmcSubchannel.None => PlextorSubchannel.None,
MmcSubchannel.Raw => PlextorSubchannel.Pack,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
_ => PlextorSubchannel.None
};
{
MmcSubchannel.None => PlextorSubchannel.None,
MmcSubchannel.Raw => PlextorSubchannel.Pack,
MmcSubchannel.Q16 => PlextorSubchannel.Q16,
_ => PlextorSubchannel.None
};
if(_resume.BadBlocks.Count <= 0 ||
_aborted ||
@@ -110,10 +110,10 @@ partial class Dump
InitProgress?.Invoke();
_trimStopwatch.Restart();
trimStart:
trimStart:
ulong[] tmpArray = _resume.BadBlocks.ToArray();
for(int b = 0; b < tmpArray.Length; b++)
for(var b = 0; b < tmpArray.Length; b++)
{
ulong badSector = tmpArray[b];
@@ -131,7 +131,7 @@ partial class Dump
Track track = tracks.OrderBy(t => t.StartSector).LastOrDefault(t => badSector >= t.StartSector);
byte sectorsToTrim = 1;
uint badSectorToRead = (uint)badSector;
var badSectorToRead = (uint)badSector;
if(_fixOffset &&
audioExtents.Contains(badSector) &&
@@ -149,8 +149,10 @@ partial class Dump
}
if(_supportsPlextorD8 && audioExtents.Contains(badSector))
{
sense = ReadPlextorWithSubchannel(out cmdBuf, out senseBuf, badSectorToRead, blockSize, sectorsToTrim,
supportedPlextorSubchannel, out cmdDuration);
}
else if(readcd)
{
if(audioExtents.Contains(badSector))
@@ -202,17 +204,25 @@ partial class Dump
totalDuration += cmdDuration;
}
else if(read16)
{
sense = _dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, badSectorToRead, blockSize, 0,
sectorsToTrim, false, _dev.Timeout, out cmdDuration);
}
else if(read12)
{
sense = _dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, badSectorToRead, blockSize,
0, sectorsToTrim, false, _dev.Timeout, out cmdDuration);
}
else if(read10)
{
sense = _dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, badSectorToRead, blockSize,
0, sectorsToTrim, _dev.Timeout, out cmdDuration);
}
else if(read6)
{
sense = _dev.Read6(out cmdBuf, out senseBuf, badSectorToRead, blockSize, sectorsToTrim, _dev.Timeout,
out cmdDuration);
}
totalDuration += cmdDuration;
@@ -239,15 +249,15 @@ partial class Dump
uint blocksToRead = sectorsToTrim;
FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel, ref blocksToRead, subSize,
ref cmdBuf, blockSize, false);
ref cmdBuf, blockSize, false);
}
if(supportedSubchannel != MmcSubchannel.None)
{
byte[] data = new byte[sectorSize];
byte[] sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
var data = new byte[sectorSize];
var sub = new byte[subSize];
Array.Copy(cmdBuf, 0, data, 0, sectorSize);
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
if(supportsLongSectors)
outputOptical.WriteSectorLong(data, badSector);