mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Convert if to switch statement.
This commit is contained in:
Submodule Aaru.Checksums updated: a9af82e47f...55fb8416e8
Submodule Aaru.CommonTypes updated: 106a911f1c...ee657ecfa5
@@ -233,31 +233,36 @@ partial class Dump
|
||||
blocksToRead += (uint)sectorsForOffset;
|
||||
}
|
||||
|
||||
if(!inData &&
|
||||
currentReadSpeed == 0xFFFF)
|
||||
switch(inData)
|
||||
{
|
||||
_dumpLog.WriteLine("Setting speed to 8x for audio reading.");
|
||||
UpdateStatus?.Invoke("Setting speed to 8x for audio reading.");
|
||||
case false when currentReadSpeed == 0xFFFF:
|
||||
_dumpLog.WriteLine("Setting speed to 8x for audio reading.");
|
||||
UpdateStatus?.Invoke("Setting speed to 8x for audio reading.");
|
||||
|
||||
_dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, 1416, 0, _dev.Timeout, out _);
|
||||
_dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, 1416, 0, _dev.Timeout, out _);
|
||||
|
||||
currentReadSpeed = 1200;
|
||||
}
|
||||
currentReadSpeed = 1200;
|
||||
|
||||
if(inData && currentReadSpeed != _speed)
|
||||
{
|
||||
_dumpLog.WriteLine($"Setting speed to {(_speed == 0xFFFF ? "MAX for data reading" : $"{_speed}x")}.");
|
||||
break;
|
||||
case true when currentReadSpeed != _speed:
|
||||
{
|
||||
_dumpLog.WriteLine($"Setting speed to {(_speed == 0xFFFF ? "MAX for data reading" : $"{_speed}x")
|
||||
}.");
|
||||
|
||||
UpdateStatus?.Invoke($"Setting speed to {(_speed == 0xFFFF ? "MAX for data reading" : $"{_speed}x")}.");
|
||||
UpdateStatus?.Invoke($"Setting speed to {(_speed == 0xFFFF ? "MAX for data reading" : $"{_speed}x")
|
||||
}.");
|
||||
|
||||
_speed *= _speedMultiplier;
|
||||
_speed *= _speedMultiplier;
|
||||
|
||||
if(_speed is 0 or > 0xFFFF)
|
||||
_speed = 0xFFFF;
|
||||
if(_speed is 0 or > 0xFFFF)
|
||||
_speed = 0xFFFF;
|
||||
|
||||
currentReadSpeed = _speed;
|
||||
currentReadSpeed = _speed;
|
||||
|
||||
_dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, (ushort)_speed, 0, _dev.Timeout, out _);
|
||||
_dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, (ushort)_speed, 0, _dev.Timeout, out _);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(inData && crossingLeadOut)
|
||||
|
||||
@@ -277,21 +277,18 @@ sealed partial class Dump
|
||||
read16 = !_dev.Read16(out cmdBuf, out _, 0, false, true, false, firstLba, 2048, 0, 1, false,
|
||||
_dev.Timeout, out _);
|
||||
|
||||
if(!read6 &&
|
||||
!read10 &&
|
||||
!read12 &&
|
||||
!read16)
|
||||
switch(read6)
|
||||
{
|
||||
_dumpLog.WriteLine("Cannot read from disc, not continuing...");
|
||||
StoppingErrorMessage?.Invoke("Cannot read from disc, not continuing...");
|
||||
case false when !read10 && !read12 && !read16:
|
||||
_dumpLog.WriteLine("Cannot read from disc, not continuing...");
|
||||
StoppingErrorMessage?.Invoke("Cannot read from disc, not continuing...");
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case true:
|
||||
_dumpLog.WriteLine("Drive supports READ(6)...");
|
||||
UpdateStatus?.Invoke("Drive supports READ(6)...");
|
||||
|
||||
if(read6)
|
||||
{
|
||||
_dumpLog.WriteLine("Drive supports READ(6)...");
|
||||
UpdateStatus?.Invoke("Drive supports READ(6)...");
|
||||
break;
|
||||
}
|
||||
|
||||
if(read10)
|
||||
@@ -344,8 +341,8 @@ sealed partial class Dump
|
||||
default:
|
||||
_dumpLog.WriteLine("Handling subchannel type {0} not supported, exiting...", supportedSubchannel);
|
||||
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Handling subchannel type {supportedSubchannel} not supported, exiting...");
|
||||
StoppingErrorMessage?.Invoke($"Handling subchannel type {supportedSubchannel
|
||||
} not supported, exiting...");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -964,8 +961,8 @@ sealed partial class Dump
|
||||
|
||||
#if DEBUG
|
||||
foreach(Track trk in tracks)
|
||||
UpdateStatus?.
|
||||
Invoke($"Track {trk.Sequence} starts at LBA {trk.StartSector} and ends at LBA {trk.EndSector}");
|
||||
UpdateStatus?.Invoke($"Track {trk.Sequence} starts at LBA {trk.StartSector} and ends at LBA {trk.EndSector
|
||||
}");
|
||||
#endif
|
||||
|
||||
// Check offset
|
||||
@@ -1058,10 +1055,12 @@ sealed partial class Dump
|
||||
{
|
||||
_dumpLog.WriteLine("Drive reading offset not found in database.");
|
||||
UpdateStatus?.Invoke("Drive reading offset not found in database.");
|
||||
_dumpLog.WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4} samples).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4} samples).");
|
||||
_dumpLog.WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4
|
||||
} samples).");
|
||||
|
||||
UpdateStatus?.Invoke($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4
|
||||
} samples).");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1165,18 +1164,18 @@ sealed partial class Dump
|
||||
_dumpLog.WriteLine("Drive reading offset not found in database.");
|
||||
UpdateStatus?.Invoke("Drive reading offset not found in database.");
|
||||
|
||||
_dumpLog.
|
||||
WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4} samples).");
|
||||
_dumpLog.WriteLine($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4
|
||||
} samples).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4} samples).");
|
||||
UpdateStatus?.Invoke($"Combined disc and drive offsets are {offsetBytes} bytes ({offsetBytes / 4
|
||||
} samples).");
|
||||
}
|
||||
else
|
||||
{
|
||||
_dumpLog.WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
|
||||
UpdateStatus?.Invoke($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4
|
||||
} samples).");
|
||||
|
||||
discOffset = offsetBytes - driveOffset;
|
||||
|
||||
@@ -1224,11 +1223,11 @@ sealed partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -1384,11 +1383,12 @@ sealed partial class Dump
|
||||
end = DateTime.UtcNow;
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - dumpStart).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - dumpStart).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -101,71 +101,76 @@ 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))
|
||||
if(trk.POINT >= 0x01 &&
|
||||
trk.POINT <= 0x63)
|
||||
switch(trk.POINT)
|
||||
{
|
||||
trackList.Add(new Track
|
||||
{
|
||||
Sequence = trk.POINT,
|
||||
Session = trk.SessionNumber,
|
||||
Type = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(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 - 150),
|
||||
BytesPerSector = (int)sectorSize,
|
||||
RawBytesPerSector = (int)sectorSize
|
||||
});
|
||||
|
||||
trackFlags?.Add(trk.POINT, trk.CONTROL);
|
||||
}
|
||||
else if(trk.POINT == 0xA2)
|
||||
{
|
||||
int phour, pmin, psec, pframe;
|
||||
|
||||
if(trk.PFRAME == 0)
|
||||
{
|
||||
pframe = 74;
|
||||
|
||||
if(trk.PSEC == 0)
|
||||
case >= 0x01 and <= 0x63:
|
||||
trackList.Add(new Track
|
||||
{
|
||||
psec = 59;
|
||||
Sequence = trk.POINT,
|
||||
Session = trk.SessionNumber,
|
||||
Type = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(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 - 150),
|
||||
BytesPerSector = (int)sectorSize,
|
||||
RawBytesPerSector = (int)sectorSize
|
||||
});
|
||||
|
||||
if(trk.PMIN == 0)
|
||||
trackFlags?.Add(trk.POINT, trk.CONTROL);
|
||||
|
||||
break;
|
||||
case 0xA2:
|
||||
{
|
||||
int phour, pmin, psec, pframe;
|
||||
|
||||
if(trk.PFRAME == 0)
|
||||
{
|
||||
pframe = 74;
|
||||
|
||||
if(trk.PSEC == 0)
|
||||
{
|
||||
pmin = 59;
|
||||
phour = trk.PHOUR - 1;
|
||||
psec = 59;
|
||||
|
||||
if(trk.PMIN == 0)
|
||||
{
|
||||
pmin = 59;
|
||||
phour = trk.PHOUR - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pmin = trk.PMIN - 1;
|
||||
phour = trk.PHOUR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pmin = trk.PMIN - 1;
|
||||
psec = trk.PSEC - 1;
|
||||
pmin = trk.PMIN;
|
||||
phour = trk.PHOUR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
psec = trk.PSEC - 1;
|
||||
pmin = trk.PMIN;
|
||||
phour = trk.PHOUR;
|
||||
pframe = trk.PFRAME - 1;
|
||||
psec = trk.PSEC;
|
||||
pmin = trk.PMIN;
|
||||
phour = trk.PHOUR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pframe = trk.PFRAME - 1;
|
||||
psec = trk.PSEC;
|
||||
pmin = trk.PMIN;
|
||||
phour = trk.PHOUR;
|
||||
}
|
||||
|
||||
lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150;
|
||||
leadOutStarts?.Add(trk.SessionNumber, lastSector + 1);
|
||||
lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150;
|
||||
leadOutStarts?.Add(trk.SessionNumber, lastSector + 1);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0xA0 when trk.ADR == 1:
|
||||
leadoutTrackType =
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
|
||||
: TrackType.Audio;
|
||||
|
||||
break;
|
||||
}
|
||||
else if(trk.POINT == 0xA0 &&
|
||||
trk.ADR == 1)
|
||||
leadoutTrackType =
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
|
||||
: TrackType.Audio;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -189,31 +194,33 @@ 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))
|
||||
if(trk.TrackNumber >= 0x01 &&
|
||||
trk.TrackNumber <= 0x63)
|
||||
switch(trk.TrackNumber)
|
||||
{
|
||||
trackList.Add(new Track
|
||||
{
|
||||
Sequence = trk.TrackNumber,
|
||||
Session = 1,
|
||||
Type = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
|
||||
: TrackType.Audio,
|
||||
StartSector = trk.TrackStartAddress,
|
||||
BytesPerSector = (int)sectorSize,
|
||||
RawBytesPerSector = (int)sectorSize
|
||||
});
|
||||
case >= 0x01 and <= 0x63:
|
||||
trackList.Add(new Track
|
||||
{
|
||||
Sequence = trk.TrackNumber,
|
||||
Session = 1,
|
||||
Type = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental
|
||||
? TrackType.Data : TrackType.Audio,
|
||||
StartSector = trk.TrackStartAddress,
|
||||
BytesPerSector = (int)sectorSize,
|
||||
RawBytesPerSector = (int)sectorSize
|
||||
});
|
||||
|
||||
trackFlags?.Add(trk.TrackNumber, trk.CONTROL);
|
||||
}
|
||||
else if(trk.TrackNumber == 0xAA)
|
||||
{
|
||||
leadoutTrackType =
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
|
||||
: TrackType.Audio;
|
||||
trackFlags?.Add(trk.TrackNumber, trk.CONTROL);
|
||||
|
||||
lastSector = trk.TrackStartAddress - 1;
|
||||
break;
|
||||
case 0xAA:
|
||||
leadoutTrackType =
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data
|
||||
: TrackType.Audio;
|
||||
|
||||
lastSector = trk.TrackStartAddress - 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,14 +244,25 @@ public partial class Dump
|
||||
uint romSectors = romSize / 512;
|
||||
uint romRemaining = romSize % 512;
|
||||
|
||||
if(romSize > 1073741824)
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes ({romSize / 1073741824d:F3} GiB)");
|
||||
else if(romSize > 1048576)
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes ({romSize / 1048576d:F3} MiB)");
|
||||
else if(romSize > 1024)
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes ({romSize / 1024d:F3} KiB)");
|
||||
else
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes");
|
||||
switch(romSize)
|
||||
{
|
||||
case > 1073741824:
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes ({romSize / 1073741824d:F3} GiB)");
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes ({romSize / 1048576d:F3} MiB)");
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes ({romSize / 1024d:F3} KiB)");
|
||||
|
||||
break;
|
||||
default:
|
||||
UpdateStatus?.Invoke($"Cartridge has {romSize} bytes");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke($"Media identified as {mediaType}.");
|
||||
_dumpLog.WriteLine("Media identified as {0}.", mediaType);
|
||||
@@ -380,11 +391,11 @@ public partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {512 * (double)(romSectors + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {512 * (double)(romSectors + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {512 * (double)(romSectors + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {512 * (double)(romSectors + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -433,11 +444,12 @@ public partial class Dump
|
||||
*/
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {512 * (double)(romSectors + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {512 * (double)(romSectors + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
// Copyright © 2011-2022 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
|
||||
|
||||
// ReSharper disable JoinDeclarationAndInitializer
|
||||
|
||||
namespace Aaru.Core.Devices.Dumping;
|
||||
@@ -127,21 +125,34 @@ partial class Dump
|
||||
|
||||
ulong totalSize = blocks * blockSize;
|
||||
|
||||
if(totalSize > 1099511627776)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)");
|
||||
else if(totalSize > 1073741824)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)");
|
||||
else if(totalSize > 1048576)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)");
|
||||
else if(totalSize > 1024)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)");
|
||||
else
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize} bytes)");
|
||||
switch(totalSize)
|
||||
{
|
||||
case > 1099511627776:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1099511627776d:F3} TiB)");
|
||||
|
||||
break;
|
||||
case > 1073741824:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1073741824d:F3} GiB)");
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1048576d:F3} MiB)");
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1024d:F3} KiB)");
|
||||
|
||||
break;
|
||||
default:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize} bytes)");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check how many blocks to read, if error show and return
|
||||
@@ -267,45 +278,52 @@ partial class Dump
|
||||
var setGeometry = false;
|
||||
|
||||
foreach(Modes.ModePage page in decMode.Value.Pages)
|
||||
if(page.Page == 0x04 &&
|
||||
page.Subpage == 0x00)
|
||||
switch(page.Page)
|
||||
{
|
||||
Modes.ModePage_04? rigidPage = Modes.DecodeModePage_04(page.PageResponse);
|
||||
case 0x04 when page.Subpage == 0x00:
|
||||
{
|
||||
Modes.ModePage_04? rigidPage = Modes.DecodeModePage_04(page.PageResponse);
|
||||
|
||||
if(!rigidPage.HasValue || setGeometry)
|
||||
continue;
|
||||
if(!rigidPage.HasValue || setGeometry)
|
||||
continue;
|
||||
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Setting geometry to {rigidPage.Value.Cylinders} cylinders, {rigidPage.Value.Heads} heads, {(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads))} sectors per track");
|
||||
UpdateStatus?.Invoke($"Setting geometry to {rigidPage.Value.Cylinders} cylinders, {
|
||||
rigidPage.Value.Heads} heads, {
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads))
|
||||
} sectors per track");
|
||||
|
||||
outputFormat.SetGeometry(rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
outputFormat.SetGeometry(rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
|
||||
setGeometry = true;
|
||||
}
|
||||
else if(page.Page == 0x05 &&
|
||||
page.Subpage == 0x00)
|
||||
{
|
||||
Modes.ModePage_05? flexiblePage = Modes.DecodeModePage_05(page.PageResponse);
|
||||
setGeometry = true;
|
||||
|
||||
if(!flexiblePage.HasValue)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case 0x05 when page.Subpage == 0x00:
|
||||
{
|
||||
Modes.ModePage_05? flexiblePage = Modes.DecodeModePage_05(page.PageResponse);
|
||||
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
if(!flexiblePage.HasValue)
|
||||
continue;
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Setting geometry to {flexiblePage.Value.Cylinders} cylinders, {flexiblePage.Value.Heads} heads, {flexiblePage.Value.SectorsPerTrack} sectors per track");
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
|
||||
outputFormat.SetGeometry(flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
UpdateStatus?.Invoke($"Setting geometry to {flexiblePage.Value.Cylinders} cylinders, {
|
||||
flexiblePage.Value.Heads} heads, {flexiblePage.Value.SectorsPerTrack} sectors per track");
|
||||
|
||||
setGeometry = true;
|
||||
outputFormat.SetGeometry(flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
|
||||
setGeometry = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,11 +442,11 @@ partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -727,8 +745,8 @@ partial class Dump
|
||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average checksum speed {blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average checksum speed {
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
||||
|
||||
@@ -801,11 +819,12 @@ partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -94,21 +94,34 @@ public partial class Dump
|
||||
|
||||
ulong totalSize = blocks * (ulong)blockSize;
|
||||
|
||||
if(totalSize > 1099511627776)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)");
|
||||
else if(totalSize > 1073741824)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)");
|
||||
else if(totalSize > 1048576)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)");
|
||||
else if(totalSize > 1024)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)");
|
||||
else
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize} bytes)");
|
||||
switch(totalSize)
|
||||
{
|
||||
case > 1099511627776:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1099511627776d:F3} TiB)");
|
||||
|
||||
break;
|
||||
case > 1073741824:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1073741824d:F3} GiB)");
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1048576d:F3} MiB)");
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1024d:F3} KiB)");
|
||||
|
||||
break;
|
||||
default:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize
|
||||
} bytes)");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks == 0)
|
||||
{
|
||||
@@ -271,11 +284,11 @@ public partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -595,8 +608,8 @@ public partial class Dump
|
||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average checksum speed {blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average checksum speed {
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
||||
|
||||
@@ -658,11 +671,12 @@ public partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -110,18 +110,29 @@ public partial class Dump
|
||||
|
||||
ulong totalSize = blocks * blockSize;
|
||||
|
||||
if(totalSize > 1073741824)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)");
|
||||
else if(totalSize > 1048576)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)");
|
||||
else if(totalSize > 1024)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)");
|
||||
else
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize} bytes)");
|
||||
switch(totalSize)
|
||||
{
|
||||
case > 1073741824:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1073741824d:F3} GiB)");
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1048576d:F3} MiB)");
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1024d:F3} KiB)");
|
||||
|
||||
break;
|
||||
default:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize
|
||||
} bytes)");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke($"Device reports {blocks} blocks ({blocks * blockSize} bytes).");
|
||||
UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");
|
||||
@@ -288,11 +299,11 @@ public partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -460,8 +471,8 @@ public partial class Dump
|
||||
break;
|
||||
}
|
||||
|
||||
PulseProgress?.
|
||||
Invoke($"Retrying sector {badSector}, pass {pass}, {(runningPersistent ? "recovering partial data, " : "")}{(forward ? "forward" : "reverse")}");
|
||||
PulseProgress?.Invoke($"Retrying sector {badSector}, pass {pass}, {
|
||||
(runningPersistent ? "recovering partial data, " : "")}{(forward ? "forward" : "reverse")}");
|
||||
|
||||
sense = _dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false,
|
||||
(uint)(umdStart + badSector * 4), 512, 0, 4, false, _dev.Timeout,
|
||||
@@ -568,11 +579,12 @@ public partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -60,8 +60,8 @@ public partial class Dump
|
||||
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
ErrorMessage?.
|
||||
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
ErrorMessage?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC
|
||||
:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
|
||||
_dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey,
|
||||
decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
@@ -75,77 +75,84 @@ public partial class Dump
|
||||
goto deviceGotReset;
|
||||
}
|
||||
|
||||
if(decSense.Value.ASC == 0x3A)
|
||||
switch(decSense.Value.ASC)
|
||||
{
|
||||
var leftRetries = 5;
|
||||
|
||||
while(leftRetries > 0)
|
||||
case 0x3A:
|
||||
{
|
||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||
var leftRetries = 5;
|
||||
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Sense.Decode(senseBuf);
|
||||
|
||||
if(decSense.HasValue)
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
ErrorMessage?.
|
||||
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||
|
||||
_dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Sense.Decode(senseBuf);
|
||||
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
ErrorMessage?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {
|
||||
decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
|
||||
_dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC,
|
||||
decSense.Value.ASCQ);
|
||||
}
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke("Please insert media in drive");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(decSense.Value.ASC == 0x04 &&
|
||||
decSense.Value.ASCQ == 0x01)
|
||||
{
|
||||
var leftRetries = 50;
|
||||
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Sense.Decode(senseBuf);
|
||||
|
||||
if(decSense.HasValue)
|
||||
if(sense)
|
||||
{
|
||||
ErrorMessage?.
|
||||
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
StoppingErrorMessage?.Invoke("Please insert media in drive");
|
||||
|
||||
_dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
leftRetries--;
|
||||
break;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
case 0x04 when decSense.Value.ASCQ == 0x01:
|
||||
{
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||
var leftRetries = 50;
|
||||
|
||||
return;
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Sense.Decode(senseBuf);
|
||||
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
ErrorMessage?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {
|
||||
decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
|
||||
_dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC,
|
||||
decSense.Value.ASCQ);
|
||||
}
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke($"Error testing unit was ready:\n{
|
||||
Sense.PrettifySense(senseBuf)}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*else if (decSense.Value.ASC == 0x29 && decSense.Value.ASCQ == 0x00)
|
||||
/*else if (decSense.Value.ASC == 0x29 && decSense.Value.ASCQ == 0x00)
|
||||
{
|
||||
if (!deviceReset)
|
||||
{
|
||||
@@ -158,47 +165,50 @@ public partial class Dump
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf)));
|
||||
return;
|
||||
}*/
|
||||
// These should be trapped by the OS but seems in some cases they're not
|
||||
else if(decSense.Value.ASC == 0x28)
|
||||
{
|
||||
var leftRetries = 10;
|
||||
|
||||
while(leftRetries > 0)
|
||||
// These should be trapped by the OS but seems in some cases they're not
|
||||
case 0x28:
|
||||
{
|
||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||
var leftRetries = 10;
|
||||
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Sense.Decode(senseBuf);
|
||||
|
||||
if(decSense.HasValue)
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
ErrorMessage?.
|
||||
Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = _dev.ScsiTestUnitReady(out senseBuf, _dev.Timeout, out _);
|
||||
|
||||
_dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
decSense = Sense.Decode(senseBuf);
|
||||
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
ErrorMessage?.Invoke($"Device not ready. Sense {decSense.Value.SenseKey} ASC {
|
||||
decSense.Value.ASC:X2}h ASCQ {decSense.Value.ASCQ:X2}h");
|
||||
|
||||
_dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC,
|
||||
decSense.Value.ASCQ);
|
||||
}
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
if(sense)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke($"Error testing unit was ready:\n{
|
||||
Sense.PrettifySense(senseBuf)}");
|
||||
|
||||
if(sense)
|
||||
{
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
StoppingErrorMessage?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)
|
||||
}");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StoppingErrorMessage?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -974,50 +974,46 @@ partial class Dump
|
||||
continue;
|
||||
}
|
||||
|
||||
if(decSense.Value.SenseKey is SenseKeys.NoSense or SenseKeys.RecoveredError &&
|
||||
(decSense.Value.ASCQ is 0x02 or 0x05 || eom))
|
||||
switch(decSense.Value.SenseKey)
|
||||
{
|
||||
// TODO: Detect end of partition
|
||||
endOfMedia = true;
|
||||
UpdateStatus?.Invoke("Found end-of-tape/partition...");
|
||||
_dumpLog.WriteLine("Found end-of-tape/partition...");
|
||||
case SenseKeys.NoSense or SenseKeys.RecoveredError when decSense.Value.ASCQ is 0x02 or 0x05 || eom:
|
||||
// TODO: Detect end of partition
|
||||
endOfMedia = true;
|
||||
UpdateStatus?.Invoke("Found end-of-tape/partition...");
|
||||
_dumpLog.WriteLine("Found end-of-tape/partition...");
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
case SenseKeys.NoSense or SenseKeys.RecoveredError when decSense.Value.ASCQ == 0x01 || filemark:
|
||||
currentTapeFile.LastBlock = currentBlock - 1;
|
||||
outputTape.AddFile(currentTapeFile);
|
||||
|
||||
if(decSense.Value.SenseKey is SenseKeys.NoSense or SenseKeys.RecoveredError &&
|
||||
(decSense.Value.ASCQ == 0x01 || filemark))
|
||||
{
|
||||
currentTapeFile.LastBlock = currentBlock - 1;
|
||||
outputTape.AddFile(currentTapeFile);
|
||||
currentFile++;
|
||||
|
||||
currentFile++;
|
||||
currentTapeFile = new TapeFile
|
||||
{
|
||||
File = currentFile,
|
||||
FirstBlock = currentBlock,
|
||||
Partition = currentPartition
|
||||
};
|
||||
|
||||
currentTapeFile = new TapeFile
|
||||
{
|
||||
File = currentFile,
|
||||
FirstBlock = currentBlock,
|
||||
Partition = currentPartition
|
||||
};
|
||||
UpdateStatus?.Invoke($"Changed to file {currentFile} at block {currentBlock}");
|
||||
_dumpLog.WriteLine("Changed to file {0} at block {1}", currentFile, currentBlock);
|
||||
|
||||
UpdateStatus?.Invoke($"Changed to file {currentFile} at block {currentBlock}");
|
||||
_dumpLog.WriteLine("Changed to file {0} at block {1}", currentFile, currentBlock);
|
||||
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(decSense is null)
|
||||
{
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Drive could not read block ${currentBlock}. Sense cannot be decoded, look at log for dump...");
|
||||
StoppingErrorMessage?.Invoke($"Drive could not read block ${currentBlock
|
||||
}. Sense cannot be decoded, look at log for dump...");
|
||||
|
||||
_dumpLog.WriteLine($"Drive could not read block ${currentBlock}. Sense bytes follow...");
|
||||
_dumpLog.WriteLine(PrintHex.ByteArrayToHexArrayString(senseBuf, 32));
|
||||
}
|
||||
else
|
||||
{
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Drive could not read block ${currentBlock}. Sense follows...\n{decSense.Value.SenseKey} {decSense.Value.Description}");
|
||||
StoppingErrorMessage?.Invoke($"Drive could not read block ${currentBlock}. Sense follows...\n{
|
||||
decSense.Value.SenseKey} {decSense.Value.Description}");
|
||||
|
||||
_dumpLog.WriteLine($"Drive could not read block ${currentBlock}. Sense follows...");
|
||||
|
||||
@@ -1084,11 +1080,11 @@ partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -1329,8 +1325,8 @@ partial class Dump
|
||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average checksum speed {blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average checksum speed {
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
||||
|
||||
@@ -1404,11 +1400,12 @@ partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -226,21 +226,34 @@ partial class Dump
|
||||
|
||||
ulong totalSize = blocks * blockSize;
|
||||
|
||||
if(totalSize > 1099511627776)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)");
|
||||
else if(totalSize > 1073741824)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)");
|
||||
else if(totalSize > 1048576)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)");
|
||||
else if(totalSize > 1024)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)");
|
||||
else
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize} bytes)");
|
||||
switch(totalSize)
|
||||
{
|
||||
case > 1099511627776:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1099511627776d:F3} TiB)");
|
||||
|
||||
break;
|
||||
case > 1073741824:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1073741824d:F3} GiB)");
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1048576d:F3} MiB)");
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize / 1024d:F3} KiB)");
|
||||
|
||||
break;
|
||||
default:
|
||||
UpdateStatus?.Invoke($"Media has {blocks} blocks of {blockSize} bytes/each. (for a total of {
|
||||
totalSize} bytes)");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check how many blocks to read, if error show and return
|
||||
@@ -309,8 +322,8 @@ partial class Dump
|
||||
// Only a block will be read, but it contains 16 sectors and command expect sector number not block number
|
||||
blocksToRead = (uint)(longBlockSize == 37856 ? 16 : 1);
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Reading {longBlockSize} raw bytes ({blockSize * blocksToRead} cooked bytes) per sector.");
|
||||
UpdateStatus?.Invoke($"Reading {longBlockSize} raw bytes ({blockSize * blocksToRead
|
||||
} cooked bytes) per sector.");
|
||||
|
||||
physicalBlockSize = longBlockSize;
|
||||
blockSize = longBlockSize;
|
||||
@@ -525,8 +538,8 @@ partial class Dump
|
||||
|
||||
#if DEBUG
|
||||
foreach(Track trk in tracks)
|
||||
UpdateStatus?.
|
||||
Invoke($"Track {trk.Sequence} starts at LBA {trk.StartSector} and ends at LBA {trk.EndSector}");
|
||||
UpdateStatus?.Invoke($"Track {trk.Sequence} starts at LBA {trk.StartSector
|
||||
} and ends at LBA {trk.EndSector}");
|
||||
#endif
|
||||
|
||||
if(canStoreNotCdTracks)
|
||||
@@ -574,45 +587,52 @@ partial class Dump
|
||||
var setGeometry = false;
|
||||
|
||||
foreach(Modes.ModePage page in decMode.Value.Pages)
|
||||
if(page.Page == 0x04 &&
|
||||
page.Subpage == 0x00)
|
||||
switch(page.Page)
|
||||
{
|
||||
Modes.ModePage_04? rigidPage = Modes.DecodeModePage_04(page.PageResponse);
|
||||
case 0x04 when page.Subpage == 0x00:
|
||||
{
|
||||
Modes.ModePage_04? rigidPage = Modes.DecodeModePage_04(page.PageResponse);
|
||||
|
||||
if(!rigidPage.HasValue || setGeometry)
|
||||
continue;
|
||||
if(!rigidPage.HasValue || setGeometry)
|
||||
continue;
|
||||
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Setting geometry to {rigidPage.Value.Cylinders} cylinders, {rigidPage.Value.Heads} heads, {(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads))} sectors per track");
|
||||
UpdateStatus?.Invoke($"Setting geometry to {rigidPage.Value.Cylinders} cylinders, {
|
||||
rigidPage.Value.Heads} heads, {
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads))
|
||||
} sectors per track");
|
||||
|
||||
outputFormat.SetGeometry(rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
outputFormat.SetGeometry(rigidPage.Value.Cylinders, rigidPage.Value.Heads,
|
||||
(uint)(blocks / (rigidPage.Value.Cylinders * rigidPage.Value.Heads)));
|
||||
|
||||
setGeometry = true;
|
||||
}
|
||||
else if(page.Page == 0x05 &&
|
||||
page.Subpage == 0x00)
|
||||
{
|
||||
Modes.ModePage_05? flexiblePage = Modes.DecodeModePage_05(page.PageResponse);
|
||||
setGeometry = true;
|
||||
|
||||
if(!flexiblePage.HasValue)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case 0x05 when page.Subpage == 0x00:
|
||||
{
|
||||
Modes.ModePage_05? flexiblePage = Modes.DecodeModePage_05(page.PageResponse);
|
||||
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
if(!flexiblePage.HasValue)
|
||||
continue;
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Setting geometry to {flexiblePage.Value.Cylinders} cylinders, {flexiblePage.Value.Heads} heads, {flexiblePage.Value.SectorsPerTrack} sectors per track");
|
||||
_dumpLog.WriteLine("Setting geometry to {0} cylinders, {1} heads, {2} sectors per track",
|
||||
flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
|
||||
outputFormat.SetGeometry(flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
UpdateStatus?.Invoke($"Setting geometry to {flexiblePage.Value.Cylinders} cylinders, {
|
||||
flexiblePage.Value.Heads} heads, {flexiblePage.Value.SectorsPerTrack} sectors per track");
|
||||
|
||||
setGeometry = true;
|
||||
outputFormat.SetGeometry(flexiblePage.Value.Cylinders, flexiblePage.Value.Heads,
|
||||
flexiblePage.Value.SectorsPerTrack);
|
||||
|
||||
setGeometry = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,11 +743,11 @@ partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -1009,8 +1029,8 @@ partial class Dump
|
||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average checksum speed {blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average checksum speed {
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
||||
|
||||
@@ -1224,11 +1244,12 @@ partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
// Copyright © 2011-2022 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
|
||||
|
||||
// ReSharper disable JoinDeclarationAndInitializer
|
||||
|
||||
namespace Aaru.Core.Devices.Dumping;
|
||||
@@ -469,24 +467,27 @@ public partial class Dump
|
||||
|
||||
if(cid != null)
|
||||
{
|
||||
if(_dev.Type == DeviceType.SecureDigital && _private)
|
||||
switch(_dev.Type)
|
||||
{
|
||||
// Clear serial number and manufacturing date
|
||||
cid[9] = 0;
|
||||
cid[10] = 0;
|
||||
cid[11] = 0;
|
||||
cid[12] = 0;
|
||||
cid[13] = 0;
|
||||
cid[14] = 0;
|
||||
}
|
||||
else if(_dev.Type == DeviceType.MMC && _private)
|
||||
{
|
||||
// Clear serial number and manufacturing date
|
||||
cid[10] = 0;
|
||||
cid[11] = 0;
|
||||
cid[12] = 0;
|
||||
cid[13] = 0;
|
||||
cid[14] = 0;
|
||||
case DeviceType.SecureDigital when _private:
|
||||
// Clear serial number and manufacturing date
|
||||
cid[9] = 0;
|
||||
cid[10] = 0;
|
||||
cid[11] = 0;
|
||||
cid[12] = 0;
|
||||
cid[13] = 0;
|
||||
cid[14] = 0;
|
||||
|
||||
break;
|
||||
case DeviceType.MMC when _private:
|
||||
// Clear serial number and manufacturing date
|
||||
cid[10] = 0;
|
||||
cid[11] = 0;
|
||||
cid[12] = 0;
|
||||
cid[13] = 0;
|
||||
cid[14] = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ret =
|
||||
@@ -686,11 +687,11 @@ public partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke($"Dump finished in {(end - start).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average dump speed {blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000)
|
||||
:F3} KiB/sec.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration:F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average write speed {blockSize * (double)(blocks + 1) / 1024 / imageWriteDuration
|
||||
:F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
|
||||
@@ -888,8 +889,8 @@ public partial class Dump
|
||||
totalChkDuration = (end - chkStart).TotalMilliseconds;
|
||||
UpdateStatus?.Invoke($"Sidecar created in {(end - chkStart).TotalSeconds} seconds.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average checksum speed {blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average checksum speed {
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000):F3} KiB/sec.");
|
||||
|
||||
_dumpLog.WriteLine("Sidecar created in {0} seconds.", (end - chkStart).TotalSeconds);
|
||||
|
||||
@@ -941,11 +942,12 @@ public partial class Dump
|
||||
|
||||
UpdateStatus?.Invoke("");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
UpdateStatus?.Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000
|
||||
:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {
|
||||
(closeEnd - closeStart).TotalSeconds:F3} closing).");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000):F3} MiB/sec.");
|
||||
UpdateStatus?.Invoke($"Average speed: {blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000)
|
||||
:F3} MiB/sec.");
|
||||
|
||||
if(maxSpeed > 0)
|
||||
UpdateStatus?.Invoke($"Fastest speed burst: {maxSpeed:F3} MiB/sec.");
|
||||
|
||||
@@ -113,32 +113,27 @@ sealed partial class Reader
|
||||
tries++;
|
||||
}
|
||||
|
||||
if(!_read6 &&
|
||||
!_read10 &&
|
||||
!_read12 &&
|
||||
!_read16)
|
||||
switch(_read6)
|
||||
{
|
||||
// Magneto-opticals may have empty LBA 0 but we know they work with READ(12)
|
||||
if(_dev.ScsiType == PeripheralDeviceTypes.OpticalDevice)
|
||||
case false when !_read10 && !_read12 && !_read16:
|
||||
{
|
||||
ErrorMessage = "Cannot read medium, aborting scan...";
|
||||
// Magneto-opticals may have empty LBA 0 but we know they work with READ(12)
|
||||
if(_dev.ScsiType == PeripheralDeviceTypes.OpticalDevice)
|
||||
{
|
||||
ErrorMessage = "Cannot read medium, aborting scan...";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_read12 = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case true when !_read10 && !_read12 && !_read16 && Blocks > 0x001FFFFF + 1:
|
||||
ErrorMessage = $"Device only supports SCSI READ (6) but has more than {0x001FFFFF + 1} blocks ({Blocks
|
||||
} blocks total)";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_read12 = true;
|
||||
}
|
||||
|
||||
if(_read6 &&
|
||||
!_read10 &&
|
||||
!_read12 &&
|
||||
!_read16 &&
|
||||
Blocks > 0x001FFFFF + 1)
|
||||
{
|
||||
ErrorMessage =
|
||||
$"Device only supports SCSI READ (6) but has more than {0x001FFFFF + 1} blocks ({Blocks} blocks total)";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(Blocks > 0x001FFFFF + 1)
|
||||
@@ -150,8 +145,8 @@ sealed partial class Reader
|
||||
if(!_read16 &&
|
||||
Blocks > 0xFFFFFFFF + (long)1)
|
||||
{
|
||||
ErrorMessage =
|
||||
$"Device only supports SCSI READ (10) but has more than {0xFFFFFFFF + (long)1} blocks ({Blocks} blocks total)";
|
||||
ErrorMessage = $"Device only supports SCSI READ (10) but has more than {0xFFFFFFFF + (long)1} blocks ({
|
||||
Blocks} blocks total)";
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -573,22 +568,23 @@ sealed partial class Reader
|
||||
{
|
||||
sense = _dev.ReadCapacity16(out cmdBuf, out senseBuf, _timeout, out _);
|
||||
|
||||
if(sense && Blocks == 0)
|
||||
if(_dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
switch(sense)
|
||||
{
|
||||
case true when Blocks == 0 && _dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice:
|
||||
ErrorMessage = "Unable to get media capacity\n" + $"{Sense.PrettifySense(senseBuf)}";
|
||||
|
||||
return true;
|
||||
case false:
|
||||
{
|
||||
var temp = new byte[8];
|
||||
|
||||
Array.Copy(cmdBuf, 0, temp, 0, 8);
|
||||
Array.Reverse(temp);
|
||||
Blocks = BitConverter.ToUInt64(temp, 0);
|
||||
LogicalBlockSize = (uint)((cmdBuf[8] << 24) + (cmdBuf[9] << 16) + (cmdBuf[10] << 8) + cmdBuf[11]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
var temp = new byte[8];
|
||||
|
||||
Array.Copy(cmdBuf, 0, temp, 0, 8);
|
||||
Array.Reverse(temp);
|
||||
Blocks = BitConverter.ToUInt64(temp, 0);
|
||||
LogicalBlockSize = (uint)((cmdBuf[8] << 24) + (cmdBuf[9] << 16) + (cmdBuf[10] << 8) + cmdBuf[11]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
// Copyright © 2011-2022 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
|
||||
|
||||
// ReSharper disable InlineOutVariableDeclaration
|
||||
|
||||
namespace Aaru.Core.Devices.Report;
|
||||
@@ -153,14 +151,17 @@ public sealed partial class DeviceReport
|
||||
report.GdRomSwapDiscCapabilities.SwapDiscLeadOutPSEC = leadOutTrack.PSEC;
|
||||
report.GdRomSwapDiscCapabilities.SwapDiscLeadOutPFRAM = leadOutTrack.PFRAME;
|
||||
|
||||
if(leadOutTrack.PMIN == 122)
|
||||
tocIsNotBcd = true;
|
||||
|
||||
if(leadOutTrack.PMIN >= 0xA0 &&
|
||||
!tocIsNotBcd)
|
||||
switch(leadOutTrack.PMIN)
|
||||
{
|
||||
min += 90;
|
||||
leadOutTrack.PMIN -= 0x90;
|
||||
case 122:
|
||||
tocIsNotBcd = true;
|
||||
|
||||
break;
|
||||
case >= 0xA0 when !tocIsNotBcd:
|
||||
min += 90;
|
||||
leadOutTrack.PMIN -= 0x90;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(tocIsNotBcd)
|
||||
|
||||
@@ -156,18 +156,33 @@ public sealed partial class MediaScan
|
||||
|
||||
if(!error)
|
||||
{
|
||||
if(duration >= 500)
|
||||
results.F += blocksToRead;
|
||||
else if(duration >= 150)
|
||||
results.E += blocksToRead;
|
||||
else if(duration >= 50)
|
||||
results.D += blocksToRead;
|
||||
else if(duration >= 10)
|
||||
results.C += blocksToRead;
|
||||
else if(duration >= 3)
|
||||
results.B += blocksToRead;
|
||||
else
|
||||
results.A += blocksToRead;
|
||||
switch(duration)
|
||||
{
|
||||
case >= 500:
|
||||
results.F += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 150:
|
||||
results.E += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 50:
|
||||
results.D += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 10:
|
||||
results.C += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 3:
|
||||
results.B += blocksToRead;
|
||||
|
||||
break;
|
||||
default:
|
||||
results.A += blocksToRead;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ScanTime?.Invoke(i, duration);
|
||||
mhddLog.Write(i, duration);
|
||||
@@ -265,25 +280,40 @@ public sealed partial class MediaScan
|
||||
currentSpeed > 0)
|
||||
results.MinSpeed = currentSpeed;
|
||||
|
||||
PulseProgress?.
|
||||
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
|
||||
PulseProgress?.Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed
|
||||
:F3} MiB/sec.)");
|
||||
|
||||
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out _);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
if(duration >= 500)
|
||||
results.F += blocksToRead;
|
||||
else if(duration >= 150)
|
||||
results.E += blocksToRead;
|
||||
else if(duration >= 50)
|
||||
results.D += blocksToRead;
|
||||
else if(duration >= 10)
|
||||
results.C += blocksToRead;
|
||||
else if(duration >= 3)
|
||||
results.B += blocksToRead;
|
||||
else
|
||||
results.A += blocksToRead;
|
||||
switch(duration)
|
||||
{
|
||||
case >= 500:
|
||||
results.F += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 150:
|
||||
results.E += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 50:
|
||||
results.D += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 10:
|
||||
results.C += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 3:
|
||||
results.B += blocksToRead;
|
||||
|
||||
break;
|
||||
default:
|
||||
results.A += blocksToRead;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ScanTime?.Invoke(currentBlock, duration);
|
||||
mhddLog.Write(currentBlock, duration);
|
||||
|
||||
@@ -115,8 +115,8 @@ public sealed partial class MediaScan
|
||||
|
||||
if(sense)
|
||||
{
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||
StoppingErrorMessage?.Invoke($"Error testing unit was ready:\n{
|
||||
Sense.PrettifySense(senseBuf)}");
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -143,8 +143,8 @@ public sealed partial class MediaScan
|
||||
|
||||
if(sense)
|
||||
{
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||
StoppingErrorMessage?.Invoke($"Error testing unit was ready:\n{
|
||||
Sense.PrettifySense(senseBuf)}");
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -152,8 +152,8 @@ public sealed partial class MediaScan
|
||||
break;
|
||||
}
|
||||
default:
|
||||
StoppingErrorMessage?.
|
||||
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||
StoppingErrorMessage?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)
|
||||
}");
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -199,21 +199,34 @@ public sealed partial class MediaScan
|
||||
|
||||
ulong totalSize = results.Blocks * blockSize;
|
||||
|
||||
if(totalSize > 1099511627776)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)");
|
||||
else if(totalSize > 1073741824)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)");
|
||||
else if(totalSize > 1048576)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)");
|
||||
else if(totalSize > 1024)
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)");
|
||||
else
|
||||
UpdateStatus?.
|
||||
Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {totalSize} bytes)");
|
||||
switch(totalSize)
|
||||
{
|
||||
case > 1099511627776:
|
||||
UpdateStatus?.Invoke($"Media has {results.Blocks} blocks of {blockSize
|
||||
} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)");
|
||||
|
||||
break;
|
||||
case > 1073741824:
|
||||
UpdateStatus?.Invoke($"Media has {results.Blocks} blocks of {blockSize
|
||||
} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)");
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
UpdateStatus?.Invoke($"Media has {results.Blocks} blocks of {blockSize
|
||||
} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)");
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
UpdateStatus?.Invoke($"Media has {results.Blocks} blocks of {blockSize
|
||||
} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)");
|
||||
|
||||
break;
|
||||
default:
|
||||
UpdateStatus?.Invoke($"Media has {results.Blocks} blocks of {blockSize
|
||||
} bytes/each. (for a total of {totalSize} bytes)");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -386,18 +399,33 @@ public sealed partial class MediaScan
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
if(cmdDuration >= 500)
|
||||
results.F += blocksToRead;
|
||||
else if(cmdDuration >= 150)
|
||||
results.E += blocksToRead;
|
||||
else if(cmdDuration >= 50)
|
||||
results.D += blocksToRead;
|
||||
else if(cmdDuration >= 10)
|
||||
results.C += blocksToRead;
|
||||
else if(cmdDuration >= 3)
|
||||
results.B += blocksToRead;
|
||||
else
|
||||
results.A += blocksToRead;
|
||||
switch(cmdDuration)
|
||||
{
|
||||
case >= 500:
|
||||
results.F += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 150:
|
||||
results.E += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 50:
|
||||
results.D += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 10:
|
||||
results.C += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 3:
|
||||
results.B += blocksToRead;
|
||||
|
||||
break;
|
||||
default:
|
||||
results.A += blocksToRead;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ScanTime?.Invoke(i, cmdDuration);
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
@@ -521,18 +549,33 @@ public sealed partial class MediaScan
|
||||
if(!sense &&
|
||||
!_dev.Error)
|
||||
{
|
||||
if(cmdDuration >= 500)
|
||||
results.F += blocksToRead;
|
||||
else if(cmdDuration >= 150)
|
||||
results.E += blocksToRead;
|
||||
else if(cmdDuration >= 50)
|
||||
results.D += blocksToRead;
|
||||
else if(cmdDuration >= 10)
|
||||
results.C += blocksToRead;
|
||||
else if(cmdDuration >= 3)
|
||||
results.B += blocksToRead;
|
||||
else
|
||||
results.A += blocksToRead;
|
||||
switch(cmdDuration)
|
||||
{
|
||||
case >= 500:
|
||||
results.F += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 150:
|
||||
results.E += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 50:
|
||||
results.D += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 10:
|
||||
results.C += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 3:
|
||||
results.B += blocksToRead;
|
||||
|
||||
break;
|
||||
default:
|
||||
results.A += blocksToRead;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ScanTime?.Invoke(i, cmdDuration);
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
// Copyright © 2011-2022 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
|
||||
|
||||
// ReSharper disable JoinDeclarationAndInitializer
|
||||
|
||||
namespace Aaru.Core.Devices.Scanning;
|
||||
@@ -259,18 +257,33 @@ public sealed partial class MediaScan
|
||||
|
||||
if(!error)
|
||||
{
|
||||
if(duration >= 500)
|
||||
results.F += blocksToRead;
|
||||
else if(duration >= 150)
|
||||
results.E += blocksToRead;
|
||||
else if(duration >= 50)
|
||||
results.D += blocksToRead;
|
||||
else if(duration >= 10)
|
||||
results.C += blocksToRead;
|
||||
else if(duration >= 3)
|
||||
results.B += blocksToRead;
|
||||
else
|
||||
results.A += blocksToRead;
|
||||
switch(duration)
|
||||
{
|
||||
case >= 500:
|
||||
results.F += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 150:
|
||||
results.E += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 50:
|
||||
results.D += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 10:
|
||||
results.C += blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 3:
|
||||
results.B += blocksToRead;
|
||||
|
||||
break;
|
||||
default:
|
||||
results.A += blocksToRead;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ScanTime?.Invoke(i, duration);
|
||||
mhddLog.Write(i, duration);
|
||||
|
||||
@@ -86,13 +86,19 @@ public static class ImageInfo
|
||||
else
|
||||
AaruConsole.WriteLine("[bold]Format:[/] [italic]{0}[/]", Markup.Escape(imageFormat.Format));
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application) &&
|
||||
!string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion))
|
||||
AaruConsole.WriteLine("Was created with [italic]{0}[/] version [italic]{1}[/]",
|
||||
Markup.Escape(imageFormat.Info.Application),
|
||||
Markup.Escape(imageFormat.Info.ApplicationVersion));
|
||||
else if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
|
||||
AaruConsole.WriteLine("Was created with [italic]{0}[/]", Markup.Escape(imageFormat.Info.Application));
|
||||
switch(string.IsNullOrWhiteSpace(imageFormat.Info.Application))
|
||||
{
|
||||
case false when !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion):
|
||||
AaruConsole.WriteLine("Was created with [italic]{0}[/] version [italic]{1}[/]",
|
||||
Markup.Escape(imageFormat.Info.Application),
|
||||
Markup.Escape(imageFormat.Info.ApplicationVersion));
|
||||
|
||||
break;
|
||||
case false:
|
||||
AaruConsole.WriteLine("Was created with [italic]{0}[/]", Markup.Escape(imageFormat.Info.Application));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
AaruConsole.WriteLine("Image without headers is {0} bytes long", imageFormat.Info.ImageSize);
|
||||
|
||||
|
||||
@@ -513,25 +513,22 @@ public static class MMC
|
||||
|
||||
if(mediaType != MediaType.CDI)
|
||||
{
|
||||
if(hasDataTrack &&
|
||||
hasAudioTrack &&
|
||||
allFirstSessionTracksAreAudio &&
|
||||
sessions == 2)
|
||||
switch(hasDataTrack)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("Media detection",
|
||||
"Disc has audio and data tracks, two sessions, and all data tracks are in second session, setting as CD+.");
|
||||
case true when hasAudioTrack && allFirstSessionTracksAreAudio && sessions == 2:
|
||||
AaruConsole.DebugWriteLine("Media detection",
|
||||
"Disc has audio and data tracks, two sessions, and all data tracks are in second session, setting as CD+.");
|
||||
|
||||
mediaType = MediaType.CDPLUS;
|
||||
}
|
||||
mediaType = MediaType.CDPLUS;
|
||||
|
||||
if(!hasDataTrack &&
|
||||
hasAudioTrack &&
|
||||
sessions == 1)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("Media detection",
|
||||
"Disc has only audio tracks in a single session, setting as CD Digital Audio.");
|
||||
break;
|
||||
case false when hasAudioTrack && sessions == 1:
|
||||
AaruConsole.DebugWriteLine("Media detection",
|
||||
"Disc has only audio tracks in a single session, setting as CD Digital Audio.");
|
||||
|
||||
mediaType = MediaType.CDDA;
|
||||
mediaType = MediaType.CDDA;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(hasDataTrack &&
|
||||
|
||||
@@ -95,59 +95,64 @@ public sealed class ScsiInfo
|
||||
goto deviceGotReset;
|
||||
}
|
||||
|
||||
if(decSense?.ASC == 0x3A)
|
||||
switch(decSense?.ASC)
|
||||
{
|
||||
var leftRetries = 5;
|
||||
|
||||
while(leftRetries > 0)
|
||||
case 0x3A:
|
||||
{
|
||||
//AaruConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||
var leftRetries = 5;
|
||||
|
||||
if(!sense)
|
||||
break;
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
//AaruConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||
|
||||
leftRetries--;
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("Please insert media in drive");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
case 0x04 when decSense?.ASCQ == 0x01:
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("Please insert media in drive");
|
||||
var leftRetries = 10;
|
||||
|
||||
return;
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
//AaruConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Sense.PrettifySense(senseBuf));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(decSense?.ASC == 0x04 &&
|
||||
decSense?.ASCQ == 0x01)
|
||||
{
|
||||
var leftRetries = 10;
|
||||
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
//AaruConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||
|
||||
if(!sense)
|
||||
break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
default:
|
||||
AaruConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Sense.PrettifySense(senseBuf));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Sense.PrettifySense(senseBuf));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -179,36 +179,65 @@ public sealed partial class Sidecar
|
||||
{
|
||||
_sidecar.BlockMedia[0].DiskType = "Quarter-inch cartridge";
|
||||
|
||||
if(totalSize <= 20 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-11";
|
||||
else if(totalSize <= 40 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-40";
|
||||
else if(totalSize <= 60 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-24";
|
||||
else if(totalSize <= 80 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-80";
|
||||
else if(totalSize <= 120 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-120";
|
||||
else if(totalSize <= 150 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-150";
|
||||
else if(totalSize <= 320 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-320";
|
||||
else if(totalSize <= 340 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3010";
|
||||
else if(totalSize <= 525 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-525";
|
||||
else if(totalSize <= 670 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3020";
|
||||
else if(totalSize <= 1200 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3080";
|
||||
else if(totalSize <= 1350 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-1350";
|
||||
else if(totalSize <= (long)4000 * 1048576)
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3095";
|
||||
else
|
||||
switch(totalSize)
|
||||
{
|
||||
_sidecar.BlockMedia[0].DiskType = "Unknown tape";
|
||||
_sidecar.BlockMedia[0].DiskSubType = "Unknown tape";
|
||||
case <= 20 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-11";
|
||||
|
||||
break;
|
||||
case <= 40 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-40";
|
||||
|
||||
break;
|
||||
case <= 60 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-24";
|
||||
|
||||
break;
|
||||
case <= 80 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-80";
|
||||
|
||||
break;
|
||||
case <= 120 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-120";
|
||||
|
||||
break;
|
||||
case <= 150 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-150";
|
||||
|
||||
break;
|
||||
case <= 320 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-320";
|
||||
|
||||
break;
|
||||
case <= 340 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3010";
|
||||
|
||||
break;
|
||||
case <= 525 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-525";
|
||||
|
||||
break;
|
||||
case <= 670 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3020";
|
||||
|
||||
break;
|
||||
case <= 1200 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3080";
|
||||
|
||||
break;
|
||||
case <= 1350 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-1350";
|
||||
|
||||
break;
|
||||
case <= (long)4000 * 1048576:
|
||||
_sidecar.BlockMedia[0].DiskSubType = "QIC-3095";
|
||||
|
||||
break;
|
||||
default:
|
||||
_sidecar.BlockMedia[0].DiskType = "Unknown tape";
|
||||
_sidecar.BlockMedia[0].DiskSubType = "Unknown tape";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Submodule Aaru.Decoders updated: d7577c9880...02d6222ae9
Submodule Aaru.Decryption updated: 9ca111c2e4...6033794823
@@ -69,10 +69,17 @@ static partial class AppleCommon
|
||||
else if((bb.bbVersion & 0xFF) == 0x0D)
|
||||
sb.AppendLine("Boot block should be executed.");
|
||||
|
||||
if(bb.bbPageFlags > 0)
|
||||
sb.AppendLine("Allocate secondary sound buffer at boot.");
|
||||
else if(bb.bbPageFlags < 0)
|
||||
sb.AppendLine("Allocate secondary sound and video buffers at boot.");
|
||||
switch(bb.bbPageFlags)
|
||||
{
|
||||
case > 0:
|
||||
sb.AppendLine("Allocate secondary sound buffer at boot.");
|
||||
|
||||
break;
|
||||
case < 0:
|
||||
sb.AppendLine("Allocate secondary sound and video buffers at boot.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("System filename: {0}", StringHandlers.PascalToString(bb.bbSysName, encoding)).AppendLine();
|
||||
|
||||
|
||||
@@ -178,11 +178,17 @@ public sealed class AppleHFSPlus : IFilesystem
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if(vh.signature == 0x482B)
|
||||
sb.AppendLine("HFS+ filesystem.");
|
||||
switch(vh.signature)
|
||||
{
|
||||
case 0x482B:
|
||||
sb.AppendLine("HFS+ filesystem.");
|
||||
|
||||
if(vh.signature == 0x4858)
|
||||
sb.AppendLine("HFSX filesystem.");
|
||||
break;
|
||||
case 0x4858:
|
||||
sb.AppendLine("HFSX filesystem.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(wrapped)
|
||||
sb.AppendLine("Volume is wrapped inside an HFS volume.");
|
||||
@@ -296,11 +302,17 @@ public sealed class AppleHFSPlus : IFilesystem
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
|
||||
if(vh.signature == 0x482B)
|
||||
XmlFsType.Type = "HFS+";
|
||||
switch(vh.signature)
|
||||
{
|
||||
case 0x482B:
|
||||
XmlFsType.Type = "HFS+";
|
||||
|
||||
if(vh.signature == 0x4858)
|
||||
XmlFsType.Type = "HFSX";
|
||||
break;
|
||||
case 0x4858:
|
||||
XmlFsType.Type = "HFSX";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(vh.drFndrInfo6 != 0 &&
|
||||
vh.drFndrInfo7 != 0)
|
||||
|
||||
@@ -166,18 +166,29 @@ public sealed partial class AppleMFS
|
||||
byte[] file;
|
||||
ErrorNumber error = ErrorNumber.NoError;
|
||||
|
||||
if(_debug && string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
|
||||
file = _directoryBlocks;
|
||||
else if(_debug &&
|
||||
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 &&
|
||||
_bootBlocks != null)
|
||||
file = _bootBlocks;
|
||||
else if(_debug && string.Compare(path, "$Bitmap", StringComparison.InvariantCulture) == 0)
|
||||
file = _blockMapBytes;
|
||||
else if(_debug && string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0)
|
||||
file = _mdbBlocks;
|
||||
else
|
||||
error = ReadFile(path, out file, false, false);
|
||||
switch(_debug)
|
||||
{
|
||||
case true when string.Compare(path, "$", StringComparison.InvariantCulture) == 0:
|
||||
file = _directoryBlocks;
|
||||
|
||||
break;
|
||||
case true when string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 && _bootBlocks != null:
|
||||
file = _bootBlocks;
|
||||
|
||||
break;
|
||||
case true when string.Compare(path, "$Bitmap", StringComparison.InvariantCulture) == 0:
|
||||
file = _blockMapBytes;
|
||||
|
||||
break;
|
||||
case true when string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0:
|
||||
file = _mdbBlocks;
|
||||
|
||||
break;
|
||||
default:
|
||||
error = ReadFile(path, out file, false, false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
return error;
|
||||
|
||||
@@ -166,20 +166,16 @@ public sealed partial class AppleMFS
|
||||
if(!_idToEntry.TryGetValue(fileId, out FileEntry entry))
|
||||
return ErrorNumber.NoSuchFile;
|
||||
|
||||
if(entry.flRLgLen > 0 &&
|
||||
string.Compare(xattr, "com.apple.ResourceFork", StringComparison.InvariantCulture) == 0)
|
||||
switch(entry.flRLgLen)
|
||||
{
|
||||
error = ReadFile(path, out buf, true, false);
|
||||
case > 0 when string.Compare(xattr, "com.apple.ResourceFork", StringComparison.InvariantCulture) == 0:
|
||||
error = ReadFile(path, out buf, true, false);
|
||||
|
||||
return error;
|
||||
}
|
||||
return error;
|
||||
case > 0 when string.Compare(xattr, "com.apple.ResourceFork.tags", StringComparison.InvariantCulture) == 0:
|
||||
error = ReadFile(path, out buf, true, true);
|
||||
|
||||
if(entry.flRLgLen > 0 &&
|
||||
string.Compare(xattr, "com.apple.ResourceFork.tags", StringComparison.InvariantCulture) == 0)
|
||||
{
|
||||
error = ReadFile(path, out buf, true, true);
|
||||
|
||||
return error;
|
||||
return error;
|
||||
}
|
||||
|
||||
if(string.Compare(xattr, "com.apple.FinderInfo", StringComparison.InvariantCulture) == 0)
|
||||
|
||||
@@ -92,29 +92,38 @@ public sealed partial class CPM
|
||||
if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(entry.filename))
|
||||
fileCount++;
|
||||
}
|
||||
else if(entry.statusUser == 0x20)
|
||||
{
|
||||
for(var f = 0; f < 8; f++)
|
||||
if(entry.filename[f] < 0x20 &&
|
||||
entry.filename[f] != 0x00)
|
||||
return false;
|
||||
else
|
||||
switch(entry.statusUser)
|
||||
{
|
||||
case 0x20:
|
||||
{
|
||||
for(var f = 0; f < 8; f++)
|
||||
if(entry.filename[f] < 0x20 &&
|
||||
entry.filename[f] != 0x00)
|
||||
return false;
|
||||
|
||||
for(var e = 0; e < 3; e++)
|
||||
if(entry.extension[e] < 0x20 &&
|
||||
entry.extension[e] != 0x00)
|
||||
return false;
|
||||
for(var e = 0; e < 3; e++)
|
||||
if(entry.extension[e] < 0x20 &&
|
||||
entry.extension[e] != 0x00)
|
||||
return false;
|
||||
|
||||
_label = Encoding.ASCII.GetString(directory, off + 1, 11).Trim();
|
||||
_labelCreationDate = new byte[4];
|
||||
_labelUpdateDate = new byte[4];
|
||||
Array.Copy(directory, off + 24, _labelCreationDate, 0, 4);
|
||||
Array.Copy(directory, off + 28, _labelUpdateDate, 0, 4);
|
||||
}
|
||||
else if(entry.statusUser == 0x21)
|
||||
if(directory[off + 1] == 0x00)
|
||||
_thirdPartyTimestamps = true;
|
||||
else
|
||||
_standardTimestamps |= directory[off + 21] == 0x00 && directory[off + 31] == 0x00;
|
||||
_label = Encoding.ASCII.GetString(directory, off + 1, 11).Trim();
|
||||
_labelCreationDate = new byte[4];
|
||||
_labelUpdateDate = new byte[4];
|
||||
Array.Copy(directory, off + 24, _labelCreationDate, 0, 4);
|
||||
Array.Copy(directory, off + 28, _labelUpdateDate, 0, 4);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x21 when directory[off + 1] == 0x00:
|
||||
_thirdPartyTimestamps = true;
|
||||
|
||||
break;
|
||||
case 0x21:
|
||||
_standardTimestamps |= directory[off + 21] == 0x00 && directory[off + 31] == 0x00;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fileCount > 0;
|
||||
|
||||
@@ -248,9 +248,10 @@ public sealed partial class CPM
|
||||
// For each directory entry
|
||||
for(var dOff = 0; dOff < directory.Length; dOff += 32)
|
||||
|
||||
// Describes a file (does not support PDOS entries with user >= 16, because they're identical to password entries
|
||||
if((directory[dOff] & 0x7F) < 0x10)
|
||||
if(allocationBlocks.Count > 256)
|
||||
switch(directory[dOff] & 0x7F)
|
||||
{
|
||||
// Describes a file (does not support PDOS entries with user >= 16, because they're identical to password entries
|
||||
case < 0x10 when allocationBlocks.Count > 256:
|
||||
{
|
||||
DirectoryEntry16 entry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<DirectoryEntry16>(directory, dOff, 32);
|
||||
@@ -360,8 +361,10 @@ public sealed partial class CPM
|
||||
}
|
||||
|
||||
dirCnt++;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
case < 0x10:
|
||||
{
|
||||
DirectoryEntry entry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<DirectoryEntry>(directory, dOff, 32);
|
||||
@@ -471,242 +474,248 @@ public sealed partial class CPM
|
||||
}
|
||||
|
||||
dirCnt++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// A password entry (or a file entry in PDOS, but this does not handle that case)
|
||||
else if((directory[dOff] & 0x7F) >= 0x10 &&
|
||||
(directory[dOff] & 0x7F) < 0x20)
|
||||
{
|
||||
PasswordEntry entry = Marshal.ByteArrayToStructureLittleEndian<PasswordEntry>(directory, dOff, 32);
|
||||
|
||||
int user = entry.userNumber & 0x0F;
|
||||
|
||||
for(var i = 0; i < 8; i++)
|
||||
entry.filename[i] &= 0x7F;
|
||||
|
||||
for(var i = 0; i < 3; i++)
|
||||
entry.extension[i] &= 0x7F;
|
||||
|
||||
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
|
||||
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
|
||||
|
||||
// If user is != 0, append user to name to have identical filenames
|
||||
if(user > 0)
|
||||
filename = $"{user:X1}:{filename}";
|
||||
|
||||
if(!string.IsNullOrEmpty(extension))
|
||||
filename = filename + "." + extension;
|
||||
|
||||
filename = filename.Replace('/', '\u2215');
|
||||
|
||||
// Do not repeat passwords
|
||||
if(_passwordCache.ContainsKey(filename))
|
||||
_passwordCache.Remove(filename);
|
||||
|
||||
// Copy whole password entry
|
||||
var tmp = new byte[32];
|
||||
Array.Copy(directory, dOff, tmp, 0, 32);
|
||||
_passwordCache.Add(filename, tmp);
|
||||
|
||||
// Count entries 3 by 3 for timestamps
|
||||
switch(dirCnt % 3)
|
||||
// A password entry (or a file entry in PDOS, but this does not handle that case)
|
||||
case >= 0x10 and < 0x20:
|
||||
{
|
||||
case 0:
|
||||
file1 = filename;
|
||||
PasswordEntry entry = Marshal.ByteArrayToStructureLittleEndian<PasswordEntry>(directory, dOff, 32);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
file2 = filename;
|
||||
int user = entry.userNumber & 0x0F;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
file3 = filename;
|
||||
for(var i = 0; i < 8; i++)
|
||||
entry.filename[i] &= 0x7F;
|
||||
|
||||
break;
|
||||
for(var i = 0; i < 3; i++)
|
||||
entry.extension[i] &= 0x7F;
|
||||
|
||||
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
|
||||
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
|
||||
|
||||
// If user is != 0, append user to name to have identical filenames
|
||||
if(user > 0)
|
||||
filename = $"{user:X1}:{filename}";
|
||||
|
||||
if(!string.IsNullOrEmpty(extension))
|
||||
filename = filename + "." + extension;
|
||||
|
||||
filename = filename.Replace('/', '\u2215');
|
||||
|
||||
// Do not repeat passwords
|
||||
if(_passwordCache.ContainsKey(filename))
|
||||
_passwordCache.Remove(filename);
|
||||
|
||||
// Copy whole password entry
|
||||
var tmp = new byte[32];
|
||||
Array.Copy(directory, dOff, tmp, 0, 32);
|
||||
_passwordCache.Add(filename, tmp);
|
||||
|
||||
// Count entries 3 by 3 for timestamps
|
||||
switch(dirCnt % 3)
|
||||
{
|
||||
case 0:
|
||||
file1 = filename;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
file2 = filename;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
file3 = filename;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dirCnt++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dirCnt++;
|
||||
// Volume label and password entry. Volume password is ignored.
|
||||
default:
|
||||
switch(directory[dOff] & 0x7F)
|
||||
{
|
||||
case 0x20:
|
||||
LabelEntry labelEntry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<LabelEntry>(directory, dOff, 32);
|
||||
|
||||
// The volume label defines if one of the fields in CP/M 3 timestamp is a creation or an
|
||||
// access time
|
||||
atime |= (labelEntry.flags & 0x40) == 0x40;
|
||||
|
||||
_label = Encoding.ASCII.GetString(directory, dOff + 1, 11).Trim();
|
||||
_labelCreationDate = new byte[4];
|
||||
_labelUpdateDate = new byte[4];
|
||||
Array.Copy(directory, dOff + 24, _labelCreationDate, 0, 4);
|
||||
Array.Copy(directory, dOff + 28, _labelUpdateDate, 0, 4);
|
||||
|
||||
// Count entries 3 by 3 for timestamps
|
||||
switch(dirCnt % 3)
|
||||
{
|
||||
case 0:
|
||||
file1 = null;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
file2 = null;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
file3 = null;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dirCnt++;
|
||||
|
||||
break;
|
||||
case 0x21:
|
||||
if(directory[dOff + 10] == 0x00 &&
|
||||
directory[dOff + 20] == 0x00 &&
|
||||
directory[dOff + 30] == 0x00 &&
|
||||
directory[dOff + 31] == 0x00)
|
||||
{
|
||||
DateEntry dateEntry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<DateEntry>(directory, dOff, 32);
|
||||
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
// Entry contains timestamps for last 3 entries, whatever the kind they are.
|
||||
if(!string.IsNullOrEmpty(file1))
|
||||
{
|
||||
if(_statCache.TryGetValue(file1, out fInfo))
|
||||
_statCache.Remove(file1);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
if(atime)
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date1);
|
||||
else
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date1);
|
||||
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date2);
|
||||
|
||||
_statCache.Add(file1, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file2))
|
||||
{
|
||||
if(_statCache.TryGetValue(file2, out fInfo))
|
||||
_statCache.Remove(file2);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
if(atime)
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date3);
|
||||
else
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date3);
|
||||
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date4);
|
||||
|
||||
_statCache.Add(file2, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file3))
|
||||
{
|
||||
if(_statCache.TryGetValue(file3, out fInfo))
|
||||
_statCache.Remove(file3);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
if(atime)
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date5);
|
||||
else
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date5);
|
||||
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date6);
|
||||
|
||||
_statCache.Add(file3, fInfo);
|
||||
}
|
||||
|
||||
file1 = null;
|
||||
file2 = null;
|
||||
file3 = null;
|
||||
dirCnt = 0;
|
||||
}
|
||||
|
||||
// However, if this byte is 0, timestamp is in Z80DOS or DOS+ format
|
||||
else if(directory[dOff + 1] == 0x00)
|
||||
{
|
||||
TrdPartyDateEntry trdPartyDateEntry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<TrdPartyDateEntry>(directory, dOff, 32);
|
||||
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
// Entry contains timestamps for last 3 entries, whatever the kind they are.
|
||||
if(!string.IsNullOrEmpty(file1))
|
||||
{
|
||||
if(_statCache.TryGetValue(file1, out fInfo))
|
||||
_statCache.Remove(file1);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
var ctime = new byte[4];
|
||||
ctime[0] = trdPartyDateEntry.create1[0];
|
||||
ctime[1] = trdPartyDateEntry.create1[1];
|
||||
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1);
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify1);
|
||||
|
||||
_statCache.Add(file1, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file2))
|
||||
{
|
||||
if(_statCache.TryGetValue(file2, out fInfo))
|
||||
_statCache.Remove(file2);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
var ctime = new byte[4];
|
||||
ctime[0] = trdPartyDateEntry.create2[0];
|
||||
ctime[1] = trdPartyDateEntry.create2[1];
|
||||
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2);
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify2);
|
||||
|
||||
_statCache.Add(file2, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file3))
|
||||
{
|
||||
if(_statCache.TryGetValue(file1, out fInfo))
|
||||
_statCache.Remove(file3);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
var ctime = new byte[4];
|
||||
ctime[0] = trdPartyDateEntry.create3[0];
|
||||
ctime[1] = trdPartyDateEntry.create3[1];
|
||||
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3);
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify3);
|
||||
|
||||
_statCache.Add(file3, fInfo);
|
||||
}
|
||||
|
||||
file1 = null;
|
||||
file2 = null;
|
||||
file3 = null;
|
||||
dirCnt = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Volume label and password entry. Volume password is ignored.
|
||||
else
|
||||
switch(directory[dOff] & 0x7F)
|
||||
{
|
||||
case 0x20:
|
||||
LabelEntry labelEntry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<LabelEntry>(directory, dOff, 32);
|
||||
|
||||
// The volume label defines if one of the fields in CP/M 3 timestamp is a creation or an
|
||||
// access time
|
||||
atime |= (labelEntry.flags & 0x40) == 0x40;
|
||||
|
||||
_label = Encoding.ASCII.GetString(directory, dOff + 1, 11).Trim();
|
||||
_labelCreationDate = new byte[4];
|
||||
_labelUpdateDate = new byte[4];
|
||||
Array.Copy(directory, dOff + 24, _labelCreationDate, 0, 4);
|
||||
Array.Copy(directory, dOff + 28, _labelUpdateDate, 0, 4);
|
||||
|
||||
// Count entries 3 by 3 for timestamps
|
||||
switch(dirCnt % 3)
|
||||
{
|
||||
case 0:
|
||||
file1 = null;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
file2 = null;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
file3 = null;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dirCnt++;
|
||||
|
||||
break;
|
||||
case 0x21:
|
||||
if(directory[dOff + 10] == 0x00 &&
|
||||
directory[dOff + 20] == 0x00 &&
|
||||
directory[dOff + 30] == 0x00 &&
|
||||
directory[dOff + 31] == 0x00)
|
||||
{
|
||||
DateEntry dateEntry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<DateEntry>(directory, dOff, 32);
|
||||
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
// Entry contains timestamps for last 3 entries, whatever the kind they are.
|
||||
if(!string.IsNullOrEmpty(file1))
|
||||
{
|
||||
if(_statCache.TryGetValue(file1, out fInfo))
|
||||
_statCache.Remove(file1);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
if(atime)
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date1);
|
||||
else
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date1);
|
||||
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date2);
|
||||
|
||||
_statCache.Add(file1, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file2))
|
||||
{
|
||||
if(_statCache.TryGetValue(file2, out fInfo))
|
||||
_statCache.Remove(file2);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
if(atime)
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date3);
|
||||
else
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date3);
|
||||
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date4);
|
||||
|
||||
_statCache.Add(file2, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file3))
|
||||
{
|
||||
if(_statCache.TryGetValue(file3, out fInfo))
|
||||
_statCache.Remove(file3);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
if(atime)
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date5);
|
||||
else
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date5);
|
||||
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date6);
|
||||
|
||||
_statCache.Add(file3, fInfo);
|
||||
}
|
||||
|
||||
file1 = null;
|
||||
file2 = null;
|
||||
file3 = null;
|
||||
dirCnt = 0;
|
||||
}
|
||||
|
||||
// However, if this byte is 0, timestamp is in Z80DOS or DOS+ format
|
||||
else if(directory[dOff + 1] == 0x00)
|
||||
{
|
||||
TrdPartyDateEntry trdPartyDateEntry =
|
||||
Marshal.ByteArrayToStructureLittleEndian<TrdPartyDateEntry>(directory, dOff, 32);
|
||||
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
// Entry contains timestamps for last 3 entries, whatever the kind they are.
|
||||
if(!string.IsNullOrEmpty(file1))
|
||||
{
|
||||
if(_statCache.TryGetValue(file1, out fInfo))
|
||||
_statCache.Remove(file1);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
var ctime = new byte[4];
|
||||
ctime[0] = trdPartyDateEntry.create1[0];
|
||||
ctime[1] = trdPartyDateEntry.create1[1];
|
||||
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1);
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify1);
|
||||
|
||||
_statCache.Add(file1, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file2))
|
||||
{
|
||||
if(_statCache.TryGetValue(file2, out fInfo))
|
||||
_statCache.Remove(file2);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
var ctime = new byte[4];
|
||||
ctime[0] = trdPartyDateEntry.create2[0];
|
||||
ctime[1] = trdPartyDateEntry.create2[1];
|
||||
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2);
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify2);
|
||||
|
||||
_statCache.Add(file2, fInfo);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(file3))
|
||||
{
|
||||
if(_statCache.TryGetValue(file1, out fInfo))
|
||||
_statCache.Remove(file3);
|
||||
else
|
||||
fInfo = new FileEntryInfo();
|
||||
|
||||
var ctime = new byte[4];
|
||||
ctime[0] = trdPartyDateEntry.create3[0];
|
||||
ctime[1] = trdPartyDateEntry.create3[1];
|
||||
|
||||
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3);
|
||||
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
|
||||
fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify3);
|
||||
|
||||
_statCache.Add(file3, fInfo);
|
||||
}
|
||||
|
||||
file1 = null;
|
||||
file2 = null;
|
||||
file3 = null;
|
||||
dirCnt = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Cache all files. As CP/M maximum volume size is 8 Mib
|
||||
// this should not be a problem
|
||||
AaruConsole.DebugWriteLine("CP/M Plugin", "Reading files.");
|
||||
|
||||
@@ -468,37 +468,38 @@ public sealed partial class FAT
|
||||
|
||||
break;
|
||||
case 0xFD:
|
||||
if(imagePlugin.Info.Sectors == 4004 &&
|
||||
imagePlugin.Info.SectorSize == 128)
|
||||
switch(imagePlugin.Info.Sectors)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB.");
|
||||
fakeBpb.bps = 128;
|
||||
fakeBpb.spc = 4;
|
||||
fakeBpb.rsectors = 4;
|
||||
fakeBpb.fats_no = 2;
|
||||
fakeBpb.root_ent = 68;
|
||||
fakeBpb.sectors = 4004;
|
||||
fakeBpb.media = 0xFD;
|
||||
fakeBpb.sptrk = 26;
|
||||
fakeBpb.heads = 2;
|
||||
fakeBpb.hsectors = 0;
|
||||
fakeBpb.spfat = 6;
|
||||
}
|
||||
else if(imagePlugin.Info.Sectors == 2002 &&
|
||||
imagePlugin.Info.SectorSize == 128)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB.");
|
||||
fakeBpb.bps = 128;
|
||||
fakeBpb.spc = 4;
|
||||
fakeBpb.rsectors = 4;
|
||||
fakeBpb.fats_no = 2;
|
||||
fakeBpb.root_ent = 68;
|
||||
fakeBpb.sectors = 2002;
|
||||
fakeBpb.media = 0xFD;
|
||||
fakeBpb.sptrk = 26;
|
||||
fakeBpb.heads = 1;
|
||||
fakeBpb.hsectors = 0;
|
||||
fakeBpb.spfat = 6;
|
||||
case 4004 when imagePlugin.Info.SectorSize == 128:
|
||||
AaruConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB.");
|
||||
fakeBpb.bps = 128;
|
||||
fakeBpb.spc = 4;
|
||||
fakeBpb.rsectors = 4;
|
||||
fakeBpb.fats_no = 2;
|
||||
fakeBpb.root_ent = 68;
|
||||
fakeBpb.sectors = 4004;
|
||||
fakeBpb.media = 0xFD;
|
||||
fakeBpb.sptrk = 26;
|
||||
fakeBpb.heads = 2;
|
||||
fakeBpb.hsectors = 0;
|
||||
fakeBpb.spfat = 6;
|
||||
|
||||
break;
|
||||
case 2002 when imagePlugin.Info.SectorSize == 128:
|
||||
AaruConsole.DebugWriteLine("FAT plugin", "Using hardcoded BPB.");
|
||||
fakeBpb.bps = 128;
|
||||
fakeBpb.spc = 4;
|
||||
fakeBpb.rsectors = 4;
|
||||
fakeBpb.fats_no = 2;
|
||||
fakeBpb.root_ent = 68;
|
||||
fakeBpb.sectors = 2002;
|
||||
fakeBpb.media = 0xFD;
|
||||
fakeBpb.sptrk = 26;
|
||||
fakeBpb.heads = 1;
|
||||
fakeBpb.hsectors = 0;
|
||||
fakeBpb.spfat = 6;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -368,33 +368,44 @@ public sealed partial class FAT
|
||||
|
||||
break;
|
||||
case 0xFD:
|
||||
if(imagePlugin.Info.Sectors == 4004 &&
|
||||
imagePlugin.Info.SectorSize == 128)
|
||||
fat2SectorNo = 7;
|
||||
else if(imagePlugin.Info.Sectors == 2002 &&
|
||||
imagePlugin.Info.SectorSize == 128)
|
||||
fat2SectorNo = 7;
|
||||
switch(imagePlugin.Info.Sectors)
|
||||
{
|
||||
case 4004 when imagePlugin.Info.SectorSize == 128:
|
||||
case 2002 when imagePlugin.Info.SectorSize == 128:
|
||||
fat2SectorNo = 7;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 0xFE:
|
||||
if(imagePlugin.Info.Sectors == 320 &&
|
||||
imagePlugin.Info.SectorSize == 512)
|
||||
fat2SectorNo = 2;
|
||||
else if(imagePlugin.Info.Sectors == 2002 &&
|
||||
imagePlugin.Info.SectorSize == 128)
|
||||
fat2SectorNo = 7;
|
||||
else if(imagePlugin.Info.Sectors == 1232 &&
|
||||
imagePlugin.Info.SectorSize == 1024)
|
||||
fat2SectorNo = 3;
|
||||
else if(imagePlugin.Info.Sectors == 616 &&
|
||||
imagePlugin.Info.SectorSize == 1024)
|
||||
fat2SectorNo = 2;
|
||||
else if(imagePlugin.Info.Sectors == 720 &&
|
||||
imagePlugin.Info.SectorSize == 128)
|
||||
fat2SectorNo = 5;
|
||||
else if(imagePlugin.Info.Sectors == 640 &&
|
||||
imagePlugin.Info.SectorSize == 512)
|
||||
fat2SectorNo = 2;
|
||||
switch(imagePlugin.Info.Sectors)
|
||||
{
|
||||
case 320 when imagePlugin.Info.SectorSize == 512:
|
||||
fat2SectorNo = 2;
|
||||
|
||||
break;
|
||||
case 2002 when imagePlugin.Info.SectorSize == 128:
|
||||
fat2SectorNo = 7;
|
||||
|
||||
break;
|
||||
case 1232 when imagePlugin.Info.SectorSize == 1024:
|
||||
fat2SectorNo = 3;
|
||||
|
||||
break;
|
||||
case 616 when imagePlugin.Info.SectorSize == 1024:
|
||||
fat2SectorNo = 2;
|
||||
|
||||
break;
|
||||
case 720 when imagePlugin.Info.SectorSize == 128:
|
||||
fat2SectorNo = 5;
|
||||
|
||||
break;
|
||||
case 640 when imagePlugin.Info.SectorSize == 512:
|
||||
fat2SectorNo = 2;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
@@ -851,8 +862,8 @@ public sealed partial class FAT
|
||||
atariBpb.serial_no[2] == 0x43)
|
||||
sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
|
||||
else
|
||||
XmlFsType.VolumeSerial =
|
||||
$"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{atariBpb.serial_no[2]:X2}";
|
||||
XmlFsType.VolumeSerial = $"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{
|
||||
atariBpb.serial_no[2]:X2}";
|
||||
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(atariBpb.oem_name);
|
||||
|
||||
@@ -866,43 +877,31 @@ public sealed partial class FAT
|
||||
fakeBpb.oem_name[7] == 0x43)
|
||||
sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
|
||||
else
|
||||
{
|
||||
// Later versions of Windows create a DOS 3 BPB without OEM name on 8 sectors/track floppies
|
||||
// OEM ID should be ASCII, otherwise ignore it
|
||||
if(fakeBpb.oem_name[0] >= 0x20 &&
|
||||
fakeBpb.oem_name[0] <= 0x7F &&
|
||||
fakeBpb.oem_name[1] >= 0x20 &&
|
||||
fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 &&
|
||||
fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 &&
|
||||
fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 &&
|
||||
fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 &&
|
||||
fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 &&
|
||||
fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 &&
|
||||
fakeBpb.oem_name[7] <= 0x7F)
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name);
|
||||
else if(fakeBpb.oem_name[0] < 0x20 &&
|
||||
fakeBpb.oem_name[1] >= 0x20 &&
|
||||
fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 &&
|
||||
fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 &&
|
||||
fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 &&
|
||||
fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 &&
|
||||
fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 &&
|
||||
fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 &&
|
||||
fakeBpb.oem_name[7] <= 0x7F)
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1);
|
||||
}
|
||||
switch(fakeBpb.oem_name[0])
|
||||
{
|
||||
// Later versions of Windows create a DOS 3 BPB without OEM name on 8 sectors/track floppies
|
||||
// OEM ID should be ASCII, otherwise ignore it
|
||||
case >= 0x20 and <= 0x7F when fakeBpb.oem_name[1] >= 0x20 && fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 && fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 && fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 && fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 && fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 && fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 && fakeBpb.oem_name[7] <= 0x7F:
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name);
|
||||
|
||||
break;
|
||||
case < 0x20 when fakeBpb.oem_name[1] >= 0x20 && fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 && fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 && fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 && fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 && fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 && fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 && fakeBpb.oem_name[7] <= 0x7F:
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(fakeBpb.signature is 0x28 or 0x29)
|
||||
XmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}";
|
||||
@@ -1096,24 +1095,29 @@ public sealed partial class FAT
|
||||
|
||||
if(XmlFsType.Bootable)
|
||||
{
|
||||
// Intel short jump
|
||||
if(bpbSector[0] == 0xEB &&
|
||||
bpbSector[1] < 0x80)
|
||||
switch(bpbSector[0])
|
||||
{
|
||||
int sigSize = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
|
||||
var bootCode = new byte[512 - sigSize - bpbSector[1] - 2];
|
||||
Array.Copy(bpbSector, bpbSector[1] + 2, bootCode, 0, bootCode.Length);
|
||||
Sha1Context.Data(bootCode, out _);
|
||||
}
|
||||
// Intel short jump
|
||||
case 0xEB when bpbSector[1] < 0x80:
|
||||
{
|
||||
int sigSize = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
|
||||
var bootCode = new byte[512 - sigSize - bpbSector[1] - 2];
|
||||
Array.Copy(bpbSector, bpbSector[1] + 2, bootCode, 0, bootCode.Length);
|
||||
Sha1Context.Data(bootCode, out _);
|
||||
|
||||
// Intel big jump
|
||||
else if(bpbSector[0] == 0xE9 &&
|
||||
BitConverter.ToUInt16(bpbSector, 1) < 0x1FC)
|
||||
{
|
||||
int sigSize = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
|
||||
var bootCode = new byte[512 - sigSize - BitConverter.ToUInt16(bpbSector, 1) - 3];
|
||||
Array.Copy(bpbSector, BitConverter.ToUInt16(bpbSector, 1) + 3, bootCode, 0, bootCode.Length);
|
||||
Sha1Context.Data(bootCode, out _);
|
||||
break;
|
||||
}
|
||||
|
||||
// Intel big jump
|
||||
case 0xE9 when BitConverter.ToUInt16(bpbSector, 1) < 0x1FC:
|
||||
{
|
||||
int sigSize = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
|
||||
var bootCode = new byte[512 - sigSize - BitConverter.ToUInt16(bpbSector, 1) - 3];
|
||||
Array.Copy(bpbSector, BitConverter.ToUInt16(bpbSector, 1) + 3, bootCode, 0, bootCode.Length);
|
||||
Sha1Context.Data(bootCode, out _);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("Volume is bootable");
|
||||
|
||||
@@ -407,8 +407,8 @@ public sealed partial class FAT
|
||||
atariBpb.serial_no[1] != 0x48 ||
|
||||
atariBpb.serial_no[2] != 0x43)
|
||||
{
|
||||
XmlFsType.VolumeSerial =
|
||||
$"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{atariBpb.serial_no[2]:X2}";
|
||||
XmlFsType.VolumeSerial = $"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{
|
||||
atariBpb.serial_no[2]:X2}";
|
||||
|
||||
_statfs.Id = new FileSystemId
|
||||
{
|
||||
@@ -428,43 +428,31 @@ public sealed partial class FAT
|
||||
if(fakeBpb.oem_name[5] != 0x49 ||
|
||||
fakeBpb.oem_name[6] != 0x48 ||
|
||||
fakeBpb.oem_name[7] != 0x43)
|
||||
{
|
||||
// Later versions of Windows create a DOS 3 BPB without OEM name on 8 sectors/track floppies
|
||||
// OEM ID should be ASCII, otherwise ignore it
|
||||
if(fakeBpb.oem_name[0] >= 0x20 &&
|
||||
fakeBpb.oem_name[0] <= 0x7F &&
|
||||
fakeBpb.oem_name[1] >= 0x20 &&
|
||||
fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 &&
|
||||
fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 &&
|
||||
fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 &&
|
||||
fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 &&
|
||||
fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 &&
|
||||
fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 &&
|
||||
fakeBpb.oem_name[7] <= 0x7F)
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name);
|
||||
else if(fakeBpb.oem_name[0] < 0x20 &&
|
||||
fakeBpb.oem_name[1] >= 0x20 &&
|
||||
fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 &&
|
||||
fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 &&
|
||||
fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 &&
|
||||
fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 &&
|
||||
fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 &&
|
||||
fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 &&
|
||||
fakeBpb.oem_name[7] <= 0x7F)
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1);
|
||||
}
|
||||
switch(fakeBpb.oem_name[0])
|
||||
{
|
||||
// Later versions of Windows create a DOS 3 BPB without OEM name on 8 sectors/track floppies
|
||||
// OEM ID should be ASCII, otherwise ignore it
|
||||
case >= 0x20 and <= 0x7F when fakeBpb.oem_name[1] >= 0x20 && fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 && fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 && fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 && fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 && fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 && fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 && fakeBpb.oem_name[7] <= 0x7F:
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name);
|
||||
|
||||
break;
|
||||
case < 0x20 when fakeBpb.oem_name[1] >= 0x20 && fakeBpb.oem_name[1] <= 0x7F &&
|
||||
fakeBpb.oem_name[2] >= 0x20 && fakeBpb.oem_name[2] <= 0x7F &&
|
||||
fakeBpb.oem_name[3] >= 0x20 && fakeBpb.oem_name[3] <= 0x7F &&
|
||||
fakeBpb.oem_name[4] >= 0x20 && fakeBpb.oem_name[4] <= 0x7F &&
|
||||
fakeBpb.oem_name[5] >= 0x20 && fakeBpb.oem_name[5] <= 0x7F &&
|
||||
fakeBpb.oem_name[6] >= 0x20 && fakeBpb.oem_name[6] <= 0x7F &&
|
||||
fakeBpb.oem_name[7] >= 0x20 && fakeBpb.oem_name[7] <= 0x7F:
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(fakeBpb.signature is 0x28 or 0x29)
|
||||
{
|
||||
|
||||
@@ -478,16 +478,17 @@ public sealed class FFSPlugin : IFilesystem
|
||||
sbInformation.AppendFormat("Hardware sector interleave: {0}", sb.fs_old_interleave).AppendLine();
|
||||
sbInformation.AppendFormat("Sector 0 skew: {0}/track", sb.fs_old_trackskew).AppendLine();
|
||||
|
||||
if(!fs_type_43bsd &&
|
||||
sb.fs_id_1 > 0 &&
|
||||
sb.fs_id_2 > 0)
|
||||
sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", sb.fs_id_1, sb.fs_id_2).AppendLine();
|
||||
else if(fs_type_43bsd &&
|
||||
sb.fs_id_1 > 0 &&
|
||||
sb.fs_id_2 > 0)
|
||||
switch(fs_type_43bsd)
|
||||
{
|
||||
sbInformation.AppendFormat("{0} µsec for head switch", sb.fs_id_1).AppendLine();
|
||||
sbInformation.AppendFormat("{0} µsec for track-to-track seek", sb.fs_id_2).AppendLine();
|
||||
case false when sb.fs_id_1 > 0 && sb.fs_id_2 > 0:
|
||||
sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", sb.fs_id_1, sb.fs_id_2).AppendLine();
|
||||
|
||||
break;
|
||||
case true when sb.fs_id_1 > 0 && sb.fs_id_2 > 0:
|
||||
sbInformation.AppendFormat("{0} µsec for head switch", sb.fs_id_1).AppendLine();
|
||||
sbInformation.AppendFormat("{0} µsec for track-to-track seek", sb.fs_id_2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sbInformation.AppendFormat("Cylinder group summary LBA: {0}", sb.fs_old_csaddr).AppendLine();
|
||||
|
||||
@@ -540,8 +540,8 @@ public sealed partial class ISO9660
|
||||
{
|
||||
int systemAreaOff = start;
|
||||
hasResourceFork = false;
|
||||
var continueSymlink = false;
|
||||
var continueSymlinkComponent = false;
|
||||
var continueSymlink = false;
|
||||
var continueSymlinkComponent = false;
|
||||
|
||||
while(systemAreaOff + 2 <= end)
|
||||
{
|
||||
@@ -724,14 +724,21 @@ public sealed partial class ISO9660
|
||||
case RRIP_POSIX_ATTRIBUTES:
|
||||
byte pxLength = data[systemAreaOff + 2];
|
||||
|
||||
if(pxLength == 36)
|
||||
entry.PosixAttributesOld =
|
||||
Marshal.ByteArrayToStructureLittleEndian<PosixAttributesOld>(data, systemAreaOff,
|
||||
Marshal.SizeOf<PosixAttributesOld>());
|
||||
else if(pxLength >= 44)
|
||||
entry.PosixAttributes =
|
||||
Marshal.ByteArrayToStructureLittleEndian<PosixAttributes>(data, systemAreaOff,
|
||||
Marshal.SizeOf<PosixAttributes>());
|
||||
switch(pxLength)
|
||||
{
|
||||
case 36:
|
||||
entry.PosixAttributesOld =
|
||||
Marshal.ByteArrayToStructureLittleEndian<PosixAttributesOld>(data, systemAreaOff,
|
||||
Marshal.SizeOf<PosixAttributesOld>());
|
||||
|
||||
break;
|
||||
case >= 44:
|
||||
entry.PosixAttributes =
|
||||
Marshal.ByteArrayToStructureLittleEndian<PosixAttributes>(data, systemAreaOff,
|
||||
Marshal.SizeOf<PosixAttributes>());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
systemAreaOff += pxLength;
|
||||
|
||||
|
||||
@@ -421,11 +421,11 @@ public sealed partial class LisaFS
|
||||
{
|
||||
byte[] sector;
|
||||
|
||||
ErrorNumber errno = !tags ? _device.ReadSectors((ulong)file.extents[i].start + _mddf.mddf_block + _volumePrefix,
|
||||
(uint)file.extents[i].length, out sector)
|
||||
: _device.ReadSectorsTag((ulong)file.extents[i].start + _mddf.mddf_block + _volumePrefix,
|
||||
(uint)file.extents[i].length, SectorTagType.AppleSectorTag,
|
||||
out sector);
|
||||
ErrorNumber errno =
|
||||
!tags ? _device.ReadSectors((ulong)file.extents[i].start + _mddf.mddf_block + _volumePrefix,
|
||||
(uint)file.extents[i].length, out sector)
|
||||
: _device.ReadSectorsTag((ulong)file.extents[i].start + _mddf.mddf_block + _volumePrefix,
|
||||
(uint)file.extents[i].length, SectorTagType.AppleSectorTag, out sector);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
return errno;
|
||||
@@ -463,19 +463,18 @@ public sealed partial class LisaFS
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(pathElements.Length == 0)
|
||||
switch(pathElements.Length)
|
||||
{
|
||||
fileId = DIRID_ROOT;
|
||||
isDir = true;
|
||||
case 0:
|
||||
fileId = DIRID_ROOT;
|
||||
isDir = true;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
return ErrorNumber.NoError;
|
||||
|
||||
// Only V3 supports subdirectories
|
||||
case > 1 when _mddf.fsversion != LISA_V3: return ErrorNumber.NotSupported;
|
||||
}
|
||||
|
||||
// Only V3 supports subdirectories
|
||||
if(pathElements.Length > 1 &&
|
||||
_mddf.fsversion != LISA_V3)
|
||||
return ErrorNumber.NotSupported;
|
||||
|
||||
if(_debug && pathElements.Length == 1)
|
||||
{
|
||||
if(string.Compare(pathElements[0], "$MDDF", StringComparison.InvariantCulture) == 0)
|
||||
|
||||
@@ -167,11 +167,17 @@ public sealed partial class OperaFS
|
||||
|
||||
var flags = (FileFlags)(entry.flags & FLAGS_MASK);
|
||||
|
||||
if(flags == FileFlags.Directory)
|
||||
stat.Attributes |= FileAttributes.Directory;
|
||||
switch(flags)
|
||||
{
|
||||
case FileFlags.Directory:
|
||||
stat.Attributes |= FileAttributes.Directory;
|
||||
|
||||
if(flags == FileFlags.Special)
|
||||
stat.Attributes |= FileAttributes.Device;
|
||||
break;
|
||||
case FileFlags.Special:
|
||||
stat.Attributes |= FileAttributes.Device;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -225,11 +225,14 @@ public sealed class XZ : IFilter
|
||||
|
||||
int Decode(byte[] buf, int sizeMax, ref ulong num)
|
||||
{
|
||||
if(sizeMax == 0)
|
||||
return 0;
|
||||
switch(sizeMax)
|
||||
{
|
||||
case 0: return 0;
|
||||
case > 9:
|
||||
sizeMax = 9;
|
||||
|
||||
if(sizeMax > 9)
|
||||
sizeMax = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
num = (ulong)(buf[0] & 0x7F);
|
||||
var i = 0;
|
||||
|
||||
@@ -107,21 +107,34 @@ public sealed class MediaInfoViewModel : ViewModelBase
|
||||
{
|
||||
ulong totalSize = scsiInfo.Blocks * scsiInfo.BlockSize;
|
||||
|
||||
if(totalSize > 1099511627776)
|
||||
MediaSize =
|
||||
$"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)";
|
||||
else if(totalSize > 1073741824)
|
||||
MediaSize =
|
||||
$"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)";
|
||||
else if(totalSize > 1048576)
|
||||
MediaSize =
|
||||
$"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)";
|
||||
else if(totalSize > 1024)
|
||||
MediaSize =
|
||||
$"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)";
|
||||
else
|
||||
MediaSize =
|
||||
$"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize} bytes/each. (for a total of {totalSize} bytes)";
|
||||
switch(totalSize)
|
||||
{
|
||||
case > 1099511627776:
|
||||
MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize
|
||||
} bytes/each. (for a total of {totalSize / 1099511627776d:F3} TiB)";
|
||||
|
||||
break;
|
||||
case > 1073741824:
|
||||
MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize
|
||||
} bytes/each. (for a total of {totalSize / 1073741824d:F3} GiB)";
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize
|
||||
} bytes/each. (for a total of {totalSize / 1048576d:F3} MiB)";
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize
|
||||
} bytes/each. (for a total of {totalSize / 1024d:F3} KiB)";
|
||||
|
||||
break;
|
||||
default:
|
||||
MediaSize = $"Media has {scsiInfo.Blocks} blocks of {scsiInfo.BlockSize
|
||||
} bytes/each. (for a total of {totalSize} bytes)";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(scsiInfo.MediaSerialNumber != null)
|
||||
@@ -388,24 +401,21 @@ public sealed class MediaInfoViewModel : ViewModelBase
|
||||
|
||||
async Task ExecuteDumpCommand()
|
||||
{
|
||||
if(_scsiInfo.MediaType is CommonTypes.MediaType.GDR or CommonTypes.MediaType.GDROM)
|
||||
switch(_scsiInfo.MediaType)
|
||||
{
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow("Error", "GD-ROM dump support is not yet implemented.", ButtonEnum.Ok,
|
||||
Icon.Error).ShowDialog(_view);
|
||||
case CommonTypes.MediaType.GDR or CommonTypes.MediaType.GDROM:
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow("Error", "GD-ROM dump support is not yet implemented.", ButtonEnum.Ok,
|
||||
Icon.Error).ShowDialog(_view);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case CommonTypes.MediaType.XGD or CommonTypes.MediaType.XGD2 or CommonTypes.MediaType.XGD3
|
||||
when _scsiInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true:
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow("Error", "Dumping Xbox discs require a Kreon drive.", ButtonEnum.Ok,
|
||||
Icon.Error).ShowDialog(_view);
|
||||
|
||||
if(_scsiInfo.MediaType is CommonTypes.MediaType.XGD or CommonTypes.MediaType.XGD2
|
||||
or CommonTypes.MediaType.XGD3 &&
|
||||
_scsiInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true)
|
||||
{
|
||||
await MessageBoxManager.
|
||||
GetMessageBoxStandardWindow("Error", "Dumping Xbox discs require a Kreon drive.", ButtonEnum.Ok,
|
||||
Icon.Error).ShowDialog(_view);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
var mediaDumpWindow = new MediaDump();
|
||||
|
||||
@@ -83,8 +83,8 @@ public sealed class SubdirectoryViewModel
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
{
|
||||
AaruConsole.
|
||||
ErrorWriteLine($"Error {errno} trying to get information about filesystem entry named {dirent}");
|
||||
AaruConsole.ErrorWriteLine($"Error {errno} trying to get information about filesystem entry named {
|
||||
dirent}");
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -247,16 +247,19 @@ public sealed class SubdirectoryViewModel
|
||||
string corrected = new(chars);
|
||||
|
||||
mboxResult = await MessageBoxManager.GetMessageBoxStandardWindow("Unsupported filename",
|
||||
$"The file name {filename} is not supported on this platform.\nDo you want to rename it to {corrected}?",
|
||||
ButtonEnum.YesNoCancel, Icon.Warning).ShowDialog(_view);
|
||||
$"The file name {filename
|
||||
} is not supported on this platform.\nDo you want to rename it to {corrected
|
||||
}?", ButtonEnum.YesNoCancel, Icon.Warning).ShowDialog(_view);
|
||||
|
||||
if(mboxResult == ButtonResult.Cancel)
|
||||
return;
|
||||
switch(mboxResult)
|
||||
{
|
||||
case ButtonResult.Cancel: return;
|
||||
case ButtonResult.No: continue;
|
||||
default:
|
||||
filename = corrected;
|
||||
|
||||
if(mboxResult == ButtonResult.No)
|
||||
continue;
|
||||
|
||||
filename = corrected;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string outputPath = Path.Combine(folder, filename);
|
||||
@@ -264,27 +267,30 @@ public sealed class SubdirectoryViewModel
|
||||
if(File.Exists(outputPath))
|
||||
{
|
||||
mboxResult = await MessageBoxManager.GetMessageBoxStandardWindow("Existing file",
|
||||
$"A file named {filename} already exists on the destination folder.\nDo you want to overwrite it?",
|
||||
$"A file named {filename
|
||||
} already exists on the destination folder.\nDo you want to overwrite it?",
|
||||
ButtonEnum.YesNoCancel, Icon.Warning).ShowDialog(_view);
|
||||
|
||||
if(mboxResult == ButtonResult.Cancel)
|
||||
return;
|
||||
|
||||
if(mboxResult == ButtonResult.No)
|
||||
continue;
|
||||
|
||||
try
|
||||
switch(mboxResult)
|
||||
{
|
||||
File.Delete(outputPath);
|
||||
}
|
||||
catch(IOException)
|
||||
{
|
||||
mboxResult = await MessageBoxManager.GetMessageBoxStandardWindow("Cannot delete",
|
||||
"Could not delete existing file.\nDo you want to continue?", ButtonEnum.YesNo,
|
||||
Icon.Error).ShowDialog(_view);
|
||||
case ButtonResult.Cancel: return;
|
||||
case ButtonResult.No: continue;
|
||||
default:
|
||||
try
|
||||
{
|
||||
File.Delete(outputPath);
|
||||
}
|
||||
catch(IOException)
|
||||
{
|
||||
mboxResult = await MessageBoxManager.GetMessageBoxStandardWindow("Cannot delete",
|
||||
"Could not delete existing file.\nDo you want to continue?",
|
||||
ButtonEnum.YesNo, Icon.Error).ShowDialog(_view);
|
||||
|
||||
if(mboxResult == ButtonResult.No)
|
||||
return;
|
||||
if(mboxResult == ButtonResult.No)
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -430,193 +430,192 @@ public sealed class ScsiInfoViewModel : ViewModelBase
|
||||
var evpdPageTitle = "";
|
||||
string evpdDecodedPage;
|
||||
|
||||
if(page.Key >= 0x01 &&
|
||||
page.Key <= 0x7F)
|
||||
switch(page.Key)
|
||||
{
|
||||
evpdPageTitle = $"ASCII Page {page.Key:X2}h";
|
||||
evpdDecodedPage = EVPD.DecodeASCIIPage(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x80)
|
||||
{
|
||||
evpdPageTitle = "Unit Serial Number";
|
||||
evpdDecodedPage = EVPD.DecodePage80(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x81)
|
||||
{
|
||||
evpdPageTitle = "SCSI Implemented operating definitions";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_81(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x82)
|
||||
{
|
||||
evpdPageTitle = "ASCII implemented operating definitions";
|
||||
evpdDecodedPage = EVPD.DecodePage82(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x83)
|
||||
{
|
||||
evpdPageTitle = "SCSI Device identification";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_83(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x84)
|
||||
{
|
||||
evpdPageTitle = "SCSI Software Interface Identifiers";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_84(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x85)
|
||||
{
|
||||
evpdPageTitle = "SCSI Management Network Addresses";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_85(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x86)
|
||||
{
|
||||
evpdPageTitle = "SCSI Extended INQUIRY Data";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_86(page.Value);
|
||||
}
|
||||
else if(page.Key == 0x89)
|
||||
{
|
||||
evpdPageTitle = "SCSI to ATA Translation Layer Data";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_89(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB0)
|
||||
{
|
||||
evpdPageTitle = "SCSI Sequential-access Device Capabilities";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_B0(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB1)
|
||||
{
|
||||
evpdPageTitle = "Manufacturer-assigned Serial Number";
|
||||
evpdDecodedPage = EVPD.DecodePageB1(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB2)
|
||||
{
|
||||
evpdPageTitle = "TapeAlert Supported Flags Bitmap";
|
||||
evpdDecodedPage = $"0x{EVPD.DecodePageB2(page.Value):X16}";
|
||||
}
|
||||
else if(page.Key == 0xB3)
|
||||
{
|
||||
evpdPageTitle = "Automation Device Serial Number";
|
||||
evpdDecodedPage = EVPD.DecodePageB3(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB4)
|
||||
{
|
||||
evpdPageTitle = "Data Transfer Device Element Address";
|
||||
evpdDecodedPage = EVPD.DecodePageB4(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC0 &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"quantum")
|
||||
{
|
||||
evpdPageTitle = "Quantum Firmware Build Information page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_Quantum(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC0 &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"seagate")
|
||||
{
|
||||
evpdPageTitle = "Seagate Firmware Numbers page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_Seagate(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC0 &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"ibm")
|
||||
{
|
||||
evpdPageTitle = "IBM Drive Component Revision Levels page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_IBM(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC1 &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"ibm")
|
||||
{
|
||||
evpdPageTitle = "IBM Drive Serial Numbers page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C1_IBM(page.Value);
|
||||
}
|
||||
else if(page.Key is 0xC0 or 0xC1 &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"certance")
|
||||
{
|
||||
evpdPageTitle = "Certance Drive Component Revision Levels page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_C1_Certance(page.Value);
|
||||
}
|
||||
else if(page.Key is 0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6 &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"certance")
|
||||
{
|
||||
switch(page.Key)
|
||||
case >= 0x01 and <= 0x7F:
|
||||
evpdPageTitle = $"ASCII Page {page.Key:X2}h";
|
||||
evpdDecodedPage = EVPD.DecodeASCIIPage(page.Value);
|
||||
|
||||
break;
|
||||
case 0x80:
|
||||
evpdPageTitle = "Unit Serial Number";
|
||||
evpdDecodedPage = EVPD.DecodePage80(page.Value);
|
||||
|
||||
break;
|
||||
case 0x81:
|
||||
evpdPageTitle = "SCSI Implemented operating definitions";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_81(page.Value);
|
||||
|
||||
break;
|
||||
case 0x82:
|
||||
evpdPageTitle = "ASCII implemented operating definitions";
|
||||
evpdDecodedPage = EVPD.DecodePage82(page.Value);
|
||||
|
||||
break;
|
||||
case 0x83:
|
||||
evpdPageTitle = "SCSI Device identification";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_83(page.Value);
|
||||
|
||||
break;
|
||||
case 0x84:
|
||||
evpdPageTitle = "SCSI Software Interface Identifiers";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_84(page.Value);
|
||||
|
||||
break;
|
||||
case 0x85:
|
||||
evpdPageTitle = "SCSI Management Network Addresses";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_85(page.Value);
|
||||
|
||||
break;
|
||||
case 0x86:
|
||||
evpdPageTitle = "SCSI Extended INQUIRY Data";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_86(page.Value);
|
||||
|
||||
break;
|
||||
case 0x89:
|
||||
evpdPageTitle = "SCSI to ATA Translation Layer Data";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_89(page.Value);
|
||||
|
||||
break;
|
||||
case 0xB0:
|
||||
evpdPageTitle = "SCSI Sequential-access Device Capabilities";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_B0(page.Value);
|
||||
|
||||
break;
|
||||
case 0xB1:
|
||||
evpdPageTitle = "Manufacturer-assigned Serial Number";
|
||||
evpdDecodedPage = EVPD.DecodePageB1(page.Value);
|
||||
|
||||
break;
|
||||
case 0xB2:
|
||||
evpdPageTitle = "TapeAlert Supported Flags Bitmap";
|
||||
evpdDecodedPage = $"0x{EVPD.DecodePageB2(page.Value):X16}";
|
||||
|
||||
break;
|
||||
case 0xB3:
|
||||
evpdPageTitle = "Automation Device Serial Number";
|
||||
evpdDecodedPage = EVPD.DecodePageB3(page.Value);
|
||||
|
||||
break;
|
||||
case 0xB4:
|
||||
evpdPageTitle = "Data Transfer Device Element Address";
|
||||
evpdDecodedPage = EVPD.DecodePageB4(page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "quantum":
|
||||
evpdPageTitle = "Quantum Firmware Build Information page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_Quantum(page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "seagate":
|
||||
evpdPageTitle = "Seagate Firmware Numbers page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_Seagate(page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "ibm":
|
||||
evpdPageTitle = "IBM Drive Component Revision Levels page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_IBM(page.Value);
|
||||
|
||||
break;
|
||||
case 0xC1 when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "ibm":
|
||||
evpdPageTitle = "IBM Drive Serial Numbers page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C1_IBM(page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 or 0xC1
|
||||
when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "certance":
|
||||
evpdPageTitle = "Certance Drive Component Revision Levels page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_C1_Certance(page.Value);
|
||||
|
||||
break;
|
||||
case 0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6
|
||||
when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "certance":
|
||||
switch(page.Key)
|
||||
{
|
||||
case 0xC2:
|
||||
evpdPageTitle = "Head Assembly Serial Number";
|
||||
|
||||
break;
|
||||
case 0xC3:
|
||||
evpdPageTitle = "Reel Motor 1 Serial Number";
|
||||
|
||||
break;
|
||||
case 0xC4:
|
||||
evpdPageTitle = "Reel Motor 2 Serial Number";
|
||||
|
||||
break;
|
||||
case 0xC5:
|
||||
evpdPageTitle = "Board Serial Number";
|
||||
|
||||
break;
|
||||
case 0xC6:
|
||||
evpdPageTitle = "Base Mechanical Serial Number";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 or 0xC1 or 0xC2 or 0xC3 or 0xC4 or 0xC5
|
||||
when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "hp":
|
||||
switch(page.Key)
|
||||
{
|
||||
case 0xC0:
|
||||
evpdPageTitle = "HP Drive Firmware Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC1:
|
||||
evpdPageTitle = "HP Drive Hardware Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC2:
|
||||
evpdPageTitle = "HP Drive PCA Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC3:
|
||||
evpdPageTitle = "HP Drive Mechanism Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC4:
|
||||
evpdPageTitle = "HP Drive Head Assembly Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC5:
|
||||
evpdPageTitle = "HP Drive ACI Revision Levels page:";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_to_C5_HP(page.Value);
|
||||
|
||||
break;
|
||||
case 0xDF when StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "certance":
|
||||
evpdPageTitle = "Certance drive status page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_DF_Certance(page.Value);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
case 0xC2:
|
||||
evpdPageTitle = "Head Assembly Serial Number";
|
||||
if(page.Key == 0x00)
|
||||
continue;
|
||||
|
||||
break;
|
||||
case 0xC3:
|
||||
evpdPageTitle = "Reel Motor 1 Serial Number";
|
||||
evpdPageTitle = $"Page {page.Key:X2}h";
|
||||
evpdDecodedPage = "Undecoded";
|
||||
|
||||
break;
|
||||
case 0xC4:
|
||||
evpdPageTitle = "Reel Motor 2 Serial Number";
|
||||
AaruConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}",
|
||||
page.Key);
|
||||
|
||||
break;
|
||||
case 0xC5:
|
||||
evpdPageTitle = "Board Serial Number";
|
||||
|
||||
break;
|
||||
case 0xC6:
|
||||
evpdPageTitle = "Base Mechanical Serial Number";
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value);
|
||||
}
|
||||
else if(page.Key is 0xC0 or 0xC1 or 0xC2 or 0xC3 or 0xC4 or 0xC5 &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"hp")
|
||||
{
|
||||
switch(page.Key)
|
||||
{
|
||||
case 0xC0:
|
||||
evpdPageTitle = "HP Drive Firmware Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC1:
|
||||
evpdPageTitle = "HP Drive Hardware Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC2:
|
||||
evpdPageTitle = "HP Drive PCA Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC3:
|
||||
evpdPageTitle = "HP Drive Mechanism Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC4:
|
||||
evpdPageTitle = "HP Drive Head Assembly Revision Levels page:";
|
||||
|
||||
break;
|
||||
case 0xC5:
|
||||
evpdPageTitle = "HP Drive ACI Revision Levels page:";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
evpdDecodedPage = EVPD.PrettifyPage_C0_to_C5_HP(page.Value);
|
||||
}
|
||||
else if(page.Key == 0xDF &&
|
||||
StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() ==
|
||||
"certance")
|
||||
{
|
||||
evpdPageTitle = "Certance drive status page";
|
||||
evpdDecodedPage = EVPD.PrettifyPage_DF_Certance(page.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(page.Key == 0x00)
|
||||
continue;
|
||||
|
||||
evpdPageTitle = $"Page {page.Key:X2}h";
|
||||
evpdDecodedPage = "Undecoded";
|
||||
|
||||
AaruConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}",
|
||||
page.Key);
|
||||
}
|
||||
|
||||
EvpdPages.Add(new ScsiPageModel
|
||||
|
||||
@@ -450,14 +450,25 @@ public sealed class MediaScanViewModel : ViewModelBase
|
||||
case 0x0020:
|
||||
case 0x0021:
|
||||
case 0x0022:
|
||||
if(blocks <= 360000)
|
||||
MaxX = 360000;
|
||||
else if(blocks <= 405000)
|
||||
MaxX = 405000;
|
||||
else if(blocks <= 445500)
|
||||
MaxX = 445500;
|
||||
else
|
||||
MaxX = blocks;
|
||||
switch(blocks)
|
||||
{
|
||||
case <= 360000:
|
||||
MaxX = 360000;
|
||||
|
||||
break;
|
||||
case <= 405000:
|
||||
MaxX = 405000;
|
||||
|
||||
break;
|
||||
case <= 445500:
|
||||
MaxX = 445500;
|
||||
|
||||
break;
|
||||
default:
|
||||
MaxX = blocks;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
StepsX = MaxX / 10;
|
||||
StepsY = 150 * 4;
|
||||
@@ -493,16 +504,29 @@ public sealed class MediaScanViewModel : ViewModelBase
|
||||
case 0x0042:
|
||||
case 0x0043:
|
||||
case 0x0040: // BD
|
||||
if(blocks <= 12219392)
|
||||
MaxX = 12219392;
|
||||
else if(blocks <= 24438784)
|
||||
MaxX = 24438784;
|
||||
else if(blocks <= 48878592)
|
||||
MaxX = 48878592;
|
||||
else if(blocks <= 62500864)
|
||||
MaxX = 62500864;
|
||||
else
|
||||
MaxX = blocks;
|
||||
switch(blocks)
|
||||
{
|
||||
case <= 12219392:
|
||||
MaxX = 12219392;
|
||||
|
||||
break;
|
||||
case <= 24438784:
|
||||
MaxX = 24438784;
|
||||
|
||||
break;
|
||||
case <= 48878592:
|
||||
MaxX = 48878592;
|
||||
|
||||
break;
|
||||
case <= 62500864:
|
||||
MaxX = 62500864;
|
||||
|
||||
break;
|
||||
default:
|
||||
MaxX = blocks;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
StepsX = MaxX / 10;
|
||||
StepsY = 4394.5;
|
||||
@@ -515,12 +539,21 @@ public sealed class MediaScanViewModel : ViewModelBase
|
||||
case 0x0053:
|
||||
case 0x0058:
|
||||
case 0x005A:
|
||||
if(blocks <= 7361599)
|
||||
MaxX = 7361599;
|
||||
else if(blocks <= 16305407)
|
||||
MaxX = 16305407;
|
||||
else
|
||||
MaxX = blocks;
|
||||
switch(blocks)
|
||||
{
|
||||
case <= 7361599:
|
||||
MaxX = 7361599;
|
||||
|
||||
break;
|
||||
case <= 16305407:
|
||||
MaxX = 16305407;
|
||||
|
||||
break;
|
||||
default:
|
||||
MaxX = blocks;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
StepsX = MaxX / 10;
|
||||
StepsY = 4394.5;
|
||||
@@ -596,22 +629,33 @@ public sealed class MediaScanViewModel : ViewModelBase
|
||||
{
|
||||
BlockMapList.Add((sector / _blocksToRead, duration));
|
||||
|
||||
if(duration < 3)
|
||||
_localResults.A += _blocksToRead;
|
||||
else if(duration >= 3 &&
|
||||
duration < 10)
|
||||
_localResults.B += _blocksToRead;
|
||||
else if(duration >= 10 &&
|
||||
duration < 50)
|
||||
_localResults.C += _blocksToRead;
|
||||
else if(duration >= 50 &&
|
||||
duration < 150)
|
||||
_localResults.D += _blocksToRead;
|
||||
else if(duration >= 150 &&
|
||||
duration < 500)
|
||||
_localResults.E += _blocksToRead;
|
||||
else if(duration >= 500)
|
||||
_localResults.F += _blocksToRead;
|
||||
switch(duration)
|
||||
{
|
||||
case < 3:
|
||||
_localResults.A += _blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 3 and < 10:
|
||||
_localResults.B += _blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 10 and < 50:
|
||||
_localResults.C += _blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 50 and < 150:
|
||||
_localResults.D += _blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 150 and < 500:
|
||||
_localResults.E += _blocksToRead;
|
||||
|
||||
break;
|
||||
case >= 500:
|
||||
_localResults.F += _blocksToRead;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
A = $"{_localResults.A} sectors took less than 3 ms.";
|
||||
B = $"{_localResults.B} sectors took less than 10 ms but more than 3 ms.";
|
||||
|
||||
Submodule Aaru.Helpers updated: c1196f636d...cd2d27c2cf
@@ -411,8 +411,8 @@ public sealed partial class AaruFormat
|
||||
|
||||
if(decompressedLength != blockHeader.length)
|
||||
{
|
||||
ErrorMessage =
|
||||
$"Error decompressing block, should be {blockHeader.length} bytes but got {decompressedLength} bytes.";
|
||||
ErrorMessage = $"Error decompressing block, should be {blockHeader.length
|
||||
} bytes but got {decompressedLength} bytes.";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -598,8 +598,8 @@ public sealed partial class AaruFormat
|
||||
if(ddtHeader.entries != _imageInfo.Sectors &&
|
||||
!IsTape)
|
||||
{
|
||||
ErrorMessage =
|
||||
$"Trying to write a media with {_imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing...";
|
||||
ErrorMessage = $"Trying to write a media with {_imageInfo.Sectors
|
||||
} sectors to an image with {ddtHeader.entries} sectors, not continuing...";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -625,8 +625,8 @@ public sealed partial class AaruFormat
|
||||
|
||||
if(decompressedLength != ddtHeader.length)
|
||||
{
|
||||
ErrorMessage =
|
||||
$"Error decompressing DDT, should be {ddtHeader.length} bytes but got {decompressedLength} bytes.";
|
||||
ErrorMessage = $"Error decompressing DDT, should be {ddtHeader.length
|
||||
} bytes but got {decompressedLength} bytes.";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -646,8 +646,8 @@ public sealed partial class AaruFormat
|
||||
|
||||
break;
|
||||
default:
|
||||
ErrorMessage =
|
||||
$"Found unsupported compression algorithm {(ushort)ddtHeader.compression}";
|
||||
ErrorMessage = $"Found unsupported compression algorithm {
|
||||
(ushort)ddtHeader.compression}";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -676,8 +676,8 @@ public sealed partial class AaruFormat
|
||||
|
||||
if(ddtHeader.entries != _imageInfo.Sectors)
|
||||
{
|
||||
ErrorMessage =
|
||||
$"Trying to write a media with {_imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing...";
|
||||
ErrorMessage = $"Trying to write a media with {_imageInfo.Sectors
|
||||
} sectors to an image with {ddtHeader.entries} sectors, not continuing...";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -702,8 +702,8 @@ public sealed partial class AaruFormat
|
||||
|
||||
if(decompressedLength != ddtHeader.length)
|
||||
{
|
||||
ErrorMessage =
|
||||
$"Error decompressing DDT, should be {ddtHeader.length} bytes but got {decompressedLength} bytes.";
|
||||
ErrorMessage = $"Error decompressing DDT, should be {ddtHeader.length
|
||||
} bytes but got {decompressedLength} bytes.";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -720,8 +720,8 @@ public sealed partial class AaruFormat
|
||||
|
||||
break;
|
||||
default:
|
||||
ErrorMessage =
|
||||
$"Found unsupported compression algorithm {(ushort)ddtHeader.compression}";
|
||||
ErrorMessage = $"Found unsupported compression algorithm {
|
||||
(ushort)ddtHeader.compression}";
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -2590,8 +2590,8 @@ public sealed partial class AaruFormat
|
||||
switch(_compressionAlgorithm)
|
||||
{
|
||||
case CompressionType.Lzma:
|
||||
int cmpLen = LZMA.EncodeBuffer(mediaTag.Value, cmpBuffer, out lzmaProperties, 9, _dictionarySize, 4, 0,
|
||||
2, 273);
|
||||
int cmpLen = LZMA.EncodeBuffer(mediaTag.Value, cmpBuffer, out lzmaProperties, 9, _dictionarySize, 4,
|
||||
0, 2, 273);
|
||||
|
||||
if(cmpLen + LZMA_PROPERTIES_LENGTH > mediaTag.Value.Length)
|
||||
doNotCompress = true;
|
||||
@@ -3330,26 +3330,56 @@ public sealed partial class AaruFormat
|
||||
uint emptyMode2Form1 = 0;
|
||||
|
||||
for(long i = 0; i < _sectorPrefixDdt.LongLength; i++)
|
||||
if((_sectorPrefixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped)
|
||||
notDumpedPrefixes++;
|
||||
else if((_sectorPrefixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct)
|
||||
correctPrefixes++;
|
||||
else if((_sectorPrefixDdt[i] & CD_DFIX_MASK) > 0)
|
||||
writtenPrefixes++;
|
||||
switch(_sectorPrefixDdt[i] & CD_XFIX_MASK)
|
||||
{
|
||||
case (uint)CdFixFlags.NotDumped:
|
||||
notDumpedPrefixes++;
|
||||
|
||||
break;
|
||||
case (uint)CdFixFlags.Correct:
|
||||
correctPrefixes++;
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if((_sectorPrefixDdt[i] & CD_DFIX_MASK) > 0)
|
||||
writtenPrefixes++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(long i = 0; i < _sectorPrefixDdt.LongLength; i++)
|
||||
if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped)
|
||||
notDumpedSuffixes++;
|
||||
else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct)
|
||||
correctSuffixes++;
|
||||
else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form1Ok)
|
||||
correctMode2Form1++;
|
||||
else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form2Ok)
|
||||
correctMode2Form2++;
|
||||
else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form2NoCrc)
|
||||
emptyMode2Form1++;
|
||||
else if((_sectorSuffixDdt[i] & CD_DFIX_MASK) > 0)
|
||||
writtenSuffixes++;
|
||||
switch(_sectorSuffixDdt[i] & CD_XFIX_MASK)
|
||||
{
|
||||
case (uint)CdFixFlags.NotDumped:
|
||||
notDumpedSuffixes++;
|
||||
|
||||
break;
|
||||
case (uint)CdFixFlags.Correct:
|
||||
correctSuffixes++;
|
||||
|
||||
break;
|
||||
case (uint)CdFixFlags.Mode2Form1Ok:
|
||||
correctMode2Form1++;
|
||||
|
||||
break;
|
||||
case (uint)CdFixFlags.Mode2Form2Ok:
|
||||
correctMode2Form2++;
|
||||
|
||||
break;
|
||||
case (uint)CdFixFlags.Mode2Form2NoCrc:
|
||||
emptyMode2Form1++;
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if((_sectorSuffixDdt[i] & CD_DFIX_MASK) > 0)
|
||||
writtenSuffixes++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine("Aaru Format plugin",
|
||||
"{0} ({1:P}% prefixes are correct, {2} ({3:P}%) prefixes have not been dumped, {4} ({5:P}%) prefixes have been written to image",
|
||||
@@ -4110,15 +4140,18 @@ public sealed partial class AaruFormat
|
||||
flags = flags
|
||||
});
|
||||
|
||||
if(!track.Indexes.ContainsKey(0) &&
|
||||
track.Pregap > 0)
|
||||
switch(track.Indexes.ContainsKey(0))
|
||||
{
|
||||
track.Indexes[0] = (int)track.StartSector;
|
||||
track.Indexes[1] = (int)(track.StartSector + track.Pregap);
|
||||
case false when track.Pregap > 0:
|
||||
track.Indexes[0] = (int)track.StartSector;
|
||||
track.Indexes[1] = (int)(track.StartSector + track.Pregap);
|
||||
|
||||
break;
|
||||
case false when !track.Indexes.ContainsKey(1):
|
||||
track.Indexes[0] = (int)track.StartSector;
|
||||
|
||||
break;
|
||||
}
|
||||
else if(!track.Indexes.ContainsKey(0) &&
|
||||
!track.Indexes.ContainsKey(1))
|
||||
track.Indexes[0] = (int)track.StartSector;
|
||||
|
||||
compactDiscIndexEntries.AddRange(track.Indexes.Select(trackIndex => new CompactDiscIndexEntry
|
||||
{
|
||||
|
||||
@@ -134,12 +134,21 @@ public sealed partial class AppleNib
|
||||
_imageInfo.LastModificationTime = imageFilter.LastWriteTime;
|
||||
_imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.Filename);
|
||||
|
||||
if(_imageInfo.Sectors == 455)
|
||||
_imageInfo.MediaType = MediaType.Apple32SS;
|
||||
else if(_imageInfo.Sectors == 560)
|
||||
_imageInfo.MediaType = MediaType.Apple33SS;
|
||||
else
|
||||
_imageInfo.MediaType = MediaType.Unknown;
|
||||
switch(_imageInfo.Sectors)
|
||||
{
|
||||
case 455:
|
||||
_imageInfo.MediaType = MediaType.Apple32SS;
|
||||
|
||||
break;
|
||||
case 560:
|
||||
_imageInfo.MediaType = MediaType.Apple33SS;
|
||||
|
||||
break;
|
||||
default:
|
||||
_imageInfo.MediaType = MediaType.Unknown;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_imageInfo.SectorSize = 256;
|
||||
_imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
|
||||
|
||||
@@ -99,28 +99,36 @@ public sealed partial class CopyQm
|
||||
|
||||
var runLength = BitConverter.ToInt16(runLengthBytes, 0);
|
||||
|
||||
if(runLength < 0)
|
||||
switch(runLength)
|
||||
{
|
||||
var repeatedByte = (byte)stream.ReadByte();
|
||||
var repeatedArray = new byte[runLength * -1];
|
||||
ArrayHelpers.ArrayFill(repeatedArray, repeatedByte);
|
||||
|
||||
for(var i = 0; i < runLength * -1; i++)
|
||||
case < 0:
|
||||
{
|
||||
_decodedImage.WriteByte(repeatedByte);
|
||||
var repeatedByte = (byte)stream.ReadByte();
|
||||
var repeatedArray = new byte[runLength * -1];
|
||||
ArrayHelpers.ArrayFill(repeatedArray, repeatedByte);
|
||||
|
||||
_calculatedDataCrc = _copyQmCrcTable[(repeatedByte ^ _calculatedDataCrc) & 0x3F] ^
|
||||
(_calculatedDataCrc >> 8);
|
||||
for(var i = 0; i < runLength * -1; i++)
|
||||
{
|
||||
_decodedImage.WriteByte(repeatedByte);
|
||||
|
||||
_calculatedDataCrc = _copyQmCrcTable[(repeatedByte ^ _calculatedDataCrc) & 0x3F] ^
|
||||
(_calculatedDataCrc >> 8);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(runLength > 0)
|
||||
{
|
||||
var nonRepeated = new byte[runLength];
|
||||
stream.Read(nonRepeated, 0, runLength);
|
||||
_decodedImage.Write(nonRepeated, 0, runLength);
|
||||
case > 0:
|
||||
{
|
||||
var nonRepeated = new byte[runLength];
|
||||
stream.Read(nonRepeated, 0, runLength);
|
||||
_decodedImage.Write(nonRepeated, 0, runLength);
|
||||
|
||||
foreach(byte c in nonRepeated)
|
||||
_calculatedDataCrc = _copyQmCrcTable[(c ^ _calculatedDataCrc) & 0x3F] ^ (_calculatedDataCrc >> 8);
|
||||
foreach(byte c in nonRepeated)
|
||||
_calculatedDataCrc =
|
||||
_copyQmCrcTable[(c ^ _calculatedDataCrc) & 0x3F] ^ (_calculatedDataCrc >> 8);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -264,37 +264,41 @@ public sealed partial class DiskCopy42
|
||||
|
||||
for(var i = 0; i < 46; i++)
|
||||
{
|
||||
if(i >= 0 &&
|
||||
i <= 3)
|
||||
sectorsToCopy = 22;
|
||||
switch(i)
|
||||
{
|
||||
case >= 0 and <= 3:
|
||||
sectorsToCopy = 22;
|
||||
|
||||
if(i >= 4 &&
|
||||
i <= 10)
|
||||
sectorsToCopy = 21;
|
||||
break;
|
||||
case >= 4 and <= 10:
|
||||
sectorsToCopy = 21;
|
||||
|
||||
if(i >= 11 &&
|
||||
i <= 16)
|
||||
sectorsToCopy = 20;
|
||||
break;
|
||||
case >= 11 and <= 16:
|
||||
sectorsToCopy = 20;
|
||||
|
||||
if(i >= 17 &&
|
||||
i <= 22)
|
||||
sectorsToCopy = 19;
|
||||
break;
|
||||
case >= 17 and <= 22:
|
||||
sectorsToCopy = 19;
|
||||
|
||||
if(i >= 23 &&
|
||||
i <= 28)
|
||||
sectorsToCopy = 18;
|
||||
break;
|
||||
case >= 23 and <= 28:
|
||||
sectorsToCopy = 18;
|
||||
|
||||
if(i >= 29 &&
|
||||
i <= 34)
|
||||
sectorsToCopy = 17;
|
||||
break;
|
||||
case >= 29 and <= 34:
|
||||
sectorsToCopy = 17;
|
||||
|
||||
if(i >= 35 &&
|
||||
i <= 41)
|
||||
sectorsToCopy = 16;
|
||||
break;
|
||||
case >= 35 and <= 41:
|
||||
sectorsToCopy = 16;
|
||||
|
||||
if(i >= 42 &&
|
||||
i <= 45)
|
||||
sectorsToCopy = 15;
|
||||
break;
|
||||
case >= 42 and <= 45:
|
||||
sectorsToCopy = 15;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Array.Copy(data, header.DataSize / 2 + copiedSectors * 512, twiggyCache,
|
||||
twiggyCache.Length - copiedSectors * 512 - sectorsToCopy * 512, sectorsToCopy * 512);
|
||||
|
||||
@@ -481,27 +481,33 @@ public sealed partial class Gdi
|
||||
|
||||
br.BaseStream.Seek(pos, SeekOrigin.Begin);
|
||||
|
||||
if(sectorOffset == 0 &&
|
||||
sectorSkip == 0 &&
|
||||
remainingSectors == length)
|
||||
buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
else if(sectorOffset == 0 &&
|
||||
sectorSkip == 0)
|
||||
switch(sectorOffset)
|
||||
{
|
||||
byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
var bufferPos = (int)((length - remainingSectors) * sectorSize);
|
||||
case 0 when sectorSkip == 0 && remainingSectors == length:
|
||||
buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
|
||||
for(ulong i = 0; i < remainingSectors; i++)
|
||||
break;
|
||||
case 0 when sectorSkip == 0:
|
||||
{
|
||||
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
|
||||
byte[] sector = br.ReadBytes((int)sectorSize);
|
||||
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
|
||||
Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
|
||||
bufferPos += (int)sectorSize;
|
||||
byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
var bufferPos = (int)((length - remainingSectors) * sectorSize);
|
||||
|
||||
for(ulong i = 0; i < remainingSectors; i++)
|
||||
{
|
||||
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
|
||||
byte[] sector = br.ReadBytes((int)sectorSize);
|
||||
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
|
||||
Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
|
||||
bufferPos += (int)sectorSize;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,27 +675,33 @@ public sealed partial class Gdi
|
||||
|
||||
br.BaseStream.Seek(pos, SeekOrigin.Begin);
|
||||
|
||||
if(sectorOffset == 0 &&
|
||||
sectorSkip == 0 &&
|
||||
remainingSectors == length)
|
||||
buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
else if(sectorOffset == 0 &&
|
||||
sectorSkip == 0)
|
||||
switch(sectorOffset)
|
||||
{
|
||||
byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
var bufferPos = (int)((length - remainingSectors) * sectorSize);
|
||||
case 0 when sectorSkip == 0 && remainingSectors == length:
|
||||
buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
|
||||
for(ulong i = 0; i < remainingSectors; i++)
|
||||
break;
|
||||
case 0 when sectorSkip == 0:
|
||||
{
|
||||
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
|
||||
byte[] sector = br.ReadBytes((int)sectorSize);
|
||||
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
|
||||
Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
|
||||
bufferPos += (int)sectorSize;
|
||||
byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
var bufferPos = (int)((length - remainingSectors) * sectorSize);
|
||||
|
||||
for(ulong i = 0; i < remainingSectors; i++)
|
||||
{
|
||||
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
|
||||
byte[] sector = br.ReadBytes((int)sectorSize);
|
||||
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
|
||||
Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
|
||||
bufferPos += (int)sectorSize;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,27 +822,33 @@ public sealed partial class Gdi
|
||||
|
||||
br.BaseStream.Seek(pos, SeekOrigin.Begin);
|
||||
|
||||
if(sectorOffset == 0 &&
|
||||
sectorSkip == 0 &&
|
||||
remainingSectors == length)
|
||||
buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
else if(sectorOffset == 0 &&
|
||||
sectorSkip == 0)
|
||||
switch(sectorOffset)
|
||||
{
|
||||
byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
var bufferPos = (int)((length - remainingSectors) * sectorSize);
|
||||
case 0 when sectorSkip == 0 && remainingSectors == length:
|
||||
buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
|
||||
for(ulong i = 0; i < remainingSectors; i++)
|
||||
break;
|
||||
case 0 when sectorSkip == 0:
|
||||
{
|
||||
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
|
||||
byte[] sector = br.ReadBytes((int)sectorSize);
|
||||
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
|
||||
Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
|
||||
bufferPos += (int)sectorSize;
|
||||
byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
|
||||
Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
var bufferPos = (int)((length - remainingSectors) * sectorSize);
|
||||
|
||||
for(ulong i = 0; i < remainingSectors; i++)
|
||||
{
|
||||
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
|
||||
byte[] sector = br.ReadBytes((int)sectorSize);
|
||||
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
|
||||
Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
|
||||
bufferPos += (int)sectorSize;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -260,10 +260,17 @@ public sealed partial class Ndif
|
||||
_imageInfo.Application = version.VersionString;
|
||||
_imageInfo.Comments = version.VersionMessage;
|
||||
|
||||
if(version.MajorVersion == 3)
|
||||
_imageInfo.Application = "ShrinkWrap™";
|
||||
else if(version.MajorVersion == 6)
|
||||
_imageInfo.Application = "DiskCopy";
|
||||
switch(version.MajorVersion)
|
||||
{
|
||||
case 3:
|
||||
_imageInfo.Application = "ShrinkWrap™";
|
||||
|
||||
break;
|
||||
case 6:
|
||||
_imageInfo.Application = "DiskCopy";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -296,18 +296,19 @@ public sealed partial class Nero
|
||||
|
||||
// MagicISO
|
||||
if(entry.SectorSize == 2352)
|
||||
{
|
||||
if(entry.Mode == 0x0000)
|
||||
switch(entry.Mode)
|
||||
{
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0005;
|
||||
case 0x0000:
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0005;
|
||||
|
||||
break;
|
||||
case 0x0002 or 0x0003:
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0006;
|
||||
|
||||
break;
|
||||
}
|
||||
else if(entry.Mode is 0x0002 or 0x0003)
|
||||
{
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0006;
|
||||
}
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine("Nero plugin", "Disc-At-Once entry {0}", i / 32 + 1);
|
||||
|
||||
@@ -411,18 +412,19 @@ public sealed partial class Nero
|
||||
|
||||
// MagicISO
|
||||
if(entry.SectorSize == 2352)
|
||||
{
|
||||
if(entry.Mode == 0x0000)
|
||||
switch(entry.Mode)
|
||||
{
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0005;
|
||||
case 0x0000:
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0005;
|
||||
|
||||
break;
|
||||
case 0x0002 or 0x0003:
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0006;
|
||||
|
||||
break;
|
||||
}
|
||||
else if(entry.Mode is 0x0002 or 0x0003)
|
||||
{
|
||||
corruptedTrackMode = true;
|
||||
entry.Mode = 0x0006;
|
||||
}
|
||||
}
|
||||
|
||||
AaruConsole.DebugWriteLine("Nero plugin", "Disc-At-Once entry {0}", i / 32 + 1);
|
||||
|
||||
|
||||
@@ -93,18 +93,16 @@ public sealed partial class Qcow
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
if(_qHdr.crypt_method > QCOW_ENCRYPTION_AES)
|
||||
switch(_qHdr.crypt_method)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("Invalid encryption method");
|
||||
case > QCOW_ENCRYPTION_AES:
|
||||
AaruConsole.ErrorWriteLine("Invalid encryption method");
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
return ErrorNumber.InvalidArgument;
|
||||
case > QCOW_ENCRYPTION_NONE:
|
||||
AaruConsole.ErrorWriteLine("AES encrypted images not yet supported");
|
||||
|
||||
if(_qHdr.crypt_method > QCOW_ENCRYPTION_NONE)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("AES encrypted images not yet supported");
|
||||
|
||||
return ErrorNumber.NotImplemented;
|
||||
return ErrorNumber.NotImplemented;
|
||||
}
|
||||
|
||||
if(_qHdr.backing_file_offset != 0)
|
||||
@@ -222,7 +220,8 @@ public sealed partial class Qcow
|
||||
if((long)l1Off >= _l1Table.LongLength)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("QCOW plugin",
|
||||
$"Trying to read past L1 table, position {l1Off} of a max {_l1Table.LongLength}");
|
||||
$"Trying to read past L1 table, position {l1Off} of a max {_l1Table.LongLength
|
||||
}");
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
@@ -86,8 +86,8 @@ public sealed partial class Qcow2
|
||||
|
||||
if((_qHdr.features & QCOW_FEATURE_MASK) != 0)
|
||||
{
|
||||
AaruConsole.
|
||||
ErrorWriteLine($"Unknown incompatible features {_qHdr.features & QCOW_FEATURE_MASK:X} enabled, not proceeding.");
|
||||
AaruConsole.ErrorWriteLine($"Unknown incompatible features {_qHdr.features & QCOW_FEATURE_MASK
|
||||
:X} enabled, not proceeding.");
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
@@ -107,18 +107,16 @@ public sealed partial class Qcow2
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
if(_qHdr.crypt_method > QCOW_ENCRYPTION_AES)
|
||||
switch(_qHdr.crypt_method)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("Invalid encryption method");
|
||||
case > QCOW_ENCRYPTION_AES:
|
||||
AaruConsole.ErrorWriteLine("Invalid encryption method");
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
return ErrorNumber.InvalidArgument;
|
||||
case > QCOW_ENCRYPTION_NONE:
|
||||
AaruConsole.ErrorWriteLine("AES encrypted images not yet supported");
|
||||
|
||||
if(_qHdr.crypt_method > QCOW_ENCRYPTION_NONE)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("AES encrypted images not yet supported");
|
||||
|
||||
return ErrorNumber.NotImplemented;
|
||||
return ErrorNumber.NotImplemented;
|
||||
}
|
||||
|
||||
if(_qHdr.backing_file_offset != 0)
|
||||
@@ -225,7 +223,8 @@ public sealed partial class Qcow2
|
||||
if((long)l1Off >= _l1Table.LongLength)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("QCOW2 plugin",
|
||||
$"Trying to read past L1 table, position {l1Off} of a max {_l1Table.LongLength}");
|
||||
$"Trying to read past L1 table, position {l1Off} of a max {_l1Table.LongLength
|
||||
}");
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
@@ -323,10 +323,17 @@ public sealed partial class Udif
|
||||
_imageInfo.Application = version.VersionString;
|
||||
_imageInfo.Comments = version.VersionMessage;
|
||||
|
||||
if(version.MajorVersion == 3)
|
||||
_imageInfo.Application = "ShrinkWrap™";
|
||||
else if(version.MajorVersion == 6)
|
||||
_imageInfo.Application = "DiskCopy";
|
||||
switch(version.MajorVersion)
|
||||
{
|
||||
case 3:
|
||||
_imageInfo.Application = "ShrinkWrap™";
|
||||
|
||||
break;
|
||||
case 6:
|
||||
_imageInfo.Application = "DiskCopy";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
_imageInfo.Application = "DiskCopy";
|
||||
|
||||
@@ -359,8 +359,8 @@ public sealed partial class VMware
|
||||
|
||||
if(extentHdr.capacity < extent.Sectors)
|
||||
{
|
||||
AaruConsole.
|
||||
ErrorWriteLine($"Extent contains incorrect number of sectors, {extentHdr.capacity}. {extent.Sectors} were expected");
|
||||
AaruConsole.ErrorWriteLine($"Extent contains incorrect number of sectors, {extentHdr.capacity}. {
|
||||
extent.Sectors} were expected");
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
@@ -400,75 +400,81 @@ public sealed partial class VMware
|
||||
long gdOffset = 0;
|
||||
uint gtEsPerGt = 0;
|
||||
|
||||
if(oneNoFlat && !cowD)
|
||||
switch(oneNoFlat)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.magic = 0x{0:X8}", _vmEHdr.magic);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.version = {0}", _vmEHdr.version);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.flags = 0x{0:X8}", _vmEHdr.flags);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.capacity = {0}", _vmEHdr.capacity);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.grainSize = {0}", _vmEHdr.grainSize);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.descriptorOffset = {0}", _vmEHdr.descriptorOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.descriptorSize = {0}", _vmEHdr.descriptorSize);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.GTEsPerGT = {0}", _vmEHdr.GTEsPerGT);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.rgdOffset = {0}", _vmEHdr.rgdOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.gdOffset = {0}", _vmEHdr.gdOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.overhead = {0}", _vmEHdr.overhead);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.uncleanShutdown = {0}", _vmEHdr.uncleanShutdown);
|
||||
case true when !cowD:
|
||||
{
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.magic = 0x{0:X8}", _vmEHdr.magic);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.version = {0}", _vmEHdr.version);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.flags = 0x{0:X8}", _vmEHdr.flags);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.capacity = {0}", _vmEHdr.capacity);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.grainSize = {0}", _vmEHdr.grainSize);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.descriptorOffset = {0}", _vmEHdr.descriptorOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.descriptorSize = {0}", _vmEHdr.descriptorSize);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.GTEsPerGT = {0}", _vmEHdr.GTEsPerGT);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.rgdOffset = {0}", _vmEHdr.rgdOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.gdOffset = {0}", _vmEHdr.gdOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.overhead = {0}", _vmEHdr.overhead);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.uncleanShutdown = {0}", _vmEHdr.uncleanShutdown);
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.singleEndLineChar = 0x{0:X2}",
|
||||
_vmEHdr.singleEndLineChar);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.singleEndLineChar = 0x{0:X2}",
|
||||
_vmEHdr.singleEndLineChar);
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.nonEndLineChar = 0x{0:X2}", _vmEHdr.nonEndLineChar);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.nonEndLineChar = 0x{0:X2}", _vmEHdr.nonEndLineChar);
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.doubleEndLineChar1 = 0x{0:X2}",
|
||||
_vmEHdr.doubleEndLineChar1);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.doubleEndLineChar1 = 0x{0:X2}",
|
||||
_vmEHdr.doubleEndLineChar1);
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.doubleEndLineChar2 = 0x{0:X2}",
|
||||
_vmEHdr.doubleEndLineChar2);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.doubleEndLineChar2 = 0x{0:X2}",
|
||||
_vmEHdr.doubleEndLineChar2);
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.compression = 0x{0:X4}", _vmEHdr.compression);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmEHdr.compression = 0x{0:X4}", _vmEHdr.compression);
|
||||
|
||||
_grainSize = _vmEHdr.grainSize;
|
||||
grains = (uint)(_imageInfo.Sectors / _vmEHdr.grainSize) + 1;
|
||||
gdEntries = grains / _vmEHdr.GTEsPerGT;
|
||||
gtEsPerGt = _vmEHdr.GTEsPerGT;
|
||||
_grainSize = _vmEHdr.grainSize;
|
||||
grains = (uint)(_imageInfo.Sectors / _vmEHdr.grainSize) + 1;
|
||||
gdEntries = grains / _vmEHdr.GTEsPerGT;
|
||||
gtEsPerGt = _vmEHdr.GTEsPerGT;
|
||||
|
||||
if((_vmEHdr.flags & FLAGS_USE_REDUNDANT_TABLE) == FLAGS_USE_REDUNDANT_TABLE)
|
||||
gdOffset = (long)_vmEHdr.rgdOffset;
|
||||
else
|
||||
gdOffset = (long)_vmEHdr.gdOffset;
|
||||
}
|
||||
else if(oneNoFlat && cowD)
|
||||
{
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.magic = 0x{0:X8}", _vmCHdr.magic);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.version = {0}", _vmCHdr.version);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.flags = 0x{0:X8}", _vmCHdr.flags);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.sectors = {0}", _vmCHdr.sectors);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.grainSize = {0}", _vmCHdr.grainSize);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.gdOffset = {0}", _vmCHdr.gdOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.numGDEntries = {0}", _vmCHdr.numGDEntries);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.freeSector = {0}", _vmCHdr.freeSector);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.cylinders = {0}", _vmCHdr.cylinders);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.heads = {0}", _vmCHdr.heads);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.spt = {0}", _vmCHdr.spt);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.generation = {0}", _vmCHdr.generation);
|
||||
if((_vmEHdr.flags & FLAGS_USE_REDUNDANT_TABLE) == FLAGS_USE_REDUNDANT_TABLE)
|
||||
gdOffset = (long)_vmEHdr.rgdOffset;
|
||||
else
|
||||
gdOffset = (long)_vmEHdr.gdOffset;
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.name = {0}", StringHandlers.CToString(_vmCHdr.name));
|
||||
break;
|
||||
}
|
||||
case true when cowD:
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.magic = 0x{0:X8}", _vmCHdr.magic);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.version = {0}", _vmCHdr.version);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.flags = 0x{0:X8}", _vmCHdr.flags);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.sectors = {0}", _vmCHdr.sectors);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.grainSize = {0}", _vmCHdr.grainSize);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.gdOffset = {0}", _vmCHdr.gdOffset);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.numGDEntries = {0}", _vmCHdr.numGDEntries);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.freeSector = {0}", _vmCHdr.freeSector);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.cylinders = {0}", _vmCHdr.cylinders);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.heads = {0}", _vmCHdr.heads);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.spt = {0}", _vmCHdr.spt);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.generation = {0}", _vmCHdr.generation);
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.description = {0}",
|
||||
StringHandlers.CToString(_vmCHdr.description));
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.name = {0}",
|
||||
StringHandlers.CToString(_vmCHdr.name));
|
||||
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.savedGeneration = {0}", _vmCHdr.savedGeneration);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.uncleanShutdown = {0}", _vmCHdr.uncleanShutdown);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.description = {0}",
|
||||
StringHandlers.CToString(_vmCHdr.description));
|
||||
|
||||
_grainSize = _vmCHdr.grainSize;
|
||||
grains = (uint)(_imageInfo.Sectors / _vmCHdr.grainSize) + 1;
|
||||
gdEntries = _vmCHdr.numGDEntries;
|
||||
gdOffset = _vmCHdr.gdOffset;
|
||||
gtEsPerGt = grains / gdEntries;
|
||||
_imageInfo.MediaTitle = StringHandlers.CToString(_vmCHdr.name);
|
||||
_imageInfo.Comments = StringHandlers.CToString(_vmCHdr.description);
|
||||
_version = _vmCHdr.version;
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.savedGeneration = {0}", _vmCHdr.savedGeneration);
|
||||
AaruConsole.DebugWriteLine("VMware plugin", "vmCHdr.uncleanShutdown = {0}", _vmCHdr.uncleanShutdown);
|
||||
|
||||
_grainSize = _vmCHdr.grainSize;
|
||||
grains = (uint)(_imageInfo.Sectors / _vmCHdr.grainSize) + 1;
|
||||
gdEntries = _vmCHdr.numGDEntries;
|
||||
gdOffset = _vmCHdr.gdOffset;
|
||||
gtEsPerGt = grains / gdEntries;
|
||||
_imageInfo.MediaTitle = StringHandlers.CToString(_vmCHdr.name);
|
||||
_imageInfo.Comments = StringHandlers.CToString(_vmCHdr.description);
|
||||
_version = _vmCHdr.version;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(oneNoFlat)
|
||||
@@ -636,19 +642,20 @@ public sealed partial class VMware
|
||||
|
||||
uint grainOff = _gTable[index];
|
||||
|
||||
if(grainOff == 0 && _hasParent)
|
||||
return _parentImage.ReadSector(sectorAddress, out buffer);
|
||||
|
||||
if(grainOff is 0 or 1)
|
||||
switch(grainOff)
|
||||
{
|
||||
buffer = new byte[SECTOR_SIZE];
|
||||
case 0 when _hasParent: return _parentImage.ReadSector(sectorAddress, out buffer);
|
||||
case 0 or 1:
|
||||
{
|
||||
buffer = new byte[SECTOR_SIZE];
|
||||
|
||||
if(_sectorCache.Count >= MAX_CACHED_SECTORS)
|
||||
_sectorCache.Clear();
|
||||
if(_sectorCache.Count >= MAX_CACHED_SECTORS)
|
||||
_sectorCache.Clear();
|
||||
|
||||
_sectorCache.Add(sectorAddress, buffer);
|
||||
_sectorCache.Add(sectorAddress, buffer);
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
}
|
||||
|
||||
if(!_grainCache.TryGetValue(grainOff, out byte[] grain))
|
||||
|
||||
@@ -39,33 +39,18 @@ public sealed partial class ZZZRawImage
|
||||
MediaType CalculateDiskType()
|
||||
{
|
||||
if(_imageInfo.SectorSize == 2048)
|
||||
{
|
||||
if(_imageInfo.Sectors == 58620544)
|
||||
return MediaType.REV120;
|
||||
|
||||
if(_imageInfo.Sectors == 17090880)
|
||||
return MediaType.REV35;
|
||||
|
||||
if(_imageInfo.Sectors <= 360000)
|
||||
return MediaType.CD;
|
||||
|
||||
if(_imageInfo.Sectors <= 2295104)
|
||||
return MediaType.DVDPR;
|
||||
|
||||
if(_imageInfo.Sectors <= 2298496)
|
||||
return MediaType.DVDR;
|
||||
|
||||
if(_imageInfo.Sectors <= 4171712)
|
||||
return MediaType.DVDRDL;
|
||||
|
||||
if(_imageInfo.Sectors <= 4173824)
|
||||
return MediaType.DVDPRDL;
|
||||
|
||||
if(_imageInfo.Sectors <= 24438784)
|
||||
return MediaType.BDR;
|
||||
|
||||
return _imageInfo.Sectors <= 62500864 ? MediaType.BDRXL : MediaType.Unknown;
|
||||
}
|
||||
switch(_imageInfo.Sectors)
|
||||
{
|
||||
case 58620544: return MediaType.REV120;
|
||||
case 17090880: return MediaType.REV35;
|
||||
case <= 360000: return MediaType.CD;
|
||||
case <= 2295104: return MediaType.DVDPR;
|
||||
case <= 2298496: return MediaType.DVDR;
|
||||
case <= 4171712: return MediaType.DVDRDL;
|
||||
case <= 4173824: return MediaType.DVDPRDL;
|
||||
case <= 24438784: return MediaType.BDR;
|
||||
default: return _imageInfo.Sectors <= 62500864 ? MediaType.BDRXL : MediaType.Unknown;
|
||||
}
|
||||
|
||||
switch(_imageInfo.ImageSize)
|
||||
{
|
||||
@@ -117,14 +102,13 @@ public sealed partial class ZZZRawImage
|
||||
if(_imageInfo.SectorSize == 256)
|
||||
return MediaType.CBM_35_DD;
|
||||
|
||||
if(_extension is ".adf" or ".adl" &&
|
||||
_imageInfo.SectorSize == 1024)
|
||||
return MediaType.ACORN_35_DS_DD;
|
||||
return _extension switch
|
||||
{
|
||||
".adf" or ".adl" when _imageInfo.SectorSize == 1024 => MediaType.ACORN_35_DS_DD,
|
||||
".st" => MediaType.ATARI_35_DS_DD,
|
||||
_ => MediaType.AppleSonyDS
|
||||
};
|
||||
|
||||
if(_extension == ".st")
|
||||
return MediaType.ATARI_35_DS_DD;
|
||||
|
||||
return MediaType.AppleSonyDS;
|
||||
case 839680: return MediaType.FDFORMAT_35_DD;
|
||||
case 901120:
|
||||
if(_extension == ".st")
|
||||
|
||||
@@ -137,79 +137,87 @@ public sealed partial class ZZZRawImage
|
||||
|
||||
break;
|
||||
default:
|
||||
if(_extension is ".adf" or ".adl" or ".ssd" or ".dsd" &&
|
||||
imageFilter.DataForkLength is 163840 or 327680 or 655360)
|
||||
_imageInfo.SectorSize = 256;
|
||||
else if(_extension is ".adf" or ".adl" &&
|
||||
imageFilter.DataForkLength == 819200)
|
||||
_imageInfo.SectorSize = 1024;
|
||||
else
|
||||
switch(imageFilter.DataForkLength)
|
||||
{
|
||||
case 242944:
|
||||
case 256256:
|
||||
case 495872:
|
||||
case 92160:
|
||||
case 133120:
|
||||
_imageInfo.SectorSize = 128;
|
||||
switch(_extension)
|
||||
{
|
||||
case ".adf" or ".adl" or ".ssd" or ".dsd"
|
||||
when imageFilter.DataForkLength is 163840 or 327680 or 655360:
|
||||
_imageInfo.SectorSize = 256;
|
||||
|
||||
break;
|
||||
case 116480:
|
||||
case 287488: // T0S0 = 128bps
|
||||
case 988416: // T0S0 = 128bps
|
||||
case 995072: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1021696: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 232960:
|
||||
case 143360:
|
||||
case 286720:
|
||||
case 512512:
|
||||
case 102400:
|
||||
case 204800:
|
||||
case 655360:
|
||||
case 80384: // T0S0 = 128bps
|
||||
case 325632: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 653312: // T0S0 = 128bps, T0S1 = 256bps
|
||||
break;
|
||||
case ".adf" or ".adl" when imageFilter.DataForkLength == 819200:
|
||||
_imageInfo.SectorSize = 1024;
|
||||
|
||||
#region Commodore
|
||||
case 174848:
|
||||
case 175531:
|
||||
case 196608:
|
||||
case 197376:
|
||||
case 349696:
|
||||
case 351062:
|
||||
case 822400:
|
||||
#endregion Commodore
|
||||
break;
|
||||
default:
|
||||
switch(imageFilter.DataForkLength)
|
||||
{
|
||||
case 242944:
|
||||
case 256256:
|
||||
case 495872:
|
||||
case 92160:
|
||||
case 133120:
|
||||
_imageInfo.SectorSize = 128;
|
||||
|
||||
_imageInfo.SectorSize = 256;
|
||||
break;
|
||||
case 116480:
|
||||
case 287488: // T0S0 = 128bps
|
||||
case 988416: // T0S0 = 128bps
|
||||
case 995072: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1021696: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 232960:
|
||||
case 143360:
|
||||
case 286720:
|
||||
case 512512:
|
||||
case 102400:
|
||||
case 204800:
|
||||
case 655360:
|
||||
case 80384: // T0S0 = 128bps
|
||||
case 325632: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 653312: // T0S0 = 128bps, T0S1 = 256bps
|
||||
|
||||
break;
|
||||
case 81664:
|
||||
_imageInfo.SectorSize = 319;
|
||||
#region Commodore
|
||||
case 174848:
|
||||
case 175531:
|
||||
case 196608:
|
||||
case 197376:
|
||||
case 349696:
|
||||
case 351062:
|
||||
case 822400:
|
||||
#endregion Commodore
|
||||
|
||||
break;
|
||||
case 306432: // T0S0 = 128bps
|
||||
case 1146624: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1177344: // T0S0 = 128bps, T0S1 = 256bps
|
||||
_imageInfo.SectorSize = 512;
|
||||
_imageInfo.SectorSize = 256;
|
||||
|
||||
break;
|
||||
case 1222400: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1304320: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1255168: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1261568:
|
||||
case 1638400:
|
||||
_imageInfo.SectorSize = 1024;
|
||||
break;
|
||||
case 81664:
|
||||
_imageInfo.SectorSize = 319;
|
||||
|
||||
break;
|
||||
case 35002122240:
|
||||
_imageInfo.SectorSize = 2048;
|
||||
break;
|
||||
case 306432: // T0S0 = 128bps
|
||||
case 1146624: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1177344: // T0S0 = 128bps, T0S1 = 256bps
|
||||
_imageInfo.SectorSize = 512;
|
||||
|
||||
break;
|
||||
default:
|
||||
_imageInfo.SectorSize = 512;
|
||||
break;
|
||||
case 1222400: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1304320: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1255168: // T0S0 = 128bps, T0S1 = 256bps
|
||||
case 1261568:
|
||||
case 1638400:
|
||||
_imageInfo.SectorSize = 1024;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 35002122240:
|
||||
_imageInfo.SectorSize = 2048;
|
||||
|
||||
break;
|
||||
default:
|
||||
_imageInfo.SectorSize = 512;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1004,44 +1012,50 @@ public sealed partial class ZZZRawImage
|
||||
if(decMode.Value.Pages != null)
|
||||
foreach(Modes.ModePage page in decMode.Value.Pages)
|
||||
|
||||
// CD-ROM page
|
||||
if(page.Page == 0x2A &&
|
||||
page.Subpage == 0)
|
||||
switch(page.Page)
|
||||
{
|
||||
if(_mediaTags.ContainsKey(MediaTagType.SCSI_MODEPAGE_2A))
|
||||
_mediaTags.Remove(MediaTagType.SCSI_MODEPAGE_2A);
|
||||
// CD-ROM page
|
||||
case 0x2A when page.Subpage == 0:
|
||||
{
|
||||
if(_mediaTags.ContainsKey(MediaTagType.SCSI_MODEPAGE_2A))
|
||||
_mediaTags.Remove(MediaTagType.SCSI_MODEPAGE_2A);
|
||||
|
||||
_mediaTags.Add(MediaTagType.SCSI_MODEPAGE_2A, page.PageResponse);
|
||||
}
|
||||
_mediaTags.Add(MediaTagType.SCSI_MODEPAGE_2A, page.PageResponse);
|
||||
|
||||
// Rigid Disk page
|
||||
else if(page.Page == 0x04 &&
|
||||
page.Subpage == 0)
|
||||
{
|
||||
Modes.ModePage_04? mode04 = Modes.DecodeModePage_04(page.PageResponse);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!mode04.HasValue)
|
||||
continue;
|
||||
// Rigid Disk page
|
||||
case 0x04 when page.Subpage == 0:
|
||||
{
|
||||
Modes.ModePage_04? mode04 = Modes.DecodeModePage_04(page.PageResponse);
|
||||
|
||||
_imageInfo.Cylinders = mode04.Value.Cylinders;
|
||||
_imageInfo.Heads = mode04.Value.Heads;
|
||||
if(!mode04.HasValue)
|
||||
continue;
|
||||
|
||||
_imageInfo.SectorsPerTrack =
|
||||
(uint)(_imageInfo.Sectors / (mode04.Value.Cylinders * mode04.Value.Heads));
|
||||
}
|
||||
_imageInfo.Cylinders = mode04.Value.Cylinders;
|
||||
_imageInfo.Heads = mode04.Value.Heads;
|
||||
|
||||
// Flexible Disk Page
|
||||
else if(page.Page == 0x05 &&
|
||||
page.Subpage == 0)
|
||||
{
|
||||
Modes.ModePage_05? mode05 = Modes.DecodeModePage_05(page.PageResponse);
|
||||
_imageInfo.SectorsPerTrack =
|
||||
(uint)(_imageInfo.Sectors / (mode04.Value.Cylinders * mode04.Value.Heads));
|
||||
|
||||
if(!mode05.HasValue)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
_imageInfo.Cylinders = mode05.Value.Cylinders;
|
||||
_imageInfo.Heads = mode05.Value.Heads;
|
||||
_imageInfo.SectorsPerTrack = mode05.Value.SectorsPerTrack;
|
||||
// Flexible Disk Page
|
||||
case 0x05 when page.Subpage == 0:
|
||||
{
|
||||
Modes.ModePage_05? mode05 = Modes.DecodeModePage_05(page.PageResponse);
|
||||
|
||||
if(!mode05.HasValue)
|
||||
continue;
|
||||
|
||||
_imageInfo.Cylinders = mode05.Value.Cylinders;
|
||||
_imageInfo.Heads = mode05.Value.Heads;
|
||||
_imageInfo.SectorsPerTrack = mode05.Value.SectorsPerTrack;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,15 +89,19 @@ public sealed class AppleMap : IPartition
|
||||
|
||||
ushort maxDrivers = 61;
|
||||
|
||||
if(sectorSize == 256)
|
||||
switch(sectorSize)
|
||||
{
|
||||
var tmp = new byte[512];
|
||||
Array.Copy(ddmSector, 0, tmp, 0, 256);
|
||||
ddmSector = tmp;
|
||||
maxDrivers = 29;
|
||||
case 256:
|
||||
{
|
||||
var tmp = new byte[512];
|
||||
Array.Copy(ddmSector, 0, tmp, 0, 256);
|
||||
ddmSector = tmp;
|
||||
maxDrivers = 29;
|
||||
|
||||
break;
|
||||
}
|
||||
case < 256: return false;
|
||||
}
|
||||
else if(sectorSize < 256)
|
||||
return false;
|
||||
|
||||
AppleDriverDescriptorMap ddm = Marshal.ByteArrayToStructureBigEndian<AppleDriverDescriptorMap>(ddmSector);
|
||||
|
||||
|
||||
@@ -94,14 +94,17 @@ static partial class ScsiMmc
|
||||
|
||||
int min = 0, sec, frame;
|
||||
|
||||
if(leadOutTrack.PMIN == 122)
|
||||
tocIsNotBcd = true;
|
||||
|
||||
if(leadOutTrack.PMIN >= 0xA0 &&
|
||||
!tocIsNotBcd)
|
||||
switch(leadOutTrack.PMIN)
|
||||
{
|
||||
min += 90;
|
||||
leadOutTrack.PMIN -= 0x90;
|
||||
case 122:
|
||||
tocIsNotBcd = true;
|
||||
|
||||
break;
|
||||
case >= 0xA0 when !tocIsNotBcd:
|
||||
min += 90;
|
||||
leadOutTrack.PMIN -= 0x90;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(tocIsNotBcd)
|
||||
|
||||
@@ -170,14 +170,17 @@ static partial class ScsiMmc
|
||||
|
||||
min = 0;
|
||||
|
||||
if(leadOutTrack.PMIN == 122)
|
||||
tocIsNotBcd = true;
|
||||
|
||||
if(leadOutTrack.PMIN >= 0xA0 &&
|
||||
!tocIsNotBcd)
|
||||
switch(leadOutTrack.PMIN)
|
||||
{
|
||||
min += 90;
|
||||
leadOutTrack.PMIN -= 0x90;
|
||||
case 122:
|
||||
tocIsNotBcd = true;
|
||||
|
||||
break;
|
||||
case >= 0xA0 when !tocIsNotBcd:
|
||||
min += 90;
|
||||
leadOutTrack.PMIN -= 0x90;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(tocIsNotBcd)
|
||||
|
||||
@@ -167,15 +167,26 @@ sealed class DeviceReportCommand : Command
|
||||
var removable = false;
|
||||
string jsonFile;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(dev.Manufacturer) &&
|
||||
!string.IsNullOrWhiteSpace(dev.FirmwareRevision))
|
||||
jsonFile = dev.Manufacturer + "_" + dev.Model + "_" + dev.FirmwareRevision + ".json";
|
||||
else if(!string.IsNullOrWhiteSpace(dev.Manufacturer))
|
||||
jsonFile = dev.Manufacturer + "_" + dev.Model + ".json";
|
||||
else if(!string.IsNullOrWhiteSpace(dev.FirmwareRevision))
|
||||
jsonFile = dev.Model + "_" + dev.FirmwareRevision + ".json";
|
||||
else
|
||||
jsonFile = dev.Model + ".json";
|
||||
switch(string.IsNullOrWhiteSpace(dev.Manufacturer))
|
||||
{
|
||||
case false when !string.IsNullOrWhiteSpace(dev.FirmwareRevision):
|
||||
jsonFile = dev.Manufacturer + "_" + dev.Model + "_" + dev.FirmwareRevision + ".json";
|
||||
|
||||
break;
|
||||
case false:
|
||||
jsonFile = dev.Manufacturer + "_" + dev.Model + ".json";
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(!string.IsNullOrWhiteSpace(dev.FirmwareRevision))
|
||||
jsonFile = dev.Model + "_" + dev.FirmwareRevision + ".json";
|
||||
else
|
||||
jsonFile = dev.Model + ".json";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jsonFile = jsonFile.Replace('\\', '_').Replace('/', '_').Replace('?', '_');
|
||||
|
||||
@@ -735,8 +746,8 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
foreach(string mediaType in mediaTypes)
|
||||
{
|
||||
if(!AnsiConsole.
|
||||
Confirm($"[italic]Do you have a {mediaType} disc that you can insert in the drive?[/]"))
|
||||
if(!AnsiConsole.Confirm($"[italic]Do you have a {mediaType
|
||||
} disc that you can insert in the drive?[/]"))
|
||||
continue;
|
||||
|
||||
AaruConsole.
|
||||
@@ -869,8 +880,8 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
for(var i = (ushort)mediaTest.BlockSize;; i++)
|
||||
{
|
||||
task.Description =
|
||||
$"Trying to READ LONG with a size of {i} bytes...";
|
||||
task.Description = $"Trying to READ LONG with a size of {i
|
||||
} bytes...";
|
||||
|
||||
task.Value = i;
|
||||
|
||||
@@ -1107,8 +1118,8 @@ sealed class DeviceReportCommand : Command
|
||||
|
||||
foreach(string mediaType in mediaTypes)
|
||||
{
|
||||
if(!AnsiConsole.
|
||||
Confirm($"[italic]Do you have a {mediaType} disc that you can insert in the drive?[/]"))
|
||||
if(!AnsiConsole.Confirm($"[italic]Do you have a {mediaType
|
||||
} disc that you can insert in the drive?[/]"))
|
||||
continue;
|
||||
|
||||
AaruConsole.WriteLine("Please insert it in the drive and press any key when it is ready.");
|
||||
@@ -1236,8 +1247,8 @@ sealed class DeviceReportCommand : Command
|
||||
{
|
||||
task.Value = i;
|
||||
|
||||
task.Description =
|
||||
$"Trying to READ LONG with a size of {i} bytes...";
|
||||
task.Description = $"Trying to READ LONG with a size of {i
|
||||
} bytes...";
|
||||
|
||||
sense = mediaTest.SupportsReadLong16 == true
|
||||
? dev.ReadLong16(out buffer, out senseBuffer, false,
|
||||
@@ -1433,8 +1444,8 @@ sealed class DeviceReportCommand : Command
|
||||
{
|
||||
task.Value = i;
|
||||
|
||||
task.Description =
|
||||
$"Trying to READ LONG with a size of {i} bytes...";
|
||||
task.Description = $"Trying to READ LONG with a size of {i
|
||||
} bytes...";
|
||||
|
||||
sense = mediaTest.SupportsReadLong16 == true
|
||||
? dev.ReadLong16(out buffer, out senseBuffer,
|
||||
@@ -1521,8 +1532,8 @@ sealed class DeviceReportCommand : Command
|
||||
{
|
||||
task.Value = i;
|
||||
|
||||
task.Description =
|
||||
$"Trying to READ LONG with a size of {i} bytes...";
|
||||
task.Description = $"Trying to READ LONG with a size of {i
|
||||
} bytes...";
|
||||
|
||||
sense = report.SCSI.ReadCapabilities.SupportsReadLong16 == true
|
||||
? dev.ReadLong16(out buffer, out senseBuffer, false,
|
||||
|
||||
@@ -375,190 +375,191 @@ sealed class DeviceInfoCommand : Command
|
||||
|
||||
if(devInfo.ScsiEvpdPages != null)
|
||||
foreach(KeyValuePair<byte, byte[]> page in devInfo.ScsiEvpdPages)
|
||||
if(page.Key >= 0x01 &&
|
||||
page.Key <= 0x7F)
|
||||
switch(page.Key)
|
||||
{
|
||||
AaruConsole.WriteLine("ASCII Page {0:X2}h: {1}", page.Key, EVPD.DecodeASCIIPage(page.Value));
|
||||
case >= 0x01 and <= 0x7F:
|
||||
AaruConsole.WriteLine("ASCII Page {0:X2}h: {1}", page.Key,
|
||||
EVPD.DecodeASCIIPage(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, page.Value);
|
||||
}
|
||||
else if(page.Key == 0x80)
|
||||
{
|
||||
AaruConsole.WriteLine("Unit Serial Number: {0}", EVPD.DecodePage80(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0x81)
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_81(page.Value));
|
||||
break;
|
||||
case 0x80:
|
||||
AaruConsole.WriteLine("Unit Serial Number: {0}", EVPD.DecodePage80(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0x82)
|
||||
{
|
||||
AaruConsole.WriteLine("ASCII implemented operating definitions: {0}",
|
||||
EVPD.DecodePage82(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0x83)
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_83(page.Value));
|
||||
break;
|
||||
case 0x81:
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_81(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0x84)
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_84(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0x85)
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_85(page.Value));
|
||||
break;
|
||||
case 0x82:
|
||||
AaruConsole.WriteLine("ASCII implemented operating definitions: {0}",
|
||||
EVPD.DecodePage82(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0x86)
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_86(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0x89)
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_89(page.Value));
|
||||
break;
|
||||
case 0x83:
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_83(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB0)
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_B0(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB1)
|
||||
{
|
||||
AaruConsole.WriteLine("Manufacturer-assigned Serial Number: {0}",
|
||||
EVPD.DecodePageB1(page.Value));
|
||||
break;
|
||||
case 0x84:
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_84(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB2)
|
||||
{
|
||||
AaruConsole.WriteLine("TapeAlert Supported Flags Bitmap: 0x{0:X16}",
|
||||
EVPD.DecodePageB2(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB3)
|
||||
{
|
||||
AaruConsole.WriteLine("Automation Device Serial Number: {0}", EVPD.DecodePageB3(page.Value));
|
||||
break;
|
||||
case 0x85:
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_85(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xB4)
|
||||
{
|
||||
AaruConsole.WriteLine("Data Transfer Device Element Address: 0x{0}",
|
||||
EVPD.DecodePageB4(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC0 &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "quantum")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Quantum(page.Value));
|
||||
break;
|
||||
case 0x86:
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_86(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC0 &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "seagate")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Seagate(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC0 &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "ibm")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_IBM(page.Value));
|
||||
break;
|
||||
case 0x89:
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_89(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xC1 &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "ibm")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C1_IBM(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key is 0xC0 or 0xC1 &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "certance")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_C1_Certance(page.Value));
|
||||
break;
|
||||
case 0xB0:
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_B0(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key is 0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6 &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "certance")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key is 0xC0 or 0xC1 or 0xC2 or 0xC3 or 0xC4 or 0xC5 &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "hp")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_to_C5_HP(page.Value));
|
||||
break;
|
||||
case 0xB1:
|
||||
AaruConsole.WriteLine("Manufacturer-assigned Serial Number: {0}",
|
||||
EVPD.DecodePageB1(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else if(page.Key == 0xDF &&
|
||||
StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant().
|
||||
Trim() == "certance")
|
||||
{
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_DF_Certance(page.Value));
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(page.Key == 0x00)
|
||||
continue;
|
||||
break;
|
||||
case 0xB2:
|
||||
AaruConsole.WriteLine("TapeAlert Supported Flags Bitmap: 0x{0:X16}",
|
||||
EVPD.DecodePageB2(page.Value));
|
||||
|
||||
AaruConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}",
|
||||
page.Key);
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
break;
|
||||
case 0xB3:
|
||||
AaruConsole.WriteLine("Automation Device Serial Number: {0}",
|
||||
EVPD.DecodePageB3(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xB4:
|
||||
AaruConsole.WriteLine("Data Transfer Device Element Address: 0x{0}",
|
||||
EVPD.DecodePageB4(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "quantum":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Quantum(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "seagate":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_Seagate(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "ibm":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_IBM(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xC1 when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "ibm":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C1_IBM(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 or 0xC1
|
||||
when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "certance":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_C1_Certance(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6
|
||||
when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "certance":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xC0 or 0xC1 or 0xC2 or 0xC3 or 0xC4 or 0xC5
|
||||
when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "hp":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_C0_to_C5_HP(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
case 0xDF when StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).
|
||||
ToLowerInvariant().Trim() == "certance":
|
||||
AaruConsole.WriteLine("{0}", EVPD.PrettifyPage_DF_Certance(page.Value));
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(page.Key == 0x00)
|
||||
continue;
|
||||
|
||||
AaruConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}",
|
||||
page.Key);
|
||||
|
||||
DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin",
|
||||
$"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(devInfo.ScsiModeSense6 != null)
|
||||
|
||||
@@ -281,35 +281,44 @@ sealed class FilesystemInfoCommand : Command
|
||||
Filesystems.Identify(imageFormat, out idPlugins, partitionsList[i]);
|
||||
});
|
||||
|
||||
if(idPlugins.Count == 0)
|
||||
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
||||
else if(idPlugins.Count > 1)
|
||||
switch(idPlugins.Count)
|
||||
{
|
||||
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
||||
case 0:
|
||||
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
||||
|
||||
foreach(string pluginName in idPlugins)
|
||||
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
||||
{
|
||||
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
||||
break;
|
||||
case > 1:
|
||||
{
|
||||
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
||||
|
||||
plugin.GetInformation(imageFormat, partitionsList[i], out information,
|
||||
encodingClass);
|
||||
foreach(string pluginName in idPlugins)
|
||||
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
||||
{
|
||||
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
||||
|
||||
AaruConsole.Write(information);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
||||
plugin.GetInformation(imageFormat, partitionsList[i], out information,
|
||||
encodingClass);
|
||||
|
||||
if(plugin == null)
|
||||
continue;
|
||||
AaruConsole.Write(information);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
}
|
||||
|
||||
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
||||
plugin.GetInformation(imageFormat, partitionsList[i], out information, encodingClass);
|
||||
AaruConsole.Write("{0}", information);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
||||
|
||||
if(plugin == null)
|
||||
continue;
|
||||
|
||||
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
||||
plugin.GetInformation(imageFormat, partitionsList[i], out information, encodingClass);
|
||||
AaruConsole.Write("{0}", information);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AaruConsole.WriteLine();
|
||||
@@ -332,31 +341,40 @@ sealed class FilesystemInfoCommand : Command
|
||||
Filesystems.Identify(imageFormat, out idPlugins, wholePart);
|
||||
});
|
||||
|
||||
if(idPlugins.Count == 0)
|
||||
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
||||
else if(idPlugins.Count > 1)
|
||||
switch(idPlugins.Count)
|
||||
{
|
||||
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
||||
case 0:
|
||||
AaruConsole.WriteLine("[bold]Filesystem not identified[/]");
|
||||
|
||||
foreach(string pluginName in idPlugins)
|
||||
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
||||
break;
|
||||
case > 1:
|
||||
{
|
||||
AaruConsole.WriteLine($"[italic]Identified by {idPlugins.Count} plugins[/]");
|
||||
|
||||
foreach(string pluginName in idPlugins)
|
||||
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
||||
{
|
||||
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
||||
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
|
||||
AaruConsole.Write(information);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
||||
|
||||
if(plugin != null)
|
||||
{
|
||||
AaruConsole.WriteLine($"[bold]As identified by {plugin.Name}.[/]");
|
||||
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
||||
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
|
||||
AaruConsole.Write(information);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(idPlugins[0], out plugin);
|
||||
|
||||
if(plugin != null)
|
||||
{
|
||||
AaruConsole.WriteLine($"[bold]Identified by {plugin.Name}.[/]");
|
||||
plugin.GetInformation(imageFormat, wholePart, out information, encodingClass);
|
||||
AaruConsole.Write(information);
|
||||
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,18 +478,16 @@ sealed class ConvertImageCommand : Command
|
||||
StringComparison.
|
||||
InvariantCultureIgnoreCase)));
|
||||
|
||||
if(candidates.Count == 0)
|
||||
switch(candidates.Count)
|
||||
{
|
||||
AaruConsole.WriteLine("No plugin supports requested extension.");
|
||||
case 0:
|
||||
AaruConsole.WriteLine("No plugin supports requested extension.");
|
||||
|
||||
return (int)ErrorNumber.FormatNotFound;
|
||||
}
|
||||
return (int)ErrorNumber.FormatNotFound;
|
||||
case > 1:
|
||||
AaruConsole.WriteLine("More than one plugin supports requested extension.");
|
||||
|
||||
if(candidates.Count > 1)
|
||||
{
|
||||
AaruConsole.WriteLine("More than one plugin supports requested extension.");
|
||||
|
||||
return (int)ErrorNumber.TooManyFormats;
|
||||
return (int)ErrorNumber.TooManyFormats;
|
||||
}
|
||||
|
||||
IBaseWritableImage outputFormat = candidates[0];
|
||||
@@ -707,8 +705,8 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
foreach(Track track in inputOptical.Tracks)
|
||||
{
|
||||
discTask.Description =
|
||||
$"Converting sectors in track {discTask.Value + 1} of {discTask.MaxValue}";
|
||||
discTask.Description = $"Converting sectors in track {discTask.Value + 1} of {
|
||||
discTask.MaxValue}";
|
||||
|
||||
doneSectors = 0;
|
||||
ulong trackSectors = track.EndSector - track.StartSector + 1;
|
||||
@@ -727,8 +725,8 @@ sealed class ConvertImageCommand : Command
|
||||
else
|
||||
sectorsToDo = (uint)(trackSectors - doneSectors);
|
||||
|
||||
trackTask.Description =
|
||||
$"Converting sectors {doneSectors + track.StartSector} to {doneSectors + sectorsToDo + track.StartSector} in track {track.Sequence}";
|
||||
trackTask.Description = $"Converting sectors {doneSectors + track.StartSector} to {
|
||||
doneSectors + sectorsToDo + track.StartSector} in track {track.Sequence}";
|
||||
|
||||
var useNotLong = false;
|
||||
var result = false;
|
||||
@@ -942,8 +940,8 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
foreach(Track track in inputOptical.Tracks)
|
||||
{
|
||||
discTask.Description =
|
||||
$"Converting tags in track {discTask.Value + 1} of {discTask.MaxValue}";
|
||||
discTask.Description = $"Converting tags in track {discTask.Value + 1} of {
|
||||
discTask.MaxValue}";
|
||||
|
||||
doneSectors = 0;
|
||||
ulong trackSectors = track.EndSector - track.StartSector + 1;
|
||||
@@ -956,31 +954,35 @@ sealed class ConvertImageCommand : Command
|
||||
case SectorTagType.CdTrackIsrc:
|
||||
errno = inputOptical.ReadSectorTag(track.Sequence, tag, out sector);
|
||||
|
||||
if(errno == ErrorNumber.NoData)
|
||||
switch(errno)
|
||||
{
|
||||
errno = ErrorNumber.NoError;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(errno == ErrorNumber.NoError)
|
||||
result = outputOptical.WriteSectorTag(sector, track.Sequence, tag);
|
||||
else
|
||||
{
|
||||
if(force)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine("Error {0} writing tag, continuing...",
|
||||
outputOptical.ErrorMessage);
|
||||
case ErrorNumber.NoData:
|
||||
errno = ErrorNumber.NoError;
|
||||
|
||||
continue;
|
||||
}
|
||||
case ErrorNumber.NoError:
|
||||
result = outputOptical.WriteSectorTag(sector, track.Sequence, tag);
|
||||
|
||||
AaruConsole.ErrorWriteLine("Error {0} writing tag, not continuing...",
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(force)
|
||||
{
|
||||
AaruConsole.
|
||||
ErrorWriteLine("Error {0} writing tag, continuing...",
|
||||
outputOptical.ErrorMessage);
|
||||
|
||||
errno = ErrorNumber.WriteError;
|
||||
continue;
|
||||
}
|
||||
|
||||
return;
|
||||
AaruConsole.
|
||||
ErrorWriteLine("Error {0} writing tag, not continuing...",
|
||||
outputOptical.ErrorMessage);
|
||||
|
||||
errno = ErrorNumber.WriteError;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!result)
|
||||
@@ -1396,8 +1398,8 @@ sealed class ConvertImageCommand : Command
|
||||
|
||||
foreach(TapeFile tapeFile in inputTape.Files)
|
||||
{
|
||||
filesTask.Description =
|
||||
$"Converting file {tapeFile.File} of partition {tapeFile.Partition}...";
|
||||
filesTask.Description = $"Converting file {tapeFile.File} of partition {
|
||||
tapeFile.Partition}...";
|
||||
|
||||
outputTape.AddFile(tapeFile);
|
||||
filesTask.Increment(1);
|
||||
|
||||
@@ -378,18 +378,16 @@ sealed class DumpMediaCommand : Command
|
||||
StringComparison.
|
||||
InvariantCultureIgnoreCase)));
|
||||
|
||||
if(candidates.Count == 0)
|
||||
switch(candidates.Count)
|
||||
{
|
||||
AaruConsole.WriteLine("No plugin supports requested extension.");
|
||||
case 0:
|
||||
AaruConsole.WriteLine("No plugin supports requested extension.");
|
||||
|
||||
return (int)ErrorNumber.FormatNotFound;
|
||||
}
|
||||
return (int)ErrorNumber.FormatNotFound;
|
||||
case > 1:
|
||||
AaruConsole.WriteLine("More than one plugin supports requested extension.");
|
||||
|
||||
if(candidates.Count > 1)
|
||||
{
|
||||
AaruConsole.WriteLine("More than one plugin supports requested extension.");
|
||||
|
||||
return (int)ErrorNumber.TooManyFormats;
|
||||
return (int)ErrorNumber.TooManyFormats;
|
||||
}
|
||||
|
||||
while(true)
|
||||
|
||||
@@ -233,21 +233,34 @@ sealed class MediaInfoCommand : Command
|
||||
{
|
||||
ulong totalSize = scsiInfo.Blocks * scsiInfo.BlockSize;
|
||||
|
||||
if(totalSize > 1099511627776)
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} TiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1099511627776d);
|
||||
else if(totalSize > 1073741824)
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} GiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1073741824d);
|
||||
else if(totalSize > 1048576)
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} MiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1048576d);
|
||||
else if(totalSize > 1024)
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} KiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1024d);
|
||||
else
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize);
|
||||
switch(totalSize)
|
||||
{
|
||||
case > 1099511627776:
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} TiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1099511627776d);
|
||||
|
||||
break;
|
||||
case > 1073741824:
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} GiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1073741824d);
|
||||
|
||||
break;
|
||||
case > 1048576:
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} MiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1048576d);
|
||||
|
||||
break;
|
||||
case > 1024:
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2:F3} KiB)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize / 1024d);
|
||||
|
||||
break;
|
||||
default:
|
||||
AaruConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)",
|
||||
scsiInfo.Blocks, scsiInfo.BlockSize, totalSize);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -682,8 +695,8 @@ sealed class MediaInfoCommand : Command
|
||||
}
|
||||
else
|
||||
{
|
||||
AaruConsole.
|
||||
WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
|
||||
AaruConsole.WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4
|
||||
} samples).");
|
||||
|
||||
AaruConsole.WriteLine("[red]Disc write offset is unknown.[/]");
|
||||
}
|
||||
@@ -696,13 +709,13 @@ sealed class MediaInfoCommand : Command
|
||||
{
|
||||
AaruConsole.WriteLine("[red]Drive reading offset not found in database.[/]");
|
||||
|
||||
AaruConsole.
|
||||
WriteLine($"Combined disc and drive offset are {offsetBytes} bytes ({offsetBytes / 4} samples).");
|
||||
AaruConsole.WriteLine($"Combined disc and drive offset are {offsetBytes} bytes ({offsetBytes / 4
|
||||
} samples).");
|
||||
}
|
||||
else
|
||||
{
|
||||
AaruConsole.
|
||||
WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4} samples).");
|
||||
AaruConsole.WriteLine($"Drive reading offset is {driveOffset} bytes ({driveOffset / 4
|
||||
} samples).");
|
||||
|
||||
AaruConsole.WriteLine($"Combined offset is {offsetBytes} bytes ({offsetBytes / 4} samples).");
|
||||
|
||||
@@ -713,6 +726,7 @@ sealed class MediaInfoCommand : Command
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev.Close();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user