Convert if to switch statement.

This commit is contained in:
2022-11-13 19:38:03 +00:00
parent 98d7ac3349
commit c5b34ee3d9
65 changed files with 2602 additions and 2126 deletions

View File

@@ -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)

View File

@@ -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.");

View File

@@ -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;
}
}

View File

@@ -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.");

View File

@@ -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.");

View File

@@ -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.");

View File

@@ -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.");

View File

@@ -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

View File

@@ -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.");

View File

@@ -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.");

View File

@@ -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.");

View File

@@ -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]);
}
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 &&

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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.");

View File

@@ -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;

View File

@@ -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");

View File

@@ -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)
{

View File

@@ -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();

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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.";

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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";

View File

@@ -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))

View File

@@ -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")

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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,

View File

@@ -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)

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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();
}
}