Add support for PD650 media.

This commit is contained in:
2019-05-16 23:29:54 +01:00
parent 3d7d50dc25
commit 8fefbb4d00
13 changed files with 290 additions and 153 deletions

View File

@@ -1542,7 +1542,12 @@ namespace DiscImageChef.CommonTypes
{ {
switch(mediumType) switch(mediumType)
{ {
case 0x00: return MediaType.CD; case 0x00:
return blockSize == 512
? blocks == 1281856
? MediaType.PD650_WORM
: MediaType.PD650
: MediaType.CD;
case 0x01: case 0x01:
case 0x05: return MediaType.CDROM; case 0x05: return MediaType.CDROM;
case 0x02: case 0x02:

View File

@@ -74,6 +74,9 @@ namespace DiscImageChef.Core.Devices.Dumping
case 0x0001: case 0x0001:
dskType = MediaType.GENERIC_HDD; dskType = MediaType.GENERIC_HDD;
goto default; goto default;
case 0x0002:
dskType = MediaType.PD650;
goto default;
case 0x0005: case 0x0005:
dskType = MediaType.CDMO; dskType = MediaType.CDMO;
break; break;
@@ -175,6 +178,8 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Device reports disc has {0} blocks", blocks); dumpLog.WriteLine("Device reports disc has {0} blocks", blocks);
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>(); Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>();
if(dskType == MediaType.PD650 && blocks == 1281856) dskType = MediaType.PD650_WORM;
#region Nintendo #region Nintendo
switch(dskType) switch(dskType)
{ {

View File

@@ -73,18 +73,18 @@ namespace DiscImageChef.Core.Devices.Dumping
fxSense = Sense.DecodeFixed(senseBuf, out string strSense); fxSense = Sense.DecodeFixed(senseBuf, out string strSense);
InitProgress?.Invoke(); InitProgress?.Invoke();
if(fxSense.HasValue && fxSense.Value.SenseKey != SenseKeys.NoSense) if(fxSense.HasValue && fxSense?.SenseKey != SenseKeys.NoSense)
{ {
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
StoppingErrorMessage?.Invoke("Drive has status error, please correct. Sense follows..." + StoppingErrorMessage?.Invoke("Drive has status error, please correct. Sense follows..." +
Environment.NewLine + strSense); Environment.NewLine + strSense);
return; return;
} }
// Not in BOM/P // Not in BOM/P
if(fxSense.HasValue && fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x00 && if(fxSense.HasValue && fxSense?.ASC == 0x00 && fxSense?.ASCQ != 0x00 && fxSense?.ASCQ != 0x04 &&
fxSense.Value.ASCQ != 0x04 && fxSense.Value.SenseKey != SenseKeys.IllegalRequest) fxSense?.SenseKey != SenseKeys.IllegalRequest)
{ {
dumpLog.WriteLine("Rewinding, please wait..."); dumpLog.WriteLine("Rewinding, please wait...");
PulseProgress?.Invoke("Rewinding, please wait..."); PulseProgress?.Invoke("Rewinding, please wait...");
@@ -99,21 +99,21 @@ namespace DiscImageChef.Core.Devices.Dumping
dev.RequestSense(out senseBuf, dev.Timeout, out duration); dev.RequestSense(out senseBuf, dev.Timeout, out duration);
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
} }
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 && while(fxSense.HasValue && fxSense?.ASC == 0x00 &&
(fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ != 0x04 || fxSense.Value.ASCQ != 0x00)); (fxSense?.ASCQ == 0x1A || fxSense?.ASCQ != 0x04 || fxSense?.ASCQ != 0x00));
dev.RequestSense(out senseBuf, dev.Timeout, out duration); dev.RequestSense(out senseBuf, dev.Timeout, out duration);
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
// And yet, did not rewind! // And yet, did not rewind!
if(fxSense.HasValue && if(fxSense.HasValue && (fxSense?.ASC == 0x00 && fxSense?.ASCQ != 0x04 && fxSense?.ASCQ != 0x00 ||
(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04 && fxSense.Value.ASCQ != 0x00 || fxSense.Value.ASC != 0x00)) fxSense?.ASC != 0x00))
{ {
StoppingErrorMessage?.Invoke("Drive could not rewind, please correct. Sense follows..." + StoppingErrorMessage?.Invoke("Drive could not rewind, please correct. Sense follows..." +
Environment.NewLine + strSense); Environment.NewLine + strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
} }
@@ -128,15 +128,14 @@ namespace DiscImageChef.Core.Devices.Dumping
// Anyway, <=SCSI-1 tapes do not support partitions // Anyway, <=SCSI-1 tapes do not support partitions
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
if(fxSense.HasValue && (fxSense.Value.ASC == 0x20 && fxSense.Value.ASCQ != 0x00 || if(fxSense.HasValue && (fxSense?.ASC == 0x20 && fxSense?.ASCQ != 0x00 ||
fxSense.Value.ASC != 0x20 && fxSense?.ASC != 0x20 && fxSense?.SenseKey != SenseKeys.IllegalRequest))
fxSense.Value.SenseKey != SenseKeys.IllegalRequest))
{ {
StoppingErrorMessage?.Invoke("Could not get position. Sense follows..." + Environment.NewLine + StoppingErrorMessage?.Invoke("Could not get position. Sense follows..." + Environment.NewLine +
strSense); strSense);
dumpLog.WriteLine("Could not get position. Sense follows..."); dumpLog.WriteLine("Could not get position. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
} }
@@ -155,8 +154,8 @@ namespace DiscImageChef.Core.Devices.Dumping
Environment.NewLine + Environment.NewLine +
strSense); strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
@@ -169,19 +168,18 @@ namespace DiscImageChef.Core.Devices.Dumping
dev.RequestSense(out senseBuf, dev.Timeout, out duration); dev.RequestSense(out senseBuf, dev.Timeout, out duration);
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
} }
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 && while(fxSense.HasValue && fxSense?.ASC == 0x00 && (fxSense?.ASCQ == 0x1A || fxSense?.ASCQ == 0x19));
(fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ == 0x19));
// And yet, did not rewind! // And yet, did not rewind!
if(fxSense.HasValue && (fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04 && fxSense.Value.ASCQ != 0x00 || if(fxSense.HasValue && (fxSense?.ASC == 0x00 && fxSense?.ASCQ != 0x04 && fxSense?.ASCQ != 0x00 ||
fxSense.Value.ASC != 0x00)) fxSense?.ASC != 0x00))
{ {
StoppingErrorMessage?.Invoke("Drive could not rewind, please correct. Sense follows..." + StoppingErrorMessage?.Invoke("Drive could not rewind, please correct. Sense follows..." +
Environment.NewLine + Environment.NewLine +
strSense); strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
@@ -194,8 +192,8 @@ namespace DiscImageChef.Core.Devices.Dumping
Environment.NewLine + Environment.NewLine +
strSense); strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
@@ -285,20 +283,20 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
if(fxSense.HasValue) if(fxSense.HasValue)
if(fxSense.Value.SenseKey == SenseKeys.IllegalRequest) if(fxSense?.SenseKey == SenseKeys.IllegalRequest)
{ {
sense = dev.Space(out senseBuf, SscSpaceCodes.LogicalBlock, -1, dev.Timeout, out duration); sense = dev.Space(out senseBuf, SscSpaceCodes.LogicalBlock, -1, dev.Timeout, out duration);
if(sense) if(sense)
{ {
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
if(!fxSense.HasValue || !fxSense.Value.EOM) if(!fxSense.HasValue || !fxSense?.EOM == true)
{ {
StoppingErrorMessage?.Invoke("Drive could not return back. Sense follows..." + StoppingErrorMessage?.Invoke("Drive could not return back. Sense follows..." +
Environment.NewLine + Environment.NewLine +
strSense); strSense);
dumpLog.WriteLine("Drive could not return back. Sense follows..."); dumpLog.WriteLine("Drive could not return back. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.SenseKey, fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
} }
@@ -313,13 +311,13 @@ namespace DiscImageChef.Core.Devices.Dumping
StoppingErrorMessage?.Invoke("Drive could not read. Sense follows..." + StoppingErrorMessage?.Invoke("Drive could not read. Sense follows..." +
Environment.NewLine + strSense); Environment.NewLine + strSense);
dumpLog.WriteLine("Drive could not read. Sense follows..."); dumpLog.WriteLine("Drive could not read. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
} }
else if(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ == 0x00 && fxSense.Value.ILI && else if(fxSense?.ASC == 0x00 && fxSense?.ASCQ == 0x00 && fxSense?.ILI == true &&
fxSense.Value.InformationValid) fxSense?.InformationValid == true)
{ {
blockSize = (uint)((int)blockSize - blockSize = (uint)((int)blockSize -
BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0)); BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0));
@@ -340,7 +338,7 @@ namespace DiscImageChef.Core.Devices.Dumping
strSense); strSense);
dumpLog.WriteLine("Drive could not go back one block. Sense follows..."); dumpLog.WriteLine("Drive could not go back one block. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.SenseKey, fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
@@ -351,8 +349,8 @@ namespace DiscImageChef.Core.Devices.Dumping
StoppingErrorMessage?.Invoke("Drive could not read. Sense follows..." + Environment.NewLine + StoppingErrorMessage?.Invoke("Drive could not read. Sense follows..." + Environment.NewLine +
strSense); strSense);
dumpLog.WriteLine("Drive could not read. Sense follows..."); dumpLog.WriteLine("Drive could not read. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
else else
@@ -367,13 +365,13 @@ namespace DiscImageChef.Core.Devices.Dumping
if(sense) if(sense)
{ {
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
if(!fxSense.HasValue || !fxSense.Value.EOM) if(!fxSense.HasValue || !fxSense?.EOM == true)
{ {
StoppingErrorMessage?.Invoke("Drive could not return back. Sense follows..." + Environment.NewLine + StoppingErrorMessage?.Invoke("Drive could not return back. Sense follows..." + Environment.NewLine +
strSense); strSense);
dumpLog.WriteLine("Drive could not return back. Sense follows..."); dumpLog.WriteLine("Drive could not return back. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, dumpLog.WriteLine("Device not ready. Sense {0} ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
} }
@@ -596,18 +594,17 @@ namespace DiscImageChef.Core.Devices.Dumping
dev.RequestSense(out senseBuf, dev.Timeout, out duration); dev.RequestSense(out senseBuf, dev.Timeout, out duration);
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
} }
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 && while(fxSense.HasValue && fxSense?.ASC == 0x00 && (fxSense?.ASCQ == 0x1A || fxSense?.ASCQ == 0x19));
(fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ == 0x19));
// And yet, did not rewind! // And yet, did not rewind!
if(fxSense.HasValue && if(fxSense.HasValue && (fxSense?.ASC == 0x00 && fxSense?.ASCQ != 0x00 && fxSense?.ASCQ != 0x04 ||
(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x00 && fxSense.Value.ASCQ != 0x04 || fxSense.Value.ASC != 0x00)) fxSense?.ASC != 0x00))
{ {
StoppingErrorMessage?.Invoke("Drive could not rewind, please correct. Sense follows..." + StoppingErrorMessage?.Invoke("Drive could not rewind, please correct. Sense follows..." +
Environment.NewLine + strSense); Environment.NewLine + strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
} }
@@ -721,11 +718,12 @@ namespace DiscImageChef.Core.Devices.Dumping
out duration); out duration);
totalDuration += duration; totalDuration += duration;
if(sense) if(sense && senseBuf?.Length != 0 && !ArrayHelpers.ArrayIsNullOrEmpty(senseBuf))
{ {
fxSense = Sense.DecodeFixed(senseBuf, out strSense); fxSense = Sense.DecodeFixed(senseBuf, out strSense);
if(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ == 0x00 && fxSense.Value.ILI &&
fxSense.Value.InformationValid) if(fxSense?.ASC == 0x00 && fxSense?.ASCQ == 0x00 && fxSense?.ILI == true &&
fxSense?.InformationValid == true)
{ {
blockSize = (uint)((int)blockSize - blockSize = (uint)((int)blockSize -
BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0)); BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0));
@@ -747,14 +745,14 @@ namespace DiscImageChef.Core.Devices.Dumping
outputPlugin.Close(); outputPlugin.Close();
dumpLog.WriteLine("Drive could not go back one block. Sense follows..."); dumpLog.WriteLine("Drive could not go back one block. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.SenseKey, fxSense?.ASC, fxSense?.ASCQ);
return; return;
} }
continue; continue;
} }
switch(fxSense.Value.SenseKey) switch(fxSense?.SenseKey)
{ {
case SenseKeys.BlankCheck when currentBlock == 0: case SenseKeys.BlankCheck when currentBlock == 0:
StoppingErrorMessage?.Invoke("Cannot dump a blank tape..."); StoppingErrorMessage?.Invoke("Cannot dump a blank tape...");
@@ -762,9 +760,9 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Cannot dump a blank tape..."); dumpLog.WriteLine("Cannot dump a blank tape...");
return; return;
// For sure this is an end-of-tape/partition // For sure this is an end-of-tape/partition
case SenseKeys.BlankCheck when fxSense.Value.ASC == 0x00 && case SenseKeys.BlankCheck when fxSense?.ASC == 0x00 &&
(fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || (fxSense?.ASCQ == 0x02 || fxSense?.ASCQ == 0x05 ||
fxSense.Value.EOM): fxSense?.EOM == true):
// TODO: Detect end of partition // TODO: Detect end of partition
endOfMedia = true; endOfMedia = true;
UpdateStatus?.Invoke("Found end-of-tape/partition..."); UpdateStatus?.Invoke("Found end-of-tape/partition...");
@@ -777,9 +775,9 @@ namespace DiscImageChef.Core.Devices.Dumping
continue; continue;
} }
if((fxSense.Value.SenseKey == SenseKeys.NoSense || if((fxSense?.SenseKey == SenseKeys.NoSense ||
fxSense.Value.SenseKey == SenseKeys.RecoveredError) && fxSense?.SenseKey == SenseKeys.RecoveredError) &&
(fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM)) (fxSense?.ASCQ == 0x02 || fxSense?.ASCQ == 0x05 || fxSense?.EOM == true))
{ {
// TODO: Detect end of partition // TODO: Detect end of partition
endOfMedia = true; endOfMedia = true;
@@ -788,9 +786,8 @@ namespace DiscImageChef.Core.Devices.Dumping
continue; continue;
} }
if((fxSense.Value.SenseKey == SenseKeys.NoSense || if((fxSense?.SenseKey == SenseKeys.NoSense || fxSense?.SenseKey == SenseKeys.RecoveredError) &&
fxSense.Value.SenseKey == SenseKeys.RecoveredError) && (fxSense?.ASCQ == 0x01 || fxSense?.Filemark == true))
(fxSense.Value.ASCQ == 0x01 || fxSense.Value.Filemark))
{ {
currentTapeFile.LastBlock = currentBlock - 1; currentTapeFile.LastBlock = currentBlock - 1;
(outputPlugin as IWritableTapeImage).AddFile(currentTapeFile); (outputPlugin as IWritableTapeImage).AddFile(currentTapeFile);
@@ -806,12 +803,21 @@ namespace DiscImageChef.Core.Devices.Dumping
continue; continue;
} }
fxSense = Sense.DecodeFixed(senseBuf, out strSense); if(fxSense is null)
{
StoppingErrorMessage StoppingErrorMessage
?.Invoke($"Drive could not read block ${currentBlock}. Sense follows...\n{fxSense.Value.SenseKey} {strSense}"); ?.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{fxSense?.SenseKey} {strSense}");
dumpLog.WriteLine($"Drive could not read block ${currentBlock}. Sense follows..."); dumpLog.WriteLine($"Drive could not read block ${currentBlock}. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense?.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ); fxSense?.ASC, fxSense?.ASCQ);
}
// TODO: Reset device after X errors // TODO: Reset device after X errors
if(stopOnError) return; // TODO: Return more cleanly if(stopOnError) return; // TODO: Return more cleanly

View File

@@ -564,7 +564,8 @@ namespace DiscImageChef.Core.Devices.Report
} }
if(mediaType.StartsWith("DVD-", StringComparison.Ordinal) || if(mediaType.StartsWith("DVD-", StringComparison.Ordinal) ||
mediaType.StartsWith("HD DVD-", StringComparison.Ordinal)) mediaType.StartsWith("HD DVD-", StringComparison.Ordinal) ||
mediaType.StartsWith("PD-", StringComparison.Ordinal))
{ {
DicConsole.WriteLine("Querying DVD PFI..."); DicConsole.WriteLine("Querying DVD PFI...");
mediaTest.CanReadPFI = !dev.ReadDiscStructure(out buffer, out senseBuffer, mediaTest.CanReadPFI = !dev.ReadDiscStructure(out buffer, out senseBuffer,
@@ -639,6 +640,7 @@ namespace DiscImageChef.Core.Devices.Report
case "DVD-RAM (1st gen, marked 2.6Gb or 5.2Gb)": case "DVD-RAM (1st gen, marked 2.6Gb or 5.2Gb)":
case "DVD-RAM (2nd gen, marked 4.7Gb or 9.4Gb)": case "DVD-RAM (2nd gen, marked 4.7Gb or 9.4Gb)":
case "HD DVD-RAM": case "HD DVD-RAM":
case "PD-650":
mediaTest.CanReadDDS = !dev.ReadDiscStructure(out buffer, out senseBuffer, mediaTest.CanReadDDS = !dev.ReadDiscStructure(out buffer, out senseBuffer,
MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureMediaType.Dvd, 0, 0,
MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout, MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout,
@@ -755,25 +757,50 @@ namespace DiscImageChef.Core.Devices.Report
if(debug) mediaTest.BluPacData = buffer; if(debug) mediaTest.BluPacData = buffer;
} }
if(mediaType.StartsWith("PD-", StringComparison.Ordinal))
{
DicConsole.WriteLine("Trying SCSI READ (6)...");
mediaTest.SupportsRead6 = !dev.Read6(out buffer, out senseBuffer, 16, 512, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead6);
if(debug) mediaTest.Read6Data = buffer;
DicConsole.WriteLine("Trying SCSI READ (10)...");
mediaTest.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 16,
512, 0, 1, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead10);
if(debug) mediaTest.Read10Data = buffer;
DicConsole.WriteLine("Trying SCSI READ (12)...");
mediaTest.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 16,
512, 0, 1, false, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead12);
if(debug) mediaTest.Read12Data = buffer;
DicConsole.WriteLine("Trying SCSI READ (16)...");
mediaTest.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 16, 512, 0,
1, false, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead16);
if(debug) mediaTest.Read16Data = buffer;
}
else
{
DicConsole.WriteLine("Trying SCSI READ (6)..."); DicConsole.WriteLine("Trying SCSI READ (6)...");
mediaTest.SupportsRead6 = !dev.Read6(out buffer, out senseBuffer, 16, 2048, dev.Timeout, out _); mediaTest.SupportsRead6 = !dev.Read6(out buffer, out senseBuffer, 16, 2048, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead6); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead6);
if(debug) mediaTest.Read6Data = buffer; if(debug) mediaTest.Read6Data = buffer;
DicConsole.WriteLine("Trying SCSI READ (10)..."); DicConsole.WriteLine("Trying SCSI READ (10)...");
mediaTest.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 16, 2048, mediaTest.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 16,
0, 1, dev.Timeout, out _); 2048, 0, 1, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead10); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead10);
if(debug) mediaTest.Read10Data = buffer; if(debug) mediaTest.Read10Data = buffer;
DicConsole.WriteLine("Trying SCSI READ (12)..."); DicConsole.WriteLine("Trying SCSI READ (12)...");
mediaTest.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 16, 2048, mediaTest.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 16,
0, 1, false, dev.Timeout, out _); 2048, 0, 1, false, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead12); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead12);
if(debug) mediaTest.Read12Data = buffer; if(debug) mediaTest.Read12Data = buffer;
DicConsole.WriteLine("Trying SCSI READ (16)..."); DicConsole.WriteLine("Trying SCSI READ (16)...");
mediaTest.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 16, 2048, 0, 1, mediaTest.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 16, 2048, 0,
false, dev.Timeout, out _); 1, false, dev.Timeout, out _);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead16); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead16);
if(debug) mediaTest.Read16Data = buffer; if(debug) mediaTest.Read16Data = buffer;
}
if(mediaType.StartsWith("CD-", StringComparison.Ordinal) || if(mediaType.StartsWith("CD-", StringComparison.Ordinal) ||
mediaType.StartsWith("DDCD-", StringComparison.Ordinal) || mediaType == "Audio CD") mediaType.StartsWith("DDCD-", StringComparison.Ordinal) || mediaType == "Audio CD")

View File

@@ -43,19 +43,19 @@ namespace DiscImageChef.Core.Logging
/// </summary> /// </summary>
class IbgLog class IbgLog
{ {
CultureInfo ibgCulture; readonly CultureInfo ibgCulture;
DateTime ibgDatePoint; DateTime ibgDatePoint;
double ibgDivider; readonly double ibgDivider;
ulong ibgIntSector; ulong ibgIntSector;
double ibgIntSpeed; double ibgIntSpeed;
double ibgMaxSpeed; double ibgMaxSpeed;
string ibgMediaType; readonly string ibgMediaType;
int ibgSampleRate; int ibgSampleRate;
StringBuilder ibgSb; readonly StringBuilder ibgSb;
int ibgSnaps; int ibgSnaps;
bool ibgStartSet; bool ibgStartSet;
double ibgStartSpeed; double ibgStartSpeed;
string logFile; readonly string logFile;
/// <summary> /// <summary>
/// Initializes the IMGBurn log /// Initializes the IMGBurn log
@@ -82,6 +82,10 @@ namespace DiscImageChef.Core.Logging
ibgMediaType = "HDD"; ibgMediaType = "HDD";
ibgDivider = 1353; ibgDivider = 1353;
break; break;
case 0x0002:
ibgMediaType = "PD-650";
ibgDivider = 150;
break;
case 0x0005: case 0x0005:
ibgMediaType = "CD-MO"; ibgMediaType = "CD-MO";
ibgDivider = 150; ibgDivider = 150;

View File

@@ -307,6 +307,9 @@ namespace DiscImageChef.Core.Media.Info
case 0x0001: case 0x0001:
MediaType = MediaType.GENERIC_HDD; MediaType = MediaType.GENERIC_HDD;
break; break;
case 0x0002:
MediaType = MediaType.PD650;
break;
case 0x0005: case 0x0005:
MediaType = MediaType.CDMO; MediaType = MediaType.CDMO;
break; break;
@@ -394,6 +397,8 @@ namespace DiscImageChef.Core.Media.Info
} }
} }
if(MediaType == MediaType.PD650 && Blocks == 1281856) MediaType = MediaType.PD650_WORM;
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0,
MmcDiscStructureFormat.RecognizedFormatLayers, 0, dev.Timeout, out _); MmcDiscStructureFormat.RecognizedFormatLayers, 0, dev.Timeout, out _);
if(sense) if(sense)
@@ -1546,6 +1551,7 @@ namespace DiscImageChef.Core.Media.Info
break; break;
} }
// TODO: Check for CD-i Ready // TODO: Check for CD-i Ready
case MediaType.CDI: break; case MediaType.CDI: break;
case MediaType.DVDROM: case MediaType.DVDROM:
@@ -1758,6 +1764,7 @@ namespace DiscImageChef.Core.Media.Info
break; break;
} }
// TODO: Check for CD-i Ready // TODO: Check for CD-i Ready
case MediaType.CDI: break; case MediaType.CDI: break;
case MediaType.DVDROM: case MediaType.DVDROM:

View File

@@ -128,13 +128,13 @@ namespace DiscImageChef.DiscImages
MediaType.DVDROM, MediaType.DVDRW, MediaType.DVDRWDL, MediaType.EVD, MediaType.FDDVD, MediaType.DVDROM, MediaType.DVDRW, MediaType.DVDRWDL, MediaType.EVD, MediaType.FDDVD,
MediaType.DTSCD, MediaType.FVD, MediaType.HDDVDR, MediaType.HDDVDRAM, MediaType.HDDVDRDL, MediaType.DTSCD, MediaType.FVD, MediaType.HDDVDR, MediaType.HDDVDRAM, MediaType.HDDVDRDL,
MediaType.HDDVDROM, MediaType.HDDVDRW, MediaType.HDDVDRWDL, MediaType.HDVMD, MediaType.HVD, MediaType.HDDVDROM, MediaType.HDDVDRW, MediaType.HDDVDRWDL, MediaType.HDVMD, MediaType.HVD,
MediaType.JaguarCD, MediaType.MEGACD, MediaType.PD650, MediaType.PD650_WORM, MediaType.PS1CD, MediaType.JaguarCD, MediaType.MEGACD, MediaType.PS1CD, MediaType.PS2CD, MediaType.PS2DVD,
MediaType.PS2CD, MediaType.PS2DVD, MediaType.PS3BD, MediaType.PS3DVD, MediaType.PS4BD, MediaType.PS3BD, MediaType.PS3DVD, MediaType.PS4BD, MediaType.SuperCDROM2, MediaType.SVCD,
MediaType.SuperCDROM2, MediaType.SVCD, MediaType.SVOD, MediaType.SATURNCD, MediaType.ThreeDO, MediaType.SVOD, MediaType.SATURNCD, MediaType.ThreeDO, MediaType.UDO, MediaType.UDO2,
MediaType.UDO, MediaType.UDO2, MediaType.UDO2_WORM, MediaType.UMD, MediaType.VCD, MediaType.VCDHD, MediaType.UDO2_WORM, MediaType.UMD, MediaType.VCD, MediaType.VCDHD, MediaType.NeoGeoCD,
MediaType.NeoGeoCD, MediaType.PCFX, MediaType.CDTV, MediaType.CD32, MediaType.Nuon, MediaType.PCFX, MediaType.CDTV, MediaType.CD32, MediaType.Nuon, MediaType.Playdia, MediaType.Pippin,
MediaType.Playdia, MediaType.Pippin, MediaType.FMTOWNS, MediaType.MilCD, MediaType.VideoNow, MediaType.FMTOWNS, MediaType.MilCD, MediaType.VideoNow, MediaType.VideoNowColor,
MediaType.VideoNowColor, MediaType.VideoNowXp MediaType.VideoNowXp
}; };
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions => public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
new (string name, Type type, string description, object @default)[] { }; new (string name, Type type, string description, object @default)[] { };

View File

@@ -200,8 +200,6 @@ namespace DiscImageChef.DiscImages
case MediaType.DTSCD: case MediaType.DTSCD:
case MediaType.JaguarCD: case MediaType.JaguarCD:
case MediaType.MEGACD: case MediaType.MEGACD:
case MediaType.PD650:
case MediaType.PD650_WORM:
case MediaType.PS1CD: case MediaType.PS1CD:
case MediaType.PS2CD: case MediaType.PS2CD:
case MediaType.SuperCDROM2: case MediaType.SuperCDROM2:

View File

@@ -137,6 +137,8 @@ namespace DiscImageChef.DiscImages
case 533403648: return MediaType.ECMA_183; case 533403648: return MediaType.ECMA_183;
case 596787200: return MediaType.ECMA_184_512; case 596787200: return MediaType.ECMA_184_512;
case 654540800: return MediaType.ECMA_184; case 654540800: return MediaType.ECMA_184;
case 656310272 when imageInfo.SectorSize == 512: return MediaType.PD650;
case 664829952 when imageInfo.SectorSize == 512: return MediaType.PD650;
case 1070617600: return MediaType.Jaz; case 1070617600: return MediaType.Jaz;
#region Commodore #region Commodore

View File

@@ -122,6 +122,8 @@ namespace DiscImageChef.DiscImages
? mode2 ? mode2
? "MODE2/2352" ? "MODE2/2352"
: "MODE1/2352" : "MODE1/2352"
: imageInfo.MediaType == MediaType.PD650 || imageInfo.MediaType == MediaType.PD650_WORM
? "DATA/512"
: "MODE1/2048", : "MODE1/2048",
Size = imageInfo.Sectors * imageInfo.SectorSize Size = imageInfo.Sectors * imageInfo.SectorSize
}; };

View File

@@ -376,8 +376,7 @@ namespace DiscImageChef.DiscImages
// Check for Xbox // Check for Xbox
if(mediaTags.TryGetValue(MediaTagType.DVD_DMI, out byte[] dmi)) if(mediaTags.TryGetValue(MediaTagType.DVD_DMI, out byte[] dmi))
if(DMI.IsXbox(dmi) || DMI.IsXbox360(dmi)) if(DMI.IsXbox(dmi) || DMI.IsXbox360(dmi))
if(DMI.IsXbox(dmi)) if(DMI.IsXbox(dmi)) imageInfo.MediaType = MediaType.XGD;
imageInfo.MediaType = MediaType.XGD;
else if(DMI.IsXbox360(dmi)) else if(DMI.IsXbox360(dmi))
{ {
imageInfo.MediaType = MediaType.XGD2; imageInfo.MediaType = MediaType.XGD2;
@@ -900,6 +899,8 @@ namespace DiscImageChef.DiscImages
case MediaType.XGD: case MediaType.XGD:
case MediaType.XGD2: case MediaType.XGD2:
case MediaType.XGD3: case MediaType.XGD3:
case MediaType.PD650:
case MediaType.PD650_WORM:
imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
break; break;
default: default:
@@ -1151,6 +1152,7 @@ namespace DiscImageChef.DiscImages
sectorSkip = 2340; sectorSkip = 2340;
break; break;
} }
case SectorTagType.CdSectorHeader: case SectorTagType.CdSectorHeader:
{ {
sectorOffset = 12; sectorOffset = 12;
@@ -1158,12 +1160,14 @@ namespace DiscImageChef.DiscImages
sectorSkip = 2336; sectorSkip = 2336;
break; break;
} }
case SectorTagType.CdSectorSubchannel: case SectorTagType.CdSectorSubchannel:
{ {
sectorOffset = 2352; sectorOffset = 2352;
sectorSize = 96; sectorSize = 96;
break; break;
} }
case SectorTagType.CdSectorSubHeader: case SectorTagType.CdSectorSubHeader:
throw new ArgumentException("Unsupported tag requested for this track", nameof(tag)); throw new ArgumentException("Unsupported tag requested for this track", nameof(tag));
case SectorTagType.CdSectorEcc: case SectorTagType.CdSectorEcc:
@@ -1173,6 +1177,7 @@ namespace DiscImageChef.DiscImages
sectorSkip = 0; sectorSkip = 0;
break; break;
} }
case SectorTagType.CdSectorEccP: case SectorTagType.CdSectorEccP:
{ {
sectorOffset = 2076; sectorOffset = 2076;
@@ -1180,6 +1185,7 @@ namespace DiscImageChef.DiscImages
sectorSkip = 104; sectorSkip = 104;
break; break;
} }
case SectorTagType.CdSectorEccQ: case SectorTagType.CdSectorEccQ:
{ {
sectorOffset = 2248; sectorOffset = 2248;
@@ -1187,6 +1193,7 @@ namespace DiscImageChef.DiscImages
sectorSkip = 0; sectorSkip = 0;
break; break;
} }
case SectorTagType.CdSectorEdc: case SectorTagType.CdSectorEdc:
{ {
sectorOffset = 2064; sectorOffset = 2064;
@@ -1194,6 +1201,7 @@ namespace DiscImageChef.DiscImages
sectorSkip = 284; sectorSkip = 284;
break; break;
} }
default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); default: throw new ArgumentException("Unsupported tag requested", nameof(tag));
} }

View File

@@ -36,6 +36,8 @@ namespace DiscImageChef.Filesystems.FAT
{ {
public partial class FAT public partial class FAT
{ {
const int UMSDOS_MAXNAME = 220;
/// <summary> /// <summary>
/// BIOS Parameter Block as used by Atari ST GEMDOS on FAT12 volumes. /// BIOS Parameter Block as used by Atari ST GEMDOS on FAT12 volumes.
/// </summary> /// </summary>
@@ -911,6 +913,70 @@ namespace DiscImageChef.Filesystems.FAT
public readonly ushort zero; public readonly ushort zero;
} }
/// <summary>
/// This structure is 256 bytes large, depending on the name, only part of it is written to disk
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct UmsdosDirectoryEntry
{
/// <summary>if == 0, then this entry is not used</summary>
public readonly byte name_len;
/// <summary>
/// UMSDOS_xxxx
/// </summary>
public readonly UmsdosFlags flags;
/// <summary>
/// How many hard links point to this entry
/// </summary>
public readonly ushort nlink;
/// <summary>
/// Owner user id
/// </summary>
public readonly int uid;
/// <summary>
/// Group id
/// </summary>
public readonly int gid;
/// <summary>
/// Access time
/// </summary>
public readonly int atime;
/// <summary>
/// Last modification time
/// </summary>
public readonly int mtime;
/// <summary>
/// Creation time
/// </summary>
public readonly int ctime;
/// <summary>
/// major and minor number of a device
/// </summary>
public readonly uint rdev;
/* */
/// <summary>
/// Standard UNIX permissions bits + type of
/// </summary>
public readonly ushort mode;
/// <summary>unused bytes for future extensions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public readonly byte[] spare;
/// <summary>
/// Not '\0' terminated but '\0' padded, so it will allow for adding news fields in this record by reducing the
/// size of name[]
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = UMSDOS_MAXNAME)]
public readonly byte[] name;
}
enum UmsdosFlags : byte
{
/// <summary>Never show this entry in directory search</summary>
UMSDOS_HIDDEN = 1,
/// <summary>It is a (pseudo) hard link</summary>
UMSDOS_HLINK = 2
}
class CompleteDirectoryEntry class CompleteDirectoryEntry
{ {
public DirectoryEntry Dirent; public DirectoryEntry Dirent;
@@ -918,11 +984,16 @@ namespace DiscImageChef.Filesystems.FAT
public HumanDirectoryEntry HumanDirent; public HumanDirectoryEntry HumanDirent;
public string HumanName; public string HumanName;
public string Lfn; public string Lfn;
public UmsdosDirectoryEntry LinuxDirent;
public string LinuxName;
public string Longname; public string Longname;
public string Shortname; public string Shortname;
public override string ToString() public override string ToString()
{ {
// This ensures UMSDOS takes preference when present
if(!string.IsNullOrEmpty(LinuxName)) return LinuxName;
// This ensures LFN takes preference when eCS is in use // This ensures LFN takes preference when eCS is in use
if(!string.IsNullOrEmpty(Lfn)) return Lfn; if(!string.IsNullOrEmpty(Lfn)) return Lfn;

View File

@@ -560,6 +560,8 @@ namespace DiscImageChef.Commands
} }
} }
if(dev.Model.StartsWith("PD-", StringComparison.Ordinal)) mediaTypes.Add("PD-650");
List<TestedMedia> mediaTests = new List<TestedMedia>(); List<TestedMedia> mediaTests = new List<TestedMedia>();
foreach(string mediaType in mediaTypes) foreach(string mediaType in mediaTypes)
{ {